Coverage Report

Created: 2024-06-28 06:19

/src/gmp-6.2.1/mpz/gcd.c
Line
Count
Source
1
/* mpz/gcd.c:   Calculate the greatest common divisor of two integers.
2
3
Copyright 1991, 1993, 1994, 1996, 2000-2002, 2005, 2010, 2015, 2016
4
Free Software Foundation, Inc.
5
6
This file is part of the GNU MP Library.
7
8
The GNU MP Library is free software; you can redistribute it and/or modify
9
it under the terms of either:
10
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.
14
15
or
16
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.
20
21
or both in parallel, as here.
22
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.
27
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/.  */
31
32
#include "gmp-impl.h"
33
#include "longlong.h"
34
35
36
void
37
mpz_gcd (mpz_ptr g, mpz_srcptr u, mpz_srcptr v)
38
722
{
39
722
  unsigned long int g_zero_bits, u_zero_bits, v_zero_bits;
40
722
  mp_size_t g_zero_limbs, u_zero_limbs, v_zero_limbs;
41
722
  mp_ptr tp;
42
722
  mp_ptr up;
43
722
  mp_size_t usize;
44
722
  mp_ptr vp;
45
722
  mp_size_t vsize;
46
722
  mp_size_t gsize;
47
722
  TMP_DECL;
48
49
722
  up = PTR(u);
50
722
  usize = ABSIZ (u);
51
722
  vp = PTR(v);
52
722
  vsize = ABSIZ (v);
53
  /* GCD(0, V) == V.  */
54
722
  if (usize == 0)
55
10
    {
56
10
      SIZ (g) = vsize;
57
10
      if (g == v)
58
3
  return;
59
7
      tp = MPZ_NEWALLOC (g, vsize);
60
7
      MPN_COPY (tp, vp, vsize);
61
7
      return;
62
7
    }
63
64
  /* GCD(U, 0) == U.  */
65
712
  if (vsize == 0)
66
5
    {
67
5
      SIZ (g) = usize;
68
5
      if (g == u)
69
3
  return;
70
2
      tp = MPZ_NEWALLOC (g, usize);
71
2
      MPN_COPY (tp, up, usize);
72
2
      return;
73
2
    }
74
75
707
  if (usize == 1)
76
117
    {
77
117
      SIZ (g) = 1;
78
117
      MPZ_NEWALLOC (g, 1)[0] = mpn_gcd_1 (vp, vsize, up[0]);
79
117
      return;
80
117
    }
81
82
590
  if (vsize == 1)
83
36
    {
84
36
      SIZ(g) = 1;
85
36
      MPZ_NEWALLOC (g, 1)[0] = mpn_gcd_1 (up, usize, vp[0]);
86
36
      return;
87
36
    }
88
89
554
  TMP_MARK;
90
91
  /*  Eliminate low zero bits from U and V and move to temporary storage.  */
92
554
  tp = up;
93
834
  while (*tp == 0)
94
280
    tp++;
95
554
  u_zero_limbs = tp - up;
96
554
  usize -= u_zero_limbs;
97
554
  count_trailing_zeros (u_zero_bits, *tp);
98
554
  up = TMP_ALLOC_LIMBS (usize);
99
554
  if (u_zero_bits != 0)
100
413
    {
101
413
      mpn_rshift (up, tp, usize, u_zero_bits);
102
413
      usize -= up[usize - 1] == 0;
103
413
    }
104
141
  else
105
141
    MPN_COPY (up, tp, usize);
106
107
554
  tp = vp;
108
691
  while (*tp == 0)
109
137
    tp++;
110
554
  v_zero_limbs = tp - vp;
111
554
  vsize -= v_zero_limbs;
112
554
  count_trailing_zeros (v_zero_bits, *tp);
113
554
  vp = TMP_ALLOC_LIMBS (vsize);
114
554
  if (v_zero_bits != 0)
115
400
    {
116
400
      mpn_rshift (vp, tp, vsize, v_zero_bits);
117
400
      vsize -= vp[vsize - 1] == 0;
118
400
    }
119
154
  else
120
154
    MPN_COPY (vp, tp, vsize);
121
122
554
  if (u_zero_limbs > v_zero_limbs)
123
104
    {
124
104
      g_zero_limbs = v_zero_limbs;
125
104
      g_zero_bits = v_zero_bits;
126
104
    }
127
450
  else
128
450
    {
129
450
      g_zero_limbs = u_zero_limbs;
130
450
      if (u_zero_limbs < v_zero_limbs)
131
26
  g_zero_bits = u_zero_bits;
132
424
      else  /*  Equal.  */
133
424
  g_zero_bits = MIN (u_zero_bits, v_zero_bits);
134
450
    }
135
136
  /*  Call mpn_gcd.  The 2nd argument must not have more bits than the 1st.  */
137
554
  vsize = (usize < vsize || (usize == vsize && up[usize-1] < vp[vsize-1]))
138
554
    ? mpn_gcd (vp, vp, vsize, up, usize)
139
554
    : mpn_gcd (vp, up, usize, vp, vsize);
140
141
  /*  Here G <-- V << (g_zero_limbs*GMP_LIMB_BITS + g_zero_bits).  */
142
554
  gsize = vsize + g_zero_limbs;
143
554
  if (g_zero_bits != 0)
144
315
    {
145
315
      mp_limb_t cy_limb;
146
315
      gsize += (vp[vsize - 1] >> (GMP_NUMB_BITS - g_zero_bits)) != 0;
147
315
      tp = MPZ_NEWALLOC (g, gsize);
148
315
      MPN_ZERO (tp, g_zero_limbs);
149
150
315
      tp = tp + g_zero_limbs;
151
315
      cy_limb = mpn_lshift (tp, vp, vsize, g_zero_bits);
152
315
      if (cy_limb != 0)
153
40
  tp[vsize] = cy_limb;
154
315
    }
155
239
  else
156
239
    {
157
239
      tp = MPZ_NEWALLOC (g, gsize);
158
239
      MPN_ZERO (tp, g_zero_limbs);
159
239
      MPN_COPY (tp + g_zero_limbs, vp, vsize);
160
239
    }
161
162
554
  SIZ (g) = gsize;
163
554
  TMP_FREE;
164
554
}