div.c revision 1.1.1.3 1 1.1 mrg /* mpq_div -- divide two rational numbers.
2 1.1 mrg
3 1.1.1.3 mrg Copyright 1991, 1994-1996, 2000, 2001, 2015 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1.1.3 mrg it under the terms of either:
9 1.1.1.3 mrg
10 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free
11 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your
12 1.1.1.3 mrg option) any later version.
13 1.1.1.3 mrg
14 1.1.1.3 mrg or
15 1.1.1.3 mrg
16 1.1.1.3 mrg * the GNU General Public License as published by the Free Software
17 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any
18 1.1.1.3 mrg later version.
19 1.1.1.3 mrg
20 1.1.1.3 mrg or both in parallel, as here.
21 1.1 mrg
22 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
23 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 1.1.1.3 mrg for more details.
26 1.1 mrg
27 1.1.1.3 mrg You should have received copies of the GNU General Public License and the
28 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not,
29 1.1.1.3 mrg see https://www.gnu.org/licenses/. */
30 1.1 mrg
31 1.1 mrg #include "gmp.h"
32 1.1 mrg #include "gmp-impl.h"
33 1.1 mrg
34 1.1 mrg
35 1.1 mrg void
36 1.1 mrg mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2)
37 1.1 mrg {
38 1.1 mrg mpz_t gcd1, gcd2;
39 1.1 mrg mpz_t tmp1, tmp2;
40 1.1.1.3 mrg mp_size_t op1_size;
41 1.1.1.3 mrg mp_size_t op2_size;
42 1.1 mrg mp_size_t alloc;
43 1.1 mrg TMP_DECL;
44 1.1 mrg
45 1.1.1.3 mrg op2_size = SIZ(NUM(op2));
46 1.1 mrg
47 1.1.1.3 mrg if (UNLIKELY (op2_size == 0))
48 1.1 mrg DIVIDE_BY_ZERO;
49 1.1 mrg
50 1.1.1.3 mrg if (UNLIKELY (quot == op2))
51 1.1.1.3 mrg {
52 1.1.1.3 mrg if (op1 == op2)
53 1.1.1.3 mrg {
54 1.1.1.3 mrg PTR(NUM(quot))[0] = 1;
55 1.1.1.3 mrg SIZ(NUM(quot)) = 1;
56 1.1.1.3 mrg PTR(DEN(quot))[0] = 1;
57 1.1.1.3 mrg SIZ(DEN(quot)) = 1;
58 1.1.1.3 mrg return;
59 1.1.1.3 mrg }
60 1.1.1.3 mrg
61 1.1.1.3 mrg /* We checked for op1 == op2: we are not in the x=x/x case.
62 1.1.1.3 mrg We compute x=y/x by computing x=inv(x)*y */
63 1.1.1.3 mrg MPN_PTR_SWAP (PTR(NUM(quot)), ALLOC(NUM(quot)),
64 1.1.1.3 mrg PTR(DEN(quot)), ALLOC(DEN(quot)));
65 1.1.1.3 mrg if (op2_size > 0)
66 1.1.1.3 mrg {
67 1.1.1.3 mrg SIZ(NUM(quot)) = SIZ(DEN(quot));
68 1.1.1.3 mrg SIZ(DEN(quot)) = op2_size;
69 1.1.1.3 mrg }
70 1.1.1.3 mrg else
71 1.1.1.3 mrg {
72 1.1.1.3 mrg SIZ(NUM(quot)) = - SIZ(DEN(quot));
73 1.1.1.3 mrg SIZ(DEN(quot)) = - op2_size;
74 1.1.1.3 mrg }
75 1.1.1.3 mrg mpq_mul (quot, quot, op1);
76 1.1.1.3 mrg return;
77 1.1.1.3 mrg }
78 1.1.1.3 mrg
79 1.1.1.3 mrg op1_size = ABSIZ(NUM(op1));
80 1.1.1.2 mrg
81 1.1.1.3 mrg if (op1_size == 0)
82 1.1 mrg {
83 1.1 mrg /* We special case this to simplify allocation logic; gcd(0,x) = x
84 1.1 mrg is a singular case for the allocations. */
85 1.1.1.2 mrg SIZ(NUM(quot)) = 0;
86 1.1.1.2 mrg PTR(DEN(quot))[0] = 1;
87 1.1.1.2 mrg SIZ(DEN(quot)) = 1;
88 1.1 mrg return;
89 1.1 mrg }
90 1.1 mrg
91 1.1.1.3 mrg op2_size = ABS(op2_size);
92 1.1.1.2 mrg
93 1.1 mrg TMP_MARK;
94 1.1 mrg
95 1.1.1.3 mrg alloc = MIN (op1_size, op2_size);
96 1.1 mrg MPZ_TMP_INIT (gcd1, alloc);
97 1.1 mrg
98 1.1.1.3 mrg alloc = MAX (op1_size, op2_size);
99 1.1 mrg MPZ_TMP_INIT (tmp1, alloc);
100 1.1 mrg
101 1.1.1.3 mrg op2_size = SIZ(DEN(op2));
102 1.1.1.3 mrg op1_size = SIZ(DEN(op1));
103 1.1 mrg
104 1.1.1.3 mrg alloc = MIN (op1_size, op2_size);
105 1.1.1.3 mrg MPZ_TMP_INIT (gcd2, alloc);
106 1.1 mrg
107 1.1.1.3 mrg alloc = MAX (op1_size, op2_size);
108 1.1.1.3 mrg MPZ_TMP_INIT (tmp2, alloc);
109 1.1.1.3 mrg
110 1.1.1.3 mrg /* QUOT might be identical to OP1, so don't store the result there
111 1.1.1.3 mrg until we are finished with the input operand. We can overwrite
112 1.1.1.3 mrg the numerator of QUOT when we are finished with the numerator of
113 1.1.1.3 mrg OP1. */
114 1.1 mrg
115 1.1.1.2 mrg mpz_gcd (gcd1, NUM(op1), NUM(op2));
116 1.1.1.2 mrg mpz_gcd (gcd2, DEN(op2), DEN(op1));
117 1.1 mrg
118 1.1.1.2 mrg mpz_divexact_gcd (tmp1, NUM(op1), gcd1);
119 1.1.1.2 mrg mpz_divexact_gcd (tmp2, DEN(op2), gcd2);
120 1.1 mrg
121 1.1.1.3 mrg mpz_mul (NUM(quot), tmp1, tmp2);
122 1.1 mrg
123 1.1.1.2 mrg mpz_divexact_gcd (tmp1, NUM(op2), gcd1);
124 1.1.1.2 mrg mpz_divexact_gcd (tmp2, DEN(op1), gcd2);
125 1.1 mrg
126 1.1.1.2 mrg mpz_mul (DEN(quot), tmp1, tmp2);
127 1.1 mrg
128 1.1 mrg /* Keep the denominator positive. */
129 1.1.1.2 mrg if (SIZ(DEN(quot)) < 0)
130 1.1 mrg {
131 1.1.1.2 mrg SIZ(DEN(quot)) = -SIZ(DEN(quot));
132 1.1.1.2 mrg SIZ(NUM(quot)) = -SIZ(NUM(quot));
133 1.1 mrg }
134 1.1 mrg
135 1.1 mrg TMP_FREE;
136 1.1 mrg }
137