PIPS
pgcd.c
Go to the documentation of this file.
1 /*
2 
3  $Id: pgcd.c 1669 2019-06-26 17:24:57Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is free software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25  /* package arithmetique
26  */
27 
28  /*LINTLIBRARY*/
29 
30 #ifdef HAVE_CONFIG_H
31  #include "config.h"
32 #endif
33 #include <stdlib.h>
34 #include <stdio.h>
35 
36 #include "arithmetique.h"
37 #include "linear_assert.h"
38 
39 /* Value pgcd_slow(Value a, Value b) computation of the gcd of a and b.
40  * the result is always positive. standard algorithm in log(max(a,b)).
41  * pgcd_slow(0,0)==1 (maybe should we abort?).
42  * I changed from a recursive for a simple iterative version, FC 07/96.
43  */
45 {
46  Value m;
47 
48  if (value_zero_p(a))
49  {
50  if (value_zero_p(b))
51  return VALUE_ONE; /* a==0, b==0 */
52  else
53  return value_abs(b); /* a==0, b!=0 */
54  }
55  else
56  if (value_zero_p(b))
57  return value_abs(a); /* a!=0, b==0 */
58 
59  value_absolute(a);
60  value_absolute(b);
61 
62  if (value_eq(a,b)) /* a==b */
63  return a;
64 
65  if (value_gt(b,a))
66  m = a, a = b, b = m; /* swap */
67 
68  /* on entry in this loop, a > b > 0 is insured */
69  do {
70  m = value_mod(a,b);
71  a = b;
72  b = m;
73  } while(value_notzero_p(b));
74 
75  return a;
76 }
77 
78 /* int pgcd_fast(int a, int b): calcul iteratif du pgcd de deux entiers;
79  * le pgcd retourne est toujours positif; il n'est pas defini si
80  * a et b sont nuls (abort);
81  */
83 {
84  Value gcd;
85 
87 
88  a = value_abs(a);
89  b = value_abs(b);
90 
91  /* si cette routine n'est JAMAIS appelee avec des arguments nuls,
92  il faudrait supprimer les deux tests d'egalite a 0; ca devrait
93  etre le cas avec les vecteurs creux */
94  if(value_gt(a,b))
95  gcd = value_zero_p(b)? a : pgcd_interne(a,b);
96  else
97  gcd = value_zero_p(a)? b : pgcd_interne(b,a);
98 
99  return gcd;
100 }
101 
102 /* int pgcd_interne(int a, int b): calcul iteratif du pgcd de deux entiers
103  * strictement positifs tels que a > b;
104  * le pgcd retourne est toujours positif;
105  */
107 {
108  /* Definition d'une look-up table pour les valeurs de a appartenant
109  a [0..GCD_MAX_A] (en fait [-GCD_MAX_A..GCD_MAX_A])
110  et pour les valeurs de b appartenant a [1..GCD_MAX_B]
111  (en fait [-GCD_MAX_B..GCD_MAX_B] a cause du changement de signe)
112 
113  Serait-il utile d'ajouter une test b==1 pour supprimer une colonne?
114  */
115 #define GCD_MAX_A 15
116 #define GCD_MAX_B 15
117  /* la commutativite du pgcd n'est pas utilisee pour reduire la
118  taille de la table */
119  static Value
120  gcd_look_up[GCD_MAX_A+1][GCD_MAX_B+1]= {
121  /* b == 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
122  {/* a == 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
123  {/* a == 1 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
124  {/* a == 2 */ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1},
125  {/* a == 3 */ 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3},
126  {/* a == 4 */ 4, 1, 2, 1, 4, 1, 2, 1, 4, 1, 2, 1, 4, 1, 2, 1},
127  {/* a == 5 */ 5, 1, 1, 1, 1, 5, 1, 1, 1, 1, 5, 1, 1, 1, 1, 5},
128  {/* a == 6 */ 6, 1, 2, 3, 2, 1, 6, 1, 2, 3, 2, 1, 6, 1, 2, 3},
129  {/* a == 7 */ 7, 1, 1, 1, 1, 1, 1, 7, 1, 1, 1, 1, 1, 1, 7, 1},
130  {/* a == 8 */ 8, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1},
131  {/* a == 9 */ 9, 1, 1, 3, 1, 1, 3, 1, 1, 9, 1, 1, 3, 1, 1, 3},
132  {/* a == 10 */10, 1, 2, 1, 2, 5, 2, 1, 2, 1,10, 1, 2, 1, 2, 5},
133  {/* a == 11 */11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,11, 1, 1, 1, 1},
134  {/* a == 12 */12, 1, 2, 3, 4, 1, 6, 1, 4, 3, 2, 1,12, 1, 2, 3},
135  {/* a == 13 */13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,13, 1, 1},
136  {/* a == 14 */14, 1, 2, 1, 2, 1, 2, 7, 2, 1, 2, 1, 2, 1,14, 1},
137  {/* a == 15 */15, 1, 1, 3, 1, 5, 3, 1, 1, 3, 5, 1, 3, 1, 1, 15}
138  };
139  /* on pourrait aussi utiliser une table des nombres premiers
140  pour diminuer le nombre de boucles */
141 
142  /* on utilise la valeur particuliere -1 pour iterer */
143  Value gcd = VALUE_MONE;
144  Value mod;
145 
146  assert(value_gt(a,b) && value_pos_p(b));
147 
148  do{
149  if(value_le(b,int_to_value(GCD_MAX_B)) &&
151  gcd = gcd_look_up[VALUE_TO_INT(a)][VALUE_TO_INT(b)];
152  break;
153  }
154  else {
155  /* compute modulo(a,b) en utilisant la routine C puisque a et b
156  sont strictement positifs (vaudrait-il mieux utiliser la
157  soustraction?) */
158  mod = value_mod(a,b);
159  if(value_zero_p(mod)) {
160  gcd = b;
161  }
162  else {
163  a = b;
164  b = mod;
165  }
166  }
167  } while(value_neg_p(gcd));
168 
169  return gcd;
170 }
171 
172 /* int gcd_subtract(int a, int b): find the gcd (pgcd) of two integers
173  *
174  * There is no precondition on the input. Negative input is handled
175  * in the same way as positive ones. If one input is zero the output
176  * is equal to the other input - thus an input of two zeros is the
177  * only way an output of zero is created.
178  *
179  * Postcondition: gcd(a,b) > 0 ; gcd(a,b)==0 iff a==0 and b==0
180  * whereas it should be undefined (F. Irigoin)
181  *
182  * Exception: gcd(0,0) aborts
183  *
184  * Implementation: by subtractions
185  *
186  * Note: the signs of a and b do not matter because they can be exactly
187  * divided by the gcd
188  */
190 {
191  a = value_abs(a);
192  b = value_abs(b);
193 
194  while (value_notzero_p(a) && value_notzero_p(b)) {
195  if (value_ge(a,b))
196  a = value_minus(a,b);
197  else
198  b = value_minus(b,a);
199  }
200 
201  if (value_zero_p(a)) {
203  return b;
204  }
205  else {
206  /* b == 0 */
208  return a;
209  }
210 }
211 
212 /* int vecteur_bezout(int u[], int v[], int l): calcul du vecteur v
213  * qui verifie le theoreme de bezout pour le vecteur u; les vecteurs u et
214  * v sont de dimension l
215  *
216  * -> -> ->
217  * < u . v > = gcd(u )
218  * i
219  */
220 Value vecteur_bezout(Value u[], Value v[], int l)
221 {
222  Value gcd, a1, x;
223  Value *p1, *p2;
224  int i, j;
225 
226  assert(l>0);
227 
228  if (l==1) {
229  v[0] = VALUE_ONE;
230  gcd = u[0];
231  }
232  else {
233  p1 = &v[0]; p2 = &v[1];
234  a1 = u[0]; gcd = u[1];
235  gcd = bezout(a1,gcd,p1,p2);
236 
237  /* printf("gcd = %d \n",gcd); */
238 
239  for (i=2;i<l;i++){
240  /* sum u * v = gcd(u )
241  * k<l k k k<l k
242  *
243  * a1 = gcd (u )
244  * k<l-1 k
245  */
246  a1 = u[i];
247  p1 = &v[i];
248  gcd = bezout(a1,gcd,p1,&x);
249  /* printf("gcd = %d\n",gcd); */
250  for (j=0;j<i;j++)
251  value_product(v[j],x);
252  }
253  }
254 
255  return gcd;
256 }
257 
258 /* int bezout(int a, int b, int *x, int *y): calcule x et y, les deux
259  * nombres qui verifient le theoreme de Bezout pour a et b; le pgcd de
260  * a et b est retourne par valeur
261  *
262  * a * x + b * y = gcd(a,b)
263  * return gcd(a,b)
264  */
266 {
268  Value a0,a1,u,v,r,q,c;
269 
270  if (value_ge(a,b))
271  {
272  a0 = a;
273  a1 = b;
274  c = VALUE_ZERO;
275  }
276  else
277  {
278  a0 = b;
279  a1 = a;
280  c = VALUE_ONE;
281  }
282 
283  r = value_mod(a0,a1);
284  while (value_notzero_p(r))
285  {
286  q = value_div(a0,a1);
287  u = value_mult(u1,q);
288  u = value_minus(u0,u);
289 
290  v = value_mult(v1,q);
291  v = value_minus(v0,v);
292  a0 = a1; a1 = r;
293  u0 = u1; u1 = u;
294  v0 = v1; v1 = v;
295 
296  r = value_mod(a0,a1);
297  }
298 
299  if (value_zero_p(c)) {
300  *x = u1;
301  *y = v1;
302  }
303  else {
304  *x = v1;
305  *y = u1;
306  }
307 
308  return(a1);
309 }
310 
311 /* int bezout_grl(int a, int b, int *x, int *y): calcule x et y, les deux
312  * entiers quelconcs qui verifient le theoreme de Bezout pour a et b; le pgcd
313  * de a et b est retourne par valeur
314  *
315  * a * x + b * y = gcd(a,b)
316  * return gcd(a,b)
317  * gcd () >=0
318  * le pre et le post conditions de pgcd sont comme la fonction gcd_subtract().
319  * les situations speciaux sont donnes ci_dessous:
320  * si (a==0 et b==0) x=y=0; gcd()=0,
321  * si (a==0)(ou b==0) x=1(ou -1) y=0 (ou x=0 y=1(ou -1))
322  * et gcd()=a(ou -a) (ou gcd()=b(ou -b))
323  */
325 {
327  Value a0,a1,u,v,r,q,c;
328  Value sa,sb; /* les signes de a et b */
329 
330  sa = sb = VALUE_ONE;
331  if (value_neg_p(a)){
332  sa = VALUE_MONE;
333  a = value_uminus(a);
334  }
335  if (value_neg_p(b)){
336  sb = VALUE_MONE;
337  b = value_uminus(b);
338  }
339  if (value_zero_p(a) && value_zero_p(b)){
340  *x = VALUE_ONE;
341  *y = VALUE_ONE;
342  return VALUE_ZERO;
343  }
344  else if(value_zero_p(a) || value_zero_p(b)){
345  if (value_zero_p(a)){
346  *x = VALUE_ZERO;
347  *y = sb;
348  return(b);
349  }
350  else{
351  *x = sa;
352  *y = VALUE_ZERO;
353  return(a);
354  }
355  }
356  else{
357 
358  if (value_ge(a,b))
359  {
360  a0 = a;
361  a1 = b;
362  c = VALUE_ZERO;
363  }
364  else
365  {
366  a0 = b;
367  a1 = a;
368  c = VALUE_ONE;
369  }
370 
371  r = value_mod(a0,a1);
372  while (value_notzero_p(r))
373  {
374  q = value_div(a0,a1);
375  u = value_mult(u1,q);
376  u = value_minus(u0,u);
377 
378  v = value_mult(v1,q);
379  v = value_minus(v0,v);
380  a0 = a1; a1 = r;
381  u0 = u1; u1 = u;
382  v0 = v1; v1 = v;
383 
384  r = value_mod(a0,a1);
385  }
386 
387  if (value_zero_p(c)) {
388  *x = value_mult(sa,u1);
389  *y = value_mult(sb,v1);
390  }
391  else {
392  *x = value_mult(sa,v1);
393  *y = value_mult(sb,u1);
394  }
395 
396  return a1;
397  }
398 }
#define value_pos_p(val)
#define VALUE_ZERO
#define int_to_value(i)
end LINEAR_VALUE_IS_INT
#define value_minus(v1, v2)
#define value_absolute(ref)
#define value_gt(v1, v2)
#define VALUE_TO_INT(val)
#define value_le(v1, v2)
#define value_notzero_p(val)
#define value_uminus(val)
unary operators on values
#define VALUE_MONE
#define value_zero_p(val)
int Value
#define value_eq(v1, v2)
bool operators on values
#define value_product(v, w)
#define VALUE_ONE
#define value_abs(val)
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
#define value_mod(v1, v2)
#define value_ge(v1, v2)
#define value_neg_p(val)
#define value_div(v1, v2)
#define assert(ex)
Definition: newgen_assert.h:41
Value pgcd_slow(Value a, Value b)
package arithmetique
Definition: pgcd.c:44
Value pgcd_fast(Value a, Value b)
int pgcd_fast(int a, int b): calcul iteratif du pgcd de deux entiers; le pgcd retourne est toujours p...
Definition: pgcd.c:82
Value gcd_subtract(Value a, Value b)
int gcd_subtract(int a, int b): find the gcd (pgcd) of two integers
Definition: pgcd.c:189
Value pgcd_interne(Value a, Value b)
int pgcd_interne(int a, int b): calcul iteratif du pgcd de deux entiers strictement positifs tels que...
Definition: pgcd.c:106
#define GCD_MAX_A
Value bezout(Value a, Value b, Value *x, Value *y)
int bezout(int a, int b, int *x, int *y): calcule x et y, les deux nombres qui verifient le theoreme ...
Definition: pgcd.c:265
Value vecteur_bezout(Value u[], Value v[], int l)
int vecteur_bezout(int u[], int v[], int l): calcul du vecteur v qui verifie le theoreme de bezout po...
Definition: pgcd.c:220
#define GCD_MAX_B
Value bezout_grl(Value a, Value b, Value *x, Value *y)
int bezout_grl(int a, int b, int *x, int *y): calcule x et y, les deux entiers quelconcs qui verifien...
Definition: pgcd.c:324
static char * x
Definition: split_file.c:159
Definition: statement.c:4047