1 /** @file reken.c
2 *
3 * This file contains the numerical routines.
4 * The arithmetic in FORM is normally over the rational numbers.
5 * Hence there are routines for dealing with integers and with rational
6 * of 'arbitrary precision' (within limits)
7 * There are also routines for that calculus modulus an integer.
8 * In addition there are the routines for factorials and bernoulli numbers.
9 * The random number function is currently only for internal purposes.
10 */
11 /* #[ License : */
12 /*
13 * Copyright (C) 1984-2017 J.A.M. Vermaseren
14 * When using this file you are requested to refer to the publication
15 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
16 * This is considered a matter of courtesy as the development was paid
17 * for by FOM the Dutch physics granting agency and we would like to
18 * be able to track its scientific use to convince FOM of its value
19 * for the community.
20 *
21 * This file is part of FORM.
22 *
23 * FORM is free software: you can redistribute it and/or modify it under the
24 * terms of the GNU General Public License as published by the Free Software
25 * Foundation, either version 3 of the License, or (at your option) any later
26 * version.
27 *
28 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
29 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
31 * details.
32 *
33 * You should have received a copy of the GNU General Public License along
34 * with FORM. If not, see <http://www.gnu.org/licenses/>.
35 */
36 /* #] License : */
37 /*
38 #[ Includes : reken.c
39 */
40
41 #include "form3.h"
42 #include <math.h>
43
44 #ifdef WITHGMP
45 #include <gmp.h>
46 #define GMPSPREAD (GMP_LIMB_BITS/BITSINWORD)
47 #endif
48
49 #define GCDMAX 3
50
51 #define NEWTRICK 1
52 /*
53 #] Includes :
54 #[ RekenRational :
55 #[ Pack : VOID Pack(a,na,b,nb)
56
57 Packs the contents of the numerator a and the denominator b into
58 one normalized fraction a.
59
60 */
61
Pack(UWORD * a,WORD * na,UWORD * b,WORD nb)62 VOID Pack(UWORD *a, WORD *na, UWORD *b, WORD nb)
63 {
64 WORD c, sgn = 1, i;
65 UWORD *to,*from;
66 if ( (c = *na) == 0 ) {
67 MLOCK(ErrorMessageLock);
68 MesPrint("Caught a zero in Pack");
69 MUNLOCK(ErrorMessageLock);
70 return;
71 }
72 if ( nb == 0 ) {
73 MLOCK(ErrorMessageLock);
74 MesPrint("Division by zero in Pack");
75 MUNLOCK(ErrorMessageLock);
76 return;
77 }
78 if ( *na < 0 ) { sgn = -sgn; c = -c; }
79 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
80 *na = MaX(c,nb);
81 to = a + c;
82 i = *na - c;
83 while ( --i >= 0 ) *to++ = 0;
84 i = *na - nb;
85 from = b;
86 NCOPY(to,from,nb);
87 while ( --i >= 0 ) *to++ = 0;
88 if ( sgn < 0 ) *na = -*na;
89 }
90
91 /*
92 #] Pack :
93 #[ UnPack : VOID UnPack(a,na,denom,numer)
94
95 Determines the sizes of the numerator and the denominator in the
96 normalized fraction a with length na.
97
98 */
99
UnPack(UWORD * a,WORD na,WORD * denom,WORD * numer)100 VOID UnPack(UWORD *a, WORD na, WORD *denom, WORD *numer)
101 {
102 UWORD *pos;
103 WORD i, sgn = na;
104 if ( na < 0 ) { na = -na; }
105 i = na;
106 if ( i > 1 ) { /* Find the respective leading words */
107 a += i;
108 a--;
109 pos = a + i;
110 while ( !(*a) ) { i--; a--; }
111 while ( !(*pos) ) { na--; pos--; }
112 }
113 *denom = na;
114 if ( sgn < 0 ) i = -i;
115 *numer = i;
116 }
117
118 /*
119 #] UnPack :
120 #[ Mully : WORD Mully(a,na,b,nb)
121
122 Multiplies the rational a by the Long b.
123
124 */
125
Mully(PHEAD UWORD * a,WORD * na,UWORD * b,WORD nb)126 WORD Mully(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
127 {
128 GETBIDENTITY
129 UWORD *d, *e;
130 WORD i, sgn = 1;
131 WORD nd, ne, adenom, anumer;
132 if ( !nb ) { *na = 0; return(0); }
133 else if ( *b == 1 ) {
134 if ( nb == 1 ) return(0);
135 else if ( nb == -1 ) { *na = -*na; return(0); }
136 }
137 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
138 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
139 UnPack(a,*na,&adenom,&anumer);
140 d = NumberMalloc("Mully"); e = NumberMalloc("Mully");
141 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
142 ne = nb;
143 if ( Simplify(BHEAD a+*na,&adenom,e,&ne) ) goto MullyEr;
144 if ( MulLong(a,anumer,e,ne,d,&nd) ) goto MullyEr;
145 b = a+*na;
146 for ( i = 0; i < *na; i++ ) { e[i] = *b++; }
147 ne = adenom;
148 *na = nd;
149 b = d;
150 *na = nd;
151 for ( i = 0; i < *na; i++ ) { a[i] = *b++; }
152 Pack(a,na,e,ne);
153 if ( sgn < 0 ) *na = -*na;
154 NumberFree(d,"Mully"); NumberFree(e,"Mully");
155 return(0);
156 MullyEr:
157 MLOCK(ErrorMessageLock);
158 MesCall("Mully");
159 MUNLOCK(ErrorMessageLock);
160 NumberFree(d,"Mully"); NumberFree(e,"Mully");
161 SETERROR(-1)
162 }
163
164 /*
165 #] Mully :
166 #[ Divvy : WORD Divvy(a,na,b,nb)
167
168 Divides the rational a by the Long b.
169
170 */
171
Divvy(PHEAD UWORD * a,WORD * na,UWORD * b,WORD nb)172 WORD Divvy(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
173 {
174 GETBIDENTITY
175 UWORD *d,*e;
176 WORD i, sgn = 1;
177 WORD nd, ne, adenom, anumer;
178 if ( !nb ) {
179 MLOCK(ErrorMessageLock);
180 MesPrint("Division by zero in Divvy");
181 MUNLOCK(ErrorMessageLock);
182 return(-1);
183 }
184 d = NumberMalloc("Divvy"); e = NumberMalloc("Divvy");
185 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
186 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
187 UnPack(a,*na,&adenom,&anumer);
188 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
189 ne = nb;
190 if ( Simplify(BHEAD a,&anumer,e,&ne) ) goto DivvyEr;
191 if ( MulLong(a+*na,adenom,e,ne,d,&nd) ) goto DivvyEr;
192 *na = anumer;
193 Pack(a,na,d,nd);
194 if ( sgn < 0 ) *na = -*na;
195 NumberFree(d,"Divvy"); NumberFree(e,"Divvy");
196 return(0);
197 DivvyEr:
198 MLOCK(ErrorMessageLock);
199 MesCall("Divvy");
200 MUNLOCK(ErrorMessageLock);
201 NumberFree(d,"Divvy"); NumberFree(e,"Divvy");
202 SETERROR(-1)
203 }
204
205 /*
206 #] Divvy :
207 #[ AddRat : WORD AddRat(a,na,b,nb,c,nc)
208 */
209
AddRat(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)210 WORD AddRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
211 {
212 GETBIDENTITY
213 UWORD *d, *e, *f, *g;
214 WORD nd, ne, nf, ng, adenom, anumer, bdenom, bnumer;
215 if ( !na ) {
216 WORD i;
217 *nc = nb;
218 if ( nb < 0 ) nb = -nb;
219 nb *= 2;
220 for ( i = 0; i < nb; i++ ) *c++ = *b++;
221 return(0);
222 }
223 else if ( !nb ) {
224 WORD i;
225 *nc = na;
226 if ( na < 0 ) na = -na;
227 na *= 2;
228 for ( i = 0; i < na; i++ ) *c++ = *a++;
229 return(0);
230 }
231 else if ( b[1] == 1 && a[1] == 1 ) {
232 if ( na == 1 ) {
233 if ( nb == 1 ) {
234 *c = *a + *b;
235 c[1] = 1;
236 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = 2; }
237 else { *nc = 1; }
238 return(0);
239 }
240 else if ( nb == -1 ) {
241 if ( *b > *a ) {
242 *c = *b - *a; *nc = -1;
243 }
244 else if ( *b < *a ) {
245 *c = *a - *b; *nc = 1;
246 }
247 else *nc = 0;
248 c[1] = 1;
249 return(0);
250 }
251 }
252 else if ( na == -1 ){
253 if ( nb == -1 ) {
254 c[1] = 1;
255 *c = *a + *b;
256 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = -2; }
257 else { *nc = -1; }
258 return(0);
259 }
260 else if ( nb == 1 ) {
261 if ( *b > *a ) {
262 *c = *b - *a; *nc = 1;
263 }
264 else if ( *b < *a ) {
265 *c = *a - *b; *nc = -1;
266 }
267 else *nc = 0;
268 c[1] = 1;
269 return(0);
270 }
271 }
272 }
273 UnPack(a,na,&adenom,&anumer);
274 UnPack(b,nb,&bdenom,&bnumer);
275 if ( na < 0 ) na = -na;
276 if ( nb < 0 ) nb = -nb;
277 if ( na == 1 && nb == 1 ) {
278 RLONG t1, t2, t3;
279 t3 = ((RLONG)a[1])*((RLONG)b[1]);
280 t1 = ((RLONG)a[0])*((RLONG)b[1]);
281 t2 = ((RLONG)a[1])*((RLONG)b[0]);
282 if ( ( anumer > 0 && bnumer > 0 ) || ( anumer < 0 && bnumer < 0 ) ) {
283 if ( ( t1 = t1 + t2 ) < t2 ) {
284 c[2] = 1;
285 c[0] = (UWORD)t1;
286 c[1] = (UWORD)(t1 >> BITSINWORD);
287 *nc = 3;
288 }
289 else {
290 c[0] = (UWORD)t1;
291 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
292 else *nc = 1;
293 }
294 }
295 else {
296 if ( t1 == t2 ) { *nc = 0; return(0); }
297 if ( t1 > t2 ) {
298 t1 -= t2;
299 }
300 else {
301 t1 = t2 - t1;
302 anumer = -anumer;
303 }
304 c[0] = (UWORD)t1;
305 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
306 else *nc = 1;
307 }
308 if ( anumer < 0 ) *nc = -*nc;
309 d = NumberMalloc("AddRat");
310 d[0] = (UWORD)t3;
311 if ( ( d[1] = (UWORD)(t3 >> BITSINWORD) ) != 0 ) nd = 2;
312 else nd = 1;
313 if ( Simplify(BHEAD c,nc,d,&nd) ) goto AddRer1;
314 }
315 /*
316 else if ( a[na] == 1 && b[nb] == 1 && adenom == 1 && bdenom == 1 ) {
317 if ( AddLong(a,na,b,nb,c,&nc) ) goto AddRer2;
318 i = ABS(nc); d = c + i; *d++ = 1;
319 while ( --i > 0 ) *d++ = 0 ;
320 return(0);
321 }
322 */
323 else {
324 d = NumberMalloc("AddRat"); e = NumberMalloc("AddRat");
325 f = NumberMalloc("AddRat"); g = NumberMalloc("AddRat");
326 if ( GcdLong(BHEAD a+na,adenom,b+nb,bdenom,d,&nd) ) goto AddRer;
327 if ( *d == 1 && nd == 1 ) nd = 0;
328 if ( nd ) {
329 if ( DivLong(a+na,adenom,d,nd,e,&ne,c,nc) ) goto AddRer;
330 if ( DivLong(b+nb,bdenom,d,nd,f,&nf,c,nc) ) goto AddRer;
331 if ( MulLong(a,anumer,f,nf,c,nc) ) goto AddRer;
332 if ( MulLong(b,bnumer,e,ne,g,&ng) ) goto AddRer;
333 }
334 else {
335 if ( MulLong(a+na,adenom,b,bnumer,c,nc) ) goto AddRer;
336 if ( MulLong(b+nb,bdenom,a,anumer,g,&ng) ) goto AddRer;
337 }
338 if ( AddLong(c,*nc,g,ng,c,nc) ) goto AddRer;
339 if ( !*nc ) {
340 NumberFree(g,"AddRat"); NumberFree(f,"AddRat");
341 NumberFree(e,"AddRat"); NumberFree(d,"AddRat");
342 return(0);
343 }
344 if ( nd ) {
345 if ( Simplify(BHEAD c,nc,d,&nd) ) goto AddRer;
346 if ( MulLong(e,ne,d,nd,g,&ng) ) goto AddRer;
347 if ( MulLong(g,ng,f,nf,d,&nd) ) goto AddRer;
348 }
349 else {
350 if ( MulLong(a+na,adenom,b+nb,bdenom,d,&nd) ) goto AddRer;
351 }
352 NumberFree(g,"AddRat"); NumberFree(f,"AddRat"); NumberFree(e,"AddRat");
353 }
354 Pack(c,nc,d,nd);
355 NumberFree(d,"AddRat");
356 return(0);
357 AddRer:
358 NumberFree(g,"AddRat"); NumberFree(f,"AddRat"); NumberFree(e,"AddRat");
359 AddRer1:
360 NumberFree(d,"AddRat");
361 /* AddRer2: */
362 MLOCK(ErrorMessageLock);
363 MesCall("AddRat");
364 MUNLOCK(ErrorMessageLock);
365 SETERROR(-1)
366 }
367
368 /*
369 #] AddRat :
370 #[ MulRat : WORD MulRat(a,na,b,nb,c,nc)
371
372 Multiplies the rationals a and b. The Gcd of the individual
373 pieces is divided out first to minimize the chances of spurious
374 overflows.
375
376 */
377
MulRat(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)378 WORD MulRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
379 {
380 WORD i;
381 WORD sgn = 1;
382 if ( *b == 1 && b[1] == 1 ) {
383 if ( nb == 1 ) {
384 *nc = na;
385 i = ABS(na); i *= 2;
386 while ( --i >= 0 ) *c++ = *a++;
387 return(0);
388 }
389 else if ( nb == -1 ) {
390 *nc = - na;
391 i = ABS(na); i *= 2;
392 while ( --i >= 0 ) *c++ = *a++;
393 return(0);
394 }
395 }
396 if ( *a == 1 && a[1] == 1 ) {
397 if ( na == 1 ) {
398 *nc = nb;
399 i = ABS(nb); i *= 2;
400 while ( --i >= 0 ) *c++ = *b++;
401 return(0);
402 }
403 else if ( na == -1 ) {
404 *nc = - nb;
405 i = ABS(nb); i *= 2;
406 while ( --i >= 0 ) *c++ = *b++;
407 return(0);
408 }
409 }
410 if ( na < 0 ) { na = -na; sgn = -sgn; }
411 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
412 if ( !na || !nb ) { *nc = 0; return(0); }
413 if ( na != 1 || nb != 1 ) {
414 GETBIDENTITY
415 UWORD *xd,*xe, *xf,*xg;
416 WORD dden, dnumr, eden, enumr;
417 UnPack(a,na,&dden,&dnumr);
418 UnPack(b,nb,&eden,&enumr);
419 xd = NumberMalloc("MulRat"); xf = NumberMalloc("MulRat");
420 for ( i = 0; i < dnumr; i++ ) xd[i] = a[i];
421 a += na;
422 for ( i = 0; i < dden; i++ ) xf[i] = a[i];
423 xe = NumberMalloc("MulRat"); xg = NumberMalloc("MulRat");
424 for ( i = 0; i < enumr; i++ ) xe[i] = b[i];
425 b += nb;
426 for ( i = 0; i < eden; i++ ) xg[i] = b[i];
427 if ( Simplify(BHEAD xd,&dnumr,xg,&eden) ||
428 Simplify(BHEAD xe,&enumr,xf,&dden) ||
429 MulLong(xd,dnumr,xe,enumr,c,nc) ||
430 MulLong(xf,dden,xg,eden,xd,&dnumr) ) {
431 MLOCK(ErrorMessageLock);
432 MesCall("MulRat");
433 MUNLOCK(ErrorMessageLock);
434 NumberFree(xd,"MulRat"); NumberFree(xe,"MulRat"); NumberFree(xf,"MulRat"); NumberFree(xg,"MulRat");
435 SETERROR(-1)
436 }
437 Pack(c,nc,xd,dnumr);
438 NumberFree(xd,"MulRat"); NumberFree(xe,"MulRat"); NumberFree(xf,"MulRat"); NumberFree(xg,"MulRat");
439 }
440 else {
441 UWORD y;
442 UWORD a0,a1,b0,b1;
443 RLONG xx;
444 y = a[0]; b1=b[1];
445 do { a0 = y % b1; y = b1; } while ( ( b1 = a0 ) != 0 );
446 if ( y != 1 ) {
447 a0 = a[0] / y;
448 b1 = b[1] / y;
449 }
450 else {
451 a0 = a[0];
452 b1 = b[1];
453 }
454 y=b[0]; a1=a[1];
455 do { b0 = y % a1; y = a1; } while ( ( a1 = b0 ) != 0 );
456 if ( y != 1 ) {
457 a1 = a[1] / y;
458 b0 = b[0] / y;
459 }
460 else {
461 a1 = a[1];
462 b0 = b[0];
463 }
464 xx = ((RLONG)a0)*b0;
465 if ( xx & AWORDMASK ) {
466 *nc = 2;
467 c[0] = (UWORD)xx;
468 c[1] = (UWORD)(xx >> BITSINWORD);
469 xx = ((RLONG)a1)*b1;
470 c[2] = (UWORD)xx;
471 c[3] = (UWORD)(xx >> BITSINWORD);
472 }
473 else {
474 c[0] = (UWORD)xx;
475 xx = ((RLONG)a1)*b1;
476 if ( xx & AWORDMASK ) {
477 c[1] = 0;
478 c[2] = (UWORD)xx;
479 c[3] = (UWORD)(xx >> BITSINWORD);
480 *nc = 2;
481 }
482 else {
483 c[1] = (UWORD)xx;
484 *nc = 1;
485 }
486 }
487 }
488 if ( sgn < 0 ) *nc = -*nc;
489 return(0);
490 }
491
492 /*
493 #] MulRat :
494 #[ DivRat : WORD DivRat(a,na,b,nb,c,nc)
495
496 Divides the rational a by the rational b.
497
498 */
499
DivRat(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)500 WORD DivRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
501 {
502 GETBIDENTITY
503 WORD i, j;
504 UWORD *xd,*xe,xx;
505 if ( !nb ) {
506 MLOCK(ErrorMessageLock);
507 MesPrint("Rational division by zero");
508 MUNLOCK(ErrorMessageLock);
509 return(-1);
510 }
511 j = i = (nb >= 0)? nb: -nb;
512 xd = b; xe = b + i;
513 do { xx = *xd; *xd++ = *xe; *xe++ = xx; } while ( --j > 0 );
514 j = MulRat(BHEAD a,na,b,nb,c,nc);
515 xd = b; xe = b + i;
516 do { xx = *xd; *xd++ = *xe; *xe++ = xx; } while ( --i > 0 );
517 return(j);
518 }
519
520 /*
521 #] DivRat :
522 #[ Simplify : WORD Simplify(a,na,b,nb)
523
524 Determines the greatest common denominator of a and b and
525 devides both by it. A possible sign is put in a. This is
526 the simplification of the fraction a/b.
527
528 */
529
Simplify(PHEAD UWORD * a,WORD * na,UWORD * b,WORD * nb)530 WORD Simplify(PHEAD UWORD *a, WORD *na, UWORD *b, WORD *nb)
531 {
532 GETBIDENTITY
533 UWORD *x1,*x2,*x3;
534 UWORD *x4;
535 WORD n1,n2,n3,n4,sgn = 1;
536 WORD i;
537 UWORD *Siscrat5, *Siscrat6, *Siscrat7, *Siscrat8;
538 if ( *na < 0 ) { *na = -*na; sgn = -sgn; }
539 if ( *nb < 0 ) { *nb = -*nb; sgn = -sgn; }
540 Siscrat5 = NumberMalloc("Simplify"); Siscrat6 = NumberMalloc("Simplify");
541 Siscrat7 = NumberMalloc("Simplify"); Siscrat8 = NumberMalloc("Simplify");
542 x1 = Siscrat8; x2 = Siscrat7;
543 if ( *nb == 1 ) {
544 x3 = Siscrat6;
545 if ( DivLong(a,*na,b,*nb,x1,&n1,x2,&n2) ) goto SimpErr;
546 if ( !n2 ) {
547 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
548 *na = n1;
549 *b = 1;
550 }
551 else {
552 UWORD y1, y2, y3;
553 y2 = *b;
554 y3 = *x2;
555 do { y1 = y2 % y3; y2 = y3; } while ( ( y3 = y1 ) != 0 );
556 if ( ( *x2 = y2 ) != 1 ) {
557 *b /= y2;
558 if ( DivLong(a,*na,x2,(WORD)1,x1,&n1,x3,&n3) ) goto SimpErr;
559 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
560 *na = n1;
561 }
562 }
563 }
564 #ifdef NEWTRICK
565 else if ( *na >= GCDMAX && *nb >= GCDMAX ) {
566 n1 = i = *na; x3 = a;
567 NCOPY(x1,x3,i);
568 x3 = b; n2 = i = *nb;
569 NCOPY(x2,x3,i);
570 x4 = Siscrat5;
571 x2 = Siscrat6;
572 x3 = Siscrat7;
573 if ( GcdLong(BHEAD Siscrat8,n1,Siscrat7,n2,x2,&n3) ) goto SimpErr;
574 n2 = n3;
575 if ( *x2 != 1 || n2 != 1 ) {
576 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
577 *na = i = n1;
578 NCOPY(a,x1,i);
579 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
580 *nb = i = n3;
581 NCOPY(b,x3,i);
582 }
583 }
584 #endif
585 else {
586 x4 = Siscrat5;
587 n1 = i = *na; x3 = a;
588 NCOPY(x1,x3,i);
589 x3 = b; n2 = i = *nb;
590 NCOPY(x2,x3,i);
591 x1 = Siscrat8; x2 = Siscrat7; x3 = Siscrat6;
592 for(;;){
593 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto SimpErr;
594 if ( !n3 ) break;
595 if ( n2 == 1 ) {
596 while ( ( *x1 = (*x2) % (*x3) ) != 0 ) { *x2 = *x3; *x3 = *x1; }
597 *x2 = *x3;
598 break;
599 }
600 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto SimpErr;
601 if ( !n1 ) { x2 = x3; n2 = n3; x3 = Siscrat7; break; }
602 if ( n3 == 1 ) {
603 while ( ( *x2 = (*x3) % (*x1) ) != 0 ) { *x3 = *x1; *x1 = *x2; }
604 *x2 = *x1;
605 n2 = 1;
606 break;
607 }
608 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto SimpErr;
609 if ( !n2 ) { x2 = x1; n2 = n1; x1 = Siscrat7; break; }
610 if ( n1 == 1 ) {
611 while ( ( *x3 = (*x1) % (*x2) ) != 0 ) { *x1 = *x2; *x2 = *x3; }
612 break;
613 }
614 }
615 if ( *x2 != 1 || n2 != 1 ) {
616 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
617 *na = i = n1;
618 NCOPY(a,x1,i);
619 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
620 *nb = i = n3;
621 NCOPY(b,x3,i);
622 }
623 }
624 if ( sgn < 0 ) *na = -*na;
625 NumberFree(Siscrat5,"Simplify"); NumberFree(Siscrat6,"Simplify");
626 NumberFree(Siscrat7,"Simplify"); NumberFree(Siscrat8,"Simplify");
627 return(0);
628 SimpErr:
629 MLOCK(ErrorMessageLock);
630 MesCall("Simplify");
631 MUNLOCK(ErrorMessageLock);
632 NumberFree(Siscrat5,"Simplify"); NumberFree(Siscrat6,"Simplify");
633 NumberFree(Siscrat7,"Simplify"); NumberFree(Siscrat8,"Simplify");
634 SETERROR(-1)
635 }
636
637 /*
638 #] Simplify :
639 #[ AccumGCD : WORD AccumGCD(PHEAD a,na,b,nb)
640
641 Routine takes the rational GCD of the fractions in a and b and
642 replaces a by the GCD of the two.
643 The rational GCD is defined as the rational that consists of
644 the GCD of the numerators divided by the GCD of the denominators
645 */
646
AccumGCD(PHEAD UWORD * a,WORD * na,UWORD * b,WORD nb)647 WORD AccumGCD(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
648 {
649 GETBIDENTITY
650 WORD nna,nnb,numa,numb,dena,denb,numc,denc;
651 UWORD *GCDbuffer = NumberMalloc("AccumGCD");
652 int i;
653 nna = *na; if ( nna < 0 ) nna = -nna; nna = (nna-1)/2;
654 nnb = nb; if ( nnb < 0 ) nnb = -nnb; nnb = (nnb-1)/2;
655 UnPack(a,nna,&dena,&numa);
656 UnPack(b,nnb,&denb,&numb);
657 if ( GcdLong(BHEAD a,numa,b,numb,GCDbuffer,&numc) ) goto AccErr;
658 numa = numc;
659 for ( i = 0; i < numa; i++ ) a[i] = GCDbuffer[i];
660 if ( GcdLong(BHEAD a+nna,dena,b+nnb,denb,GCDbuffer,&denc) ) goto AccErr;
661 dena = denc;
662 for ( i = 0; i < dena; i++ ) a[i+nna] = GCDbuffer[i];
663 Pack(a,&numa,a+nna,dena);
664 *na = INCLENG(numa);
665 NumberFree(GCDbuffer,"AccumGCD");
666 return(0);
667 AccErr:
668 MLOCK(ErrorMessageLock);
669 MesCall("AccumGCD");
670 MUNLOCK(ErrorMessageLock);
671 NumberFree(GCDbuffer,"AccumGCD");
672 SETERROR(-1)
673 }
674
675 /*
676 #] AccumGCD :
677 #[ TakeRatRoot:
678 */
679
TakeRatRoot(UWORD * a,WORD * n,WORD power)680 int TakeRatRoot(UWORD *a, WORD *n, WORD power)
681 {
682 WORD numer,denom, nn;
683 if ( ( power & 1 ) == 0 && *n < 0 ) return(1);
684 if ( ABS(*n) == 1 && a[0] == 1 && a[1] == 1 ) return(0);
685 nn = ABS(*n);
686 UnPack(a,nn,&denom,&numer);
687 if ( TakeLongRoot(a+nn,&denom,power) ) return(1);
688 if ( TakeLongRoot(a,&numer,power) ) return(1);
689 Pack(a,&numer,a+nn,denom);
690 if ( *n < 0 ) *n = -numer;
691 else *n = numer;
692 return(0);
693 }
694
695 /*
696 #] TakeRatRoot:
697 #] RekenRational :
698 #[ RekenLong :
699 #[ AddLong : WORD AddLong(a,na,b,nb,c,nc)
700
701 Long addition. Uses addition and subtraction of positive numbers.
702
703 */
704
AddLong(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)705 WORD AddLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
706 {
707 WORD sgn, res;
708 if ( na < 0 ) {
709 if ( nb < 0 ) {
710 if ( AddPLon(a,-na,b,-nb,c,nc) ) return(-1);
711 *nc = -*nc;
712 return(0);
713 }
714 else {
715 na = -na;
716 sgn = -1;
717 }
718 }
719 else {
720 if ( nb < 0 ) {
721 nb = -nb;
722 sgn = 1;
723 }
724 else { return( AddPLon(a,na,b,nb,c,nc) ); }
725 }
726 if ( ( res = BigLong(a,na,b,nb) ) > 0 ) {
727 SubPLon(a,na,b,nb,c,nc);
728 if ( sgn < 0 ) *nc = -*nc;
729 }
730 else if ( res < 0 ) {
731 SubPLon(b,nb,a,na,c,nc);
732 if ( sgn > 0 ) *nc = -*nc;
733 }
734 else {
735 *nc = 0;
736 *c = 0;
737 }
738 return(0);
739 }
740
741 /*
742 #] AddLong :
743 #[ AddPLon : WORD AddPLon(a,na,b,nb,c,nc)
744
745 Adds two long integers a and b and puts the result in c.
746 The length of a and b are na and nb. The length of c is returned in nc.
747 c can be a or b.
748 */
749
AddPLon(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)750 WORD AddPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
751 {
752 UWORD carry = 0, e, nd = 0;
753 while ( na && nb ) {
754 e = *a;
755 *c = e + *b + carry;
756 if ( carry ) {
757 if ( e < *c ) carry = 0;
758 }
759 else {
760 if ( e > *c ) carry = 1;
761 }
762 a++; b++; c++; nd++; na--; nb--;
763 }
764 while ( na ) {
765 if ( carry ) {
766 *c = *a++ + carry;
767 if ( *c++ ) carry = 0;
768 }
769 else *c++ = *a++;
770 nd++; na--;
771 }
772 while ( nb ) {
773 if ( carry ) {
774 *c = *b++ + carry;
775 if ( *c++ ) carry = 0;
776 }
777 else *c++ = *b++;
778 nd++; nb--;
779 }
780 if ( carry ) {
781 nd++;
782 if ( nd > (UWORD)AM.MaxTal ) {
783 MLOCK(ErrorMessageLock);
784 MesPrint("Overflow in addition");
785 MUNLOCK(ErrorMessageLock);
786 return(-1);
787 }
788 *c++ = carry;
789 }
790 *nc = nd;
791 return(0);
792 }
793
794 /*
795 #] AddPLon :
796 #[ SubPLon : VOID SubPLon(a,na,b,nb,c,nc)
797
798 Subtracts b from a. Assumes that a > b. Result in c.
799 c can be a or b.
800
801 */
802
SubPLon(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)803 VOID SubPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
804 {
805 UWORD borrow = 0, e, nd = 0;
806 while ( nb ) {
807 e = *a;
808 if ( borrow ) {
809 *c = e - *b - borrow;
810 if ( *c < e ) borrow = 0;
811 }
812 else {
813 *c = e - *b;
814 if ( *c > e ) borrow = 1;
815 }
816 a++; b++; c++; na--; nb--; nd++;
817 }
818 while ( na ) {
819 if ( borrow ) {
820 if ( *a ) { *c++ = *a++ - 1; borrow = 0; }
821 else { *c++ = (UWORD)(-1); a++; }
822 }
823 else *c++ = *a++;
824 na--; nd++;
825 }
826 while ( nd && !*--c ) { nd--; }
827 *nc = (WORD)nd;
828 }
829
830 /*
831 #] SubPLon :
832 #[ MulLong : WORD MulLong(a,na,b,nb,c,nc)
833
834 Does a Long multiplication. Assumes that WORD is half the size
835 of a LONG to work out the scheme! The number of operations is
836 the canonical na*nm multiplications.
837 c should not overlap with a or b.
838
839 */
840
MulLong(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)841 WORD MulLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
842 {
843 WORD sgn = 1;
844 UWORD i, *ic, *ia;
845 RLONG t, bb;
846 if ( !na || !nb ) { *nc = 0; return(0); }
847 if ( na < 0 ) { na = -na; sgn = -sgn; }
848 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
849 *nc = i = na + nb;
850 if ( i > (UWORD)(AM.MaxTal+1) ) goto MulLov;
851 ic = c;
852 /*
853 #[ GMP stuff :
854 */
855 #ifdef WITHGMP
856 if (na > 3 && nb > 3) {
857 /* mp_limb_t res; */
858 UWORD *to, *from;
859 int j;
860 GETIDENTITY
861 UWORD *DLscrat9 = NumberMalloc("MulLong"), *DLscratA = NumberMalloc("MulLong"), *DLscratB = NumberMalloc("MulLong");
862 #if ( GMPSPREAD != 1 )
863 if ( na & 1 ) {
864 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
865 a[na++] = 0;
866 ++*nc;
867 } else
868 #endif
869 if ( (LONG)a & (sizeof(mp_limb_t)-1) ) {
870 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
871 }
872
873 #if ( GMPSPREAD != 1 )
874 if ( nb & 1 ) {
875 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
876 b[nb++] = 0;
877 ++*nc;
878 } else
879 #endif
880 if ( (LONG)b & (sizeof(mp_limb_t)-1) ) {
881 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
882 }
883
884 if ( ( *nc > (WORD)i ) || ( (LONG)c & (LONG)(sizeof(mp_limb_t)-1) ) ) {
885 ic = DLscratB;
886 }
887 if ( na < nb ) {
888 /* res = */
889 mpn_mul((mp_ptr)ic, (mp_srcptr)b, nb/GMPSPREAD, (mp_srcptr)a, na/GMPSPREAD);
890 } else {
891 /* res = */
892 mpn_mul((mp_ptr)ic, (mp_srcptr)a, na/GMPSPREAD, (mp_srcptr)b, nb/GMPSPREAD);
893 }
894 while ( ic[i-1] == 0 ) i--;
895 *nc = i;
896 /*
897 if ( res == 0 ) *nc -= GMPSPREAD;
898 else if ( res <= WORDMASK ) --*nc;
899 */
900 if ( ic != c ) {
901 j = *nc; NCOPY(c, ic, j);
902 }
903 if ( sgn < 0 ) *nc = -(*nc);
904 NumberFree(DLscrat9,"MulLong"); NumberFree(DLscratA,"MulLong"); NumberFree(DLscratB,"MulLong");
905 return(0);
906 }
907 #endif
908 /*
909 #] GMP stuff :
910 */
911 do { *ic++ = 0; } while ( --i > 0 );
912 do {
913 ia = a;
914 ic = c++;
915 t = 0;
916 i = na;
917 bb = (RLONG)(*b++);
918 do {
919 t = (*ia++) * bb + t + *ic;
920 *ic++ = (WORD)t;
921 t >>= BITSINWORD; /* should actually be a swap */
922 } while ( --i > 0 );
923 if ( t ) *ic = (UWORD)t;
924 } while ( --nb > 0 );
925 if ( !*ic ) (*nc)--;
926 if ( *nc > AM.MaxTal ) goto MulLov;
927 if ( sgn < 0 ) *nc = -(*nc);
928 return(0);
929 MulLov:
930 MLOCK(ErrorMessageLock);
931 MesPrint("Overflow in Multiplication");
932 MUNLOCK(ErrorMessageLock);
933 return(-1);
934 }
935
936 /*
937 #] MulLong :
938 #[ BigLong : WORD BigLong(a,na,b,nb)
939
940 Returns > 0 if a > b, < 0 if b > a and 0 if a == b
941
942 */
943
BigLong(UWORD * a,WORD na,UWORD * b,WORD nb)944 WORD BigLong(UWORD *a, WORD na, UWORD *b, WORD nb)
945 {
946 a += na;
947 b += nb;
948 while ( na && !*--a ) na--;
949 while ( nb && !*--b ) nb--;
950 if ( nb < na ) return(1);
951 if ( nb > na ) return(-1);
952 while ( --na >= 0 ) {
953 if ( *a > *b ) return(1);
954 else if ( *b > *a ) return(-1);
955 a--; b--;
956 }
957 return(0);
958 }
959
960 /*
961 #] BigLong :
962 #[ DivLong : WORD DivLong(a,na,b,nb,c,nc,d,nd)
963
964 This is the long division which knows a couple of exceptions.
965 It uses therefore a recursive call for the renormalization.
966 The quotient comes in c and the remainder in d.
967 d may be overlapping with b. It may also be identical to a.
968 c should not overlap with a, but it can overlap with b.
969
970 */
971
DivLong(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc,UWORD * d,WORD * nd)972 WORD DivLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c,
973 WORD *nc, UWORD *d, WORD *nd)
974 {
975 WORD sgna = 1, sgnb = 1, ne, nf, ng, nh;
976 WORD i, ni;
977 UWORD *w1, *w2;
978 RLONG t, v;
979 UWORD *e, *f, *ff, *g, norm, estim;
980 #ifdef WITHGMP
981 UWORD *DLscrat9, *DLscratA, *DLscratB, *DLscratC;
982 #endif
983 RLONG esthelp;
984 if ( !nb ) {
985 MLOCK(ErrorMessageLock);
986 MesPrint("Division by zero");
987 MUNLOCK(ErrorMessageLock);
988 return(-1);
989 }
990 if ( !na ) { *nc = *nd = 0; return(0); }
991 if ( na < 0 ) { sgna = -sgna; na = -na; }
992 if ( nb < 0 ) { sgnb = -sgnb; nb = -nb; }
993 if ( na < nb ) {
994 for ( i = 0; i < na; i++ ) *d++ = *a++;
995 *nd = na;
996 *nc = 0;
997 }
998 else if ( nb == na && ( i = BigLong(b,nb,a,na) ) >= 0 ) {
999 if ( i > 0 ) {
1000 for ( i = 0; i < na; i++ ) *d++ = *a++;
1001 *nd = na;
1002 *nc = 0;
1003 }
1004 else {
1005 *c = 1;
1006 *nc = 1;
1007 *nd = 0;
1008 }
1009 }
1010 else if ( nb == 1 ) {
1011 if ( *b == 1 ) {
1012 for ( i = 0; i < na; i++ ) *c++ = *a++;
1013 *nc = na;
1014 *nd = 0;
1015 }
1016 else {
1017 w1 = a+na;
1018 *nc = ni = na;
1019 *nd = 1;
1020 w2 = c+ni;
1021 v = (RLONG)(*b);
1022 t = (RLONG)(*--w1);
1023 while ( --ni >= 0 ) {
1024 *--w2 = t / v;
1025 t -= v * (*w2);
1026 if ( ni ) {
1027 t <<= BITSINWORD;
1028 t += *--w1;
1029 }
1030 }
1031 if ( ( *d = (UWORD)t ) == 0 ) *nd = 0;
1032 if ( !*(c+na-1) ) (*nc)--;
1033 }
1034 }
1035 else {
1036 GETIDENTITY
1037 /*
1038 #[ GMP stuff :
1039
1040 We start with copying a and b.
1041 Then we make space for c and d.
1042 Next we call mpn_tdiv_qr
1043 We adjust sizes and copy to c and d if needed.
1044 Finally the signs are settled.
1045 */
1046 #ifdef WITHGMP
1047 if ( na > 4 && nb > 3 ) {
1048 UWORD *ic, *id, *to, *from;
1049 int j = na - nb;
1050 DLscrat9 = NumberMalloc("DivLong"); DLscratA = NumberMalloc("DivLong");
1051 DLscratB = NumberMalloc("DivLong"); DLscratC = NumberMalloc("DivLong");
1052
1053 #if ( GMPSPREAD != 1 )
1054 if ( na & 1 ) {
1055 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1056 a[na++] = 0;
1057 } else
1058 #endif
1059 if ( (LONG)a & (sizeof(mp_limb_t)-1) ) {
1060 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1061 }
1062
1063 #if ( GMPSPREAD != 1 )
1064 if ( nb & 1 ) {
1065 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1066 b[nb++] = 0;
1067 } else
1068 #endif
1069 if ( ( (LONG)b & (sizeof(mp_limb_t)-1) ) != 0 ) {
1070 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1071 }
1072 if ( ( (LONG)c & (sizeof(mp_limb_t)-1) ) != 0 ) ic = DLscratB;
1073 else ic = c;
1074
1075 if ( ( (LONG)d & (sizeof(mp_limb_t)-1) ) != 0 ) id = DLscratC;
1076 else id = d;
1077 mpn_tdiv_qr((mp_limb_t *)ic,(mp_limb_t *)id,(mp_size_t)0,
1078 (const mp_limb_t *)a,(mp_size_t)(na/GMPSPREAD),
1079 (const mp_limb_t *)b,(mp_size_t)(nb/GMPSPREAD));
1080 while ( j >= 0 && ic[j] == 0 ) j--;
1081 j++; *nc = j;
1082 if ( c != ic ) { NCOPY(c,ic,j); }
1083 j = nb-1;
1084 while ( j >= 0 && id[j] == 0 ) j--;
1085 j++; *nd = j;
1086 if ( d != id ) { NCOPY(d,id,j); }
1087 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1088 if ( sgnb < 0 ) { *nc = -(*nc); }
1089 NumberFree(DLscrat9,"DivLong"); NumberFree(DLscratA,"DivLong");
1090 NumberFree(DLscratB,"DivLong"); NumberFree(DLscratC,"DivLong");
1091 return(0);
1092 }
1093 #endif
1094 /*
1095 #] GMP stuff :
1096 */
1097 /* Start with normalization operation */
1098
1099 e = NumberMalloc("DivLong"); f = NumberMalloc("DivLong"); g = NumberMalloc("DivLong");
1100 if ( b[nb-1] == (FULLMAX-1) ) norm = 1;
1101 else {
1102 norm = (UWORD)(((ULONG)FULLMAX) / (ULONG)((b[nb-1]+1L)));
1103 }
1104 f[na] = 0;
1105 if ( MulLong(b,nb,&norm,1,e,&ne) ||
1106 MulLong(a,na,&norm,1,f,&nf) ) {
1107 NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
1108 return(-1);
1109 }
1110 if ( BigLong(f+nf-ne,ne,e,ne) >= 0 ) {
1111 SubPLon(f+nf-ne,ne,e,ne,f+nf-ne,&nh);
1112 w1 = c + (nf-ne);
1113 *nc = nf-ne+1;
1114 }
1115 else {
1116 nh = ne;
1117 *nc = nf-ne;
1118 w1 = 0;
1119 }
1120 w2 = c; i = *nc; do { *w2++ = 0; } while ( --i > 0 );
1121 nf = na;
1122 ni = nf-ne;
1123 esthelp = (RLONG)(e[ne-1]) + 1L;
1124 while ( nf >= ne ) {
1125 if ( (WORD)esthelp == 0 ) {
1126 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])>>BITSINWORD);
1127 }
1128 else {
1129 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])/esthelp);
1130 }
1131 /* This estimate may be up to two too small */
1132 if ( estim ) {
1133 MulLong(e,ne,&estim,1,g,&ng);
1134 nh = ne + 1; if ( !f[ni+ne] ) nh--;
1135 SubPLon(f+ni,nh,g,ng,f+ni,&nh);
1136 }
1137 else {
1138 w2 = f+ni+ne; nh = ne+1;
1139 while ( ( nh > 0 ) && !*w2 ) { nh--; w2--; }
1140 }
1141 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1142 estim++;
1143 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1144 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1145 estim++;
1146 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1147 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1148 MLOCK(ErrorMessageLock);
1149 MesPrint("Problems in DivLong");
1150 AO.OutSkip = 3;
1151 FiniLine();
1152 i = na;
1153 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)" "); }
1154 FiniLine();
1155 i = nb;
1156 while ( --i >= 0 ) { TalToLine((UWORD)(*b++)); TokenToLine((UBYTE *)" "); }
1157 AO.OutSkip = 0;
1158 FiniLine();
1159 MUNLOCK(ErrorMessageLock);
1160 NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
1161 return(-1);
1162 }
1163 }
1164 }
1165 c[ni] = estim;
1166 nf--;
1167 ni--;
1168 }
1169 if ( w1 ) *w1 = 1;
1170
1171 /* Finish with the renormalization operation */
1172
1173 if ( nh > 0 ) {
1174 if ( norm == 1 ) {
1175 *nd = i = nh; ff = f;
1176 NCOPY(d,ff,i);
1177 }
1178 else {
1179 w1 = f+nh;
1180 *nd = ni = nh;
1181 w2 = d+ni;
1182 v = norm;
1183 t = (RLONG)(*--w1);
1184 while ( --ni >= 0 ) {
1185 *--w2 = t / v;
1186 t -= v * (*w2);
1187 if ( ni ) {
1188 t <<= BITSINWORD;
1189 t += *--w1;
1190 }
1191 }
1192 if ( t ) {
1193 MLOCK(ErrorMessageLock);
1194 MesPrint("Error in DivLong");
1195 MUNLOCK(ErrorMessageLock);
1196 NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
1197 return(-1);
1198 }
1199 if ( !*(d+nh-1) ) (*nd)--;
1200 }
1201 }
1202 else { *nd = 0; }
1203 NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
1204 }
1205 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1206 if ( sgnb < 0 ) { *nc = -(*nc); }
1207 return(0);
1208 }
1209
1210 /*
1211 #] DivLong :
1212 #[ RaisPow : WORD RaisPow(a,na,b)
1213
1214 Raises a to the power b. a is a Long integer and b >= 0.
1215 The method that is used works with a bitdecomposition of b.
1216 */
1217
RaisPow(PHEAD UWORD * a,WORD * na,UWORD b)1218 WORD RaisPow(PHEAD UWORD *a, WORD *na, UWORD b)
1219 {
1220 GETBIDENTITY
1221 WORD i, nu;
1222 UWORD *it, *iu, c;
1223 UWORD *is, *iss;
1224 WORD ns, nt, nmod;
1225 nmod = ABS(AN.ncmod);
1226 if ( !*na || ( ( *na == 1 ) && ( *a == 1 ) ) ) return(0);
1227 if ( !b ) { *na=1; *a=1; return(0); }
1228 is = NumberMalloc("RaisPow");
1229 it = NumberMalloc("RaisPow");
1230 for ( i = 0; i < ABS(*na); i++ ) is[i] = a[i];
1231 ns = *na;
1232 c = b;
1233 for ( i = 0; i < BITSINWORD; i++ ) {
1234 if ( !c ) break;
1235 c /= 2;
1236 }
1237 i--;
1238 c = 1 << i;
1239 while ( --i >= 0 ) {
1240 c /= 2;
1241 if(MulLong(is,ns,is,ns,it,&nt)) goto RaisOvl;
1242 if ( b & c ) {
1243 if ( MulLong(it,nt,a,*na,is,&ns) ) goto RaisOvl;
1244 }
1245 else {
1246 iu = is; is = it; it = iu;
1247 nu = ns; ns = nt; nt = nu;
1248 }
1249 if ( nmod != 0 ) {
1250 if ( DivLong(is,ns,(UWORD *)AC.cmod,nmod,it,&nt,is,&ns) ) goto RaisOvl;
1251 }
1252 }
1253 if ( ( nmod != 0 ) && ( ( AC.modmode & POSNEG ) != 0 ) ) {
1254 NormalModulus(is,&ns);
1255 }
1256 if ( ( *na = i = ns ) != 0 ) { iss = is; i=ABS(i); NCOPY(a,iss,i); }
1257 NumberFree(is,"RaisPow"); NumberFree(it,"RaisPow");
1258 return(0);
1259 RaisOvl:
1260 MLOCK(ErrorMessageLock);
1261 MesCall("RaisPow");
1262 MUNLOCK(ErrorMessageLock);
1263 NumberFree(is,"RaisPow"); NumberFree(it,"RaisPow");
1264 SETERROR(-1)
1265 }
1266
1267 /*
1268 #] RaisPow :
1269 #[ RaisPowCached :
1270 */
1271
1272 /** Computes power x^n and caches the value
1273 *
1274 * Description
1275 * ===========
1276 * Calculates the power x^n and stores the results for caching
1277 * purposes. The pointer c (i.e., the pointer, and not what it
1278 * points to) is overwritten. What it points to should not be
1279 * overwritten in the calling function.
1280 *
1281 * Notes
1282 * =====
1283 * - Caching is done in AT.small_power[]. This array is extended
1284 * if necessary.
1285 */
RaisPowCached(PHEAD WORD x,WORD n,UWORD ** c,WORD * nc)1286 VOID RaisPowCached (PHEAD WORD x, WORD n, UWORD **c, WORD *nc) {
1287
1288 int i,j;
1289 WORD new_small_power_maxx, new_small_power_maxn, ID;
1290 WORD *new_small_power_n;
1291 UWORD **new_small_power;
1292
1293 /* check whether to extend the array */
1294 if (x>=AT.small_power_maxx || n>=AT.small_power_maxn) {
1295
1296 new_small_power_maxx = AT.small_power_maxx;
1297 if (x>=AT.small_power_maxx)
1298 new_small_power_maxx = MaX(2*AT.small_power_maxx, x+1);
1299
1300 new_small_power_maxn = AT.small_power_maxn;
1301 if (n>=AT.small_power_maxn)
1302 new_small_power_maxn = MaX(2*AT.small_power_maxn, n+1);
1303
1304 new_small_power_n = (WORD*) Malloc1(new_small_power_maxx*new_small_power_maxn*sizeof(WORD),"RaisPowCached");
1305 new_small_power = (UWORD **) Malloc1(new_small_power_maxx*new_small_power_maxn*sizeof(UWORD *),"RaisPowCached");
1306
1307 for (i=0; i<new_small_power_maxx * new_small_power_maxn; i++) {
1308 new_small_power_n[i] = 0;
1309 new_small_power [i] = NULL;
1310 }
1311
1312 for (i=0; i<AT.small_power_maxx; i++)
1313 for (j=0; j<AT.small_power_maxn; j++) {
1314 new_small_power_n[i*new_small_power_maxn+j] = AT.small_power_n[i*AT.small_power_maxn+j];
1315 new_small_power [i*new_small_power_maxn+j] = AT.small_power [i*AT.small_power_maxn+j];
1316 }
1317
1318 if (AT.small_power_n != NULL) {
1319 M_free(AT.small_power_n,"RaisPowCached");
1320 M_free(AT.small_power,"RaisPowCached");
1321 }
1322
1323 AT.small_power_maxx = new_small_power_maxx;
1324 AT.small_power_maxn = new_small_power_maxn;
1325 AT.small_power_n = new_small_power_n;
1326 AT.small_power = new_small_power;
1327 }
1328
1329 /* check whether the results is already calculated */
1330 ID = x * AT.small_power_maxn + n;
1331
1332 if (AT.small_power[ID] == NULL) {
1333 #ifdef OLDRAISPOWCACHED
1334 AT.small_power[ID] = NumberMalloc("RaisPowCached");
1335 AT.small_power_n[ID] = 1;
1336 AT.small_power[ID][0] = x;
1337 RaisPow(BHEAD AT.small_power[ID],&AT.small_power_n[ID],n);
1338 #else
1339 UWORD *c = NumberMalloc("RaisPowCached");
1340 WORD i, k = 1;
1341 c[0] = x;
1342 RaisPow(BHEAD c,&k,n);
1343 /*
1344 And now get the proper amount.
1345 */
1346 if ( AT.InNumMem < k ) { /* We should start a new buffer */
1347 AT.InNumMem = 5*AM.MaxTal;
1348 AT.NumMem = (UWORD *)Malloc1(AT.InNumMem*sizeof(UWORD),"RaisPowCached");
1349 /*
1350 MesPrint(" Got an extra %l UWORDS in RaisPowCached",AT.InNumMem);
1351 */
1352 }
1353 for ( i = 0; i < k; i++ ) AT.NumMem[i] = c[i];
1354 AT.small_power[ID] = AT.NumMem;
1355 AT.small_power_n[ID] = k;
1356 AT.NumMem += k;
1357 AT.InNumMem -= k;
1358 NumberFree(c,"RaisPowCached");
1359 #endif
1360 }
1361
1362 /* return the result */
1363 *c = AT.small_power[ID];
1364 *nc = AT.small_power_n[ID];
1365 }
1366
1367 /*
1368 #] RaisPowCached :
1369 #[ RaisPowMod :
1370
1371 Computes the power x^n mod m
1372 */
RaisPowMod(WORD x,WORD n,WORD m)1373 WORD RaisPowMod (WORD x, WORD n, WORD m) {
1374 LONG y=1, z=x;
1375 while (n) {
1376 if (n&1) { y*=z; y%=m; }
1377 z*=z; z%=m;
1378 n /= 2;
1379 }
1380 return (WORD)y;
1381 }
1382
1383 /*
1384 #] RaisPowMod :
1385 #[ NormalModulus : int NormalModulus(UWORD *a,WORD *na)
1386 */
1387 /**
1388 * Brings a modular representation in the range -p/2 to +p/2
1389 * The return value tells whether anything was done.
1390 * Routine made in the general modulus revamp of July 2008 (JV).
1391 */
1392
NormalModulus(UWORD * a,WORD * na)1393 int NormalModulus(UWORD *a,WORD *na)
1394 {
1395 WORD n;
1396 if ( AC.halfmod == 0 ) {
1397 LOCK(AC.halfmodlock);
1398 if ( AC.halfmod == 0 ) {
1399 UWORD two[1],remain[1];
1400 WORD dummy;
1401 two[0] = 2;
1402 AC.halfmod = (UWORD *)Malloc1((ABS(AC.ncmod))*sizeof(UWORD),"halfmod");
1403 DivLong((UWORD *)AC.cmod,(ABS(AC.ncmod)),two,1
1404 ,(UWORD *)AC.halfmod,&(AC.nhalfmod),remain,&dummy);
1405 }
1406 UNLOCK(AC.halfmodlock);
1407 }
1408 n = ABS(*na);
1409 if ( BigLong(a,n,AC.halfmod,AC.nhalfmod) > 0 ) {
1410 SubPLon((UWORD *)AC.cmod,(ABS(AC.ncmod)),a,n,a,&n);
1411 if ( *na > 0 ) { *na = -n; }
1412 else { *na = n; }
1413 return(1);
1414 }
1415 return(0);
1416 }
1417
1418 /*
1419 #] NormalModulus :
1420 #[ MakeInverses :
1421 */
1422 /**
1423 * Makes a table of inverses in modular calculus
1424 * The modulus is in AC.cmod and AC.ncmod
1425 * One should notice that the table of inverses can only be made if
1426 * the modulus fits inside a single FORM word. Otherwise the table lookup
1427 * becomes too difficult and the table too long.
1428 */
1429
MakeInverses()1430 int MakeInverses()
1431 {
1432 WORD n = AC.cmod[0], i, inv2;
1433 if ( AC.ncmod != 1 ) return(1);
1434 if ( AC.modinverses == 0 ) {
1435 LOCK(AC.halfmodlock);
1436 if ( AC.modinverses == 0 ) {
1437 AC.modinverses = (UWORD *)Malloc1(n*sizeof(UWORD),"modinverses");
1438 AC.modinverses[0] = 0;
1439 AC.modinverses[1] = 1;
1440 for ( i = 2; i < n; i++ ) {
1441 if ( GetModInverses(i,n,
1442 (WORD *)(&(AC.modinverses[i])),&inv2) ) {
1443 SETERROR(-1)
1444 }
1445 }
1446 }
1447 UNLOCK(AC.halfmodlock);
1448 }
1449 return(0);
1450 }
1451
1452 /*
1453 #] MakeInverses :
1454 #[ GetModInverses :
1455 */
1456 /**
1457 * Input m1 and m2, which are relative prime.
1458 * determines a*m1+b*m2 = 1 (and 1 is the gcd of m1 and m2)
1459 * then a*m1 = 1 mod m2 and hence im1 = a.
1460 * and b*m2 = 1 mod m1 and hence im2 = b.
1461 * Set m1 = 0*m1+1*m2 = a1*m1+b1*m2
1462 * m2 = 1*m1+0*m2 = a2*m1+b2*m2
1463 * If everything is OK, the return value is zero
1464 */
1465
GetModInverses(WORD m1,WORD m2,WORD * im1,WORD * im2)1466 int GetModInverses(WORD m1, WORD m2, WORD *im1, WORD *im2)
1467 {
1468 WORD a1, a2, a3;
1469 WORD b1, b2, b3;
1470 WORD x = m1, y, c, d = m2;
1471 if ( x < 1 || d <= 1 ) goto somethingwrong;
1472 a1 = 0; a2 = 1;
1473 b1 = 1; b2 = 0;
1474 for(;;) {
1475 c = d/x; y = d%x; /* a good compiler makes this faster than y=d-c*x */
1476 if ( y == 0 ) break;
1477 a3 = a1-c*a2; a1 = a2; a2 = a3;
1478 b3 = b1-c*b2; b1 = b2; b2 = b3;
1479 d = x; x = y;
1480 }
1481 if ( x != 1 ) goto somethingwrong;
1482 if ( a2 < 0 ) a2 += m2;
1483 if ( b2 < 0 ) b2 += m1;
1484 if (im1!=NULL) *im1 = a2;
1485 if (im2!=NULL) *im2 = b2;
1486 return(0);
1487 somethingwrong:
1488 MLOCK(ErrorMessageLock);
1489 MesPrint("Error trying to determine inverses in GetModInverses");
1490 MUNLOCK(ErrorMessageLock);
1491 return(-1);
1492 }
1493 /*
1494 #] GetModInverses :
1495 #[ GetLongModInverses :
1496 */
1497
GetLongModInverses(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * ia,WORD * nia,UWORD * ib,WORD * nib)1498 int GetLongModInverses(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *ia, WORD *nia, UWORD *ib, WORD *nib) {
1499
1500 UWORD *s, *t, *sa, *sb, *ta, *tb, *x, *y, *swap1;
1501 WORD ns, nt, nsa, nsb, nta, ntb, nx, ny, swap2;
1502
1503 s = NumberMalloc("GetLongModInverses");
1504 ns = na;
1505 WCOPY(s, a, ABS(ns));
1506
1507 t = NumberMalloc("GetLongModInverses");
1508 nt = nb;
1509 WCOPY(t, b, ABS(nt));
1510
1511 sa = NumberMalloc("GetLongModInverses");
1512 nsa = 1;
1513 sa[0] = 1;
1514
1515 sb = NumberMalloc("GetLongModInverses");
1516 nsb = 0;
1517
1518 ta = NumberMalloc("GetLongModInverses");
1519 nta = 0;
1520
1521 tb = NumberMalloc("GetLongModInverses");
1522 ntb = 1;
1523 tb[0] = 1;
1524
1525 x = NumberMalloc("GetLongModInverses");
1526 y = NumberMalloc("GetLongModInverses");
1527
1528 while (nt != 0) {
1529 DivLong(s,ns,t,nt,x,&nx,y,&ny);
1530 swap1=s; s=y; y=swap1;
1531 ns=ny;
1532 MulLong(x,nx,ta,nta,y,&ny);
1533 AddLong(sa,nsa,y,-ny,sa,&nsa);
1534 MulLong(x,nx,tb,ntb,y,&ny);
1535 AddLong(sb,nsb,y,-ny,sb,&nsb);
1536
1537 swap1=s; s=t; t=swap1;
1538 swap2=ns; ns=nt; nt=swap2;
1539 swap1=sa; sa=ta; ta=swap1;
1540 swap2=nsa; nsa=nta; nta=swap2;
1541 swap1=sb; sb=tb; tb=swap1;
1542 swap2=nsb; nsb=ntb; ntb=swap2;
1543 }
1544
1545 if (ia!=NULL) {
1546 *nia = nsa*ns;
1547 WCOPY(ia,sa,ABS(*nia));
1548 }
1549
1550 if (ib!=NULL) {
1551 *nib = nsb*ns;
1552 WCOPY(ib,sb,ABS(*nib));
1553 }
1554
1555 NumberFree(s,"GetLongModInverses");
1556 NumberFree(t,"GetLongModInverses");
1557 NumberFree(sa,"GetLongModInverses");
1558 NumberFree(sb,"GetLongModInverses");
1559 NumberFree(ta,"GetLongModInverses");
1560 NumberFree(tb,"GetLongModInverses");
1561 NumberFree(x,"GetLongModInverses");
1562 NumberFree(y,"GetLongModInverses");
1563
1564 return 0;
1565 }
1566
1567 /*
1568 #] GetLongModInverses :
1569 #[ Product : WORD Product(a,na,b)
1570
1571 Multiplies the Long number in a with the WORD b.
1572
1573 */
1574
Product(UWORD * a,WORD * na,WORD b)1575 WORD Product(UWORD *a, WORD *na, WORD b)
1576 {
1577 WORD i, sgn = 1;
1578 RLONG t, u;
1579 if ( *na < 0 ) { *na = -(*na); sgn = -sgn; }
1580 if ( b < 0 ) { b = -b; sgn = -sgn; }
1581 t = 0;
1582 u = (RLONG)b;
1583 for ( i = 0; i < *na; i++ ) {
1584 t += *a * u;
1585 *a++ = (UWORD)t;
1586 t >>= BITSINWORD;
1587 }
1588 if ( t > 0 ) {
1589 if ( ++(*na) > AM.MaxTal ) {
1590 MLOCK(ErrorMessageLock);
1591 MesPrint("Overflow in Product");
1592 MUNLOCK(ErrorMessageLock);
1593 return(-1);
1594 }
1595 *a = (UWORD)t;
1596 }
1597 if ( sgn < 0 ) *na = -(*na);
1598 return(0);
1599 }
1600
1601 /*
1602 #] Product :
1603 #[ Quotient : UWORD Quotient(a,na,b)
1604
1605 Routine divides the long number a by b with the assumption that
1606 there is no remainder (like while computing binomials).
1607
1608 */
1609
Quotient(UWORD * a,WORD * na,WORD b)1610 UWORD Quotient(UWORD *a, WORD *na, WORD b)
1611 {
1612 RLONG v, t;
1613 WORD i, j, sgn = 1;
1614 if ( ( i = *na ) < 0 ) { sgn = -1; i = -i; }
1615 if ( b < 0 ) { b = -b; sgn = -sgn; }
1616 if ( i == 1 ) {
1617 if ( ( *a /= (UWORD)b ) == 0 ) *na = 0;
1618 if ( sgn < 0 ) *na = -*na;
1619 return(0);
1620 }
1621 a += i;
1622 j = i;
1623 v = (RLONG)b;
1624 t = (RLONG)(*--a);
1625 while ( --i >= 0 ) {
1626 *a = t / v;
1627 t -= v * (*a);
1628 if ( i ) {
1629 t <<= BITSINWORD;
1630 t += *--a;
1631 }
1632 }
1633 a += j - 1;
1634 if ( !*a ) j--;
1635 if ( sgn < 0 ) j = -j;
1636 *na = j;
1637 return(0);
1638 }
1639
1640 /*
1641 #] Quotient :
1642 #[ Remain10 : WORD Remain10(a,na)
1643
1644 Routine devides a by 10 and gives the remainder as return value.
1645 The value of a will be the quotient! a must be positive.
1646
1647 */
1648
Remain10(UWORD * a,WORD * na)1649 WORD Remain10(UWORD *a, WORD *na)
1650 {
1651 WORD i;
1652 RLONG t, u;
1653 UWORD *b;
1654 i = *na;
1655 t = 0;
1656 b = a + i - 1;
1657 while ( --i >= 0 ) {
1658 t += *b;
1659 *b-- = u = t / 10;
1660 t -= u * 10;
1661 if ( i > 0 ) t <<= BITSINWORD;
1662 }
1663 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1664 return((WORD)t);
1665 }
1666
1667 /*
1668 #] Remain10 :
1669 #[ Remain4 : WORD Remain4(a,na)
1670
1671 Routine devides a by 10000 and gives the remainder as return value.
1672 The value of a will be the quotient! a must be positive.
1673
1674 */
1675
Remain4(UWORD * a,WORD * na)1676 WORD Remain4(UWORD *a, WORD *na)
1677 {
1678 WORD i;
1679 RLONG t, u;
1680 UWORD *b;
1681 i = *na;
1682 t = 0;
1683 b = a + i - 1;
1684 while ( --i >= 0 ) {
1685 t += *b;
1686 *b-- = u = t / 10000;
1687 t -= u * 10000;
1688 if ( i > 0 ) t <<= BITSINWORD;
1689 }
1690 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1691 return((WORD)t);
1692 }
1693
1694 /*
1695 #] Remain4 :
1696 #[ PrtLong : VOID PrtLong(a,na,s)
1697
1698 Puts the long number a in string s.
1699
1700 */
1701
PrtLong(UWORD * a,WORD na,UBYTE * s)1702 VOID PrtLong(UWORD *a, WORD na, UBYTE *s)
1703 {
1704 GETIDENTITY
1705 WORD q, i;
1706 UBYTE *sa, *sb;
1707 UBYTE c;
1708 UWORD *bb, *b;
1709
1710 if ( na < 0 ) {
1711 *s++ = '-';
1712 na = -na;
1713 }
1714
1715 b = NumberMalloc("PrtLong");
1716 bb = b;
1717 i = na; while ( --i >= 0 ) *bb++ = *a++;
1718 a = b;
1719 if ( na > 2 ) {
1720 sa = s;
1721 do {
1722 q = Remain4(a,&na);
1723 *sa++ = (UBYTE)('0' + (q%10));
1724 q /= 10;
1725 *sa++ = (UBYTE)('0' + (q%10));
1726 q /= 10;
1727 *sa++ = (UBYTE)('0' + (q%10));
1728 q /= 10;
1729 *sa++ = (UBYTE)('0' + (q%10));
1730 } while ( na );
1731 while ( sa[-1] == '0' ) sa--;
1732 sb = s;
1733 s = sa;
1734 sa--;
1735 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1736 }
1737 else if ( na ) {
1738 sa = s;
1739 do {
1740 q = Remain10(a,&na);
1741 *sa++ = (UBYTE)('0' + q);
1742 } while ( na );
1743 sb = s;
1744 s = sa;
1745 sa--;
1746 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1747 }
1748 else *s++ = '0';
1749 *s = '\0';
1750 NumberFree(b,"PrtLong");
1751 }
1752
1753 /*
1754 #] PrtLong :
1755 #[ GetLong : WORD GetLong(s,a,na)
1756
1757 Reads a long number from a string.
1758 The string is zero terminated and contains only digits!
1759
1760 New algorithm: try to read 4 digits together before the result
1761 is accumulated.
1762 */
1763
GetLong(UBYTE * s,UWORD * a,WORD * na)1764 WORD GetLong(UBYTE *s, UWORD *a, WORD *na)
1765 {
1766 /*
1767 UWORD digit;
1768 *a = 0;
1769 *na = 0;
1770 while ( FG.cTable[*s] == 1 ) {
1771 digit = *s++ - '0';
1772 if ( *na && Product(a,na,(WORD)10) ) return(-1);
1773 if ( digit && AddLong(a,*na,&digit,(WORD)1,a,na) ) return(-1);
1774 }
1775 return(0);
1776 */
1777 UWORD digit, x = 0, y = 0;
1778 *a = 0;
1779 *na = 0;
1780 while ( FG.cTable[*s] == 1 ) {
1781 x = *s++ - '0';
1782 if ( FG.cTable[*s] != 1 ) { y = 10; break; }
1783 x = 10*x + *s++ - '0';
1784 if ( FG.cTable[*s] != 1 ) { y = 100; break; }
1785 x = 10*x + *s++ - '0';
1786 if ( FG.cTable[*s] != 1 ) { y = 1000; break; }
1787 x = 10*x + *s++ - '0';
1788 if ( *na && Product(a,na,(WORD)10000) ) return(-1);
1789 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1790 return(-1);
1791 y = 0;
1792 }
1793 if ( y ) {
1794 if ( *na && Product(a,na,(WORD)y) ) return(-1);
1795 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1796 return(-1);
1797 }
1798 return(0);
1799 }
1800
1801 /*
1802 #] GetLong :
1803 #[ GCD : WORD GCD(a,na,b,nb,c,nc)
1804
1805 Algorithm to compute the GCD of two long numbers.
1806 See Knuth, sec 4.5.2 algorithm L.
1807
1808 We assume that both numbers are positive
1809
1810 NOTE!!!!!. NumberMalloc gets called and it may not be freed
1811 */
1812
1813 #ifdef EXTRAGCD
1814
1815 #define Convert(ia,aa,naa) \
1816 if ( (LONG)ia < 0 ) { \
1817 ia = (ULONG)(-(LONG)ia); \
1818 aa[0] = ia; \
1819 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = -2; \
1820 else naa = -1; \
1821 } \
1822 else if ( ia == 0 ) { aa[0] = 0; naa = 0; } \
1823 else { \
1824 aa[0] = ia; \
1825 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = 2; \
1826 else naa = 1; \
1827 }
1828
GCD(UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)1829 VOID GCD(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1830 {
1831 int ja = 0, jb = 0, j;
1832 UWORD *r,*t;
1833 UWORD *x1, *x2, *x3;
1834 WORD nd,naa,nbb;
1835 ULONG ia,ib,ic,id,u,v,w,q,T;
1836 UWORD aa[2], bb[2];
1837 /*
1838 First eliminate easy powers of 2^...
1839 */
1840 while ( a[0] == 0 ) { na--; ja++; a++; }
1841 while ( b[0] == 0 ) { nb--; jb++; b++; }
1842 if ( ja > jb ) ja = jb;
1843 if ( ja > 0 ) {
1844 j = ja;
1845 do { *c++ = 0; } while ( --j > 0 );
1846 }
1847 /*
1848 Now arrange things such that a >= b
1849 */
1850 if ( na < nb ) {
1851 jb = na; na = nb; nb = jb;
1852 exch:
1853 r = a; a = b; b = r;
1854 }
1855 else if ( na == nb ) {
1856 r = a+na;
1857 t = b+nb;
1858 j = na;
1859 while ( --j >= 0 ) {
1860 if ( *--r > *--t ) break;
1861 if ( *r < *t ) goto exch;
1862 }
1863 if ( j < 0 ) {
1864 out:
1865 j = nb;
1866 NCOPY(c,b,j);
1867 *nc = nb+ja;
1868 return;
1869 }
1870 }
1871 /*
1872 {
1873 MLOCK(ErrorMessageLock);
1874 MesPrint("Ordered input, ja = %d",(WORD)ja);
1875 AO.OutSkip = 3;
1876 FiniLine();
1877 j = na; r = a;
1878 while ( --j >= 0 ) { TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)" "); }
1879 FiniLine();
1880 j = nb; r = b;
1881 while ( --j >= 0 ) { TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)" "); }
1882 AO.OutSkip = 0;
1883 FiniLine();
1884 MUNLOCK(ErrorMessageLock);
1885 }
1886 */
1887 /*
1888 We have now that A > B
1889 The loop recognizes the case that na-nb >= 1
1890 In that case we just have to divide!
1891 */
1892 r = x1 = NumberMalloc("GCD"); t = x2 = NumberMalloc("GCD"); x3 = NumberMalloc("GCD");
1893 j = na;
1894 NCOPY(r,a,j);
1895 j = nb;
1896 NCOPY(t,b,j);
1897
1898 for(;;) {
1899
1900 while ( na > nb ) {
1901 toobad:
1902 DivLong(x1,na,x2,nb,c,nc,x3,&nd);
1903 if ( nd == 0 ) { b = x2; goto out; }
1904 t = x1; x1 = x2; x2 = x3; x3 = t; na = nb; nb = nd;
1905 if ( na == 2 ) break;
1906 }
1907 /*
1908 Here we can use the shortcut.
1909 */
1910 if ( na == 2 ) {
1911 v = x1[0] + ( ((ULONG)x1[1]) << BITSINWORD );
1912 w = x2[0];
1913 if ( nb == 2 ) w += ((ULONG)x2[1]) << BITSINWORD;
1914 #ifdef EXTRAGCD2
1915 v = GCD2(v,w);
1916 #else
1917 do { u = v%w; v = w; w = u; } while ( w );
1918 #endif
1919 c[0] = (UWORD)v;
1920 if ( ( c[1] = (UWORD)(v >> BITSINWORD) ) != 0 ) *nc = 2+ja;
1921 else *nc = 1+ja;
1922 NumberFree(x1,"GCD"); NumberFree(x2,"GCD"); NumberFree(x3,"GCD");
1923 return;
1924 }
1925 if ( na == 1 ) {
1926 UWORD ui, uj;
1927 ui = x1[0]; uj = x2[0];
1928 #ifdef EXTRAGCD2
1929 ui = (UWORD)GCD2((ULONG)ui,(ULONG)uj);
1930 #else
1931 do { nd = ui%uj; ui = uj; uj = nd; } while ( nd );
1932 #endif
1933 c[0] = ui;
1934 *nc = 1 + ja;
1935 NumberFree(x1,"GCD"); NumberFree(x2,"GCD"); NumberFree(x3,"GCD");
1936 return;
1937 }
1938 ia = 1; ib = 0; ic = 0; id = 1;
1939 u = ( ((ULONG)x1[na-1]) << BITSINWORD ) + x1[na-2];
1940 v = ( ((ULONG)x2[nb-1]) << BITSINWORD ) + x2[nb-2];
1941
1942 while ( v+ic != 0 && v+id != 0 &&
1943 ( q = (u+ia)/(v+ic) ) == (u+ib)/(v+id) ) {
1944 T = ia-q*ic; ia = ic; ic = T;
1945 T = ib-q*id; ib = id; id = T;
1946 T = u - q*v; u = v; v = T;
1947 }
1948 if ( ib == 0 ) goto toobad;
1949 Convert(ia,aa,naa);
1950 Convert(ib,bb,nbb);
1951 MulLong(x1,na,aa,naa,x3,&nd);
1952 MulLong(x2,nb,bb,nbb,c,nc);
1953 AddLong(x3,nd,c,*nc,c,nc);
1954 Convert(ic,aa,naa);
1955 Convert(id,bb,nbb);
1956 MulLong(x1,na,aa,naa,x3,&nd);
1957 t = c; na = j = *nc; r = x1;
1958 NCOPY(r,t,j);
1959 MulLong(x2,nb,bb,nbb,c,nc);
1960 AddLong(x3,nd,c,*nc,x2,&nb);
1961 }
1962 }
1963
1964 #endif
1965
1966 /*
1967 #] GCD :
1968 #[ GcdLong : WORD GcdLong(a,na,b,nb,c,nc)
1969
1970 Returns the Greatest Common Divider of a and b in c.
1971 If a and or b are zero an error message will be returned.
1972 The answer is always positive.
1973 In principle a and c can be the same.
1974 */
1975
1976 #ifndef NEWTRICK
1977 /*
1978 #[ Old Routine :
1979 */
1980
GcdLong(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)1981 WORD GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1982 {
1983 GETBIDENTITY
1984 if ( !na || !nb ) {
1985 if ( !na && !nb ) {
1986 MLOCK(ErrorMessageLock);
1987 MesPrint("Cannot take gcd");
1988 MUNLOCK(ErrorMessageLock);
1989 return(-1);
1990 }
1991
1992 if ( !na ) {
1993 *nc = abs(nb);
1994 NCOPY(c,b,*nc);
1995 *nc = abs(nb);
1996 return(0);
1997 }
1998
1999 *nc = abs(na);
2000 NCOPY(c,a,*nc);
2001 *nc = abs(na);
2002 return(0);
2003 }
2004 if ( na < 0 ) na = -na;
2005 if ( nb < 0 ) nb = -nb;
2006 if ( na == 1 && nb == 1 ) {
2007 #ifdef EXTRAGCD2
2008 *c = (UWORD)GCD2((ULONG)*a,(ULONG)*b);
2009 #else
2010 UWORD x,y,z;
2011 x = *a;
2012 y = *b;
2013 do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2014 *c = x;
2015 #endif
2016 *nc = 1;
2017 }
2018 else if ( na <= 2 && nb <= 2 ) {
2019 RLONG lx,ly,lz;
2020 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2021 else { lx = *a; }
2022 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2023 else { ly = *b; }
2024 #ifdef LONGWORD
2025 #ifdef EXTRAGCD2
2026 lx = GCD2(lx,ly);
2027 #else
2028 do { lz = lx % ly; lx = ly; } while ( ( ly = lz ) != 0 );
2029 #endif
2030 #else
2031 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2032 do {
2033 lz = lx % ly; lx = ly;
2034 } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2035 if ( ly ) {
2036 do { *c = ((UWORD)lx)%((UWORD)ly); lx = ly; } while ( ( ly = *c ) != 0 );
2037 *c = (UWORD)lx;
2038 *nc = 1;
2039 }
2040 else
2041 #endif
2042 {
2043 *c++ = (UWORD)lx;
2044 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2045 else *nc = 1;
2046 }
2047 }
2048 else {
2049 #ifdef EXTRAGCD
2050 GCD(a,na,b,nb,c,nc);
2051 #else
2052 #ifdef NEWGCD
2053 UWORD *x3,*x1,*x2, *GLscrat7, *GLscrat8;
2054 WORD n1,n2,n3,n4;
2055 WORD i, j;
2056 x1 = c; x3 = a; n1 = i = na;
2057 NCOPY(x1,x3,i);
2058 GLscrat7 = NumberMalloc("GcdLong"); GLscrat8 = NumberMalloc("GcdLong");
2059 x2 = GLscrat8; x3 = b; n2 = i = nb;
2060 NCOPY(x2,x3,i);
2061 x1 = c; i = 0;
2062 while ( x1[0] == 0 ) { i += BITSINWORD; x1++; n1--; }
2063 while ( ( x1[0] & 1 ) == 0 ) { i++; SCHUIF(x1,n1) }
2064 x2 = GLscrat8; j = 0;
2065 while ( x2[0] == 0 ) { j += BITSINWORD; x2++; n2--; }
2066 while ( ( x2[0] & 1 ) == 0 ) { j++; SCHUIF(x2,n2) }
2067 if ( j > i ) j = i; /* powers of two in GCD */
2068 for(;;){
2069 if ( n1 > n2 ) {
2070 firstbig:
2071 SubPLon(x1,n1,x2,n2,x1,&n3);
2072 n1 = n3;
2073 if ( n1 == 0 ) {
2074 x1 = c;
2075 n1 = i = n2; NCOPY(x1,x2,i);
2076 break;
2077 }
2078 while ( ( x1[0] & 1 ) == 0 ) SCHUIF(x1,n1)
2079 if ( n1 == 1 ) {
2080 if ( DivLong(x2,n2,x1,n1,GLscrat7,&n3,x2,&n4) ) goto GcdErr;
2081 n2 = n4;
2082 if ( n2 == 0 ) {
2083 i = n1; x2 = c; NCOPY(x2,x1,i);
2084 break;
2085 }
2086 #ifdef EXTRAGCD2
2087 *c = (UWORD)GCD2((ULONG)x1[0],(ULONG)x2[0]);
2088 #else
2089 {
2090 UWORD x,y,z;
2091 x = x1[0];
2092 y = x2[0];
2093 do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2094 *c = x;
2095 }
2096 #endif
2097 n1 = 1;
2098 break;
2099 }
2100 }
2101 else if ( n1 < n2 ) {
2102 lastbig:
2103 SubPLon(x2,n2,x1,n1,x2,&n3);
2104 n2 = n3;
2105 if ( n2 == 0 ) {
2106 i = n1; x2 = c; NCOPY(x2,x1,i);
2107 break;
2108 }
2109 while ( ( x2[0] & 1 ) == 0 ) SCHUIF(x2,n2)
2110 if ( n2 == 1 ) {
2111 if ( DivLong(x1,n1,x2,n2,GLscrat7,&n3,x1,&n4) ) goto GcdErr;
2112 n1 = n4;
2113 if ( n1 == 0 ) {
2114 x1 = c;
2115 n1 = i = n2; NCOPY(x1,x2,i);
2116 break;
2117 }
2118 #ifdef EXTRAGCD2
2119 *c = (UWORD)GCD2((ULONG)x2[0],(ULONG)x1[0]);
2120 #else
2121 {
2122 UWORD x,y,z;
2123 x = x2[0];
2124 y = x1[0];
2125 do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2126 *c = x;
2127 }
2128 #endif
2129 n1 = 1;
2130 break;
2131 }
2132 }
2133 else {
2134 for ( i = n1-1; i >= 0; i-- ) {
2135 if ( x1[i] > x2[i] ) goto firstbig;
2136 else if ( x1[i] < x2[i] ) goto lastbig;
2137 }
2138 i = n1; x2 = c; NCOPY(x2,x1,i);
2139 break;
2140 }
2141 }
2142 /*
2143 Now the GCD is in c but still needs j powers of 2.
2144 */
2145 x1 = c;
2146 while ( j >= BITSINWORD ) {
2147 for ( i = n1; i > 0; i-- ) x1[i] = x1[i-1];
2148 x1[0] = 0; n1++;
2149 j -= BITSINWORD;
2150 }
2151 if ( j > 0 ) {
2152 ULONG a1,a2 = 0;
2153 for ( i = 0; i < n1; i++ ) {
2154 a1 = x1[i]; a1 <<= j;
2155 a2 += a1;
2156 x1[i] = a2;
2157 a2 >>= BITSINWORD;
2158 }
2159 if ( a2 != 0 ) {
2160 x1[n1++] = a2;
2161 }
2162 }
2163 *nc = n1;
2164 NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
2165 #else
2166 UWORD *x1,*x2,*x3,*x4,*c1,*c2;
2167 WORD n1,n2,n3,n4,i;
2168 x1 = c; x3 = a; n1 = i = na;
2169 NCOPY(x1,x3,i);
2170 x1 = c; c1 = x2 = NumberMalloc("GcdLong"); x3 = NumberMalloc("GcdLong"); x4 = NumberMalloc("GcdLong");
2171 c2 = b; n2 = i = nb;
2172 NCOPY(c1,c2,i);
2173 for(;;){
2174 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto GcdErr;
2175 if ( !n3 ) { x1 = x2; n1 = n2; break; }
2176 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto GcdErr;
2177 if ( !n1 ) { x1 = x3; n1 = n3; break; }
2178 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto GcdErr;
2179 if ( !n2 ) {
2180 *nc = n1;
2181 NumberFree(x2,"GcdLong"); NumberFree(x3,"GcdLong"); NumberFree(x4,"GcdLong");
2182 return(0);
2183 }
2184 }
2185 *nc = i = n1;
2186 NCOPY(c,x1,i);
2187 NumberFree(x2,"GcdLong"); NumberFree(x3,"GcdLong"); NumberFree(x4,"GcdLong");
2188 #endif
2189 #endif
2190 }
2191 return(0);
2192 GcdErr:
2193 MLOCK(ErrorMessageLock);
2194 MesCall("GcdLong");
2195 MUNLOCK(ErrorMessageLock);
2196 SETERROR(-1)
2197 }
2198 /*
2199 #] Old Routine :
2200 */
2201 #else
2202
2203 /*
2204 New routine for GcdLong that uses smart shortcuts.
2205 Algorithm by J. Vermaseren 15-nov-2006.
2206 It runs faster for very big numbers but only by a fixed factor.
2207 There is no improvement in the power behaviour.
2208 Improvement on the whole of hf9 (multiple zeta values at weight 9):
2209 Better than a factor 2 on a 32 bits architecture and 2.76 on a
2210 64 bits architecture.
2211 On hf10 (MZV's at weight 10), 64 bits architecture: factor 7.
2212
2213 If we have two long numbers (na,nb > GCDMAX) we will work in a
2214 truncated way. At the moment of writing (15-nov-2006) it isn't
2215 clear whether this algorithm is an invention or a reinvention.
2216 A short search on the web didn't show anything.
2217
2218 31-jul-2007:
2219 A better search shows that this is an adaptation of the Lehmer-Euclid
2220 algorithm, already described in Knuth. Here we can work without upper
2221 and lower limit because we are only interested in the GCD, not the
2222 extra numbers. Also it takes already some features of the double
2223 digit Lehmer-Euclid algorithm of Jebelean it seems.
2224
2225 Maybe this can be programmed slightly better and we can get another
2226 few percent speed increase. Further improvements for the assymptotic
2227 case come from splitting the calculation as in Karatsuba and working
2228 with FFT divisions and multiplications etc. But this is when hundreds
2229 of words are involved at the least.
2230
2231 Algorithm
2232
2233 1: while ( na > nb || nb < GCDMAX ) {
2234 if ( nb == 0 ) { result in a }
2235 c = a % b;
2236 a = b;
2237 b = c;
2238 }
2239 2: Make the truncated values in which a and b are the combinations
2240 of the top two words of a and b. The whole numbers are aa and bb now.
2241 3: ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2242 4: A = a; B = b; m = a/b; c = a - m*b;
2243 c = ma1*a+ma2*b-m*(mb1*a+mb2*b) = (ma1-m*mb1)*a+(ma2-m*mb2)*b
2244 mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2245 5: a = b; ma1 = mb1; ma2 = mb2;
2246 b = c; mb1 = mc1; mb2 = mc2;
2247 6: if ( b != 0 && nb >= FULLMAX ) goto 4;
2248 7: Now construct the new quantities
2249 ma1*aa+ma2*bb and mb1*aa+mb2*bb
2250 8: goto 1;
2251
2252 The essence of the above algorithm is that we do the divisions only
2253 on relatively short numbers. Also usually there are many steps 4&5
2254 for each step 7. This eliminates many operations.
2255 The termination at FULLMAX is that we make errors by not considering
2256 the tail of the number. If we run b down all the way, the errors combine
2257 in such a way that the new numbers may be of the same order as the old
2258 numbers. By stopping halfway we don't get the error beyond halfway
2259 either. Unfortunately this means that a >= FULLMAX and hence na > nb
2260 which means that next we will have a complete division. But just once.
2261 Running the steps 4-6 till a < FULLMAX runs already into problems.
2262 It may be necessary to experiment a bit to obtain the optimum value
2263 of GCDMAX.
2264 */
2265
GcdLong(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)2266 WORD GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2267 {
2268 GETBIDENTITY
2269 UWORD x,y,z;
2270 UWORD *x1,*x2,*x3,*x4,*x5,*d;
2271 UWORD *GLscrat6, *GLscrat7, *GLscrat8, *GLscrat9, *GLscrat10;
2272 WORD n1,n2,n3,n4,n5,i;
2273 RLONG lx,ly,lz;
2274 LONG ma1, ma2, mb1, mb2, mc1, mc2, m;
2275 if ( !na || !nb ) {
2276 if ( !na && !nb ) {
2277 MLOCK(ErrorMessageLock);
2278 MesPrint("Cannot take gcd");
2279 MUNLOCK(ErrorMessageLock);
2280 return(-1);
2281 }
2282
2283 if ( !na ) {
2284 *nc = abs(nb);
2285 NCOPY(c,b,*nc);
2286 *nc = abs(nb);
2287 return(0);
2288 }
2289
2290 *nc = abs(na);
2291 NCOPY(c,a,*nc);
2292 *nc = abs(na);
2293 return(0);
2294 }
2295 if ( na < 0 ) na = -na;
2296 if ( nb < 0 ) nb = -nb;
2297 /*
2298 #[ GMP stuff :
2299 */
2300 #ifdef WITHGMP
2301 if ( na > 3 && nb > 3 ) {
2302 int ii;
2303 mp_limb_t *upa, *upb, *upc, xx;
2304 UWORD *uw, *u1, *u2;
2305 unsigned int tcounta, tcountb, tcounta1, tcountb1;
2306 mp_size_t ana, anb, anc;
2307
2308 u1 = uw = NumberMalloc("GcdLong");
2309 upa = (mp_limb_t *)u1;
2310 ana = na; tcounta1 = 0;
2311 while ( a[0] == 0 ) { a++; ana--; tcounta1++; }
2312 for ( ii = 0; ii < ana; ii++ ) { *uw++ = *a++; }
2313 if ( ( ana & 1 ) != 0 ) { *uw = 0; ana++; }
2314 ana /= 2;
2315
2316 u2 = uw = NumberMalloc("GcdLong");
2317 upb = (mp_limb_t *)u2;
2318 anb = nb; tcountb1 = 0;
2319 while ( b[0] == 0 ) { b++; anb--; tcountb1++; }
2320 for ( ii = 0; ii < anb; ii++ ) { *uw++ = *b++; }
2321 if ( ( anb & 1 ) != 0 ) { *uw = 0; anb++; }
2322 anb /= 2;
2323
2324 xx = upa[0]; tcounta = 0;
2325 while ( ( xx & 15 ) == 0 ) { tcounta += 4; xx >>= 4; }
2326 while ( ( xx & 1 ) == 0 ) { tcounta += 1; xx >>= 1; }
2327 xx = upb[0]; tcountb = 0;
2328 while ( ( xx & 15 ) == 0 ) { tcountb += 4; xx >>= 4; }
2329 while ( ( xx & 1 ) == 0 ) { tcountb += 1; xx >>= 1; }
2330
2331 if ( tcounta ) {
2332 mpn_rshift(upa,upa,ana,tcounta);
2333 if ( upa[ana-1] == 0 ) ana--;
2334 }
2335 if ( tcountb ) {
2336 mpn_rshift(upb,upb,anb,tcountb);
2337 if ( upb[anb-1] == 0 ) anb--;
2338 }
2339
2340 upc = (mp_limb_t *)(NumberMalloc("GcdLong"));
2341 if ( ( ana > anb ) || ( ( ana == anb ) && ( upa[ana-1] >= upb[ana-1] ) ) ) {
2342 anc = mpn_gcd(upc,upa,ana,upb,anb);
2343 }
2344 else {
2345 anc = mpn_gcd(upc,upb,anb,upa,ana);
2346 }
2347
2348 tcounta = tcounta1*BITSINWORD + tcounta;
2349 tcountb = tcountb1*BITSINWORD + tcountb;
2350 if ( tcountb > tcounta ) tcountb = tcounta;
2351 tcounta = tcountb/BITSINWORD;
2352 tcountb = tcountb%BITSINWORD;
2353
2354 if ( tcountb ) {
2355 xx = mpn_lshift(upc,upc,anc,tcountb);
2356 if ( xx ) { upc[anc] = xx; anc++; }
2357 }
2358
2359 uw = (UWORD *)upc; anc *= 2;
2360 while ( uw[anc-1] == 0 ) anc--;
2361 for ( ii = 0; ii < (int)tcounta; ii++ ) *c++ = 0;
2362 for ( ii = 0; ii < anc; ii++ ) *c++ = *uw++;
2363 *nc = anc + tcounta;
2364 NumberFree(u1,"GcdLong"); NumberFree(u2,"GcdLong"); NumberFree((UWORD *)(upc),"GcdLong");
2365 return(0);
2366 }
2367 #endif
2368 /*
2369 #] GMP stuff :
2370 */
2371 /*
2372 #[ Easy cases :
2373 */
2374 if ( na == 1 && nb == 1 ) {
2375 x = *a;
2376 y = *b;
2377 do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2378 *c = x;
2379 *nc = 1;
2380 return(0);
2381 }
2382 else if ( na <= 2 && nb <= 2 ) {
2383 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2384 else { lx = *a; }
2385 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2386 else { ly = *b; }
2387 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2388 #if ( BITSINWORD == 16 )
2389 do {
2390 lz = lx % ly; lx = ly;
2391 } while ( ( ly = lz ) != 0 );
2392 #else
2393 do {
2394 lz = lx % ly; lx = ly;
2395 } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2396 if ( ly ) {
2397 x = (UWORD)lx; y = (UWORD)ly;
2398 do { *c = x % y; x = y; } while ( ( y = *c ) != 0 );
2399 *c = x;
2400 *nc = 1;
2401 }
2402 else
2403 #endif
2404 {
2405 *c++ = (UWORD)lx;
2406 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2407 else *nc = 1;
2408 }
2409 return(0);
2410 }
2411 /*
2412 #] Easy cases :
2413 */
2414 GLscrat6 = NumberMalloc("GcdLong"); GLscrat7 = NumberMalloc("GcdLong");
2415 GLscrat8 = NumberMalloc("GcdLong");
2416 GLscrat9 = NumberMalloc("GcdLong"); GLscrat10 = NumberMalloc("GcdLong");
2417 restart:;
2418 /*
2419 #[ Easy cases :
2420 */
2421 if ( na == 1 && nb == 1 ) {
2422 x = *a;
2423 y = *b;
2424 do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2425 *c = x;
2426 *nc = 1;
2427 }
2428 else if ( na <= 2 && nb <= 2 ) {
2429 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2430 else { lx = *a; }
2431 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2432 else { ly = *b; }
2433 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2434 #if ( BITSINWORD == 16 )
2435 do {
2436 lz = lx % ly; lx = ly;
2437 } while ( ( ly = lz ) != 0 );
2438 #else
2439 do {
2440 lz = lx % ly; lx = ly;
2441 } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2442 if ( ly ) {
2443 x = (UWORD)lx; y = (UWORD)ly;
2444 do { *c = x % y; x = y; } while ( ( y = *c ) != 0 );
2445 *c = x;
2446 *nc = 1;
2447 }
2448 else
2449 #endif
2450 {
2451 *c++ = (UWORD)lx;
2452 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2453 else *nc = 1;
2454 }
2455 }
2456 /*
2457 #] Easy cases :
2458 #[ Original code :
2459 */
2460 else if ( na < GCDMAX || nb < GCDMAX || na != nb ) {
2461 if ( na < nb ) {
2462 x2 = GLscrat8; x3 = a; n2 = i = na;
2463 NCOPY(x2,x3,i);
2464 x1 = c; x3 = b; n1 = i = nb;
2465 NCOPY(x1,x3,i);
2466 }
2467 else {
2468 x1 = c; x3 = a; n1 = i = na;
2469 NCOPY(x1,x3,i);
2470 x2 = GLscrat8; x3 = b; n2 = i = nb;
2471 NCOPY(x2,x3,i);
2472 }
2473 x1 = c; x2 = GLscrat8; x3 = GLscrat7; x4 = GLscrat6;
2474 for(;;){
2475 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto GcdErr;
2476 if ( !n3 ) { x1 = x2; n1 = n2; break; }
2477 if ( n2 <= 2 ) { a = x2; b = x3; na = n2; nb = n3; goto restart; }
2478 if ( n3 >= GCDMAX && n2 == n3 ) {
2479 a = GLscrat9; b = GLscrat10; na = n2; nb = n3;
2480 for ( i = 0; i < na; i++ ) a[i] = x2[i];
2481 for ( i = 0; i < nb; i++ ) b[i] = x3[i];
2482 goto newtrick;
2483 }
2484 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto GcdErr;
2485 if ( !n1 ) { x1 = x3; n1 = n3; break; }
2486 if ( n3 <= 2 ) { a = x3; b = x1; na = n3; nb = n1; goto restart; }
2487 if ( n1 >= GCDMAX && n1 == n3 ) {
2488 a = GLscrat9; b = GLscrat10; na = n3; nb = n1;
2489 for ( i = 0; i < na; i++ ) a[i] = x3[i];
2490 for ( i = 0; i < nb; i++ ) b[i] = x1[i];
2491 goto newtrick;
2492 }
2493 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto GcdErr;
2494 if ( !n2 ) { *nc = n1; goto normalend; }
2495 if ( n1 <= 2 ) { a = x1; b = x2; na = n1; nb = n2; goto restart; }
2496 if ( n2 >= GCDMAX && n2 == n1 ) {
2497 a = GLscrat9; b = GLscrat10; na = n1; nb = n2;
2498 for ( i = 0; i < na; i++ ) a[i] = x1[i];
2499 for ( i = 0; i < nb; i++ ) b[i] = x2[i];
2500 goto newtrick;
2501 }
2502 }
2503 *nc = i = n1;
2504 NCOPY(c,x1,i);
2505 }
2506 /*
2507 #] Original code :
2508 #[ New code :
2509 */
2510 else {
2511 /*
2512 This is the new algorithm starting at step 3.
2513
2514 3: ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2515 4: A = a; B = b; m = a/b; c = a - m*b;
2516 c = ma1*a+ma2*b-m*(mb1*a+mb2*b) = (ma1-m*mb1)*a+(ma2-m*mb2)*b
2517 mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2518 5: a = b; ma1 = mb1; ma2 = mb2;
2519 b = c; mb1 = mc1; mb2 = mc2;
2520 6: if ( b != 0 ) goto 4;
2521 */
2522 newtrick:;
2523 ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2524 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2525 ly = (((RLONG)(b[nb-1]))<<BITSINWORD) + b[nb-2];
2526 if ( ly > lx ) { lz = lx; lx = ly; ly = lz; d = a; a = b; b = d; }
2527 do {
2528 m = lx/ly;
2529 mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2530 ma1 = mb1; ma2 = mb2; mb1 = mc1; mb2 = mc2;
2531 lz = lx - m*ly; lx = ly; ly = lz;
2532 } while ( ly >= FULLMAX );
2533 /*
2534 Next the construction of the two new numbers
2535
2536 7: Now construct the new quantities
2537 a = ma1*aa+ma2*bb and b = mb1*aa+mb2*bb
2538 */
2539 x1 = GLscrat6;
2540 x2 = GLscrat7;
2541 x3 = GLscrat8;
2542 x5 = GLscrat10;
2543 if ( ma1 < 0 ) {
2544 ma1 = -ma1;
2545 x1[0] = (UWORD)ma1;
2546 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2547 if ( x1[1] ) n1 = -2;
2548 else n1 = -1;
2549 }
2550 else {
2551 x1[0] = (UWORD)ma1;
2552 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2553 if ( x1[1] ) n1 = 2;
2554 else n1 = 1;
2555 }
2556 if ( MulLong(a,na,x1,n1,x2,&n2) ) goto GcdErr;
2557 if ( ma2 < 0 ) {
2558 ma2 = -ma2;
2559 x1[0] = (UWORD)ma2;
2560 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2561 if ( x1[1] ) n1 = -2;
2562 else n1 = -1;
2563 }
2564 else {
2565 x1[0] = (UWORD)ma2;
2566 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2567 if ( x1[1] ) n1 = 2;
2568 else n1 = 1;
2569 }
2570 if ( MulLong(b,nb,x1,n1,x3,&n3) ) goto GcdErr;
2571 if ( AddLong(x2,n2,x3,n3,c,&n4) ) goto GcdErr;
2572 if ( mb1 < 0 ) {
2573 mb1 = -mb1;
2574 x1[0] = (UWORD)mb1;
2575 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2576 if ( x1[1] ) n1 = -2;
2577 else n1 = -1;
2578 }
2579 else {
2580 x1[0] = (UWORD)mb1;
2581 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2582 if ( x1[1] ) n1 = 2;
2583 else n1 = 1;
2584 }
2585 if ( MulLong(a,na,x1,n1,x2,&n2) ) goto GcdErr;
2586 if ( mb2 < 0 ) {
2587 mb2 = -mb2;
2588 x1[0] = (UWORD)mb2;
2589 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2590 if ( x1[1] ) n1 = -2;
2591 else n1 = -1;
2592 }
2593 else {
2594 x1[0] = (UWORD)mb2;
2595 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2596 if ( x1[1] ) n1 = 2;
2597 else n1 = 1;
2598 }
2599 if ( MulLong(b,nb,x1,n1,x3,&n3) ) goto GcdErr;
2600 if ( AddLong(x2,n2,x3,n3,x5,&n5) ) goto GcdErr;
2601 a = c; na = n4; b = x5; nb = n5;
2602 if ( nb == 0 ) { *nc = n4; goto normalend; }
2603 x4 = GLscrat9;
2604 for ( i = 0; i < na; i++ ) x4[i] = a[i];
2605 a = x4;
2606 if ( na < 0 ) na = -na;
2607 if ( nb < 0 ) nb = -nb;
2608 /*
2609 The typical case now is that in a we have the last step to go
2610 to loose the leading word, while in b we have lost the leading word.
2611 We could go to DivLong now but we can also add an extra step that
2612 is less wasteful.
2613 In the case that the new leading word of b is extrememly short (like 1)
2614 we make a rather large error of course. In the worst case the whole
2615 will be intercepted by DivLong after all, but that is so rare that
2616 it shouldn't influence any timing in a measurable way.
2617 */
2618 if ( nb >= GCDMAX && na == nb+1 && b[nb-1] >= HALFMAX && b[nb-1] > a[na-1] ) {
2619 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2620 x1[0] = lx/b[nb-1]; n1 = 1;
2621 MulLong(b,nb,x1,n1,x2,&n2);
2622 n2 = -n2;
2623 AddLong(a,na,x2,n2,x4,&n4);
2624 if ( n4 == 0 ) {
2625 *nc = nb;
2626 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2627 goto normalend;
2628 }
2629 if ( n4 < 0 ) n4 = -n4;
2630 a = b; na = nb; b = x4; nb = n4;
2631 }
2632 goto restart;
2633 /*
2634 #] New code :
2635 */
2636 }
2637 normalend:
2638 NumberFree(GLscrat6,"GcdLong"); NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
2639 NumberFree(GLscrat9,"GcdLong"); NumberFree(GLscrat10,"GcdLong");
2640 return(0);
2641 GcdErr:
2642 MLOCK(ErrorMessageLock);
2643 MesCall("GcdLong");
2644 MUNLOCK(ErrorMessageLock);
2645 NumberFree(GLscrat6,"GcdLong"); NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
2646 NumberFree(GLscrat9,"GcdLong"); NumberFree(GLscrat10,"GcdLong");
2647 SETERROR(-1)
2648 }
2649
2650 #endif
2651
2652 /*
2653 #] GcdLong :
2654 #[ GetBinom : WORD GetBinom(a,na,i1,i2)
2655 */
2656
GetBinom(UWORD * a,WORD * na,WORD i1,WORD i2)2657 WORD GetBinom(UWORD *a, WORD *na, WORD i1, WORD i2)
2658 {
2659 GETIDENTITY
2660 WORD j, k, l;
2661 UWORD *GBscrat3, *GBscrat4;
2662 if ( i1-i2 < i2 ) i2 = i1-i2;
2663 if ( i2 == 0 ) { *a = 1; *na = 1; return(0); }
2664 if ( i2 > i1 ) { *a = 0; *na = 0; return(0); }
2665 *a = i1; *na = 1;
2666 GBscrat3 = NumberMalloc("GetBinom"); GBscrat4 = NumberMalloc("GetBinom");
2667 for ( j = 2; j <= i2; j++ ) {
2668 GBscrat3[0] = i1+1-j;
2669 if ( MulLong(a,*na,GBscrat3,(WORD)1,GBscrat4,&k) ) goto CalledFrom;
2670 GBscrat3[0] = j;
2671 if ( DivLong(GBscrat4,k,GBscrat3,(WORD)1,a,na,GBscrat3,&l) ) goto CalledFrom;
2672 }
2673 NumberFree(GBscrat3,"GetBinom"); NumberFree(GBscrat4,"GetBinom");
2674 return(0);
2675 CalledFrom:
2676 MLOCK(ErrorMessageLock);
2677 MesCall("GetBinom");
2678 MUNLOCK(ErrorMessageLock);
2679 NumberFree(GBscrat3,"GetBinom"); NumberFree(GBscrat4,"GetBinom");
2680 SETERROR(-1)
2681 }
2682
2683 /*
2684 #] GetBinom :
2685 #[ LcmLong : WORD LcmLong(a,na,b,nb)
2686
2687 Computes the LCM of the long numbers a and b and puts the result
2688 in c. c is allowed to be equal to a.
2689 */
2690
LcmLong(PHEAD UWORD * a,WORD na,UWORD * b,WORD nb,UWORD * c,WORD * nc)2691 WORD LcmLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2692 {
2693 WORD error = 0;
2694 UWORD *d = NumberMalloc("LcmLong");
2695 UWORD *e = NumberMalloc("LcmLong");
2696 UWORD *f = NumberMalloc("LcmLong");
2697 WORD nd, ne, nf;
2698 GcdLong(BHEAD a, na, b, nb, d, &nd);
2699 DivLong(a,na,d,nd,e,&ne,f,&nf);
2700 if ( MulLong(b,nb,e,ne,c,nc) ) {
2701 MLOCK(ErrorMessageLock);
2702 MesCall("LcmLong");
2703 MUNLOCK(ErrorMessageLock);
2704 error = -1;
2705 }
2706 NumberFree(f,"LcmLong");
2707 NumberFree(e,"LcmLong");
2708 NumberFree(d,"LcmLong");
2709 return(error);
2710 }
2711
2712 /*
2713 #] LcmLong :
2714 #[ TakeLongRoot: int TakeLongRoot(a,n,power)
2715
2716 Takes the 'power'-root of the long number in a.
2717 If the root could be taken the return value is zero.
2718 If the root could not be taken, the return value is 1.
2719 The root will be in a if it could be taken, otherwise there will be garbage
2720 Algorithm: (assume b is guess of root, b' better guess)
2721 b' = (a-(power-1)*b^power)/(n*b^(power-1))
2722 Note: power should be positive!
2723 */
2724
TakeLongRoot(UWORD * a,WORD * n,WORD power)2725 int TakeLongRoot(UWORD *a, WORD *n, WORD power)
2726 {
2727 GETIDENTITY
2728 int numbits, guessbits, i, retval = 0;
2729 UWORD x, *b, *c, *d, *e;
2730 WORD na, nb, nc, nd, ne;
2731 if ( *n < 0 && ( power & 1 ) == 0 ) return(1);
2732 if ( power == 1 ) return(0);
2733 if ( *n < 0 ) { na = -*n; }
2734 else { na = *n; }
2735 if ( na == 1 ) {
2736 /* Special cases that are the most frequent */
2737 if ( a[0] == 1 ) return(0);
2738 if ( power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<power) ) {
2739 a[0] = 2; return(0);
2740 }
2741 if ( 2*power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<(2*power)) ) {
2742 a[0] = 4; return(0);
2743 }
2744 }
2745 /*
2746 Step 1: make a guess. We count the number of bits.
2747 numbits will be the 1+2log(a)
2748 */
2749 numbits = BITSINWORD*(na-1);
2750 x = a[na-1];
2751 while ( ( x >> 8 ) != 0 ) { numbits += 8; x >>= 8; }
2752 if ( ( x >> 4 ) != 0 ) { numbits += 4; x >>= 4; }
2753 if ( ( x >> 2 ) != 0 ) { numbits += 2; x >>= 2; }
2754 if ( ( x >> 1 ) != 0 ) numbits++;
2755 guessbits = numbits / power;
2756 if ( guessbits <= 0 ) return(1); /* root < 2 and 1 we did already */
2757 nb = guessbits/BITSINWORD;
2758 /*
2759 The recursion is:
2760 (b'-b) = (a/b^(power-1)-b)/n
2761 = (a/c-b)/n
2762 = (d-b)/n (remainder of a/c is e)
2763 = c/n (we reuse the scratch array c)
2764 Termination can be tricky. When a/c has no remainder and = b we have a root.
2765 When d = b but the remainder of a/c != 0, there is definitely no root.
2766 */
2767 b = NumberMalloc("TakeLongRoot"); c = NumberMalloc("TakeLongRoot");
2768 d = NumberMalloc("TakeLongRoot"); e = NumberMalloc("TakeLongRoot");
2769 for ( i = 0; i < nb; i++ ) { b[i] = 0; }
2770 b[nb] = 1 << (guessbits%BITSINWORD);
2771 nb++;
2772 for(;;) {
2773 nc = nb;
2774 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2775 if ( RaisPow(BHEAD c,&nc,power-1) ) goto TLcall;
2776 if ( DivLong(a,na,c,nc,d,&nd,e,&ne) ) goto TLcall;
2777 nb = -nb;
2778 if ( AddLong(d,nd,b,nb,c,&nc) ) goto TLcall;
2779 nb = -nb;
2780 if ( nc == 0 ) {
2781 if ( ne == 0 ) break;
2782 retval = 1; break;
2783 /*
2784 else {
2785 NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2786 NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2787 return(1);
2788 }
2789 */
2790 }
2791 DivLong(c,nc,(UWORD *)(&power),1,d,&nd,e,&ne);
2792 if ( nd == 0 ) {
2793 retval = 1;
2794 break;
2795 /*
2796 NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2797 NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2798 return(1);
2799 */
2800 /*
2801 This code tries b+1 as a final possibility.
2802 We believe this is not needed
2803 UWORD one = 1;
2804 if ( AddLong(b,nb,&one,1,c,&nc) ) goto TLcall;
2805 if ( RaisPow(BHEAD c,&nc,power-1) ) goto TLcall;
2806 if ( DivLong(a,na,c,nc,d,&nd,e,&ne) ) goto TLcall;
2807 if ( ne != 0 ) return(1);
2808 nb = -nb;
2809 if ( SubLong(d,nd,b,nb,c,&nc) ) goto TLcall;
2810 nb = -nb;
2811 if ( nc != 0 ) {
2812 NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2813 NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2814 return(1);
2815 }
2816 break;
2817 */
2818 }
2819 if ( AddLong(b,nb,d,nd,b,&nb) ) goto TLcall;
2820 }
2821 for ( i = 0; i < nb; i++ ) a[i] = b[i];
2822 if ( *n < 0 ) *n = -nb;
2823 else *n = nb;
2824 NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2825 NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2826 return(retval);
2827 TLcall:
2828 MLOCK(ErrorMessageLock);
2829 MesCall("TakeLongRoot");
2830 MUNLOCK(ErrorMessageLock);
2831 NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2832 NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2833 Terminate(-1);
2834 return(-1);
2835 }
2836
2837 /*
2838 #] TakeLongRoot:
2839 #[ MakeRational:
2840
2841 Makes the integer a mod m into a traction b/c with |b|,|c| < sqrt(m)
2842 For the algorithm, see MakeLongRational.
2843 */
2844
MakeRational(WORD a,WORD m,WORD * b,WORD * c)2845 int MakeRational(WORD a,WORD m, WORD *b, WORD *c)
2846 {
2847 LONG x1,x2,x3,x4,y1,y2;
2848 if ( a < 0 ) { a = a+m; }
2849 if ( a <= 1 ) {
2850 if ( a > m/2 ) a = a-m;
2851 *b = a; *c = 1; return(0);
2852 }
2853 x1 = m; x2 = a;
2854 if ( x2*x2 >= m ) {
2855 y1 = x1/x2; y2 = x1%x2; x3 = 1; x4 = -y1; x1 = x2; x2 = y2;
2856 while ( x2*x2 >= m ) {
2857 y1 = x1/x2; y2 = x1%x2; x1 = x2; x2 = y2; y2 = x3-y1*x4; x3 = x4; x4 = y2;
2858 }
2859 }
2860 else x4 = 1;
2861 if ( x2 == 0 ) { return(1); }
2862 if ( x2 > m/2 ) *b = x2-m;
2863 else *b = x2;
2864 if ( x4 > m/2 ) { *c = x4-m; *c = -*c; *b = -*b; }
2865 else if ( x4 <= -m/2 ) { x4 += m; *c = x4; }
2866 else if ( x4 < 0 ) { x4 = -x4; *c = x4; *b = -*b; }
2867 else *c = x4;
2868 return(0);
2869 }
2870
2871 /*
2872 #] MakeRational:
2873 #[ MakeLongRational:
2874
2875 Converts the long number a mod m into the fraction b
2876 One of the properties of b is that num,den < sqrt(m)
2877 The algorithm: Start with: m 0
2878 a 1
2879 Make now c=m%a, c1=m/a c c2=0-c1*1
2880 Make now d=a%c d1=a/c d d2=1-d1*c2
2881 Make now e=c%d e1=c/d e e2=1-e1*d2
2882 etc till in the first column we get a number < sqrt(m)
2883 We have then f,f2 and the fraction is f/f2.
2884 If at any moment we get a zero, m contained an unlucky prime.
2885
2886 Note that this can be made a lot faster when we make the same
2887 improvements as in the GCD routine. That is something for later.
2888 #ifdef WITHMAKERATIONAL
2889 */
2890
2891 #define COPYLONG(x1,nx1,x2,nx2) { int i; for(i=0;i<ABS(nx2);i++)x1[i]=x2[i];nx1=nx2; }
2892
MakeLongRational(PHEAD UWORD * a,WORD na,UWORD * m,WORD nm,UWORD * b,WORD * nb)2893 int MakeLongRational(PHEAD UWORD *a, WORD na, UWORD *m, WORD nm, UWORD *b, WORD *nb)
2894 {
2895 UWORD *root = NumberMalloc("MakeRational");
2896 UWORD *x1 = NumberMalloc("MakeRational");
2897 UWORD *x2 = NumberMalloc("MakeRational");
2898 UWORD *x3 = NumberMalloc("MakeRational");
2899 UWORD *x4 = NumberMalloc("MakeRational");
2900 UWORD *y1 = NumberMalloc("MakeRational");
2901 UWORD *y2 = NumberMalloc("MakeRational");
2902 WORD nroot,nx1,nx2,nx3,nx4,ny1,ny2,retval = 0;
2903 WORD sign = 1;
2904 /*
2905 Step 1: Take the square root of m
2906 */
2907 COPYLONG(root,nroot,m,nm)
2908 TakeLongRoot(root,&nroot,2);
2909 /*
2910 Step 2: Set the start values
2911 */
2912 if ( na < 0 ) { na = -na; sign = -sign; }
2913 COPYLONG(x1,nx1,m,nm)
2914 COPYLONG(x2,nx2,a,na)
2915 /*
2916 x3[0] = 0, nx3 = 0;
2917 x4[0] = 1, nx4 = 1;
2918 */
2919 /*
2920 The start operation needs some special attention because of the zero.
2921 */
2922 if ( BigLong(x2,nx2,root,nroot) <= 0 ) {
2923 x4[0] = 1, nx4 = 1;
2924 goto gottheanswer;
2925 }
2926 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2927 if ( ny2 == 0 ) { retval = 1; goto cleanup; }
2928 COPYLONG(x1,nx1,x2,nx2)
2929 COPYLONG(x2,nx2,y2,ny2)
2930 x3[0] = 1; nx3 = 1;
2931 COPYLONG(x4,nx4,y1,ny1)
2932 nx4 = -nx4;
2933 /*
2934 Now the loop.
2935 */
2936 while ( BigLong(x2,nx2,root,nroot) > 0 ) {
2937 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2938 if ( ny2 == 0 ) { retval = 1; goto cleanup; }
2939 COPYLONG(x1,nx1,x2,nx2)
2940 COPYLONG(x2,nx2,y2,ny2)
2941 MulLong(y1,ny1,x4,nx4,y2,&ny2);
2942 ny2 = -ny2;
2943 AddLong(x3,nx3,y2,ny2,y1,&ny1);
2944 COPYLONG(x3,nx3,x4,nx4)
2945 COPYLONG(x4,nx4,y1,ny1)
2946 }
2947 /*
2948 Now we have the answer. It is x2/x4. It has to be packed into b.
2949 */
2950 gottheanswer:
2951 if ( nx4 < 0 ) { sign = -sign; nx4 = -nx4; }
2952 COPYLONG(b,*nb,x2,nx2)
2953 Pack(b,nb,x4,nx4);
2954 if ( sign < 0 ) *nb = -*nb;
2955 cleanup:
2956 NumberFree(y2,"MakeRational");
2957 NumberFree(y1,"MakeRational");
2958 NumberFree(x4,"MakeRational");
2959 NumberFree(x3,"MakeRational");
2960 NumberFree(x2,"MakeRational");
2961 NumberFree(x1,"MakeRational");
2962 NumberFree(root,"MakeRational");
2963 return(retval);
2964 }
2965
2966 /*
2967 #endif
2968 #] MakeLongRational:
2969 #[ ChineseRemainder:
2970 */
2971 /**
2972 * Routine takes a1 mod m1 and a2 mod m2 and returns a mod m1*m2 with
2973 * a mod m1 = a1 and a mod m2 = a2
2974 * Chinese remainder:
2975 * a%(m1*m2) = q1*m1+a1
2976 * a%(m1*m2) = q2*m2+a2
2977 * Compute n1 such that (n1*m1)%m2 is one
2978 * Compute n2 such that (n2*m2)%m1 is one
2979 * Then (a1*n2*m2+a2*n1*m1)%(m1*m2) is a%(m1*m2)
2980 *
2981 */
2982 #ifdef WITHCHINESEREMAINDER
2983
ChineseRemainder(PHEAD MODNUM * a1,MODNUM * a2,MODNUM * a)2984 int ChineseRemainder(PHEAD MODNUM *a1, MODNUM *a2, MODNUM *a)
2985 {
2986 UWORD *inv1 = NumberMalloc("ChineseRemainder");
2987 UWORD *inv2 = NumberMalloc("ChineseRemainder");
2988 UWORD *fac1 = NumberMalloc("ChineseRemainder");
2989 UWORD *fac2 = NumberMalloc("ChineseRemainder");
2990 UWORD two[1];
2991 WORD ninv1, ninv2, nfac1, nfac2;
2992 if ( a1->na < 0 ) {
2993 AddLong(a1->a,a1->na,a1->m,a1->nm,a1->a,&(a1->na));
2994 }
2995 if ( a2->na < 0 ) {
2996 AddLong(a2->a,a2->na,a2->m,a2->nm,a2->a,&(a2->na));
2997 }
2998 MulLong(a1->m,a1->nm,a2->m,a2->nm,a->m,&(a->nm));
2999
3000 GetLongModInverses(BHEAD a1->m,a1->nm,a2->m,a2->nm,inv1,&ninv1,inv2,&ninv2);
3001 MulLong(inv1,ninv1,a1->m,a1->nm,fac1,&nfac1);
3002 MulLong(inv2,ninv2,a2->m,a2->nm,fac2,&nfac2);
3003
3004 MulLong(fac1,nfac1,a2->a,a2->na,inv1,&ninv1);
3005 MulLong(fac2,nfac2,a1->a,a1->na,inv2,&ninv2);
3006 AddLong(inv1,ninv1,inv2,ninv2,a->a,&(a->na));
3007
3008 two[0] = 2;
3009 MulLong(a->a,a->na,two,1,fac1,&nfac1);
3010 if ( BigLong(fac1,nfac1,a->m,a->nm) > 0 ) {
3011 a->nm = -a->nm;
3012 AddLong(a->a,a->na,a->m,a->nm,a->a,&(a->na));
3013 a->nm = -a->nm;
3014 }
3015 NumberFree(fac2,"ChineseRemainder");
3016 NumberFree(fac1,"ChineseRemainder");
3017 NumberFree(inv2,"ChineseRemainder");
3018 NumberFree(inv1,"ChineseRemainder");
3019 return(0);
3020 }
3021
3022 #endif
3023
3024 /*
3025 #] ChineseRemainder:
3026 #] RekenLong :
3027 #[ RekenTerms :
3028 #[ CompCoef : WORD CompCoef(term1,term2)
3029
3030 Compares the coefficients of term1 and term2 by subtracting them.
3031 This does more work than needed but this routine is only called
3032 when sorting functions and function arguments.
3033 (and comparing values
3034 */
3035 /* #define 64SAVE */
3036
CompCoef(WORD * term1,WORD * term2)3037 WORD CompCoef(WORD *term1, WORD *term2)
3038 {
3039 GETIDENTITY
3040 UWORD *c;
3041 WORD n1,n2,n3,*a;
3042 GETCOEF(term1,n1);
3043 GETCOEF(term2,n2);
3044 if ( term1[1] == 0 && n1 == 1 ) {
3045 if ( term2[1] == 0 && n2 == 1 ) return(0);
3046 if ( n2 < 0 ) return(1);
3047 return(-1);
3048 }
3049 else if ( term2[1] == 0 && n2 == 1 ) {
3050 if ( n1 < 0 ) return(-1);
3051 return(1);
3052 }
3053 if ( n1 > 0 ) {
3054 if ( n2 < 0 ) return(1);
3055 }
3056 else {
3057 if ( n2 > 0 ) return(-1);
3058 a = term1; term1 = term2; term2 = a;
3059 n3 = -n1; n1 = -n2; n2 = n3;
3060 }
3061 if ( term1[1] == 1 && term2[1] == 1 && n1 == 1 && n2 == 1 ) {
3062 if ( (UWORD)*term1 > (UWORD)*term2 ) return(1);
3063 else if ( (UWORD)*term1 < (UWORD)*term2 ) return(-1);
3064 else return(0);
3065 }
3066
3067 /*
3068 The next call should get dedicated code, as AddRat does more than
3069 strictly needed. Also more attention should be given to overflow.
3070 */
3071 c = NumberMalloc("CompCoef");
3072 if ( AddRat(BHEAD (UWORD *)term1,n1,(UWORD *)term2,-n2,c,&n3) ) {
3073 MLOCK(ErrorMessageLock);
3074 MesCall("CompCoef");
3075 MUNLOCK(ErrorMessageLock);
3076 NumberFree(c,"CompCoef");
3077 SETERROR(-1)
3078 }
3079 NumberFree(c,"CompCoef");
3080 return(n3);
3081 }
3082
3083 /*
3084 #] CompCoef :
3085 #[ Modulus : WORD Modulus(term)
3086
3087 Routine takes the coefficient of term modulus b. The answer
3088 is in term again and the length of term is adjusted.
3089
3090 */
3091
Modulus(WORD * term)3092 WORD Modulus(WORD *term)
3093 {
3094 WORD *t;
3095 WORD n1;
3096 t = term;
3097 GETCOEF(t,n1);
3098 if ( TakeModulus((UWORD *)t,&n1,AC.cmod,AC.ncmod,UNPACK) ) {
3099 MLOCK(ErrorMessageLock);
3100 MesCall("Modulus");
3101 MUNLOCK(ErrorMessageLock);
3102 SETERROR(-1)
3103 }
3104 if ( !n1 ) {
3105 *term = 0;
3106 return(0);
3107 }
3108 else if ( n1 > 0 ) {
3109 n1 *= 2;
3110 t += n1; /* Note that n1 >= 0 */
3111 n1++;
3112 }
3113 else if ( n1 < 0 ) {
3114 n1 *= 2;
3115 t += -n1;
3116 n1--;
3117 }
3118 *t++ = n1;
3119 *term = WORDDIF(t,term);
3120 return(0);
3121 }
3122
3123 /*
3124 #] Modulus :
3125 #[ TakeModulus : WORD TakeModulus(a,na,cmodvec,ncmod,par)
3126
3127 Routine gets the rational number in a with reduced length na.
3128 It is called when AC.ncmod != 0 and the number in AC.cmod is the
3129 number wrt which we need the modulus.
3130 The result is returned in a and na again.
3131
3132 If par == NOUNPACK we only do a single number, not a fraction.
3133 In addition we don't do fancy. We want a positive number and
3134 the input was supposed to be positive.
3135 We don't pack the result. The calling routine is responsible for that.
3136 This may not be a good idea. To be checked.
3137 */
3138
TakeModulus(UWORD * a,WORD * na,UWORD * cmodvec,WORD ncmod,WORD par)3139 WORD TakeModulus(UWORD *a, WORD *na, UWORD *cmodvec, WORD ncmod, WORD par)
3140 {
3141 GETIDENTITY
3142 UWORD *c, *d, *e, *f, *g, *h;
3143 UWORD *x4,*x2;
3144 UWORD *x3,*x1,*x5,*x6,*x7,*x8;
3145 WORD y3,y1,y5,y6;
3146 WORD n1, i, y2, y4;
3147 WORD nh, tdenom, tnumer, nmod;
3148 LONG x;
3149 if ( ncmod == 0 ) return(0); /* No modulus operation */
3150 nmod = ABS(ncmod);
3151 n1 = *na;
3152 if ( ( par & UNPACK ) != 0 ) UnPack(a,n1,&tdenom,&tnumer);
3153 else { tnumer = n1; }
3154 /*
3155 We fish out the special case that the coefficient is short as well.
3156 There is no need to make lots of calls etc
3157 */
3158 if ( ( ( par & UNPACK ) == 0 ) && nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3159 goto simplecase;
3160 }
3161 else if ( nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3162 if ( a[1] != 1 ) {
3163 a[1] = a[1] % cmodvec[0];
3164 if ( a[1] == 0 ) {
3165 MesPrint("Division by zero in short modulus arithmetic");
3166 return(-1);
3167 }
3168 y1 = 0;
3169 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 ) ) {
3170 y1 = AC.modinverses[a[1]];
3171 }
3172 else {
3173 GetModInverses(a[1],cmodvec[0],&y1,&y2);
3174 }
3175 x = a[0];
3176 a[0] = (x*y1) % cmodvec[0];
3177 a[1] = 1;
3178 }
3179 else {
3180 simplecase:
3181 a[0] = a[0] % cmodvec[0];
3182 }
3183 if ( a[0] == 0 ) { *na = 0; return(0); }
3184 if ( ( AC.modmode & POSNEG ) != 0 ) {
3185 if ( a[0] > (UWORD)(cmodvec[0]/2) ) {
3186 a[0] = cmodvec[0] - a[0];
3187 *na = -*na;
3188 }
3189 }
3190 else if ( *na < 0 ) {
3191 *na = 1; a[0] = cmodvec[0] - a[0];
3192 }
3193 return(0);
3194 }
3195 c = NumberMalloc("TakeModulus"); d = NumberMalloc("TakeModulus"); e = NumberMalloc("TakeModulus");
3196 f = NumberMalloc("TakeModulus"); g = NumberMalloc("TakeModulus"); h = NumberMalloc("TakeModulus");
3197 n1 = ABS(n1);
3198 if ( DivLong(a,tnumer,(UWORD *)cmodvec,nmod,
3199 c,&nh,a,&tnumer) ) goto ModErr;
3200 if ( tnumer == 0 ) { *na = 0; goto normalreturn; }
3201 if ( ( par & UNPACK ) == 0 ) {
3202 if ( ( AC.modmode & POSNEG ) != 0 ) {
3203 NormalModulus(a,&tnumer);
3204 }
3205 else if ( tnumer < 0 ) {
3206 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3207 }
3208 *na = tnumer;
3209 goto normalreturn;
3210 }
3211 if ( tdenom == 1 && a[n1] == 1 ) {
3212 if ( ( AC.modmode & POSNEG ) != 0 ) {
3213 NormalModulus(a,&tnumer);
3214 }
3215 else if ( tnumer < 0 ) {
3216 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3217 }
3218 *na = tnumer;
3219 i = ABS(tnumer);
3220 a += i;
3221 *a++ = 1;
3222 while ( --i > 0 ) *a++ = 0;
3223 goto normalreturn;
3224 }
3225 if ( DivLong(a+n1,tdenom,(UWORD *)cmodvec,nmod,c,&nh,a+n1,&tdenom) ) goto ModErr;
3226 if ( !tdenom ) {
3227 MLOCK(ErrorMessageLock);
3228 MesPrint("Division by zero in modulus arithmetic");
3229 if ( AP.DebugFlag ) {
3230 AO.OutSkip = 3;
3231 FiniLine();
3232 i = *na;
3233 if ( i < 0 ) i = -i;
3234 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)" "); }
3235 i = *na;
3236 if ( i < 0 ) i = -i;
3237 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)" "); }
3238 TalToLine((UWORD)(*na));
3239 AO.OutSkip = 0;
3240 FiniLine();
3241 }
3242 MUNLOCK(ErrorMessageLock);
3243 NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
3244 NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
3245 return(-1);
3246 }
3247 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 )
3248 && ( tdenom == 1 || tdenom == -1 ) ) {
3249 *d = AC.modinverses[a[n1]]; y1 = 1; y2 = tdenom;
3250 if ( MulLong(a,tnumer,d,y1,c,&y3) ) goto ModErr;
3251 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) ) goto ModErr;
3252 if ( y2 < 0 ) tdenom = -tdenom;
3253 }
3254 else {
3255 x2 = (UWORD *)cmodvec; x1 = c; i = nmod; while ( --i >= 0 ) *x1++ = *x2++;
3256 x1 = c; x2 = a+n1; x3 = d; x4 = e; x5 = f; x6 = g;
3257 y1 = nmod; y2 = tdenom; y4 = 0; y5 = 1; *x5 = 1;
3258 for(;;) {
3259 if ( DivLong(x1,y1,x2,y2,h,&nh,x3,&y3) ) goto ModErr;
3260 if ( MulLong(x5,y5,h,nh,x6,&y6) ) goto ModErr;
3261 if ( AddLong(x4,y4,x6,-y6,x6,&y6) ) goto ModErr;
3262 if ( !y3 ) {
3263 if ( y2 != 1 || *x2 != 1 ) {
3264 MLOCK(ErrorMessageLock);
3265 MesPrint("Inverse in modulus arithmetic doesn't exist");
3266 MesPrint("Denominator and modulus are not relative prime");
3267 MUNLOCK(ErrorMessageLock);
3268 goto ModErr;
3269 }
3270 break;
3271 }
3272 x7 = x1; x1 = x2; y1 = y2; x2 = x3; y2 = y3; x3 = x7;
3273 x8 = x4; x4 = x5; y4 = y5; x5 = x6; y5 = y6; x6 = x8;
3274 }
3275 if ( y5 < 0 && AddLong((UWORD *)cmodvec,nmod,x5,y5,x5,&y5) ) goto ModErr;
3276 if ( MulLong(a,tnumer,x5,y5,c,&y3) ) goto ModErr;
3277 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) ) goto ModErr;
3278 }
3279 if ( !tdenom ) { *na = 0; goto normalreturn; }
3280 if ( ( ( AC.modmode & POSNEG ) != 0 ) && ( ( par & FROMFUNCTION ) == 0 ) ) {
3281 NormalModulus(a,&tdenom);
3282 }
3283 else if ( tdenom < 0 ) {
3284 SubPLon((UWORD *)cmodvec,nmod,a,-tdenom,a,&tdenom);
3285 }
3286 *na = tdenom;
3287 i = ABS(tdenom);
3288 a += i;
3289 *a++ = 1;
3290 while ( --i > 0 ) *a++ = 0;
3291 normalreturn:
3292 NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
3293 NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
3294 return(0);
3295 ModErr:
3296 MLOCK(ErrorMessageLock);
3297 MesCall("TakeModulus");
3298 MUNLOCK(ErrorMessageLock);
3299 NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
3300 NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
3301 SETERROR(-1)
3302 }
3303
3304 /*
3305 #] TakeModulus :
3306 #[ TakeNormalModulus : WORD TakeNormalModulus(a,na,par)
3307
3308 added by Jan [01-09-2010]
3309 */
3310
TakeNormalModulus(UWORD * a,WORD * na,UWORD * c,WORD nc,WORD par)3311 WORD TakeNormalModulus (UWORD *a, WORD *na, UWORD *c, WORD nc, WORD par)
3312 {
3313 WORD n;
3314 WORD nhalfc;
3315 UWORD *halfc;
3316
3317 GETIDENTITY;
3318
3319 /* determine c/2 by right shifting */
3320 halfc = NumberMalloc("TakeNormalModulus");
3321 nhalfc=nc;
3322 WCOPY(halfc,c,nc);
3323
3324 for (n=0; n<nhalfc; n++) {
3325 halfc[n] /= 2;
3326 if (n+1<nc) halfc[n] |= c[n+1] << (BITSINWORD-1);
3327 }
3328
3329 if (halfc[nhalfc-1]==0)
3330 nhalfc--;
3331
3332 /* takes care of the number never expanding, e.g., -1(mod 100) -> 99 -> -1 */
3333 if (BigLong(a,ABS(*na),halfc,nhalfc) > 0) {
3334
3335 TakeModulus(a,na,c,nc,par);
3336
3337 n = ABS(*na);
3338 if (BigLong(a,n,halfc,nhalfc) > 0) {
3339 SubPLon(c,nc,a,n,a,&n);
3340 *na = (*na > 0 ? -n : n);
3341 }
3342 }
3343
3344 NumberFree(halfc,"TakeNormalModulus");
3345 return(0);
3346 }
3347
3348 /*
3349 #] TakeNormalModulus :
3350 #[ MakeModTable : WORD MakeModTable()
3351 */
3352
MakeModTable()3353 WORD MakeModTable()
3354 {
3355 LONG size, i, j, n;
3356 n = ABS(AC.ncmod);
3357 if ( AC.modpowers ) {
3358 M_free(AC.modpowers,"AC.modpowers");
3359 AC.modpowers = NULL;
3360 }
3361 if ( n > 2 ) {
3362 MLOCK(ErrorMessageLock);
3363 MesPrint("&No memory for modulus generator power table");
3364 MUNLOCK(ErrorMessageLock);
3365 Terminate(-1);
3366 }
3367 if ( n == 0 ) return(0);
3368 size = (LONG)(*AC.cmod);
3369 if ( n == 2 ) size += (((LONG)AC.cmod[1])<<BITSINWORD);
3370 AC.modpowers = (UWORD *)Malloc1(size*n*sizeof(UWORD),"table for powers of modulus");
3371 if ( n == 1 ) {
3372 j = 1;
3373 for ( i = 0; i < size; i++ ) AC.modpowers[i] = 0;
3374 for ( i = 0; i < size; i++ ) {
3375 AC.modpowers[j] = (WORD)i;
3376 j *= *AC.powmod;
3377 j %= *AC.cmod;
3378 }
3379 for ( i = 2; i < size; i++ ) {
3380 if ( AC.modpowers[i] == 0 ) {
3381 MLOCK(ErrorMessageLock);
3382 MesPrint("&improper generator for this modulus");
3383 MUNLOCK(ErrorMessageLock);
3384 M_free(AC.modpowers,"AC.modpowers");
3385 return(-1);
3386 }
3387 }
3388 AC.modpowers[1] = 0;
3389 }
3390 else {
3391 GETIDENTITY
3392 WORD nScrat, n2;
3393 UWORD *MMscrat7 = NumberMalloc("MakeModTable"), *MMscratC = NumberMalloc("MakeModTable");
3394 *MMscratC = 1;
3395 nScrat = 1;
3396 j = size * 2;
3397 for ( i = 0; i < j; i+=2 ) { AC.modpowers[i] = 0; AC.modpowers[i+1] = 0; }
3398 for ( i = 0; i < size; i++ ) {
3399 j = *MMscratC + (((LONG)MMscratC[1])<<BITSINWORD);
3400 j *= 2;
3401 AC.modpowers[j] = (WORD)(i & WORDMASK);
3402 AC.modpowers[j+1] = (WORD)(i >> BITSINWORD);
3403 MulLong((UWORD *)MMscratC,nScrat,(UWORD *)AC.powmod,
3404 AC.npowmod,(UWORD *)MMscrat7,&n2);
3405 TakeModulus(MMscrat7,&n2,AC.cmod,AC.ncmod,NOUNPACK);
3406 *MMscratC = *MMscrat7; MMscratC[1] = MMscrat7[1]; nScrat = n2;
3407 }
3408 NumberFree(MMscrat7,"MakeModTable"); NumberFree(MMscratC,"MakeModTable");
3409 j = size * 2;
3410 for ( i = 4; i < j; i+=2 ) {
3411 if ( AC.modpowers[i] == 0 && AC.modpowers[i+1] == 0 ) {
3412 MLOCK(ErrorMessageLock);
3413 MesPrint("&improper generator for this modulus");
3414 MUNLOCK(ErrorMessageLock);
3415 M_free(AC.modpowers,"AC.modpowers");
3416 return(-1);
3417 }
3418 }
3419 AC.modpowers[2] = AC.modpowers[3] = 0;
3420 }
3421 return(0);
3422 }
3423
3424 /*
3425 #] MakeModTable :
3426 #] RekenTerms :
3427 #[ Functions :
3428 #[ Factorial : WORD Factorial(n,a,na)
3429
3430 Starts with only the value of fac_(0).
3431 Builds up what is needed and remembers it for the next time.
3432
3433 We have:
3434 AT.nfac: the number of the highest stored factorial
3435 AT.pfac: the array of locations in the array of stored factorials
3436 AT.factorials: the array with stored factorials
3437 */
3438
Factorial(PHEAD WORD n,UWORD * a,WORD * na)3439 int Factorial(PHEAD WORD n, UWORD *a, WORD *na)
3440 {
3441 GETBIDENTITY
3442 UWORD *b, *c;
3443 WORD nc;
3444 int i, j;
3445 LONG ii;
3446 if ( n > AT.nfac ) {
3447 if ( AT.factorials == 0 ) {
3448 AT.nfac = 0; AT.mfac = 50; AT.sfact = 400;
3449 AT.pfac = (LONG *)Malloc1((AT.mfac+2)*sizeof(LONG),"factorials");
3450 AT.factorials = (UWORD *)Malloc1(AT.sfact*sizeof(UWORD),"factorials");
3451 AT.factorials[0] = 1; AT.pfac[0] = 0; AT.pfac[1] = 1;
3452 }
3453 b = a;
3454 c = AT.factorials+AT.pfac[AT.nfac];
3455 nc = i = AT.pfac[AT.nfac+1] - AT.pfac[AT.nfac];
3456 while ( --i >= 0 ) *b++ = *c++;
3457 for ( j = AT.nfac+1; j <= n; j++ ) {
3458 Product(a,&nc,j);
3459 if ( nc > AM.MaxTal ) {
3460 MLOCK(ErrorMessageLock);
3461 MesPrint("Overflow in factorial. MaxTal = %d",AM.MaxTal);
3462 MesPrint("Increase MaxTerm in %s",setupfilename);
3463 MUNLOCK(ErrorMessageLock);
3464 return(-1);
3465 }
3466 if ( j > AT.mfac ) { /* double the pfac buffer */
3467 LONG *p;
3468 p = (LONG *)Malloc1((AT.mfac*2+2)*sizeof(LONG),"factorials");
3469 i = AT.mfac;
3470 for ( i = AT.mfac+1; i >= 0; i-- ) p[i] = AT.pfac[i];
3471 M_free(AT.pfac,"factorial pointers"); AT.pfac = p; AT.mfac *= 2;
3472 }
3473 if ( AT.pfac[j] + nc >= AT.sfact ) { /* double the factorials buffer */
3474 UWORD *f;
3475 f = (UWORD *)Malloc1(AT.sfact*2*sizeof(UWORD),"factorials");
3476 ii = AT.sfact;
3477 c = AT.factorials; b = f;
3478 while ( --ii >= 0 ) *b++ = *c++;
3479 M_free(AT.factorials,"factorials");
3480 AT.factorials = f;
3481 AT.sfact *= 2;
3482 }
3483 b = a; c = AT.factorials + AT.pfac[j]; i = nc;
3484 while ( --i >= 0 ) *c++ = *b++;
3485 AT.pfac[j+1] = AT.pfac[j] + nc;
3486 }
3487 *na = nc;
3488 AT.nfac = n;
3489 }
3490 else if ( n == 0 ) {
3491 *a = 1; *na = 1;
3492 }
3493 else {
3494 *na = i = AT.pfac[n+1] - AT.pfac[n];
3495 b = AT.factorials + AT.pfac[n];
3496 while ( --i >= 0 ) *a++ = *b++;
3497 }
3498 return(0);
3499 }
3500
3501 /*
3502 #] Factorial :
3503 #[ Bernoulli : WORD Bernoulli(n,a,na)
3504
3505 Starts with only the value of bernoulli_(0).
3506 Builds up what is needed and remembers it for the next time.
3507 b_0 = 1
3508 (n+1)*b_n = -b_{n-1}-sum_(i,1,n-1,b_i*b_{n-i})
3509 The n-1 playes only a role for b_2.
3510 We have hard coded b_0,b_1,b_2 and b_odd. After that:
3511 (2n+1)*b_2n = -sum_(i,1,n-1,b_2i*b_{2n-2i})
3512
3513 We have:
3514 AT.nBer: the number of the highest stored Bernoulli number
3515 AT.pBer: the array of locations in the array of stored Bernoulli numbers
3516 AT.bernoullis: the array with stored Bernoulli numbers
3517 */
3518
Bernoulli(WORD n,UWORD * a,WORD * na)3519 int Bernoulli(WORD n, UWORD *a, WORD *na)
3520 {
3521 GETIDENTITY
3522 UWORD *b, *c, *scrib, *ntop, *ntop1;
3523 WORD i, i1, i2, nhalf, nqua, nscrib, nntop, nntop1, *oldworkpointer;
3524 UWORD twee = 2, twonplus1;
3525 int j;
3526 LONG ii;
3527 if ( n <= 1 ) {
3528 if ( n == 0 ) { a[0] = a[1] = 1; *na = 3; }
3529 else if ( n == 1 ) { a[0] = 1; a[1] = 2; *na = 3; }
3530 return(0);
3531 }
3532 if ( ( n & 1 ) != 0 ) { a[0] = a[1] = 0; *na = 0; return(0); }
3533 nhalf = n/2;
3534 if ( nhalf > AT.nBer ) {
3535 oldworkpointer = AT.WorkPointer;
3536 if ( AT.bernoullis == 0 ) {
3537 AT.nBer = 1; AT.mBer = 50; AT.sBer = 400;
3538 AT.pBer = (LONG *)Malloc1((AT.mBer+2)*sizeof(LONG),"bernoullis");
3539 AT.bernoullis = (UWORD *)Malloc1(AT.sBer*sizeof(UWORD),"bernoullis");
3540 AT.pBer[1] = 0; AT.pBer[2] = 3;
3541 AT.bernoullis[0] = 3; AT.bernoullis[1] = 1; AT.bernoullis[2] = 12;
3542 if ( nhalf == 1 ) {
3543 a[0] = 1; a[1] = 12; *na = 3; return(0);
3544 }
3545 }
3546 while ( nhalf > AT.mBer ) {
3547 LONG *p;
3548 p = (LONG *)Malloc1((AT.mBer*2+1)*sizeof(LONG),"bernoullis");
3549 i = AT.mBer;
3550 for ( i = AT.mBer; i >= 0; i-- ) p[i] = AT.pBer[i];
3551 M_free(AT.pBer,"factorial pointers"); AT.pBer = p; AT.mBer *= 2;
3552 }
3553 for ( n = AT.nBer+1; n <= nhalf; n++ ) {
3554 scrib = (UWORD *)(AT.WorkPointer);
3555 nqua = n/2;
3556 if ( ( n & 1 ) == 1 ) {
3557 nscrib = 0; ntop = scrib;
3558 }
3559 else {
3560 b = AT.bernoullis + AT.pBer[nqua];
3561 nscrib = *b++;
3562 i = (WORD)(REDLENG(nscrib));
3563 MulRat(BHEAD b,i,b,i,scrib,&nscrib);
3564 ntop = scrib + 2*nscrib;
3565 nqua--;
3566 }
3567 for ( j = 1; j <= nqua; j++ ) {
3568 b = AT.bernoullis + AT.pBer[j];
3569 c = AT.bernoullis + AT.pBer[n-j];
3570 i1 = (WORD)(*b); i2 = (WORD)(*c);
3571 i1 = REDLENG(i1);
3572 i2 = REDLENG(i2);
3573 MulRat(BHEAD b+1,i1,c+1,i2,ntop,&nntop);
3574 Mully(BHEAD ntop,&nntop,&twee,1);
3575 if ( nscrib ) {
3576 i = (WORD)nntop; if ( i < 0 ) i = -i;
3577 ntop1 = ntop + 2*i;
3578 AddRat(BHEAD ntop,nntop,scrib,nscrib,ntop1,&nntop1);
3579 }
3580 else {
3581 ntop1 = ntop; nntop1 = nntop;
3582 }
3583 nscrib = i1 = (WORD)nntop1;
3584 if ( i1 < 0 ) i1 = - i1;
3585 i1 = 2*i1;
3586 for ( i = 0; i < i1; i++ ) scrib[i] = ntop1[i];
3587 ntop = scrib + i1;
3588 }
3589 twonplus1 = 2*n+1;
3590 Divvy(BHEAD scrib,&nscrib,&twonplus1,-1);
3591 i1 = INCLENG(nscrib);
3592 i2 = i1; if ( i2 < 0 ) i2 = -i2;
3593 i = (WORD)(AT.bernoullis[AT.pBer[n-1]]);
3594 if ( i < 0 ) i = -i;
3595 AT.pBer[n] = AT.pBer[n-1]+i;
3596 if ( AT.pBer[n] + i2 >= AT.sBer ) {
3597 UWORD *f;
3598 f = (UWORD *)Malloc1(AT.sBer*2*sizeof(UWORD),"bernoullis");
3599 ii = AT.sBer;
3600 c = AT.bernoullis; b = f;
3601 while ( --ii >= 0 ) *b++ = *c++;
3602 M_free(AT.bernoullis,"bernoullis");
3603 AT.bernoullis = f;
3604 AT.sBer *= 2;
3605 }
3606 c = AT.bernoullis + AT.pBer[n]; b = scrib;
3607 *c++ = i1;
3608 for ( i = 1; i < i2; i++ ) *c++ = *b++;
3609 }
3610 AT.nBer = nhalf;
3611 AT.WorkPointer = oldworkpointer;
3612 }
3613 b = AT.bernoullis + AT.pBer[nhalf];
3614 *na = i = (WORD)(*b++);
3615 if ( i < 0 ) i = -i;
3616 i--;
3617 while ( --i >= 0 ) *a++ = *b++;
3618 return(0);
3619 }
3620
3621 /*
3622 #] Bernoulli :
3623 #[ NextPrime :
3624 */
3625 /**
3626 * Gives the next prime number in the list of prime numbers.
3627 *
3628 * If the list isn't long enough we expand it.
3629 * For ease in ParForm and because these lists shouldn't be very big
3630 * we let each worker keep its own list.
3631 *
3632 * The list is cut off at MAXPOWER, because we don't want to get into
3633 * trouble that the power of a variable gets larger than the prime number.
3634 */
3635
3636 #if ( BITSINWORD == 32 )
3637
StartPrimeList(PHEAD0)3638 void StartPrimeList(PHEAD0)
3639 {
3640 int i, j;
3641 AR.PrimeList[AR.numinprimelist++] = 3;
3642 for ( i = 5; i < 46340; i += 2 ) {
3643 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*AR.PrimeList[j] <= i; j++ ) {
3644 if ( i % AR.PrimeList[j] == 0 ) goto nexti;
3645 }
3646 AR.PrimeList[AR.numinprimelist++] = i;
3647 nexti:;
3648 }
3649 AR.notfirstprime = 1;
3650 }
3651
3652 #endif
3653
NextPrime(PHEAD WORD num)3654 WORD NextPrime(PHEAD WORD num)
3655 {
3656 int i, j;
3657 WORD *newpl;
3658 LONG newsize, x;
3659 #if ( BITSINWORD == 32 )
3660 if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
3661 #endif
3662 if ( num > AT.inprimelist ) {
3663 while ( AT.inprimelist < num ) {
3664 if ( num >= AT.sizeprimelist ) {
3665 if ( AT.sizeprimelist == 0 ) newsize = 32;
3666 else newsize = 2*AT.sizeprimelist;
3667 while ( num >= newsize ) newsize = newsize*2;
3668 newpl = (WORD *)Malloc1(newsize*sizeof(WORD),"NextPrime");
3669 for ( i = 0; i < AT.sizeprimelist; i++ ) {
3670 newpl[i] = AT.primelist[i];
3671 }
3672 if ( AT.sizeprimelist > 0 ) {
3673 M_free(AT.primelist,"NextPrime");
3674 }
3675 AT.sizeprimelist = newsize;
3676 AT.primelist = newpl;
3677 }
3678 if ( AT.inprimelist < 0 ) { i = MAXPOSITIVE; }
3679 else { i = AT.primelist[AT.inprimelist]; }
3680 while ( i > MAXPOWER ) {
3681 i -= 2; x = i;
3682 #if ( BITSINWORD == 32 )
3683 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*(LONG)(AR.PrimeList[j]) <= x; j++ ) {
3684 if ( x % AR.PrimeList[j] == 0 ) goto nexti;
3685 }
3686 #else
3687 for ( j = 3; j*((LONG)j) <= x; j += 2 ) {
3688 if ( x % j == 0 ) goto nexti;
3689 }
3690 #endif
3691 AT.inprimelist++;
3692 AT.primelist[AT.inprimelist] = i;
3693 break;
3694 nexti:;
3695 }
3696 if ( i < MAXPOWER ) {
3697 MLOCK(ErrorMessageLock);
3698 MesPrint("There are not enough short prime numbers for this calculation");
3699 MesPrint("Try to use a computer with a %d-bits architecture",
3700 (int)(BITSINWORD*4));
3701 MUNLOCK(ErrorMessageLock);
3702 Terminate(-1);
3703 }
3704 }
3705 }
3706 return(AT.primelist[num]);
3707 }
3708
3709 /*
3710 #] NextPrime :
3711 #[ wranf :
3712
3713 A random number generator that generates random WORDs with a very
3714 long sequence. It is based on the Knuth generator.
3715
3716 We take some care that each thread can run its own, but each
3717 uses its own startup. Hence the seed includes the identity of
3718 the thread.
3719
3720 For NPAIR1, NPAIR2 we can use any pair from the table on page 28.
3721 Candidates are 24,55 (the example on the pages 171,172)
3722 or (33,97) or (38,89)
3723 These values are defined in fsizes.h and used in startup.c and threads.c
3724 */
3725
3726 #define WARMUP 6
3727
wranfnew(PHEAD0)3728 static void wranfnew(PHEAD0)
3729 {
3730 int i;
3731 LONG j;
3732 for ( i = 0; i < AR.wranfnpair1; i++ ) {
3733 j = AR.wranfia[i] - AR.wranfia[i+(AR.wranfnpair2-AR.wranfnpair1)];
3734 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3735 AR.wranfia[i] = j;
3736 }
3737 for ( i = AR.wranfnpair1; i < AR.wranfnpair2; i++ ) {
3738 j = AR.wranfia[i] - AR.wranfia[i-AR.wranfnpair1];
3739 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3740 AR.wranfia[i] = j;
3741 }
3742 }
3743
iniwranf(PHEAD0)3744 void iniwranf(PHEAD0)
3745 {
3746 int imax = AR.wranfnpair2-1;
3747 ULONG i, ii, seed = AR.wranfseed;
3748 LONG j, k;
3749 ULONG offset = 12345;
3750 #ifdef PARALLELCODE
3751 int id;
3752 #if defined(WITHPTHREADS)
3753 id = AT.identity;
3754 #elif defined(WITHMPI)
3755 id = PF.me;
3756 #endif
3757 seed += id;
3758 i = id + 1;
3759 if ( i > 1 ) {
3760 ULONG pow, accu;
3761 pow = offset; accu = 1;
3762 while ( i ) {
3763 if ( ( i & 1 ) != 0 ) accu *= pow;
3764 i /= 2; pow = pow*pow;
3765 }
3766 offset = accu;
3767 }
3768 #endif
3769 if ( seed < ((LONG)1<<(BITSINWORD-1)) ) {
3770 j = ( (seed+31459L) << (BITSINWORD-2))+offset;
3771 }
3772 else if ( seed < ((LONG)1<<(BITSINWORD+10-1)) ) {
3773 j = ( (seed+31459L) << (BITSINWORD-10-2))+offset;
3774 }
3775 else {
3776 j = ( (seed+31459L) << 1)+offset;
3777 }
3778 if ( ( seed & 1 ) == 1 ) seed++;
3779 j += seed;
3780 AR.wranfia[imax] = j;
3781 k = 1;
3782 for ( i = 0; i <= (ULONG)(imax); i++ ) {
3783 ii = (AR.wranfnpair1*i)%AR.wranfnpair2;
3784 AR.wranfia[ii] = k;
3785 k = ULongToLong((ULONG)j - (ULONG)k);
3786 if ( k < 0 ) k += (LONG)1 << (2*BITSINWORD-2);
3787 j = AR.wranfia[ii];
3788 }
3789 for ( i = 0; i < WARMUP; i++ ) wranfnew(BHEAD0);
3790 AR.wranfcall = 0;
3791 }
3792
wranf(PHEAD0)3793 UWORD wranf(PHEAD0)
3794 {
3795 UWORD wval;
3796 if ( AR.wranfia == 0 ) {
3797 AR.wranfia = (ULONG *)Malloc1(AR.wranfnpair2*sizeof(ULONG),"wranf");
3798 iniwranf(BHEAD0);
3799 }
3800 if ( AR.wranfcall >= AR.wranfnpair2) {
3801 wranfnew(BHEAD0);
3802 AR.wranfcall = 0;
3803 }
3804 wval = (UWORD)(AR.wranfia[AR.wranfcall++]>>(BITSINWORD-1));
3805 return(wval);
3806 }
3807
3808 /*
3809 Returns a random UWORD in the range (0,...,imax-1)
3810 */
3811
iranf(PHEAD UWORD imax)3812 UWORD iranf(PHEAD UWORD imax)
3813 {
3814 UWORD i;
3815 ULONG x = (LONG)1 << BITSINWORD, xmax = x - x%imax;
3816 while ( ( i = wranf(BHEAD0) ) >= xmax ) {}
3817 return(i%imax);
3818 }
3819
3820 /*
3821 #] wranf :
3822 #[ PreRandom :
3823
3824 The random number generator of the preprocessor.
3825 This one is completely different from the execution time generator
3826 random_(number). In the preprocessor we generate a floating point
3827 number in a string according to a distribution.
3828 Currently allowed are:
3829 RANDOM_(log,min,max)
3830 RANDOM_(lin,min,max)
3831 The return value is a string with the floating point number.
3832 */
3833
PreRandom(UBYTE * s)3834 UBYTE *PreRandom(UBYTE *s)
3835 {
3836 GETIDENTITY
3837 UBYTE *mode,*mins = 0,*maxs = 0, *outval;
3838 float num;
3839 double minval, maxval, value = 0;
3840 int linlog = -1;
3841 mode = s;
3842 while ( FG.cTable[*s] <= 1 ) s++;
3843 if ( *s == ',' ) { *s = 0; s++; }
3844 mins = s;
3845 while ( *s && *s != ',' ) s++;
3846 if ( *s == ',' ) { *s = 0; s++; }
3847 maxs = s;
3848 while ( *s && *s != ',' ) s++;
3849 if ( *s || *maxs == 0 || *mins == 0 ) {
3850 MesPrint("@Illegal arguments in macro RANDOM_");
3851 Terminate(-1);
3852 }
3853 if ( StrICmp(mode,(UBYTE *)"lin") == 0 ) {
3854 linlog = 0;
3855 }
3856 else if ( StrICmp(mode,(UBYTE *)"log") == 0 ) {
3857 linlog = 1;
3858 }
3859 else {
3860 MesPrint("@Illegal mode argument in macro RANDOM_");
3861 Terminate(-1);
3862 }
3863
3864 sscanf((char *)mins,"%f",&num); minval = num;
3865 sscanf((char *)maxs,"%f",&num); maxval = num;
3866
3867 /*
3868 * Note on ParFORM: we should use the same random number on all the
3869 * processes in the complication phase. The random number is generated
3870 * on the master and broadcast to the other processes.
3871 */
3872 {
3873 UWORD x;
3874 double xx;
3875 #ifdef WITHMPI
3876 x = 0;
3877 if ( PF.me == MASTER ) {
3878 x = wranf(BHEAD0);
3879 }
3880 x = (UWORD)PF_BroadcastNumber((LONG)x);
3881 #else
3882 x = wranf(BHEAD0);
3883 #endif
3884 xx = x/pow(2.0,(double)(BITSINWORD-1));
3885 if ( linlog == 0 ) {
3886 value = minval + (maxval-minval)*xx;
3887 }
3888 else if ( linlog == 1 ) {
3889 value = minval * pow(maxval/minval,xx);
3890 }
3891 }
3892
3893 outval = (UBYTE *)Malloc1(64,"PreRandom");
3894 if ( ABS(value) < 0.00001 || ABS(value) > 1000000. ) {
3895 sprintf((char *)outval,"%e",value);
3896 }
3897 else if ( ABS(value) < 0.0001 ) { sprintf((char *)outval,"%10f",value); }
3898 else if ( ABS(value) < 0.001 ) { sprintf((char *)outval,"%9f",value); }
3899 else if ( ABS(value) < 0.01 ) { sprintf((char *)outval,"%8f",value); }
3900 else if ( ABS(value) < 0.1 ) { sprintf((char *)outval,"%7f",value); }
3901 else if ( ABS(value) < 1. ) { sprintf((char *)outval,"%6f",value); }
3902 else if ( ABS(value) < 10. ) { sprintf((char *)outval,"%5f",value); }
3903 else if ( ABS(value) < 100. ) { sprintf((char *)outval,"%4f",value); }
3904 else if ( ABS(value) < 1000. ) { sprintf((char *)outval,"%3f",value); }
3905 else if ( ABS(value) < 10000. ) { sprintf((char *)outval,"%2f",value); }
3906 else { sprintf((char *)outval,"%1f",value); }
3907 return(outval);
3908 }
3909
3910 /*
3911 #] PreRandom :
3912 #] Functions :
3913 */
3914