beta-0.89.2
[luatex.git] / source / libs / gmp / gmp-src / mpz / gcd.c
blob87c6a8f17b7ca8a269c0919fd737ba2c834df09f
1 /* mpz/gcd.c: Calculate the greatest common divisor of two integers.
3 Copyright 1991, 1993, 1994, 1996, 2000-2002, 2005, 2010 Free Software
4 Foundation, Inc.
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of either:
11 * the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
17 * the GNU General Public License as published by the Free Software
18 Foundation; either version 2 of the License, or (at your option) any
19 later version.
21 or both in parallel, as here.
23 The GNU MP Library is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 for more details.
28 You should have received copies of the GNU General Public License and the
29 GNU Lesser General Public License along with the GNU MP Library. If not,
30 see https://www.gnu.org/licenses/. */
32 #include "gmp.h"
33 #include "gmp-impl.h"
34 #include "longlong.h"
37 void
38 mpz_gcd (mpz_ptr g, mpz_srcptr u, mpz_srcptr v)
40 unsigned long int g_zero_bits, u_zero_bits, v_zero_bits;
41 mp_size_t g_zero_limbs, u_zero_limbs, v_zero_limbs;
42 mp_ptr tp;
43 mp_ptr up;
44 mp_size_t usize;
45 mp_ptr vp;
46 mp_size_t vsize;
47 mp_size_t gsize;
48 TMP_DECL;
50 up = PTR(u);
51 usize = ABSIZ (u);
52 vp = PTR(v);
53 vsize = ABSIZ (v);
54 /* GCD(0, V) == V. */
55 if (usize == 0)
57 SIZ (g) = vsize;
58 if (g == v)
59 return;
60 MPZ_REALLOC (g, vsize);
61 MPN_COPY (PTR (g), vp, vsize);
62 return;
65 /* GCD(U, 0) == U. */
66 if (vsize == 0)
68 SIZ (g) = usize;
69 if (g == u)
70 return;
71 MPZ_REALLOC (g, usize);
72 MPN_COPY (PTR (g), up, usize);
73 return;
76 if (usize == 1)
78 SIZ (g) = 1;
79 PTR (g)[0] = mpn_gcd_1 (vp, vsize, up[0]);
80 return;
83 if (vsize == 1)
85 SIZ(g) = 1;
86 PTR (g)[0] = mpn_gcd_1 (up, usize, vp[0]);
87 return;
90 TMP_MARK;
92 /* Eliminate low zero bits from U and V and move to temporary storage. */
93 while (*up == 0)
94 up++;
95 u_zero_limbs = up - PTR(u);
96 usize -= u_zero_limbs;
97 count_trailing_zeros (u_zero_bits, *up);
98 tp = up;
99 up = TMP_ALLOC_LIMBS (usize);
100 if (u_zero_bits != 0)
102 mpn_rshift (up, tp, usize, u_zero_bits);
103 usize -= up[usize - 1] == 0;
105 else
106 MPN_COPY (up, tp, usize);
108 while (*vp == 0)
109 vp++;
110 v_zero_limbs = vp - PTR (v);
111 vsize -= v_zero_limbs;
112 count_trailing_zeros (v_zero_bits, *vp);
113 tp = vp;
114 vp = TMP_ALLOC_LIMBS (vsize);
115 if (v_zero_bits != 0)
117 mpn_rshift (vp, tp, vsize, v_zero_bits);
118 vsize -= vp[vsize - 1] == 0;
120 else
121 MPN_COPY (vp, tp, vsize);
123 if (u_zero_limbs > v_zero_limbs)
125 g_zero_limbs = v_zero_limbs;
126 g_zero_bits = v_zero_bits;
128 else if (u_zero_limbs < v_zero_limbs)
130 g_zero_limbs = u_zero_limbs;
131 g_zero_bits = u_zero_bits;
133 else /* Equal. */
135 g_zero_limbs = u_zero_limbs;
136 g_zero_bits = MIN (u_zero_bits, v_zero_bits);
139 /* Call mpn_gcd. The 2nd argument must not have more bits than the 1st. */
140 vsize = (usize < vsize || (usize == vsize && up[usize-1] < vp[vsize-1]))
141 ? mpn_gcd (vp, vp, vsize, up, usize)
142 : mpn_gcd (vp, up, usize, vp, vsize);
144 /* Here G <-- V << (g_zero_limbs*GMP_LIMB_BITS + g_zero_bits). */
145 gsize = vsize + g_zero_limbs;
146 if (g_zero_bits != 0)
148 mp_limb_t cy_limb;
149 gsize += (vp[vsize - 1] >> (GMP_NUMB_BITS - g_zero_bits)) != 0;
150 MPZ_REALLOC (g, gsize);
151 MPN_ZERO (PTR (g), g_zero_limbs);
153 tp = PTR(g) + g_zero_limbs;
154 cy_limb = mpn_lshift (tp, vp, vsize, g_zero_bits);
155 if (cy_limb != 0)
156 tp[vsize] = cy_limb;
158 else
160 MPZ_REALLOC (g, gsize);
161 MPN_ZERO (PTR (g), g_zero_limbs);
162 MPN_COPY (PTR (g) + g_zero_limbs, vp, vsize);
165 SIZ (g) = gsize;
166 TMP_FREE;