• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

form-dev / form / 15701338753

17 Jun 2025 07:49AM UTC coverage: 50.382% (-0.004%) from 50.386%
15701338753

Pull #662

github

web-flow
Merge f1f68c050 into 207386593
Pull Request #662: Cleanup: change VOID into void

178 of 245 new or added lines in 34 files covered. (72.65%)

2 existing lines in 1 file now uncovered.

41784 of 82935 relevant lines covered (50.38%)

2640008.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.75
/sources/reken.c
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-2023 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

62
void Pack(UWORD *a, WORD *na, UWORD *b, WORD nb)
19,741,844✔
63
{
64
        WORD c, sgn = 1, i;
19,741,844✔
65
        UWORD *to,*from;
19,741,844✔
66
        if ( (c = *na) == 0 ) {
19,741,844✔
67
                MLOCK(ErrorMessageLock);
×
68
                MesPrint("Caught a zero in Pack");
×
69
                MUNLOCK(ErrorMessageLock);
×
70
                return;
×
71
        }
72
        if ( nb == 0 ) {
19,741,844✔
73
                MLOCK(ErrorMessageLock);
×
74
                MesPrint("Division by zero in Pack");
×
75
                MUNLOCK(ErrorMessageLock);
×
76
                return;
×
77
        }
78
        if ( *na < 0 ) { sgn = -sgn; c = -c; }
19,741,844✔
79
        if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
19,741,844✔
80
        *na = MaX(c,nb);
19,741,844✔
81
        to = a + c;
19,741,844✔
82
        i = *na - c;
19,741,844✔
83
        while ( --i >= 0 ) *to++ = 0;
32,015,495✔
84
        i = *na - nb;
19,741,844✔
85
        from = b;
19,741,844✔
86
        NCOPY(to,from,nb);
52,057,281✔
87
        while ( --i >= 0 ) *to++ = 0;
21,395,484✔
88
        if ( sgn < 0 ) *na = -*na;
19,741,844✔
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

100
void UnPack(UWORD *a, WORD na, WORD *denom, WORD *numer)
22,646,219✔
101
{
102
        UWORD *pos;
22,646,219✔
103
        WORD i, sgn = na;
22,646,219✔
104
        if ( na < 0 ) { na = -na; }
22,646,219✔
105
        i = na;
22,646,219✔
106
        if ( i > 1 ) {                /* Find the respective leading words */
22,646,219✔
107
                a += i;
3,453,858✔
108
                a--;
3,453,858✔
109
                pos = a + i;
3,453,858✔
110
                while ( !(*a) ) { i--; a--; }
15,871,575✔
111
                while ( !(*pos) ) { na--; pos--; }
5,749,060✔
112
        }
113
        *denom = na;
22,646,219✔
114
        if ( sgn < 0 ) i = -i;
22,646,219✔
115
        *numer = i;
22,646,219✔
116
}
22,646,219✔
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

126
WORD Mully(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
34,300,907✔
127
{
128
        GETBIDENTITY
129
        UWORD *d, *e;
34,300,907✔
130
        WORD i, sgn = 1;
34,300,907✔
131
        WORD nd, ne, adenom, anumer;
34,300,907✔
132
        if ( !nb ) { *na = 0; return(0); }
34,300,907✔
133
        else if ( *b == 1 ) {
34,300,907✔
134
                if ( nb == 1 ) return(0);
18,386,022✔
135
                else if ( nb == -1 ) { *na = -*na; return(0); }
246✔
136
        }
137
        if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
15,914,885✔
138
        if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
15,914,885✔
139
        UnPack(a,*na,&adenom,&anumer);
15,914,885✔
140
        d = NumberMalloc("Mully"); e = NumberMalloc("Mully");
15,914,885✔
141
        for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
32,327,824✔
142
        ne = nb;
15,914,885✔
143
        if ( Simplify(BHEAD a+*na,&adenom,e,&ne) ) goto MullyEr;
15,914,885✔
144
        if ( MulLong(a,anumer,e,ne,d,&nd) ) goto MullyEr;
15,914,885✔
145
        b = a+*na;
15,914,885✔
146
        for ( i = 0; i < *na; i++ ) { e[i] = *b++; }
32,324,140✔
147
        ne = adenom;
15,914,885✔
148
        *na = nd;
15,914,885✔
149
        b = d;
15,914,885✔
150
        *na = nd;
15,914,885✔
151
        for ( i = 0; i < *na; i++ ) { a[i] = *b++; }
31,835,035✔
152
        Pack(a,na,e,ne);
15,914,885✔
153
        if ( sgn < 0 ) *na = -*na;
15,914,885✔
154
        NumberFree(d,"Mully"); NumberFree(e,"Mully");
15,914,885✔
155
        return(0);
15,914,885✔
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

172
WORD Divvy(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
22,650✔
173
{
174
        GETBIDENTITY
175
        UWORD *d,*e;
22,650✔
176
        WORD i, sgn = 1;
22,650✔
177
        WORD nd, ne, adenom, anumer;
22,650✔
178
        if ( !nb ) {
22,650✔
179
                MLOCK(ErrorMessageLock);
×
180
                MesPrint("Division by zero in Divvy");
×
181
                MUNLOCK(ErrorMessageLock);
×
182
                return(-1);
×
183
        }
184
        d = NumberMalloc("Divvy"); e = NumberMalloc("Divvy");
22,650✔
185
        if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
22,650✔
186
        if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
22,650✔
187
        UnPack(a,*na,&adenom,&anumer);
22,650✔
188
        for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
67,950✔
189
        ne = nb;
22,650✔
190
        if ( Simplify(BHEAD a,&anumer,e,&ne) ) goto DivvyEr;
22,650✔
191
        if ( MulLong(a+*na,adenom,e,ne,d,&nd) ) goto DivvyEr;
22,650✔
192
        *na = anumer;
22,650✔
193
        Pack(a,na,d,nd);
22,650✔
194
        if ( sgn < 0 ) *na = -*na;
22,650✔
195
        NumberFree(d,"Divvy"); NumberFree(e,"Divvy");
22,650✔
196
        return(0);
22,650✔
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

210
WORD AddRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
17,301,313✔
211
{
212
        GETBIDENTITY
213
        UWORD *d, *e, *f, *g;
17,301,313✔
214
        WORD nd, ne, nf, ng, adenom, anumer, bdenom, bnumer;
17,301,313✔
215
        if ( !na ) {
17,301,313✔
216
                WORD i;
6,270✔
217
                *nc = nb;
6,270✔
218
                if ( nb < 0 ) nb = -nb;
6,270✔
219
                nb *= 2;
6,270✔
220
                for ( i = 0; i < nb; i++ ) *c++ = *b++;
6,424✔
221
                return(0);
222
        }
223
        else if ( !nb ) {
17,295,043✔
224
                WORD i;
1,800✔
225
                *nc = na;
1,800✔
226
                if ( na < 0 ) na = -na;
1,800✔
227
                na *= 2;
1,800✔
228
                for ( i = 0; i < na; i++ ) *c++ = *a++;
5,400✔
229
                return(0);
230
        }
231
        else if ( b[1] == 1 && a[1] == 1 ) {
17,293,243✔
232
                if ( na == 1 ) {
16,614,641✔
233
                        if ( nb == 1 ) {
11,827,311✔
234
                                *c = *a + *b;
8,451,013✔
235
                                c[1] = 1;
8,451,013✔
236
                                if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = 2; }
8,451,013✔
237
                                else { *nc = 1; }
8,451,003✔
238
                                return(0);
8,451,013✔
239
                        }
240
                        else if ( nb == -1 ) {
3,376,298✔
241
                                if ( *b > *a ) { 
3,376,292✔
242
                                        *c = *b - *a; *nc = -1;
727,339✔
243
                                }
244
                                else if ( *b < *a ) {
2,648,953✔
245
                                        *c = *a - *b; *nc = 1;
1,089,004✔
246
                                }
247
                                else *nc = 0;
1,559,949✔
248
                                c[1] = 1;
3,376,292✔
249
                                return(0);
3,376,292✔
250
                        }
251
                }
252
                else if ( na == -1 ){
4,787,330✔
253
                        if ( nb == -1 ) {
4,753,838✔
254
                                c[1] = 1;
1,486,637✔
255
                                *c = *a + *b;
1,486,637✔
256
                                if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = -2; }
1,486,637✔
257
                                else { *nc = -1; }
1,486,637✔
258
                                return(0);
1,486,637✔
259
                        }
260
                        else if ( nb == 1 ) {
3,267,201✔
261
                                if ( *b > *a ) {
3,267,177✔
262
                                        *c = *b - *a; *nc = 1;
776,060✔
263
                                }
264
                                else if ( *b < *a ) {
2,491,117✔
265
                                        *c = *a - *b; *nc = -1;
1,000,749✔
266
                                }
267
                                else *nc = 0;
1,490,368✔
268
                                c[1] = 1;
3,267,177✔
269
                                return(0);
3,267,177✔
270
                        }
271
                }
272
        }
273
        UnPack(a,na,&adenom,&anumer);
712,124✔
274
        UnPack(b,nb,&bdenom,&bnumer);
712,124✔
275
        if ( na < 0 ) na = -na;
712,124✔
276
        if ( nb < 0 ) nb = -nb;
712,124✔
277
        if ( na == 1 && nb == 1 ) {
712,124✔
278
                RLONG t1, t2, t3;
235,530✔
279
                t3 = ((RLONG)a[1])*((RLONG)b[1]);
235,530✔
280
                t1 = ((RLONG)a[0])*((RLONG)b[1]);
235,530✔
281
                t2 = ((RLONG)a[1])*((RLONG)b[0]);
235,530✔
282
                if ( ( anumer > 0 && bnumer > 0 ) || ( anumer < 0 && bnumer < 0 ) ) {
235,530✔
283
                        if ( ( t1 = t1 + t2 ) < t2 ) {
16,224✔
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;
16,224✔
291
                                if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
16,224✔
292
                                else *nc = 1;
11,850✔
293
                        }
294
                }
295
                else {
296
                        if ( t1 == t2 ) { *nc = 0; return(0); }
219,306✔
297
                        if ( t1 > t2 ) {
846✔
298
                                t1 -= t2;
390✔
299
                        }
300
                        else {
301
                                t1 = t2 - t1;
456✔
302
                                anumer = -anumer;
456✔
303
                        }
304
                        c[0] = (UWORD)t1;
846✔
305
                        if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
846✔
306
                        else *nc = 1;
738✔
307
                }
308
                if ( anumer < 0 ) *nc = -*nc;
17,070✔
309
                d = NumberMalloc("AddRat");
17,070✔
310
                d[0] = (UWORD)t3;
17,070✔
311
                if ( ( d[1] = (UWORD)(t3 >> BITSINWORD) ) != 0 ) nd = 2;
17,070✔
312
                else nd = 1;
15,018✔
313
                if ( Simplify(BHEAD c,nc,d,&nd) ) goto AddRer1;
17,070✔
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");
476,594✔
325
                f = NumberMalloc("AddRat"); g = NumberMalloc("AddRat");
476,594✔
326
                if ( GcdLong(BHEAD a+na,adenom,b+nb,bdenom,d,&nd) ) goto AddRer;
476,594✔
327
                if ( *d == 1 && nd == 1 ) nd = 0;
476,594✔
328
                if ( nd ) {
476,594✔
329
                        if ( DivLong(a+na,adenom,d,nd,e,&ne,c,nc) ) goto AddRer;
260,396✔
330
                        if ( DivLong(b+nb,bdenom,d,nd,f,&nf,c,nc) ) goto AddRer;
260,396✔
331
                        if ( MulLong(a,anumer,f,nf,c,nc) ) goto AddRer;
260,396✔
332
                        if ( MulLong(b,bnumer,e,ne,g,&ng) ) goto AddRer;
260,396✔
333
                }
334
                else {
335
                        if ( MulLong(a+na,adenom,b,bnumer,c,nc) ) goto AddRer;
216,198✔
336
                        if ( MulLong(b+nb,bdenom,a,anumer,g,&ng) ) goto AddRer;
216,198✔
337
                }
338
                if ( AddLong(c,*nc,g,ng,c,nc) ) goto AddRer;
476,594✔
339
                if ( !*nc ) {
476,594✔
340
                        NumberFree(g,"AddRat"); NumberFree(f,"AddRat");
321,398✔
341
                        NumberFree(e,"AddRat"); NumberFree(d,"AddRat");
321,398✔
342
                        return(0);
321,398✔
343
                }
344
                if ( nd ) {
155,196✔
345
                        if ( Simplify(BHEAD c,nc,d,&nd) ) goto AddRer;
128,576✔
346
                        if ( MulLong(e,ne,d,nd,g,&ng) ) goto AddRer;
128,576✔
347
                        if ( MulLong(g,ng,f,nf,d,&nd) ) goto AddRer;
128,576✔
348
                }
349
                else {
350
                        if ( MulLong(a+na,adenom,b+nb,bdenom,d,&nd) ) goto AddRer;
26,620✔
351
                }
352
                NumberFree(g,"AddRat"); NumberFree(f,"AddRat"); NumberFree(e,"AddRat");
155,196✔
353
        }
354
        Pack(c,nc,d,nd);
172,266✔
355
        NumberFree(d,"AddRat");
172,266✔
356
        return(0);
172,266✔
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

378
WORD MulRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
44,238,996✔
379
{
380
        WORD i;
44,238,996✔
381
        WORD sgn = 1;
44,238,996✔
382
        if ( *b == 1 && b[1] == 1 ) {
44,238,996✔
383
                if ( nb == 1 ) {
1,151,970✔
384
                        *nc = na;
766,134✔
385
                        i = ABS(na); i *= 2;
766,134✔
386
                        while ( --i >= 0 ) *c++ = *a++;
2,298,402✔
387
                        return(0);
388
                }
389
                else if ( nb == -1 ) {
385,836✔
390
                        *nc = - na;
385,824✔
391
                        i = ABS(na); i *= 2;
385,824✔
392
                        while ( --i >= 0 ) *c++ = *a++;
1,157,472✔
393
                        return(0);
394
                }
395
        }
396
        if ( *a == 1 && a[1] == 1 ) {
43,087,038✔
397
                if ( na == 1 ) {
21,642,320✔
398
                        *nc = nb;
17,719,964✔
399
                        i = ABS(nb); i *= 2;
17,719,964✔
400
                        while ( --i >= 0 ) *c++ = *b++;
54,165,228✔
401
                        return(0);
402
                }
403
                else if ( na == -1 ) {
3,922,356✔
404
                        *nc = - nb;
3,922,356✔
405
                        i = ABS(nb); i *= 2;
3,922,356✔
406
                        while ( --i >= 0 ) *c++ = *b++;
12,111,828✔
407
                        return(0);
408
                }
409
        }
410
        if ( na < 0 ) { na = -na; sgn = -sgn; }
21,444,718✔
411
        if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
21,444,718✔
412
        if ( !na || !nb ) { *nc = 0; return(0); }
21,444,718✔
413
        if ( na != 1 || nb != 1 ) {
21,444,718✔
414
                GETBIDENTITY
415
                UWORD *xd,*xe, *xf,*xg;
2,441,568✔
416
                WORD dden, dnumr, eden, enumr;
2,441,568✔
417
                UnPack(a,na,&dden,&dnumr);
2,441,568✔
418
                UnPack(b,nb,&eden,&enumr);
2,441,568✔
419
                xd = NumberMalloc("MulRat"); xf = NumberMalloc("MulRat");
2,441,568✔
420
                for ( i = 0; i < dnumr; i++ ) xd[i] = a[i];
6,189,522✔
421
                a += na;
2,441,568✔
422
                for ( i = 0; i < dden; i++ ) xf[i] = a[i];
16,610,382✔
423
                xe = NumberMalloc("MulRat"); xg = NumberMalloc("MulRat");
2,441,568✔
424
                for ( i = 0; i < enumr; i++ ) xe[i] = b[i];
4,894,188✔
425
                b += nb;
2,441,568✔
426
                for ( i = 0; i < eden; i++ ) xg[i] = b[i];
5,000,160✔
427
                if ( Simplify(BHEAD xd,&dnumr,xg,&eden) ||
4,883,136✔
428
                     Simplify(BHEAD xe,&enumr,xf,&dden) ||
4,883,136✔
429
                     MulLong(xd,dnumr,xe,enumr,c,nc) ||
4,883,136✔
430
                     MulLong(xf,dden,xg,eden,xd,&dnumr) ) {
2,441,568✔
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);
2,441,568✔
438
                NumberFree(xd,"MulRat"); NumberFree(xe,"MulRat"); NumberFree(xf,"MulRat"); NumberFree(xg,"MulRat");
2,441,568✔
439
        }
440
        else {
441
                UWORD y;
19,003,150✔
442
                UWORD a0,a1,b0,b1;
19,003,150✔
443
                RLONG xx;
19,003,150✔
444
                y = a[0]; b1=b[1];
19,003,150✔
445
                do { a0 = y % b1; y = b1; } while ( ( b1 = a0 ) != 0 );
20,694,076✔
446
                if ( y != 1 ) {
19,003,150✔
447
                        a0 = a[0] / y;
2,343,090✔
448
                        b1 = b[1] / y;
2,343,090✔
449
                }
450
                else {
451
                        a0 = a[0];
452
                        b1 = b[1];
453
                }
454
                y=b[0]; a1=a[1];
19,003,150✔
455
                do { b0 = y % a1; y = a1; } while ( ( a1 = b0 ) != 0 );
19,428,096✔
456
                if ( y != 1 ) {
19,003,150✔
457
                        a1 = a[1] / y;
1,582,872✔
458
                        b0 = b[0] / y;
1,582,872✔
459
                }
460
                else {
461
                        a1 = a[1];
462
                        b0 = b[0];
463
                }
464
                xx = ((RLONG)a0)*b0;
19,003,150✔
465
                if ( xx & AWORDMASK ) {
19,003,150✔
466
                        *nc = 2;
132,482✔
467
                        c[0] = (UWORD)xx;
132,482✔
468
                        c[1] = (UWORD)(xx >> BITSINWORD);
132,482✔
469
                        xx = ((RLONG)a1)*b1;
132,482✔
470
                        c[2] = (UWORD)xx;
132,482✔
471
                        c[3] = (UWORD)(xx >> BITSINWORD);
132,482✔
472
                }
473
                else {
474
                        c[0] = (UWORD)xx;
18,870,668✔
475
                        xx = ((RLONG)a1)*b1;
18,870,668✔
476
                        if ( xx & AWORDMASK ) {
18,870,668✔
477
                                c[1] = 0;
30,036✔
478
                                c[2] = (UWORD)xx;
30,036✔
479
                                c[3] = (UWORD)(xx >> BITSINWORD);
30,036✔
480
                                *nc = 2;
30,036✔
481
                        }
482
                        else {
483
                                c[1] = (UWORD)xx;
18,840,632✔
484
                                *nc = 1;
18,840,632✔
485
                        }
486
                }
487
        }
488
        if ( sgn < 0 ) *nc = -*nc;
21,444,718✔
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

500
WORD DivRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
4,578✔
501
{
502
        GETBIDENTITY
503
        WORD i, j;
4,578✔
504
        UWORD *xd,*xe,xx;
4,578✔
505
        if ( !nb ) {
4,578✔
506
                MLOCK(ErrorMessageLock);
×
507
                MesPrint("Rational division by zero");
×
508
                MUNLOCK(ErrorMessageLock);
×
509
                return(-1);
×
510
        }
511
        j = i = (nb >= 0)? nb: -nb;
4,578✔
512
        xd = b; xe = b + i;
4,578✔
513
        do { xx = *xd; *xd++ = *xe; *xe++ = xx; } while ( --j > 0 );
9,888✔
514
        j = MulRat(BHEAD a,na,b,nb,c,nc);
4,578✔
515
        xd = b; xe = b + i;
4,578✔
516
        do { xx = *xd; *xd++ = *xe; *xe++ = xx; } while ( --i > 0 );
9,888✔
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
        divides both by it. A possible sign is put in a. This is
526
        the simplification of the fraction a/b.
527

528
*/
529

530
WORD Simplify(PHEAD UWORD *a, WORD *na, UWORD *b, WORD *nb)
23,036,322✔
531
{
532
        GETBIDENTITY
533
        UWORD *x1,*x2,*x3;
23,036,322✔
534
        UWORD *x4;
23,036,322✔
535
        WORD n1,n2,n3,n4,sgn = 1;
23,036,322✔
536
        WORD i;
23,036,322✔
537
        UWORD *Siscrat5, *Siscrat6, *Siscrat7, *Siscrat8;
23,036,322✔
538
        if ( *na < 0 ) { *na = -*na; sgn = -sgn; }
23,036,322✔
539
        if ( *nb < 0 ) { *nb = -*nb; sgn = -sgn; }
23,036,322✔
540
        Siscrat5 = NumberMalloc("Simplify"); Siscrat6 = NumberMalloc("Simplify"); 
23,036,322✔
541
        Siscrat7 = NumberMalloc("Simplify"); Siscrat8 = NumberMalloc("Simplify"); 
23,036,322✔
542
        x1 = Siscrat8; x2 = Siscrat7;
23,036,322✔
543
        if ( *nb == 1 ) {
23,036,322✔
544
                x3 = Siscrat6;
20,902,094✔
545
                if ( DivLong(a,*na,b,*nb,x1,&n1,x2,&n2) ) goto SimpErr;
20,902,094✔
546
                if ( !n2 ) {
20,902,094✔
547
                        for ( i = 0; i < n1; i++ ) *a++ = *x1++;
7,654,104✔
548
                        *na = n1;
3,376,946✔
549
                        *b = 1;
3,376,946✔
550
                }
551
                else {
552
                        UWORD y1, y2, y3;
17,525,148✔
553
                        y2 = *b;
17,525,148✔
554
                        y3 = *x2;
17,525,148✔
555
                        do { y1 = y2 % y3; y2 = y3; } while ( ( y3 = y1 ) != 0 );
19,080,701✔
556
                        if ( ( *x2 = y2 ) != 1 ) {
17,525,148✔
557
                                *b /= y2;
210,635✔
558
                                if ( DivLong(a,*na,x2,(WORD)1,x1,&n1,x3,&n3) ) goto SimpErr;
210,635✔
559
                                for ( i = 0; i < n1; i++ ) *a++ = *x1++;
475,189✔
560
                                *na = n1;
210,635✔
561
                        }
562
                }
563
        }
564
#ifdef NEWTRICK
565
        else if ( *na >= GCDMAX && *nb >= GCDMAX ) {
2,134,228✔
566
                n1 = i = *na; x3 = a;
405,118✔
567
                NCOPY(x1,x3,i);
2,154,883✔
568
                x3 = b; n2 = i = *nb;
405,118✔
569
                NCOPY(x2,x3,i);
2,114,854✔
570
                x4 = Siscrat5;
405,118✔
571
                x2 = Siscrat6;
405,118✔
572
                x3 = Siscrat7;
405,118✔
573
                if ( GcdLong(BHEAD Siscrat8,n1,Siscrat7,n2,x2,&n3) ) goto SimpErr;
405,118✔
574
                n2 = n3;
405,118✔
575
                if ( *x2 != 1 || n2 != 1 ) {
405,118✔
576
                        DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
373,974✔
577
                        *na = i = n1;
373,974✔
578
                        NCOPY(a,x1,i);
886,512✔
579
                        DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
373,974✔
580
                        *nb = i = n3;
373,974✔
581
                        NCOPY(b,x3,i);
817,583✔
582
                }
583
        }
584
#endif
585
        else {
586
                x4 = Siscrat5;
1,729,110✔
587
                n1 = i = *na; x3 = a;
1,729,110✔
588
                NCOPY(x1,x3,i);
3,925,044✔
589
                x3 = b; n2 = i = *nb;
1,729,110✔
590
                NCOPY(x2,x3,i);
15,557,559✔
591
                x1 = Siscrat8; x2 = Siscrat7; x3 = Siscrat6;
2,124,083✔
592
                for(;;){
2,124,083✔
593
                        if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto SimpErr;
2,124,083✔
594
                        if ( !n3 ) break;
2,124,083✔
595
                        if ( n2 == 1 ) {
2,006,312✔
596
                                while ( ( *x1 = (*x2) % (*x3) ) != 0 ) { *x2 = *x3; *x3 = *x1; }
464,146✔
597
                                *x2 = *x3;
38,214✔
598
                                break;
38,214✔
599
                        }
600
                        if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto SimpErr;
1,968,098✔
601
                        if ( !n1 ) { x2 = x3; n2 = n3; x3 = Siscrat7; break; }
1,968,098✔
602
                        if ( n3 == 1 ) {
553,478✔
603
                                while ( ( *x2 = (*x3) % (*x1) ) != 0 ) { *x3 = *x1; *x1 = *x2; }
716,348✔
604
                                *x2 = *x1;
85,771✔
605
                                n2 = 1;
85,771✔
606
                                break;
85,771✔
607
                        }
608
                        if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto SimpErr;
467,707✔
609
                        if ( !n2 ) { x2 = x1; n2 = n1; x1 = Siscrat7; break; }
467,707✔
610
                        if ( n1 == 1 ) {
455,359✔
611
                                while ( ( *x3 = (*x1) % (*x2) ) != 0 ) { *x1 = *x2; *x2 = *x3; }
595,895✔
612
                                break;
613
                        }
614
                }
615
                if ( *x2 != 1 || n2 != 1 ) {
1,729,110✔
616
                        DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
258,267✔
617
                        *na = i = n1;
258,267✔
618
                        NCOPY(a,x1,i);
631,826✔
619
                        DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
258,267✔
620
                        *nb = i = n3;
258,267✔
621
                        NCOPY(b,x3,i);
564,084✔
622
                }
623
        }
624
        if ( sgn < 0 ) *na = -*na;
23,036,322✔
625
        NumberFree(Siscrat5,"Simplify"); NumberFree(Siscrat6,"Simplify");
23,036,322✔
626
        NumberFree(Siscrat7,"Simplify"); NumberFree(Siscrat8,"Simplify");
23,036,322✔
627
        return(0);
23,036,322✔
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

647
WORD AccumGCD(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
61,242✔
648
{
649
        GETBIDENTITY
650
        WORD nna,nnb,numa,numb,dena,denb,numc,denc;
61,242✔
651
        UWORD *GCDbuffer = NumberMalloc("AccumGCD");
61,242✔
652
        int i;
61,242✔
653
        nna = *na; if ( nna < 0 ) nna = -nna; nna = (nna-1)/2;
61,242✔
654
        nnb = nb;  if ( nnb < 0 ) nnb = -nnb; nnb = (nnb-1)/2;
61,242✔
655
        UnPack(a,nna,&dena,&numa);
61,242✔
656
        UnPack(b,nnb,&denb,&numb);
61,242✔
657
        if ( GcdLong(BHEAD a,numa,b,numb,GCDbuffer,&numc) ) goto AccErr;
61,242✔
658
        numa = numc;
61,242✔
659
        for ( i = 0; i < numa; i++ ) a[i] = GCDbuffer[i];
122,484✔
660
        if ( GcdLong(BHEAD a+nna,dena,b+nnb,denb,GCDbuffer,&denc) ) goto AccErr;
61,242✔
661
        dena = denc;
61,242✔
662
        for ( i = 0; i < dena; i++ ) a[i+nna] = GCDbuffer[i];
122,484✔
663
        Pack(a,&numa,a+nna,dena);
61,242✔
664
        *na = INCLENG(numa);
61,242✔
665
        NumberFree(GCDbuffer,"AccumGCD");
61,242✔
666
        return(0);
61,242✔
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

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

705
WORD AddLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
163,931,154✔
706
{
707
        WORD sgn, res;
163,931,154✔
708
        if ( na < 0 ) {
163,931,154✔
709
                if ( nb < 0 ) {
61,879,784✔
710
                        if ( AddPLon(a,-na,b,-nb,c,nc) ) return(-1);
32,816,894✔
711
                        *nc = -*nc;
32,816,894✔
712
                        return(0);
32,816,894✔
713
                }
714
                else {
715
                        na = -na;
29,062,890✔
716
                        sgn = -1;
29,062,890✔
717
                }
718
        }
719
        else {
720
                if ( nb < 0 ) {
102,051,370✔
721
                        nb = -nb;
17,333,425✔
722
                        sgn = 1;
17,333,425✔
723
                }
724
                else { return( AddPLon(a,na,b,nb,c,nc) ); }
84,717,945✔
725
        }
726
        if ( ( res = BigLong(a,na,b,nb) ) > 0 ) {
46,396,315✔
727
                SubPLon(a,na,b,nb,c,nc);
15,663,745✔
728
                if ( sgn < 0 ) *nc = -*nc;
15,663,745✔
729
        }
730
        else if ( res < 0 ) {
30,732,570✔
731
                SubPLon(b,nb,a,na,c,nc);
23,170,400✔
732
                if ( sgn > 0 ) *nc = -*nc;
23,170,400✔
733
        }
734
        else {
735
                *nc = 0;
7,562,170✔
736
                *c = 0;
7,562,170✔
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

750
WORD AddPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
117,534,839✔
751
{
752
        UWORD carry = 0, e, nd = 0;
117,534,839✔
753
        while ( na && nb ) {
1,012,233,444✔
754
                e = *a;
894,698,605✔
755
                *c = e + *b + carry;
894,698,605✔
756
                if ( carry ) {
894,698,605✔
757
                        if ( e < *c ) carry = 0;
384,302,408✔
758
                }
759
                else {
760
                        if ( e > *c ) carry = 1;
510,396,197✔
761
                }
762
                a++; b++; c++; nd++; na--; nb--;
894,698,605✔
763
        }
764
        while ( na ) {
299,262,919✔
765
                if ( carry ) {
181,728,080✔
766
                        *c = *a++ + carry;
1,036,854✔
767
                        if ( *c++ ) carry = 0;
1,036,854✔
768
                }
769
                else *c++ = *a++;
180,691,226✔
770
                nd++; na--;
181,728,080✔
771
        }
772
        while ( nb ) {
142,489,193✔
773
                if ( carry ) {
24,954,354✔
774
                        *c = *b++ + carry;
2,108,479✔
775
                        if ( *c++ ) carry = 0;
2,108,479✔
776
                }
777
                else *c++ = *b++;
22,845,875✔
778
                nd++; nb--;
24,954,354✔
779
        }
780
        if ( carry ) {
117,534,839✔
781
                nd++;
652,807✔
782
                if ( nd > (UWORD)AM.MaxTal ) {
652,807✔
783
                        MLOCK(ErrorMessageLock);
×
784
                        MesPrint("Overflow in addition");
×
785
                        MUNLOCK(ErrorMessageLock);
×
786
                        return(-1);
×
787
                }
788
                *c++ = carry;
652,807✔
789
        }
790
        *nc = nd;
117,534,839✔
791
        return(0);
117,534,839✔
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

803
void SubPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
47,864,522✔
804
{
805
        UWORD borrow = 0, e, nd = 0;
47,864,522✔
806
        while ( nb ) {
218,056,682✔
807
                e = *a;
170,192,160✔
808
                if ( borrow ) {
170,192,160✔
809
                        *c = e - *b - borrow;
63,074,070✔
810
                        if ( *c < e ) borrow = 0;
63,074,070✔
811
                }
812
                else {
813
                        *c = e - *b;
107,118,090✔
814
                        if ( *c > e ) borrow = 1;
107,118,090✔
815
                }
816
                a++; b++; c++; na--; nb--; nd++;
170,192,160✔
817
        }
818
        while ( na ) {
92,333,936✔
819
                if ( borrow ) {
44,469,414✔
820
                        if ( *a ) { *c++ = *a++ - 1; borrow = 0; }
2,180,839✔
821
                        else { *c++ = (UWORD)(-1); a++; }
147,055✔
822
                }
823
                else *c++ = *a++;
42,288,575✔
824
                na--; nd++;
44,469,414✔
825
        }
826
        while ( nd && !*--c ) { nd--; }
55,594,260✔
827
        *nc = (WORD)nd;
47,864,522✔
828
}
47,864,522✔
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

841
WORD MulLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
225,599,100✔
842
{
843
        WORD sgn = 1;
225,599,100✔
844
        UWORD i, *ic, *ia;
225,599,100✔
845
        RLONG t, bb;
225,599,100✔
846
        if ( !na || !nb ) { *nc = 0; return(0); }
225,599,100✔
847
        if ( na < 0 ) { na = -na; sgn = -sgn; }
225,427,200✔
848
        if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
225,427,200✔
849
        *nc = i = na + nb;
225,427,200✔
850
        if ( i > (UWORD)(AM.MaxTal+1) ) goto MulLov;
225,427,200✔
851
        ic = c;
225,427,200✔
852
/*
853
          #[ GMP stuff :
854
*/
855
#ifdef WITHGMP
856
        if (na > 3 && nb > 3) {
225,427,200✔
857
/*                mp_limb_t res;  */
858
                UWORD *to, *from;
36,117,769✔
859
                int j;
36,117,769✔
860
                GETIDENTITY
24,011,099✔
861
                UWORD *DLscrat9 = NumberMalloc("MulLong"), *DLscratA = NumberMalloc("MulLong"), *DLscratB = NumberMalloc("MulLong");
36,117,769✔
862
#if ( GMPSPREAD != 1 )
863
                if ( na & 1 ) {
36,117,769✔
864
                        from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
168,856,154✔
865
                        a[na++] = 0;
16,790,893✔
866
                        ++*nc;
16,790,893✔
867
                } else
868
#endif
869
                if ( (LONG)a & (sizeof(mp_limb_t)-1) ) {
19,326,876✔
870
                        from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
92,272,584✔
871
                }
872

873
#if ( GMPSPREAD != 1 )
874
                if ( nb & 1 ) {
36,117,769✔
875
                        from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
232,476,188✔
876
                        b[nb++] = 0;
16,951,214✔
877
                        ++*nc;
16,951,214✔
878
                } else
879
#endif
880
                if ( (LONG)b & (sizeof(mp_limb_t)-1) ) {
19,166,555✔
881
                        from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
119,128,377✔
882
                }
883

884
                if ( ( *nc > (WORD)i ) || ( (LONG)c & (LONG)(sizeof(mp_limb_t)-1) ) ) {
36,117,769✔
885
                        ic = DLscratB;
25,802,609✔
886
                }
887
                if ( na < nb ) {
36,117,769✔
888
                        /* res = */
889
                        mpn_mul((mp_ptr)ic, (mp_srcptr)b, nb/GMPSPREAD, (mp_srcptr)a, na/GMPSPREAD);
16,081,466✔
890
                } else {
891
                        /* res = */
892
                        mpn_mul((mp_ptr)ic, (mp_srcptr)a, na/GMPSPREAD, (mp_srcptr)b, nb/GMPSPREAD);
20,036,303✔
893
                }
894
                while ( ic[i-1] == 0 ) i--;
55,073,350✔
895
                *nc = i;
36,117,769✔
896
/*
897
                if ( res == 0 ) *nc -= GMPSPREAD;
898
                else if ( res <= WORDMASK ) --*nc;
899
*/
900
                if ( ic != c ) {
36,117,769✔
901
                        j = *nc; NCOPY(c, ic, j);
562,231,642✔
902
                }
903
                if ( sgn < 0 ) *nc = -(*nc);
36,117,769✔
904
                NumberFree(DLscrat9,"MulLong"); NumberFree(DLscratA,"MulLong"); NumberFree(DLscratB,"MulLong");
36,117,769✔
905
                return(0);
36,117,769✔
906
        }
907
#endif
908
/*
909
          #] GMP stuff : 
910
*/
911
        do { *ic++ = 0; } while ( --i > 0 );
793,400,056✔
912
        do {
409,321,224✔
913
                ia = a;
409,321,224✔
914
                ic = c++;
409,321,224✔
915
                t = 0;
409,321,224✔
916
                i = na;
409,321,224✔
917
                bb = (RLONG)(*b++);
409,321,224✔
918
                do {
907,630,461✔
919
                        t = (*ia++) * bb + t + *ic;
907,630,461✔
920
                        *ic++ = (WORD)t;
907,630,461✔
921
                        t >>= BITSINWORD;                /* should actually be a swap */
907,630,461✔
922
                } while ( --i > 0 );
907,630,461✔
923
                if ( t ) *ic = (UWORD)t;
409,321,224✔
924
        } while ( --nb > 0 );
409,321,224✔
925
        if ( !*ic ) (*nc)--;
189,309,431✔
926
        if ( *nc > AM.MaxTal ) goto MulLov;
189,309,431✔
927
        if ( sgn < 0 ) *nc = -(*nc);
189,309,431✔
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

944
WORD BigLong(UWORD *a, WORD na, UWORD *b, WORD nb)
144,879,973✔
945
{
946
        a += na;
144,879,973✔
947
        b += nb;
144,879,973✔
948
        while ( na && !*--a ) na--;
144,879,973✔
949
        while ( nb && !*--b ) nb--;
144,879,973✔
950
        if ( nb < na ) return(1);
144,879,973✔
951
        if ( nb > na ) return(-1);
131,626,340✔
952
        while ( --na >= 0 ) {
154,770,874✔
953
                if ( *a > *b ) return(1);
119,680,843✔
954
                else if ( *b > *a ) return(-1);
86,152,496✔
955
                a--; b--;
41,156,211✔
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

972
WORD DivLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c,
77,628,442✔
973
             WORD *nc, UWORD *d, WORD *nd)
974
{
975
        WORD sgna = 1, sgnb = 1, ne, nf, ng, nh;
77,628,442✔
976
        WORD i, ni;
77,628,442✔
977
        UWORD *w1, *w2;
77,628,442✔
978
        RLONG t, v;
77,628,442✔
979
        UWORD *e, *f, *ff, *g, norm, estim;
77,628,442✔
980
#ifdef WITHGMP
981
        UWORD *DLscrat9, *DLscratA, *DLscratB, *DLscratC;
77,628,442✔
982
#endif
983
        RLONG esthelp;
77,628,442✔
984
        if ( !nb ) {
77,628,442✔
985
                MLOCK(ErrorMessageLock);
×
986
                MesPrint("Division by zero");
×
987
                MUNLOCK(ErrorMessageLock);
×
988
                return(-1);
×
989
        }
990
        if ( !na ) { *nc = *nd = 0; return(0); }
77,628,442✔
991
        if ( na < 0 ) { sgna = -sgna; na = -na; }
77,628,442✔
992
        if ( nb < 0 ) { sgnb = -sgnb; nb = -nb; }
77,628,442✔
993
        if ( na < nb ) {
77,628,442✔
994
                for ( i = 0; i < na; i++ ) *d++ = *a++;
2,898,027✔
995
                *nd = na;
1,442,610✔
996
                *nc = 0;
1,442,610✔
997
        }
998
        else if ( nb == na && ( i = BigLong(b,nb,a,na) ) >= 0 ) {
76,185,832✔
999
                if ( i > 0 ) {
42,815,427✔
1000
                        for ( i = 0; i < na; i++ ) *d++ = *a++;
35,014,795✔
1001
                        *nd = na;
17,266,896✔
1002
                        *nc = 0;
17,266,896✔
1003
                }
1004
                else {
1005
                        *c = 1;
25,548,531✔
1006
                        *nc = 1;
25,548,531✔
1007
                        *nd = 0;
25,548,531✔
1008
                }
1009
        }
1010
        else if ( nb == 1 ) {
33,370,405✔
1011
                if ( *b == 1 ) {
28,771,128✔
1012
                        for ( i = 0; i < na; i++ ) *c++ = *a++;
219,611,242✔
1013
                        *nc = na;
18,801,043✔
1014
                        *nd = 0;
18,801,043✔
1015
                }
1016
                else {
1017
                        w1 = a+na;
9,970,085✔
1018
                        *nc = ni = na;
9,970,085✔
1019
                        *nd = 1;
9,970,085✔
1020
                        w2 = c+ni;
9,970,085✔
1021
                        v = (RLONG)(*b);
9,970,085✔
1022
                        t = (RLONG)(*--w1);
9,970,085✔
1023
                        while ( --ni >= 0 ) {
48,605,149✔
1024
                                *--w2 = t / v;
38,635,064✔
1025
                                t -= v * (*w2);
38,635,064✔
1026
                                if ( ni ) {
38,635,064✔
1027
                                        t <<= BITSINWORD;
28,664,979✔
1028
                                        t += *--w1;
28,664,979✔
1029
                                }
1030
                        }
1031
                        if ( ( *d = (UWORD)t ) == 0 ) *nd = 0;
9,970,085✔
1032
                        if ( !*(c+na-1) ) (*nc)--;
9,970,085✔
1033
                }
1034
        }
1035
        else {
1036
                GETIDENTITY
3,066,963✔
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 ) {
4,599,277✔
1048
                  UWORD *ic, *id, *to, *from;
1,835,467✔
1049
                  int j = na - nb;
1,835,467✔
1050
                  DLscrat9 = NumberMalloc("DivLong"); DLscratA = NumberMalloc("DivLong");
1,835,467✔
1051
                  DLscratB = NumberMalloc("DivLong"); DLscratC = NumberMalloc("DivLong");
1,835,467✔
1052

1053
#if ( GMPSPREAD != 1 )
1054
                  if ( na & 1 ) {
1,835,467✔
1055
                        from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
9,217,532✔
1056
                        a[na++] = 0;
1,013,830✔
1057
                  } else
1058
#endif
1059
                  if ( (LONG)a & (sizeof(mp_limb_t)-1) ) {
821,637✔
1060
                        from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1,286,641✔
1061
                  }
1062

1063
#if ( GMPSPREAD != 1 )
1064
                  if ( nb & 1 ) {
1,835,467✔
1065
                        from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
10,572,380✔
1066
                        b[nb++] = 0;
1,739,665✔
1067
                  } else
1068
#endif
1069
                  if ( ( (LONG)b & (sizeof(mp_limb_t)-1) ) != 0 ) {
95,802✔
1070
                        from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
994✔
1071
                  }
1072
#if ( GMPSPREAD != 1 )
1073
/*
1074
          Not recognizing this case was a nasty and extremely rare bug.
1075
          In the case that c == a and na is odd and nc == na and b
1076
          still needs to be used, the least significant UWORD of b got
1077
          overwritten by zero. (22-mar-2023)
1078
*/
1079
                  ic = DLscratB; id = DLscratC;
1,835,467✔
1080
#else
1081
                  if ( ( (LONG)c & (sizeof(mp_limb_t)-1) ) != 0 ) ic = DLscratB;
1082
                  else                                            ic = c;
1083

1084
                  if ( ( (LONG)d & (sizeof(mp_limb_t)-1) ) != 0 ) id = DLscratC;
1085
                  else                                            id = d;
1086
#endif
1087
                  mpn_tdiv_qr((mp_limb_t *)ic,(mp_limb_t *)id,(mp_size_t)0,
1,835,467✔
1088
                        (const mp_limb_t *)a,(mp_size_t)(na/GMPSPREAD),
1,835,467✔
1089
                        (const mp_limb_t *)b,(mp_size_t)(nb/GMPSPREAD));
1,835,467✔
1090
                  while ( j >= 0 && ic[j] == 0 ) j--;
2,465,229✔
1091
                  j++; *nc = j;
1,835,467✔
1092
                  if ( c != ic ) { NCOPY(c,ic,j); }
8,851,833✔
1093
                  j = nb-1;
1,835,467✔
1094
                  while ( j >= 0 && id[j] == 0 ) j--;
5,218,043✔
1095
                  j++; *nd = j;
1,835,467✔
1096
                  if ( d != id ) { NCOPY(d,id,j); }
9,786,613✔
1097
                  if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1,835,467✔
1098
                  if ( sgnb < 0 ) { *nc = -(*nc); }
1,835,467✔
1099
                  NumberFree(DLscrat9,"DivLong"); NumberFree(DLscratA,"DivLong");
1,835,467✔
1100
                  NumberFree(DLscratB,"DivLong"); NumberFree(DLscratC,"DivLong");
1,835,467✔
1101
                  return(0);
1,835,467✔
1102
                }
1103
#endif
1104
/*
1105
                 #] GMP stuff : 
1106
*/
1107
                /* Start with normalization operation */
1108
 
1109
                e = NumberMalloc("DivLong"); f = NumberMalloc("DivLong"); g = NumberMalloc("DivLong");
2,763,810✔
1110
                if ( b[nb-1] == (FULLMAX-1) ) norm = 1;
2,763,810✔
1111
                else {
1112
                        norm = (UWORD)(((ULONG)FULLMAX) / (ULONG)((b[nb-1]+1L)));
2,763,810✔
1113
                }
1114
                f[na] = 0;
2,763,810✔
1115
                if ( MulLong(b,nb,&norm,1,e,&ne) ||
5,527,620✔
1116
                     MulLong(a,na,&norm,1,f,&nf) ) {
2,763,810✔
1117
                        NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
×
1118
                        return(-1);
×
1119
                }
1120
                if ( BigLong(f+nf-ne,ne,e,ne) >= 0 ) {
2,763,810✔
1121
                        SubPLon(f+nf-ne,ne,e,ne,f+nf-ne,&nh);
49,253✔
1122
                        w1 = c + (nf-ne);
49,253✔
1123
                        *nc = nf-ne+1;
49,253✔
1124
                }
1125
                else {
1126
                        nh = ne;
2,714,557✔
1127
                        *nc = nf-ne;
2,714,557✔
1128
                        w1 = 0;
2,714,557✔
1129
                }
1130
                w2 = c; i = *nc; do { *w2++ = 0; } while ( --i > 0 );
3,910,203✔
1131
                nf = na;
2,763,810✔
1132
                ni = nf-ne;
2,763,810✔
1133
                esthelp = (RLONG)(e[ne-1]) + 1L;
2,763,810✔
1134
                while ( nf >= ne ) {
7,441,454✔
1135
                        if ( (WORD)esthelp == 0 ) {
4,677,644✔
1136
                                estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])>>BITSINWORD);
50✔
1137
                        }
1138
                        else {
1139
                                estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])/esthelp);
4,677,594✔
1140
                        }
1141
                        /* This estimate may be up to two too small */
1142
                        if ( estim ) {
4,677,644✔
1143
                                MulLong(e,ne,&estim,1,g,&ng);
3,860,533✔
1144
                                nh = ne + 1; if ( !f[ni+ne] ) nh--;
3,860,533✔
1145
                                SubPLon(f+ni,nh,g,ng,f+ni,&nh);
3,860,533✔
1146
                        }
1147
                        else {
1148
                                w2 = f+ni+ne; nh = ne+1;
817,111✔
1149
                                while ( ( nh > 0 ) && !*w2 ) { nh--; w2--; }
1,640,584✔
1150
                        }
1151
                        if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
4,677,644✔
1152
                                estim++;
1,296,843✔
1153
                                SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1,296,843✔
1154
                                if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1,296,843✔
1155
                                        estim++;
4,446✔
1156
                                        SubPLon(f+ni,nh,e,ne,f+ni,&nh);
4,446✔
1157
                                        if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
4,446✔
1158
                                                MLOCK(ErrorMessageLock);
×
1159
                                                MesPrint("Problems in DivLong");
×
1160
                                                AO.OutSkip = 3;
×
1161
                                                FiniLine();
×
1162
                                                i = na;
×
1163
                                                while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)"  "); }
×
1164
                                                FiniLine();
×
1165
                                                i = nb;
×
1166
                                                while ( --i >= 0 ) { TalToLine((UWORD)(*b++)); TokenToLine((UBYTE *)"  "); }
×
1167
                                                AO.OutSkip = 0;
×
1168
                                                FiniLine();
×
1169
                                                MUNLOCK(ErrorMessageLock);
×
1170
                                                NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
×
1171
                                                return(-1);
×
1172
                                        }
1173
                                }
1174
                        }
1175
                        c[ni] = estim;
4,677,644✔
1176
                        nf--;
4,677,644✔
1177
                        ni--;
4,677,644✔
1178
                }
1179
                if ( w1 ) *w1 = 1;
2,763,810✔
1180

1181
                /* Finish with the renormalization operation */
1182

1183
                if ( nh > 0 ) {
2,763,810✔
1184
                        if ( norm == 1 ) {
1,774,016✔
1185
                                *nd = i = nh; ff = f;
116,304✔
1186
                                NCOPY(d,ff,i);
349,105✔
1187
                        }
1188
                        else {
1189
                                w1 = f+nh;
1,657,712✔
1190
                                *nd = ni = nh;
1,657,712✔
1191
                                w2 = d+ni;
1,657,712✔
1192
                                v = norm;
1,657,712✔
1193
                                t = (RLONG)(*--w1);
1,657,712✔
1194
                                while ( --ni >= 0 ) {
5,026,456✔
1195
                                        *--w2 = t / v;
3,368,744✔
1196
                                        t -= v * (*w2);
3,368,744✔
1197
                                        if ( ni ) {
3,368,744✔
1198
                                                t <<= BITSINWORD;
1,711,032✔
1199
                                                t += *--w1;
1,711,032✔
1200
                                        }
1201
                                }
1202
                                if ( t ) {
1,657,712✔
1203
                                        MLOCK(ErrorMessageLock);
×
1204
                                        MesPrint("Error in DivLong");
×
1205
                                        MUNLOCK(ErrorMessageLock);
×
1206
                                        NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
×
1207
                                        return(-1);
×
1208
                                }
1209
                                if ( !*(d+nh-1) ) (*nd)--;
1,657,712✔
1210
                        }
1211
                }
1212
                else { *nd = 0; }
989,794✔
1213
                NumberFree(e,"DivLong"); NumberFree(f,"DivLong"); NumberFree(g,"DivLong");
2,763,810✔
1214
        }
1215
        if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
75,792,975✔
1216
        if ( sgnb < 0 ) { *nc = -(*nc); }
75,792,975✔
1217
        return(0);
1218
}
1219

1220
/*
1221
                 #] DivLong : 
1222
                 #[ RaisPow :                WORD RaisPow(a,na,b)
1223

1224
        Raises a to the power b. a is a Long integer and b >= 0.
1225
        The method that is used works with a bitdecomposition of b.
1226
*/
1227

1228
WORD RaisPow(PHEAD UWORD *a, WORD *na, UWORD b)
15,664,661✔
1229
{
1230
        GETBIDENTITY
1231
        WORD i, nu;
15,664,661✔
1232
        UWORD *it, *iu, c;
15,664,661✔
1233
        UWORD *is, *iss;
15,664,661✔
1234
        WORD ns, nt, nmod;
15,664,661✔
1235
        nmod = ABS(AN.ncmod);
15,664,661✔
1236
        if ( !*na || ( ( *na == 1 ) && ( *a == 1 ) ) ) return(0);
15,664,661✔
1237
        if ( !b ) {        *na=1; *a=1; return(0); }
15,607,359✔
1238
        is = NumberMalloc("RaisPow");
15,603,543✔
1239
        it = NumberMalloc("RaisPow");
15,603,543✔
1240
        for ( i = 0; i < ABS(*na); i++ ) is[i] = a[i];
31,207,086✔
1241
        ns = *na;
15,603,543✔
1242
        c = b;
15,603,543✔
1243
        for ( i = 0; i < BITSINWORD; i++ ) {
31,479,720✔
1244
                if ( !c ) break;
31,479,720✔
1245
                c /= 2;
15,876,177✔
1246
        }
1247
        i--;
15,603,543✔
1248
        c = 1 << i;
15,603,543✔
1249
        while ( --i >= 0 ) {
15,876,177✔
1250
                c /= 2;
272,634✔
1251
                if(MulLong(is,ns,is,ns,it,&nt)) goto RaisOvl;
272,634✔
1252
                if ( b & c ) {
272,634✔
1253
                        if ( MulLong(it,nt,a,*na,is,&ns) ) goto RaisOvl;
127,016✔
1254
                }
1255
                else {
1256
                        iu = is; is = it; it = iu;
145,618✔
1257
                        nu = ns; ns = nt; nt = nu;
145,618✔
1258
                }
1259
                if ( nmod != 0 ) {
272,634✔
1260
                        if ( DivLong(is,ns,(UWORD *)AC.cmod,nmod,it,&nt,is,&ns) ) goto RaisOvl;
×
1261
                }
1262
        }
1263
        if ( ( nmod != 0 ) && ( ( AC.modmode & POSNEG ) != 0 ) ) {
15,603,543✔
1264
                NormalModulus(is,&ns);
×
1265
        }
1266
        if ( ( *na = i = ns ) != 0 ) { iss = is; i=ABS(i); NCOPY(a,iss,i); }
31,755,556✔
1267
        NumberFree(is,"RaisPow"); NumberFree(it,"RaisPow");
15,603,543✔
1268
        return(0);
15,603,543✔
1269
RaisOvl:
×
1270
        MLOCK(ErrorMessageLock);
×
1271
        MesCall("RaisPow");
×
1272
        MUNLOCK(ErrorMessageLock);
×
1273
        NumberFree(is,"RaisPow"); NumberFree(it,"RaisPow");
×
1274
        SETERROR(-1)
×
1275
}
1276

1277
/*
1278
                 #] RaisPow : 
1279
                 #[ RaisPowCached :
1280
*/
1281

1282
/**  Computes power x^n and caches the value
1283
 *
1284
 *   Description
1285
 *   ===========
1286
 *   Calculates the power x^n and stores the results for caching
1287
 *   purposes. The pointer c (i.e., the pointer, and not what it
1288
 *   points to) is overwritten. What it points to should not be
1289
 *   overwritten in the calling function.
1290
 *
1291
 *   Notes
1292
 *   =====
1293
 *   - Caching is done in AT.small_power[]. This array is extended
1294
 *     if necessary.
1295
 */
1296
void RaisPowCached (PHEAD WORD x, WORD n, UWORD **c, WORD *nc) {
262,446✔
1297

1298
        int i,j;
262,446✔
1299
        WORD new_small_power_maxx, new_small_power_maxn, ID;
262,446✔
1300
        WORD *new_small_power_n;
262,446✔
1301
        UWORD **new_small_power;
262,446✔
1302
        
1303
        /* check whether to extend the array */
1304
        if (x>=AT.small_power_maxx || n>=AT.small_power_maxn) {
262,446✔
1305

1306
                new_small_power_maxx = AT.small_power_maxx;
129✔
1307
                if (x>=AT.small_power_maxx)
129✔
1308
                        new_small_power_maxx = MaX(2*AT.small_power_maxx, x+1);
89✔
1309
                
1310
                new_small_power_maxn = AT.small_power_maxn;
129✔
1311
                if (n>=AT.small_power_maxn)
129✔
1312
                        new_small_power_maxn = MaX(2*AT.small_power_maxn, n+1);
110✔
1313
                
1314
                new_small_power_n = (WORD*) Malloc1(new_small_power_maxx*new_small_power_maxn*sizeof(WORD),"RaisPowCached");
129✔
1315
                new_small_power = (UWORD **) Malloc1(new_small_power_maxx*new_small_power_maxn*sizeof(UWORD *),"RaisPowCached");
129✔
1316

1317
                for (i=0; i<new_small_power_maxx * new_small_power_maxn; i++) {
24,030✔
1318
                        new_small_power_n[i] = 0;
23,772✔
1319
                        new_small_power  [i] = NULL;
23,772✔
1320
                }
1321
                                         
1322
                for (i=0; i<AT.small_power_maxx; i++) 
1,661✔
1323
                        for (j=0; j<AT.small_power_maxn; j++) {
9,632✔
1324
                                new_small_power_n[i*new_small_power_maxn+j] =        AT.small_power_n[i*AT.small_power_maxn+j];
8,100✔
1325
                                new_small_power  [i*new_small_power_maxn+j] = AT.small_power  [i*AT.small_power_maxn+j];
8,100✔
1326
                        }
1327

1328
                if (AT.small_power_n != NULL) {
129✔
1329
                        M_free(AT.small_power_n,"RaisPowCached");
59✔
1330
                        M_free(AT.small_power,"RaisPowCached");
59✔
1331
                }
1332

1333
                AT.small_power_maxx = new_small_power_maxx;
129✔
1334
                AT.small_power_maxn = new_small_power_maxn;
129✔
1335
                AT.small_power_n    = new_small_power_n;
129✔
1336
                AT.small_power      = new_small_power;                                
129✔
1337
        }
1338

1339
        /* check whether the results is already calculated */
1340
        ID = x * AT.small_power_maxn + n;
262,446✔
1341

1342
        if (AT.small_power[ID] == NULL) {
262,446✔
1343
#ifdef OLDRAISPOWCACHED
1344
        AT.small_power[ID] = NumberMalloc("RaisPowCached");
1345
        AT.small_power_n[ID] = 1;
1346
        AT.small_power[ID][0] = x;
1347
        RaisPow(BHEAD AT.small_power[ID],&AT.small_power_n[ID],n);
1348
#else
1349
        UWORD *c = NumberMalloc("RaisPowCached");
159✔
1350
        WORD i, k = 1;
159✔
1351
                c[0] = x;
159✔
1352
        RaisPow(BHEAD c,&k,n);
159✔
1353
/*
1354
        And now get the proper amount.
1355
*/
1356
        if ( AT.InNumMem < k ) {    /* We should start a new buffer */
159✔
1357
            AT.InNumMem = 5*AM.MaxTal;
70✔
1358
            AT.NumMem = (UWORD *)Malloc1(AT.InNumMem*sizeof(UWORD),"RaisPowCached");
70✔
1359
/*
1360
                        MesPrint("  Got an extra %l UWORDS in RaisPowCached",AT.InNumMem);
1361
*/
1362
        }
1363
        for ( i = 0; i < k; i++ ) AT.NumMem[i] = c[i];
373✔
1364
        AT.small_power[ID] = AT.NumMem;
159✔
1365
        AT.small_power_n[ID] = k;
159✔
1366
        AT.NumMem += k;
159✔
1367
        AT.InNumMem -= k;
159✔
1368
        NumberFree(c,"RaisPowCached");
159✔
1369
#endif
1370
        }
1371

1372
        /* return the result */
1373
        *c  = AT.small_power[ID];
262,446✔
1374
        *nc = AT.small_power_n[ID];
262,446✔
1375
}
262,446✔
1376

1377
/*
1378
                 #] RaisPowCached : 
1379
                 #[ RaisPowMod :
1380
                
1381
   Computes the power x^n mod m
1382
 */
1383
WORD RaisPowMod (WORD x, WORD n, WORD m) {
14,105,731✔
1384
        LONG y=1, z=x;
14,105,731✔
1385
        while (n) {
43,852,706✔
1386
                if (n&1) { y*=z; y%=m; }
29,746,975✔
1387
                z*=z; z%=m;
29,746,975✔
1388
                n /= 2;
29,746,975✔
1389
        }
1390
        return (WORD)y;
14,105,731✔
1391
}
1392

1393
/*
1394
          #] RaisPowMod : 
1395
                 #[ NormalModulus :  int NormalModulus(UWORD *a,WORD *na)
1396
*/
1397
/**
1398
 *        Brings a modular representation in the range -p/2 to +p/2
1399
 *        The return value tells whether anything was done.
1400
 *        Routine made in the general modulus revamp of July 2008 (JV).
1401
 */
1402

1403
int NormalModulus(UWORD *a,WORD *na)
×
1404
{
1405
        WORD n;
×
1406
        if ( AC.halfmod == 0 ) {
×
1407
          LOCK(AC.halfmodlock);
×
1408
          if ( AC.halfmod == 0 ) {
×
1409
                UWORD two[1],remain[1];
×
1410
                WORD dummy;
×
1411
                two[0] = 2;
×
1412
                AC.halfmod = (UWORD *)Malloc1((ABS(AC.ncmod))*sizeof(UWORD),"halfmod");
×
1413
                DivLong((UWORD *)AC.cmod,(ABS(AC.ncmod)),two,1
×
1414
                                ,(UWORD *)AC.halfmod,&(AC.nhalfmod),remain,&dummy);
1415
          }
1416
          UNLOCK(AC.halfmodlock);
×
1417
        }
1418
        n = ABS(*na);
×
1419
        if ( BigLong(a,n,AC.halfmod,AC.nhalfmod) > 0 ) {
×
1420
                SubPLon((UWORD *)AC.cmod,(ABS(AC.ncmod)),a,n,a,&n);
×
1421
                if ( *na > 0 ) { *na = -n; }
×
1422
                else { *na = n; }
×
1423
                return(1);
×
1424
        }
1425
        return(0);
1426
}
1427

1428
/*
1429
                 #] NormalModulus : 
1430
                 #[ MakeInverses :
1431
*/
1432
/**
1433
 *        Makes a table of inverses in modular calculus
1434
 *        The modulus is in AC.cmod and AC.ncmod
1435
 *        One should notice that the table of inverses can only be made if
1436
 *        the modulus fits inside a single FORM word. Otherwise the table lookup
1437
 *        becomes too difficult and the table too long.
1438
 */
1439

NEW
1440
int MakeInverses(void)
×
1441
{
1442
        WORD n = AC.cmod[0], i, inv2;
×
1443
        if ( AC.ncmod != 1 ) return(1);
×
1444
        if ( AC.modinverses == 0 ) {
×
1445
          LOCK(AC.halfmodlock);
×
1446
          if ( AC.modinverses == 0 ) {
×
1447
                AC.modinverses = (UWORD *)Malloc1(n*sizeof(UWORD),"modinverses");
×
1448
                AC.modinverses[0] = 0;
×
1449
                AC.modinverses[1] = 1;
×
1450
                for ( i = 2; i < n; i++ ) {
×
1451
                        if ( GetModInverses(i,n,
×
1452
                                                (WORD *)(&(AC.modinverses[i])),&inv2) ) {
×
1453
                                SETERROR(-1)
×
1454
                        }
1455
                }
1456
          }
1457
          UNLOCK(AC.halfmodlock);
1458
        }
1459
        return(0);
1460
}
1461

1462
/*
1463
                 #] MakeInverses : 
1464
                 #[ GetModInverses :
1465
*/
1466
/**
1467
 *        Input m1 and m2, which are relative prime.
1468
 *        determines a*m1+b*m2 = 1  (and 1 is the gcd of m1 and m2)
1469
 *        then a*m1 = 1 mod m2 and hence im1 = a.
1470
 *        and  b*m2 = 1 mod m1 and hence im2 = b.
1471
 *        Set m1 = 0*m1+1*m2 = a1*m1+b1*m2
1472
 *            m2 = 1*m1+0*m2 = a2*m1+b2*m2
1473
 *        If everything is OK, the return value is zero
1474
 */
1475

1476
int GetModInverses(WORD m1, WORD m2, WORD *im1, WORD *im2)
5,927,497✔
1477
{
1478
        WORD a1, a2, a3;
5,927,497✔
1479
        WORD b1, b2, b3;
5,927,497✔
1480
        WORD x = m1, y, c, d = m2;
5,927,497✔
1481
        if ( x < 1 || d <= 1 ) goto somethingwrong;
5,927,497✔
1482
        a1 = 0; a2 = 1;
1483
        b1 = 1; b2 = 0;
1484
        for(;;) {
172,538,351✔
1485
                c = d/x; y = d%x; /* a good compiler makes this faster than y=d-c*x */
89,232,924✔
1486
                if ( y == 0 ) break;
89,232,924✔
1487
                a3 = a1-c*a2; a1 = a2; a2 = a3;
83,305,427✔
1488
                b3 = b1-c*b2; b1 = b2; b2 = b3;
83,305,427✔
1489
                d = x; x = y;
83,305,427✔
1490
        }
1491
        if ( x != 1 ) goto somethingwrong;
5,927,497✔
1492
        if ( a2 < 0 ) a2 += m2;
5,927,497✔
1493
        if ( b2 < 0 ) b2 += m1;
5,927,497✔
1494
        if (im1!=NULL) *im1 = a2;
5,927,497✔
1495
        if (im2!=NULL) *im2 = b2;
5,927,497✔
1496
        return(0);
1497
somethingwrong:
×
1498
        MLOCK(ErrorMessageLock);
×
1499
        MesPrint("Error trying to determine inverses in GetModInverses");
×
1500
        MUNLOCK(ErrorMessageLock);
×
1501
        return(-1);
×
1502
}
1503
/*
1504
                 #] GetModInverses : 
1505
                 #[ GetLongModInverses :
1506
*/
1507

1508
int GetLongModInverses(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *ia, WORD *nia, UWORD *ib, WORD *nib) {
60,636✔
1509

1510
        UWORD *s, *t, *sa, *sb, *ta, *tb, *x, *y, *swap1;
60,636✔
1511
        WORD ns, nt, nsa, nsb, nta, ntb, nx, ny, swap2;
60,636✔
1512
                 
1513
        s = NumberMalloc("GetLongModInverses");
60,636✔
1514
        ns = na;
60,636✔
1515
        WCOPY(s, a, ABS(ns));
121,272✔
1516

1517
        t = NumberMalloc("GetLongModInverses");
60,636✔
1518
        nt = nb;
60,636✔
1519
        WCOPY(t, b, ABS(nt));
131,064✔
1520

1521
        sa = NumberMalloc("GetLongModInverses");
60,636✔
1522
        nsa = 1;
60,636✔
1523
        sa[0] = 1;
60,636✔
1524

1525
        sb = NumberMalloc("GetLongModInverses");
60,636✔
1526
        nsb = 0;
60,636✔
1527

1528
        ta = NumberMalloc("GetLongModInverses");
60,636✔
1529
        nta = 0;
60,636✔
1530

1531
        tb = NumberMalloc("GetLongModInverses");
60,636✔
1532
        ntb = 1;
60,636✔
1533
        tb[0] = 1;
60,636✔
1534

1535
        x = NumberMalloc("GetLongModInverses");
60,636✔
1536
        y = NumberMalloc("GetLongModInverses");
60,636✔
1537

1538
        while (nt != 0) {
239,736✔
1539
                DivLong(s,ns,t,nt,x,&nx,y,&ny);
179,100✔
1540
                swap1=s; s=y; y=swap1;
179,100✔
1541
                ns=ny;
179,100✔
1542
                MulLong(x,nx,ta,nta,y,&ny);
179,100✔
1543
                AddLong(sa,nsa,y,-ny,sa,&nsa);
179,100✔
1544
                MulLong(x,nx,tb,ntb,y,&ny);
179,100✔
1545
                AddLong(sb,nsb,y,-ny,sb,&nsb);
179,100✔
1546

1547
                swap1=s; s=t; t=swap1;
179,100✔
1548
                swap2=ns; ns=nt; nt=swap2;
179,100✔
1549
                swap1=sa; sa=ta; ta=swap1;
179,100✔
1550
                swap2=nsa; nsa=nta; nta=swap2;
179,100✔
1551
                swap1=sb; sb=tb; tb=swap1;
179,100✔
1552
                swap2=nsb; nsb=ntb; ntb=swap2;
179,100✔
1553
        }
1554

1555
        if (ia!=NULL) {
60,636✔
1556
                *nia = nsa*ns;
60,636✔
1557
                WCOPY(ia,sa,ABS(*nia));
121,272✔
1558
        }
1559

1560
        if (ib!=NULL) {
60,636✔
1561
                *nib = nsb*ns;
12✔
1562
                WCOPY(ib,sb,ABS(*nib));
24✔
1563
        }
1564
        
1565
        NumberFree(s,"GetLongModInverses");
60,636✔
1566
        NumberFree(t,"GetLongModInverses");
60,636✔
1567
        NumberFree(sa,"GetLongModInverses");
60,636✔
1568
        NumberFree(sb,"GetLongModInverses");
60,636✔
1569
        NumberFree(ta,"GetLongModInverses");
60,636✔
1570
        NumberFree(tb,"GetLongModInverses");
60,636✔
1571
        NumberFree(x,"GetLongModInverses");
60,636✔
1572
        NumberFree(y,"GetLongModInverses");
60,636✔
1573

1574
        return 0;
60,636✔
1575
}
1576

1577
/*
1578
                 #] GetLongModInverses : 
1579
                 #[ Product :                WORD Product(a,na,b)
1580

1581
        Multiplies the Long number in a with the WORD b.
1582

1583
*/
1584

1585
WORD Product(UWORD *a, WORD *na, WORD b)
24,225✔
1586
{
1587
        WORD i, sgn = 1;
24,225✔
1588
        RLONG t, u;
24,225✔
1589
        if ( *na < 0 ) { *na = -(*na); sgn = -sgn; }
24,225✔
1590
        if ( b < 0 ) { b = -b; sgn = -sgn; }
24,225✔
1591
        t = 0;
24,225✔
1592
        u = (RLONG)b;
24,225✔
1593
        for ( i = 0; i < *na; i++ ) {
49,026✔
1594
                t += *a * u;
24,801✔
1595
                *a++ = (UWORD)t;
24,801✔
1596
                t >>= BITSINWORD;
24,801✔
1597
        }
1598
        if ( t > 0 ) {
24,225✔
1599
                if ( ++(*na) > AM.MaxTal ) {
294✔
1600
                        MLOCK(ErrorMessageLock);
×
1601
                        MesPrint("Overflow in Product");
×
1602
                        MUNLOCK(ErrorMessageLock);
×
1603
                        return(-1);
×
1604
                }
1605
                *a = (UWORD)t;
294✔
1606
        }
1607
        if ( sgn < 0 ) *na = -(*na);
24,225✔
1608
        return(0);
1609
}
1610

1611
/*
1612
                 #] Product : 
1613
                 #[ Quotient :                UWORD Quotient(a,na,b)
1614

1615
                Routine divides the long number a by b with the assumption that
1616
                there is no remainder (like while computing binomials).
1617

1618
*/
1619

1620
UWORD Quotient(UWORD *a, WORD *na, WORD b)
×
1621
{
1622
        RLONG v, t;
×
1623
        WORD i, j, sgn = 1;
×
1624
        if ( ( i = *na ) < 0 ) { sgn = -1; i = -i; }
×
1625
        if ( b < 0 ) { b = -b; sgn = -sgn; }
×
1626
        if ( i == 1 ) {
×
1627
                if ( ( *a /= (UWORD)b ) == 0 ) *na = 0;
×
1628
                if ( sgn < 0 ) *na = -*na;
×
1629
                return(0);
×
1630
        }
1631
        a += i;
×
1632
        j = i;
×
1633
        v = (RLONG)b;
×
1634
        t = (RLONG)(*--a);
×
1635
        while ( --i >= 0 ) {
×
1636
                *a = t / v;
×
1637
                t -= v * (*a);
×
1638
                if ( i ) {
×
1639
                        t <<= BITSINWORD;
×
1640
                        t += *--a;
×
1641
                }
1642
        }
1643
        a += j - 1;
×
1644
        if ( !*a ) j--;
×
1645
        if ( sgn < 0 ) j = -j;
×
1646
        *na = j;
×
1647
        return(0);
×
1648
}
1649

1650
/*
1651
                 #] Quotient : 
1652
                 #[ Remain10 :                WORD Remain10(a,na)
1653

1654
        Routine divides a by 10 and gives the remainder as return value.
1655
        The value of a will be the quotient! a must be positive.
1656

1657
*/
1658

1659
WORD Remain10(UWORD *a, WORD *na)
30,246✔
1660
{
1661
        WORD i;
30,246✔
1662
        RLONG t, u;
30,246✔
1663
        UWORD *b;
30,246✔
1664
        i = *na;
30,246✔
1665
        t = 0;
30,246✔
1666
        b = a + i - 1;
30,246✔
1667
        while ( --i >= 0 ) {
66,732✔
1668
                t += *b;
36,486✔
1669
                *b-- = u = t / 10;
36,486✔
1670
                t -= u * 10;
36,486✔
1671
                if ( i > 0 ) t <<= BITSINWORD;
36,486✔
1672
        }
1673
        if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
30,246✔
1674
        return((WORD)t);
30,246✔
1675
}
1676

1677
/*
1678
                 #] Remain10 : 
1679
                 #[ Remain4 :                WORD Remain4(a,na)
1680

1681
        Routine divides a by 10000 and gives the remainder as return value.
1682
        The value of a will be the quotient! a must be positive.
1683

1684
*/
1685

1686
WORD Remain4(UWORD *a, WORD *na)
6,948✔
1687
{
1688
        WORD i;
6,948✔
1689
        RLONG t, u;
6,948✔
1690
        UWORD *b;
6,948✔
1691
        i = *na;
6,948✔
1692
        t = 0;
6,948✔
1693
        b = a + i - 1;
6,948✔
1694
        while ( --i >= 0 ) {
21,390✔
1695
                t += *b;
14,442✔
1696
                *b-- = u = t / 10000;
14,442✔
1697
                t -= u * 10000;
14,442✔
1698
                if ( i > 0 ) t <<= BITSINWORD;
14,442✔
1699
        }
1700
        if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
6,948✔
1701
        return((WORD)t);
6,948✔
1702
}
1703

1704
/*
1705
                 #] Remain4 : 
1706
                 #[ PrtLong :                void PrtLong(a,na,s)
1707

1708
        Puts the long number a in string s.
1709

1710
*/
1711

1712
void PrtLong(UWORD *a, WORD na, UBYTE *s)
3,474✔
1713
{
1714
        GETIDENTITY
2,316✔
1715
        WORD q, i;
3,474✔
1716
        UBYTE *sa, *sb;
3,474✔
1717
        UBYTE c;
3,474✔
1718
        UWORD *bb, *b;
3,474✔
1719

1720
        if ( na < 0 ) {
3,474✔
1721
                *s++ = '-';
×
1722
                na = -na;
×
1723
        }
1724

1725
        b = NumberMalloc("PrtLong");
3,474✔
1726
        bb = b;
3,474✔
1727
        i = na; while ( --i >= 0 ) *bb++ = *a++;
11,622✔
1728
        a = b;
3,474✔
1729
        if ( na > 2 ) {
3,474✔
1730
                sa = s;
1731
                do {
6,948✔
1732
                        q = Remain4(a,&na);
6,948✔
1733
                        *sa++ = (UBYTE)('0' + (q%10));
6,948✔
1734
                        q /= 10;
6,948✔
1735
                        *sa++ = (UBYTE)('0' + (q%10));
6,948✔
1736
                        q /= 10;
6,948✔
1737
                        *sa++ = (UBYTE)('0' + (q%10));
6,948✔
1738
                        q /= 10;
6,948✔
1739
                        *sa++ = (UBYTE)('0' + (q%10));
6,948✔
1740
                } while ( na );
6,948✔
1741
                while ( sa[-1] == '0' ) sa--;
2,700✔
1742
                sb = s;
966✔
1743
                s = sa;
966✔
1744
                sa--;
966✔
1745
                while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
13,710✔
1746
        }
1747
        else if ( na ) {
2,508✔
1748
                sa = s;
1749
                do {
30,246✔
1750
                        q = Remain10(a,&na);
30,246✔
1751
                        *sa++ = (UBYTE)('0' + q);
30,246✔
1752
                } while ( na );
30,246✔
1753
                sb = s;
1754
                s = sa;
17,034✔
1755
                sa--;
1756
                while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
17,034✔
1757
        }
1758
        else *s++ = '0';
×
1759
        *s = '\0';
3,474✔
1760
        NumberFree(b,"PrtLong");
3,474✔
1761
}
3,474✔
1762

1763
/*
1764
                 #] PrtLong : 
1765
                 #[ GetLong :                WORD GetLong(s,a,na)
1766

1767
        Reads a long number from a string.
1768
        The string is zero terminated and contains only digits!
1769

1770
        New algorithm: try to read 4 digits together before the result
1771
        is accumulated.
1772
*/
1773

1774
WORD GetLong(UBYTE *s, UWORD *a, WORD *na)
48✔
1775
{
1776
/*
1777
        UWORD digit;
1778
        *a = 0;
1779
        *na = 0;
1780
        while ( FG.cTable[*s] == 1 ) {
1781
                digit = *s++ - '0';
1782
                if ( *na && Product(a,na,(WORD)10) ) return(-1);
1783
                if ( digit && AddLong(a,*na,&digit,(WORD)1,a,na) ) return(-1);
1784
        }
1785
        return(0);
1786
*/
1787
        UWORD digit, x = 0, y = 0;
48✔
1788
        *a = 0;
48✔
1789
        *na = 0;
48✔
1790
        while ( FG.cTable[*s] == 1 ) {
60✔
1791
                x = *s++ - '0';
60✔
1792
                if ( FG.cTable[*s] != 1 ) { y = 10; break; }
60✔
1793
                x = 10*x + *s++ - '0';
18✔
1794
                if ( FG.cTable[*s] != 1 ) { y = 100; break; }
18✔
1795
                x = 10*x + *s++ - '0';
12✔
1796
                if ( FG.cTable[*s] != 1 ) { y = 1000; break; }
12✔
1797
                x = 10*x + *s++ - '0';
12✔
1798
                if ( *na && Product(a,na,(WORD)10000) ) return(-1);
12✔
1799
                if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
12✔
1800
                        return(-1);
1801
                y = 0;
1802
        }
1803
        if ( y ) {
48✔
1804
                if ( *na && Product(a,na,(WORD)y) ) return(-1);
48✔
1805
                if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
48✔
1806
                        return(-1);
×
1807
        }
1808
        return(0);
1809
}
1810

1811
/*
1812
                 #] GetLong : 
1813
                 #[ GCD :                        WORD GCD(a,na,b,nb,c,nc)
1814

1815
        Algorithm to compute the GCD of two long numbers.
1816
        See Knuth, sec 4.5.2 algorithm L.
1817

1818
        We assume that both numbers are positive
1819

1820
        NOTE!!!!!. NumberMalloc gets called and it may not be freed
1821
*/
1822

1823
#ifdef EXTRAGCD
1824

1825
#define Convert(ia,aa,naa) \
1826
        if ( (LONG)ia < 0 ) {        \
1827
                ia = (ULONG)(-(LONG)ia); \
1828
                aa[0] = ia;              \
1829
                if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = -2; \
1830
                else naa = -1;           \
1831
        }                            \
1832
        else if ( ia == 0 ) { aa[0] = 0; naa = 0; } \
1833
        else {                       \
1834
                aa[0] = ia;              \
1835
                if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = 2; \
1836
                else naa = 1;            \
1837
        }
1838

1839
void GCD(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1840
{
1841
        int ja = 0, jb = 0, j;
1842
        UWORD *r,*t;
1843
        UWORD *x1, *x2, *x3;
1844
        WORD nd,naa,nbb;
1845
        ULONG ia,ib,ic,id,u,v,w,q,T;
1846
        UWORD aa[2], bb[2];
1847
/*
1848
        First eliminate easy powers of 2^...
1849
*/
1850
        while ( a[0] == 0 ) { na--; ja++; a++; }
1851
        while ( b[0] == 0 ) { nb--; jb++; b++; }
1852
        if ( ja > jb ) ja = jb;
1853
        if ( ja > 0 ) {
1854
                j = ja;
1855
                do { *c++ = 0; } while ( --j > 0 );
1856
        }
1857
/*
1858
        Now arrange things such that a >= b
1859
*/
1860
        if ( na < nb ) {
1861
                jb = na; na = nb; nb = jb;
1862
exch:
1863
                r = a; a = b; b = r;
1864
        }
1865
        else if ( na == nb ) {
1866
                r = a+na;
1867
                t = b+nb;
1868
                j = na;
1869
                while ( --j >= 0 ) {
1870
                        if ( *--r > *--t ) break;
1871
                        if ( *r < *t ) goto exch;
1872
                }
1873
                if ( j < 0 ) {
1874
out:
1875
                        j = nb;
1876
                        NCOPY(c,b,j);
1877
                        *nc = nb+ja;
1878
                        return;
1879
                }
1880
        }
1881
/*
1882
        {
1883
                MLOCK(ErrorMessageLock);
1884
                MesPrint("Ordered input, ja = %d",(WORD)ja);
1885
                AO.OutSkip = 3;
1886
                FiniLine();
1887
                j = na; r = a;
1888
                while ( --j >= 0 ) { TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)"  "); }
1889
                FiniLine();
1890
                j = nb; r = b;
1891
                while ( --j >= 0 ) { TalToLine((UWORD)(*r++)); TokenToLine((UBYTE *)"  "); }
1892
                AO.OutSkip = 0;
1893
                FiniLine();
1894
                MUNLOCK(ErrorMessageLock);
1895
        }
1896
*/
1897
/*
1898
        We have now that A > B
1899
        The loop recognizes the case that na-nb >= 1
1900
        In that case we just have to divide!
1901
*/
1902
        r = x1 = NumberMalloc("GCD"); t = x2 = NumberMalloc("GCD"); x3 = NumberMalloc("GCD");
1903
        j = na;
1904
        NCOPY(r,a,j);
1905
        j = nb;
1906
        NCOPY(t,b,j);
1907

1908
        for(;;) {
1909

1910
                while ( na > nb ) {
1911
toobad:
1912
                        DivLong(x1,na,x2,nb,c,nc,x3,&nd);
1913
                        if ( nd == 0 ) { b = x2; goto out; }
1914
                        t = x1; x1 = x2; x2 = x3; x3 = t; na = nb; nb = nd;
1915
                        if ( na == 2 ) break;
1916
                }
1917
/*
1918
        Here we can use the shortcut.
1919
*/
1920
        if ( na == 2 ) {
1921
                v = x1[0] + ( ((ULONG)x1[1]) << BITSINWORD );
1922
                w = x2[0];
1923
                if ( nb == 2 ) w += ((ULONG)x2[1]) << BITSINWORD;
1924
#ifdef EXTRAGCD2
1925
                v = GCD2(v,w);
1926
#else
1927
                do { u = v%w; v = w; w = u; } while ( w );
1928
#endif
1929
                c[0] = (UWORD)v;
1930
                if ( ( c[1] = (UWORD)(v >> BITSINWORD) ) != 0 ) *nc = 2+ja;
1931
                else *nc = 1+ja;
1932
                NumberFree(x1,"GCD"); NumberFree(x2,"GCD"); NumberFree(x3,"GCD");
1933
                return;
1934
        }
1935
        if ( na == 1 ) {
1936
                UWORD ui, uj;
1937
                ui = x1[0]; uj = x2[0];
1938
#ifdef EXTRAGCD2
1939
                ui = (UWORD)GCD2((ULONG)ui,(ULONG)uj);
1940
#else
1941
                do { nd = ui%uj; ui = uj; uj = nd; } while ( nd );
1942
#endif
1943
                c[0] = ui;
1944
                *nc = 1 + ja;
1945
                NumberFree(x1,"GCD"); NumberFree(x2,"GCD"); NumberFree(x3,"GCD");
1946
                return;
1947
        }
1948
        ia = 1; ib = 0; ic = 0; id = 1;
1949
        u = ( ((ULONG)x1[na-1]) << BITSINWORD ) + x1[na-2];
1950
        v = ( ((ULONG)x2[nb-1]) << BITSINWORD ) + x2[nb-2];
1951

1952
        while ( v+ic != 0 && v+id != 0 &&
1953
                 ( q = (u+ia)/(v+ic) ) == (u+ib)/(v+id) ) {
1954
                T = ia-q*ic; ia = ic; ic = T;
1955
                T = ib-q*id; ib = id; id = T;
1956
                T = u - q*v; u = v; v = T;
1957
        }
1958
        if ( ib == 0 ) goto toobad;
1959
        Convert(ia,aa,naa);
1960
        Convert(ib,bb,nbb);
1961
        MulLong(x1,na,aa,naa,x3,&nd);
1962
        MulLong(x2,nb,bb,nbb,c,nc);
1963
        AddLong(x3,nd,c,*nc,c,nc);
1964
        Convert(ic,aa,naa);
1965
        Convert(id,bb,nbb);
1966
        MulLong(x1,na,aa,naa,x3,&nd);
1967
        t = c; na = j = *nc; r = x1;
1968
        NCOPY(r,t,j);
1969
        MulLong(x2,nb,bb,nbb,c,nc);
1970
        AddLong(x3,nd,c,*nc,x2,&nb);
1971
        }
1972
}
1973

1974
#endif
1975

1976
/*
1977
                 #] GCD : 
1978
                 #[ GcdLong :                WORD GcdLong(a,na,b,nb,c,nc)
1979

1980
        Returns the Greatest Common Divider of a and b in c.
1981
        If a and or b are zero an error message will be returned.
1982
        The answer is always positive.
1983
        In principle a and c can be the same.
1984
*/
1985

1986
#ifndef NEWTRICK
1987
/*
1988
          #[ Old Routine :
1989
*/
1990

1991
WORD GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1992
{
1993
        GETBIDENTITY
1994
        if ( !na || !nb ) {
1995
                if ( !na && !nb ) {
1996
                        MLOCK(ErrorMessageLock);
1997
                        MesPrint("Cannot take gcd");
1998
                        MUNLOCK(ErrorMessageLock);
1999
                        return(-1);
2000
                }
2001
                
2002
                if ( !na ) {
2003
                        *nc = abs(nb);
2004
                        NCOPY(c,b,*nc);
2005
                        *nc = abs(nb);
2006
                        return(0);
2007
                }
2008
                
2009
                *nc = abs(na);
2010
                NCOPY(c,a,*nc);
2011
                *nc = abs(na);
2012
                return(0);
2013
        }
2014
        if ( na < 0 ) na = -na;
2015
        if ( nb < 0 ) nb = -nb;
2016
        if ( na == 1 && nb == 1 ) {
2017
#ifdef EXTRAGCD2
2018
                *c = (UWORD)GCD2((ULONG)*a,(ULONG)*b);
2019
#else
2020
                UWORD x,y,z;
2021
                x = *a;
2022
                y = *b;
2023
                do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2024
                *c = x;
2025
#endif
2026
                *nc = 1;
2027
        }
2028
        else if ( na <= 2 && nb <= 2 ) {
2029
                RLONG lx,ly,lz;
2030
                if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2031
                else { lx = *a; }
2032
                if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2033
                else { ly = *b; }
2034
#ifdef LONGWORD
2035
#ifdef EXTRAGCD2
2036
                lx = GCD2(lx,ly);
2037
#else
2038
                do { lz = lx % ly; lx = ly; } while ( ( ly = lz ) != 0 );
2039
#endif
2040
#else
2041
          if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2042
                do {
2043
                        lz = lx % ly; lx = ly;
2044
                } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2045
                if ( ly ) {
2046
                        do { *c = ((UWORD)lx)%((UWORD)ly); lx = ly; } while ( ( ly = *c ) != 0 );
2047
                        *c = (UWORD)lx;
2048
                        *nc = 1;
2049
                }
2050
                else
2051
#endif
2052
                {
2053
                        *c++ = (UWORD)lx;
2054
                        if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2055
                        else *nc = 1;
2056
                }
2057
        }
2058
        else {
2059
#ifdef EXTRAGCD
2060
                GCD(a,na,b,nb,c,nc);
2061
#else
2062
#ifdef NEWGCD
2063
                UWORD *x3,*x1,*x2, *GLscrat7, *GLscrat8;
2064
                WORD n1,n2,n3,n4;
2065
                WORD i, j;
2066
                x1 = c; x3 = a; n1 = i = na;
2067
                NCOPY(x1,x3,i);
2068
                GLscrat7 = NumberMalloc("GcdLong"); GLscrat8 = NumberMalloc("GcdLong");
2069
                x2 = GLscrat8; x3 = b; n2 = i = nb;
2070
                NCOPY(x2,x3,i);
2071
                x1 = c; i = 0;
2072
                while ( x1[0] == 0 ) { i += BITSINWORD; x1++; n1--; }
2073
                while ( ( x1[0] & 1 ) == 0 ) { i++; SCHUIF(x1,n1) }
2074
                x2 = GLscrat8; j = 0;
2075
                while ( x2[0] == 0 ) { j += BITSINWORD; x2++; n2--; }
2076
                while ( ( x2[0] & 1 ) == 0 ) { j++; SCHUIF(x2,n2) }
2077
                if ( j > i ) j = i;                /* powers of two in GCD */
2078
                for(;;){
2079
                        if ( n1 > n2 ) {
2080
firstbig:
2081
                                SubPLon(x1,n1,x2,n2,x1,&n3);
2082
                                n1 = n3;
2083
                                if ( n1 == 0 ) {
2084
                                        x1 = c;
2085
                                        n1 = i = n2; NCOPY(x1,x2,i);
2086
                                        break;
2087
                                }
2088
                                while ( ( x1[0] & 1 ) == 0 ) SCHUIF(x1,n1)
2089
                                if ( n1 == 1 ) {
2090
                                        if ( DivLong(x2,n2,x1,n1,GLscrat7,&n3,x2,&n4) ) goto GcdErr;
2091
                                        n2 = n4;
2092
                                        if ( n2 == 0 ) {
2093
                                                i = n1; x2 = c; NCOPY(x2,x1,i);
2094
                                                break;
2095
                                        }
2096
#ifdef EXTRAGCD2
2097
                                        *c = (UWORD)GCD2((ULONG)x1[0],(ULONG)x2[0]);
2098
#else
2099
                                        {
2100
                                                UWORD x,y,z;
2101
                                                x = x1[0];
2102
                                                y = x2[0];
2103
                                                do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2104
                                                *c = x;
2105
                                        }
2106
#endif
2107
                                        n1 = 1;
2108
                                        break;
2109
                                }
2110
                        }
2111
                        else if ( n1 < n2 ) {
2112
lastbig:
2113
                                SubPLon(x2,n2,x1,n1,x2,&n3);
2114
                                n2 = n3;
2115
                                if ( n2 == 0 ) {
2116
                                        i = n1; x2 = c; NCOPY(x2,x1,i);
2117
                                        break;
2118
                                }
2119
                                while ( ( x2[0] & 1 ) == 0 ) SCHUIF(x2,n2)
2120
                                if ( n2 == 1 ) {
2121
                                        if ( DivLong(x1,n1,x2,n2,GLscrat7,&n3,x1,&n4) ) goto GcdErr;
2122
                                        n1 = n4;
2123
                                        if ( n1 == 0 ) {
2124
                                                x1 = c;
2125
                                                n1 = i = n2; NCOPY(x1,x2,i);
2126
                                                break;
2127
                                        }
2128
#ifdef EXTRAGCD2
2129
                                        *c = (UWORD)GCD2((ULONG)x2[0],(ULONG)x1[0]);
2130
#else
2131
                                        {
2132
                                                UWORD x,y,z;
2133
                                                x = x2[0];
2134
                                                y = x1[0];
2135
                                                do { z = x % y; x = y; } while ( ( y = z ) != 0 );
2136
                                                *c = x;
2137
                                        }
2138
#endif
2139
                                        n1 = 1;
2140
                                        break;
2141
                                }
2142
                        }
2143
                        else {
2144
                                for ( i = n1-1; i >= 0; i-- ) {
2145
                                        if ( x1[i] > x2[i] ) goto firstbig;
2146
                                        else if ( x1[i] < x2[i] ) goto lastbig;
2147
                                }
2148
                                i = n1; x2 = c; NCOPY(x2,x1,i);
2149
                                break;
2150
                        }
2151
                }
2152
/*
2153
                Now the GCD is in c but still needs j powers of 2.
2154
*/
2155
                x1 = c;
2156
                while ( j >= BITSINWORD ) {
2157
                        for ( i = n1; i > 0; i-- ) x1[i] = x1[i-1];
2158
                        x1[0] = 0; n1++;
2159
                        j -= BITSINWORD;
2160
                }
2161
                if ( j > 0 ) {
2162
                        ULONG a1,a2 = 0;
2163
                        for ( i = 0; i < n1; i++ ) {
2164
                                a1 = x1[i]; a1 <<= j;
2165
                                a2 += a1;
2166
                                x1[i] = a2;
2167
                                a2 >>= BITSINWORD;
2168
                        }
2169
                        if ( a2 != 0 ) {
2170
                                x1[n1++] = a2;
2171
                        }
2172
                }
2173
                *nc = n1;
2174
                NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
2175
#else
2176
                UWORD *x1,*x2,*x3,*x4,*c1,*c2;
2177
                WORD n1,n2,n3,n4,i;
2178
                x1 = c; x3 = a; n1 = i = na;
2179
                NCOPY(x1,x3,i);
2180
                x1 = c; c1 = x2 = NumberMalloc("GcdLong"); x3 = NumberMalloc("GcdLong"); x4 = NumberMalloc("GcdLong");
2181
                c2 = b; n2 = i = nb;
2182
                NCOPY(c1,c2,i);
2183
                for(;;){
2184
                        if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto GcdErr;
2185
                        if ( !n3 ) { x1 = x2; n1 = n2; break; }
2186
                        if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto GcdErr;
2187
                        if ( !n1 ) { x1 = x3; n1 = n3; break; }
2188
                        if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto GcdErr;
2189
                        if ( !n2 ) {
2190
                                *nc = n1;
2191
                                NumberFree(x2,"GcdLong"); NumberFree(x3,"GcdLong"); NumberFree(x4,"GcdLong");
2192
                                return(0);
2193
                        }
2194
                }
2195
                *nc = i = n1;
2196
                NCOPY(c,x1,i);
2197
                NumberFree(x2,"GcdLong"); NumberFree(x3,"GcdLong"); NumberFree(x4,"GcdLong");
2198
#endif
2199
#endif
2200
        }
2201
        return(0);
2202
GcdErr:
2203
        MLOCK(ErrorMessageLock);
2204
        MesCall("GcdLong");
2205
        MUNLOCK(ErrorMessageLock);
2206
        SETERROR(-1)
2207
}
2208
/*
2209
          #] Old Routine : 
2210
*/
2211
#else
2212

2213
/*
2214
        New routine for GcdLong that uses smart shortcuts.
2215
        Algorithm by J. Vermaseren 15-nov-2006.
2216
        It runs faster for very big numbers but only by a fixed factor.
2217
        There is no improvement in the power behaviour.
2218
        Improvement on the whole of hf9 (multiple zeta values at weight 9):
2219
                Better than a factor 2 on a 32 bits architecture and 2.76 on a
2220
                64 bits architecture.
2221
        On hf10 (MZV's at weight 10), 64 bits architecture: factor 7.
2222

2223
        If we have two long numbers (na,nb > GCDMAX) we will work in a
2224
        truncated way. At the moment of writing (15-nov-2006) it isn't
2225
        clear whether this algorithm is an invention or a reinvention.
2226
        A short search on the web didn't show anything.
2227

2228
        31-jul-2007:
2229
        A better search shows that this is an adaptation of the Lehmer-Euclid
2230
        algorithm, already described in Knuth. Here we can work without upper
2231
        and lower limit because we are only interested in the GCD, not the
2232
        extra numbers. Also it takes already some features of the double
2233
        digit Lehmer-Euclid algorithm of Jebelean it seems.
2234

2235
        Maybe this can be programmed slightly better and we can get another
2236
        few percent speed increase. Further improvements for the asymptotic
2237
        case come from splitting the calculation as in Karatsuba and working
2238
        with FFT divisions and multiplications etc. But this is when hundreds
2239
        of words are involved at the least.
2240

2241
        Algorithm
2242

2243
        1: while ( na > nb || nb < GCDMAX ) {
2244
                if ( nb == 0 ) { result in a }
2245
                c = a % b;
2246
                a = b;
2247
                b = c;
2248
           }
2249
        2: Make the truncated values in which a and b are the combinations
2250
           of the top two words of a and b. The whole numbers are aa and bb now.
2251
        3: ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2252
        4: A = a; B = b; m = a/b; c = a - m*b;
2253
           c = ma1*a+ma2*b-m*(mb1*a+mb2*b) = (ma1-m*mb1)*a+(ma2-m*mb2)*b
2254
           mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2255
        5: a = b; ma1 = mb1; ma2 = mb2;
2256
           b = c; mb1 = mc1; mb2 = mc2;
2257
        6: if ( b != 0 && nb >= FULLMAX ) goto 4;
2258
        7: Now construct the new quantities
2259
                ma1*aa+ma2*bb and mb1*aa+mb2*bb
2260
        8: goto 1;
2261

2262
        The essence of the above algorithm is that we do the divisions only
2263
        on relatively short numbers. Also usually there are many steps 4&5
2264
        for each step 7. This eliminates many operations.
2265
        The termination at FULLMAX is that we make errors by not considering
2266
        the tail of the number. If we run b down all the way, the errors combine
2267
        in such a way that the new numbers may be of the same order as the old
2268
        numbers. By stopping halfway we don't get the error beyond halfway
2269
        either. Unfortunately this means that a >= FULLMAX and hence na > nb
2270
        which means that next we will have a complete division. But just once.
2271
        Running the steps 4-6 till a < FULLMAX runs already into problems.
2272
        It may be necessary to experiment a bit to obtain the optimum value
2273
        of GCDMAX.
2274
*/
2275

2276
WORD GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
60,848,598✔
2277
{
2278
        GETBIDENTITY
2279
        UWORD x,y,z;
60,848,598✔
2280
        UWORD *x1,*x2,*x3,*x4,*x5,*d;
60,848,598✔
2281
        UWORD *GLscrat6, *GLscrat7, *GLscrat8, *GLscrat9, *GLscrat10;
60,848,598✔
2282
        WORD n1,n2,n3,n4,n5,i;
60,848,598✔
2283
        RLONG lx,ly,lz;
60,848,598✔
2284
        LONG ma1, ma2, mb1, mb2, mc1, mc2, m;
60,848,598✔
2285
        if ( !na || !nb ) {
60,848,598✔
2286
                if ( !na && !nb ) {
10,975,419✔
2287
                        MLOCK(ErrorMessageLock);
×
2288
                        MesPrint("Cannot take gcd");
×
2289
                        MUNLOCK(ErrorMessageLock);
×
2290
                        return(-1);
×
2291
                }
2292
                
2293
                if ( !na ) {
10,975,419✔
2294
                        *nc = abs(nb);
10,975,419✔
2295
                        NCOPY(c,b,*nc);
27,467,729✔
2296
                        *nc = abs(nb);
10,975,419✔
2297
                        return(0);
10,975,419✔
2298
                }
2299
                
2300
                *nc = abs(na);
×
2301
                NCOPY(c,a,*nc);
×
2302
                *nc = abs(na);
×
2303
                return(0);
×
2304
        }
2305
        if ( na < 0 ) na = -na;
49,873,179✔
2306
        if ( nb < 0 ) nb = -nb;
49,873,179✔
2307
/*
2308
          #[ GMP stuff :
2309
*/
2310
#ifdef WITHGMP
2311
        if ( na > 3 && nb > 3 ) {
49,873,179✔
2312
                int ii;
177,936✔
2313
                mp_limb_t *upa, *upb, *upc, xx;
177,936✔
2314
                UWORD *uw, *u1, *u2;
177,936✔
2315
                unsigned int tcounta, tcountb, tcounta1, tcountb1;
177,936✔
2316
                mp_size_t ana, anb, anc;
177,936✔
2317

2318
                u1 = uw = NumberMalloc("GcdLong");
177,936✔
2319
                upa = (mp_limb_t *)u1;
177,936✔
2320
                ana = na; tcounta1 = 0;
177,936✔
2321
                while ( a[0] == 0 ) { a++; ana--; tcounta1++; }
223,119✔
2322
                for ( ii = 0; ii < ana; ii++ ) { *uw++ = *a++; }
5,851,386✔
2323
                if ( ( ana & 1 ) != 0 ) { *uw = 0; ana++; }
177,936✔
2324
                ana /= 2;
177,936✔
2325

2326
                u2 = uw = NumberMalloc("GcdLong");
177,936✔
2327
                upb = (mp_limb_t *)u2;
177,936✔
2328
                anb = nb; tcountb1 = 0;
177,936✔
2329
                while ( b[0] == 0 ) { b++; anb--; tcountb1++; }
223,419✔
2330
                for ( ii = 0; ii < anb; ii++ ) { *uw++ = *b++; }
6,025,738✔
2331
                if ( ( anb & 1 ) != 0 ) { *uw = 0; anb++; }
177,936✔
2332
                anb /= 2;
177,936✔
2333

2334
                xx = upa[0]; tcounta = 0;
177,936✔
2335
                while ( ( xx & 15 ) == 0 ) { tcounta += 4; xx >>= 4; }
442,803✔
2336
                while ( ( xx &  1 ) == 0 ) { tcounta += 1; xx >>= 1; }
378,914✔
2337
                xx = upb[0]; tcountb = 0;
177,936✔
2338
                while ( ( xx & 15 ) == 0 ) { tcountb += 4; xx >>= 4; }
475,484✔
2339
                while ( ( xx &  1 ) == 0 ) { tcountb += 1; xx >>= 1; }
393,694✔
2340

2341
                if ( tcounta ) {
177,936✔
2342
                        mpn_rshift(upa,upa,ana,tcounta);
134,512✔
2343
                        if ( upa[ana-1] == 0 ) ana--;
134,512✔
2344
                }
2345
                if ( tcountb ) {
177,936✔
2346
                        mpn_rshift(upb,upb,anb,tcountb);
141,011✔
2347
                        if ( upb[anb-1] == 0 ) anb--;
141,011✔
2348
                }
2349

2350
                upc = (mp_limb_t *)(NumberMalloc("GcdLong"));
177,936✔
2351
                if ( ( ana > anb ) || ( ( ana == anb ) && ( upa[ana-1] >= upb[ana-1] ) ) ) {
177,936✔
2352
                        anc = mpn_gcd(upc,upa,ana,upb,anb);
92,814✔
2353
                }
2354
                else {
2355
                        anc = mpn_gcd(upc,upb,anb,upa,ana);
85,122✔
2356
                }
2357

2358
                tcounta = tcounta1*BITSINWORD + tcounta;
177,936✔
2359
                tcountb = tcountb1*BITSINWORD + tcountb;
177,936✔
2360
                if ( tcountb > tcounta ) tcountb = tcounta;
177,936✔
2361
                tcounta = tcountb/BITSINWORD;
177,936✔
2362
                tcountb = tcountb%BITSINWORD;
177,936✔
2363

2364
                if ( tcountb ) {
177,936✔
2365
                        xx = mpn_lshift(upc,upc,anc,tcountb);
126,916✔
2366
                        if ( xx ) { upc[anc] = xx; anc++; }
126,916✔
2367
                }
2368

2369
                uw = (UWORD *)upc; anc *= 2;
177,936✔
2370
                while ( uw[anc-1] == 0 ) anc--;
291,554✔
2371
                for ( ii = 0; ii < (int)tcounta; ii++ ) *c++ = 0;
221,983✔
2372
                for ( ii = 0; ii < anc; ii++ ) *c++ = *uw++;
1,451,306✔
2373
                *nc = anc + tcounta;
177,936✔
2374
                NumberFree(u1,"GcdLong"); NumberFree(u2,"GcdLong"); NumberFree((UWORD *)(upc),"GcdLong");
177,936✔
2375
                return(0);
177,936✔
2376
        }
2377
#endif
2378
/*
2379
          #] GMP stuff : 
2380
*/
2381
/*
2382
          #[ Easy cases :
2383
*/
2384
        if ( na == 1 && nb == 1 ) {
49,695,243✔
2385
                x = *a;
44,473,065✔
2386
                y = *b;
44,473,065✔
2387
                do { z = x % y; x = y; } while ( ( y = z ) != 0 );
72,267,028✔
2388
                *c = x;
44,473,065✔
2389
                *nc = 1;
44,473,065✔
2390
                return(0);
44,473,065✔
2391
        }
2392
        else if ( na <= 2 && nb <= 2 ) {
5,222,178✔
2393
                if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
1,656,188✔
2394
                else { lx = *a; }
1,540,605✔
2395
                if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
1,656,188✔
2396
                else { ly = *b; }
21,292✔
2397
                if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
1,656,188✔
2398
#if ( BITSINWORD == 16 )
2399
                do {
2400
                        lz = lx % ly; lx = ly;
2401
                } while ( ( ly = lz ) != 0 );
2402
#else
2403
                do {
1,773,955✔
2404
                        lz = lx % ly; lx = ly;
1,773,955✔
2405
                } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
1,773,955✔
2406
                if ( ly ) {
1,656,188✔
2407
                        x = (UWORD)lx; y = (UWORD)ly;
108,095✔
2408
                        do { *c = x % y; x = y; } while ( ( y = *c ) != 0 );
432,186✔
2409
                        *c = x;
108,095✔
2410
                        *nc = 1;
108,095✔
2411
                }
2412
                else
2413
#endif
2414
                {
2415
                        *c++ = (UWORD)lx;
1,548,093✔
2416
                        if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
1,548,093✔
2417
                        else *nc = 1;
1,479,069✔
2418
                }
2419
                return(0);
1,656,188✔
2420
        }
2421
/*
2422
          #] Easy cases : 
2423
*/
2424
        GLscrat6 = NumberMalloc("GcdLong"); GLscrat7 = NumberMalloc("GcdLong");
3,565,990✔
2425
        GLscrat8 = NumberMalloc("GcdLong");
3,565,990✔
2426
        GLscrat9 = NumberMalloc("GcdLong"); GLscrat10 = NumberMalloc("GcdLong");
3,565,990✔
2427
restart:;
614,187✔
2428
/*
2429
          #[ Easy cases :
2430
*/
2431
        if ( na == 1 && nb == 1 ) {
4,180,177✔
2432
                x = *a;
47,777✔
2433
                y = *b;
47,777✔
2434
                do { z = x % y; x = y; } while ( ( y = z ) != 0 );
142,261✔
2435
                *c = x;
47,777✔
2436
                *nc = 1;
47,777✔
2437
        }
2438
        else if ( na <= 2 && nb <= 2 ) {
4,132,400✔
2439
                if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
310,684✔
2440
                else { lx = *a; }
×
2441
                if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
310,684✔
2442
                else { ly = *b; }
4,109✔
2443
                if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
310,684✔
2444
#if ( BITSINWORD == 16 )
2445
                do {
2446
                        lz = lx % ly; lx = ly;
2447
                } while ( ( ly = lz ) != 0 );
2448
#else
2449
                do {
2,980,929✔
2450
                        lz = lx % ly; lx = ly;
2,980,929✔
2451
                } while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2,980,929✔
2452
                if ( ly ) {
310,684✔
2453
                        x = (UWORD)lx; y = (UWORD)ly;
125,192✔
2454
                        do { *c = x % y; x = y; } while ( ( y = *c ) != 0 );
1,591,822✔
2455
                        *c = x;
125,192✔
2456
                        *nc = 1;
125,192✔
2457
                }
2458
                else
2459
#endif
2460
                {
2461
                        *c++ = (UWORD)lx;
185,492✔
2462
                        if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
185,492✔
2463
                        else *nc = 1;
6,130✔
2464
                }
2465
        }
2466
/*
2467
          #] Easy cases : 
2468
          #[ Original code :
2469
*/
2470
        else if ( na < GCDMAX || nb < GCDMAX || na != nb ) {
3,821,716✔
2471
                if ( na < nb ) {
3,433,116✔
2472
                        x2 = GLscrat8; x3 = a; n2 = i = na;
3,124,855✔
2473
                        NCOPY(x2,x3,i);
6,382,838✔
2474
                        x1 = c; x3 = b; n1 = i = nb;
3,124,855✔
2475
                        NCOPY(x1,x3,i);
32,741,198✔
2476
                }
2477
                else {
2478
                        x1 = c; x3 = a; n1 = i = na;
308,261✔
2479
                        NCOPY(x1,x3,i);
1,435,902✔
2480
                        x2 = GLscrat8; x3 = b; n2 = i = nb;
308,261✔
2481
                        NCOPY(x2,x3,i);
951,655✔
2482
                }
2483
                x1 = c; x2 = GLscrat8; x3 = GLscrat7; x4 = GLscrat6;
3,433,116✔
2484
                for(;;){
3,433,116✔
2485
                        if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) ) goto GcdErr;
3,433,116✔
2486
                        if ( !n3 ) { x1 = x2; n1 = n2; break; }
3,433,116✔
2487
                        if ( n2 <= 2 ) { a = x2; b = x3; na = n2; nb = n3; goto restart; }
398,994✔
2488
                        if ( n3 >= GCDMAX && n2 == n3 ) {
55,240✔
2489
                                a = GLscrat9; b = GLscrat10; na = n2; nb = n3;
162,080✔
2490
                                for ( i = 0; i < na; i++ ) a[i] = x2[i];
162,080✔
2491
                                for ( i = 0; i < nb; i++ ) b[i] = x3[i];
162,080✔
2492
                                goto newtrick;
40,520✔
2493
                        }
2494
                        if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) ) goto GcdErr;
14,720✔
2495
                        if ( !n1 ) { x1 = x3; n1 = n3; break; }
14,720✔
2496
                        if ( n3 <= 2 ) { a = x3; b = x1; na = n3; nb = n1; goto restart; }
14,573✔
2497
                        if ( n1 >= GCDMAX && n1 == n3 ) {
×
2498
                                a = GLscrat9; b = GLscrat10; na = n3; nb = n1;
×
2499
                                for ( i = 0; i < na; i++ ) a[i] = x3[i];
×
2500
                                for ( i = 0; i < nb; i++ ) b[i] = x1[i];
×
2501
                                goto newtrick;
×
2502
                        }
2503
                        if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) ) goto GcdErr;
×
2504
                        if ( !n2 ) { *nc = n1; goto normalend; }
×
2505
                        if ( n1 <= 2 ) { a = x1; b = x2; na = n1; nb = n2; goto restart; }
×
2506
                        if ( n2 >= GCDMAX && n2 == n1 ) {
×
2507
                                a = GLscrat9; b = GLscrat10; na = n1; nb = n2;
×
2508
                                for ( i = 0; i < na; i++ ) a[i] = x1[i];
×
2509
                                for ( i = 0; i < nb; i++ ) b[i] = x2[i];
×
2510
                                goto newtrick;
×
2511
                        }
2512
                }
2513
                *nc = i = n1;
3,034,269✔
2514
                NCOPY(c,x1,i);
6,130,277✔
2515
        }
2516
/*
2517
          #] Original code : 
2518
          #[ New code :
2519
*/
2520
        else {
2521
/*
2522
                This is the new algorithm starting at step 3.
2523

2524
        3: ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2525
        4: A = a; B = b; m = a/b; c = a - m*b;
2526
           c = ma1*a+ma2*b-m*(mb1*a+mb2*b) = (ma1-m*mb1)*a+(ma2-m*mb2)*b
2527
           mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2528
        5: a = b; ma1 = mb1; ma2 = mb2;
2529
           b = c; mb1 = mc1; mb2 = mc2;
2530
        6: if ( b != 0 ) goto 4;
2531
*/
2532
newtrick:;
388,600✔
2533
                ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
429,120✔
2534
                lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
429,120✔
2535
                ly = (((RLONG)(b[nb-1]))<<BITSINWORD) + b[nb-2];
429,120✔
2536
                if ( ly > lx ) { lz = lx; lx = ly; ly = lz; d = a; a = b; b = d; }
429,120✔
2537
                do {
1,346,450✔
2538
                        m = lx/ly;
1,346,450✔
2539
                        mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
1,346,450✔
2540
                        ma1 = mb1; ma2 = mb2; mb1 = mc1; mb2 = mc2;
1,346,450✔
2541
                        lz = lx - m*ly; lx = ly; ly = lz;
1,346,450✔
2542
                } while ( ly >= FULLMAX );
1,346,450✔
2543
/*
2544
                Next the construction of the two new numbers
2545

2546
        7: Now construct the new quantities
2547
                a = ma1*aa+ma2*bb and b = mb1*aa+mb2*bb
2548
*/
2549
                x1 = GLscrat6;
429,120✔
2550
                x2 = GLscrat7;
429,120✔
2551
                x3 = GLscrat8;
429,120✔
2552
                x5 = GLscrat10;
429,120✔
2553
                if ( ma1 < 0 ) {
429,120✔
2554
                        ma1 = -ma1;
115,025✔
2555
                        x1[0] = (UWORD)ma1;
115,025✔
2556
                        x1[1] = (UWORD)(ma1 >> BITSINWORD);
115,025✔
2557
                        if ( x1[1] ) n1 = -2;
115,025✔
2558
                        else         n1 = -1;
115,025✔
2559
                }
2560
                else {
2561
                        x1[0] = (UWORD)ma1;
314,095✔
2562
                        x1[1] = (UWORD)(ma1 >> BITSINWORD);
314,095✔
2563
                        if ( x1[1] ) n1 = 2;
314,095✔
2564
                        else         n1 = 1;
314,095✔
2565
                }
2566
                if ( MulLong(a,na,x1,n1,x2,&n2) ) goto GcdErr;
429,120✔
2567
                if ( ma2 < 0 ) {
429,120✔
2568
                        ma2 = -ma2;
117,826✔
2569
                        x1[0] = (UWORD)ma2;
117,826✔
2570
                        x1[1] = (UWORD)(ma2 >> BITSINWORD);
117,826✔
2571
                        if ( x1[1] ) n1 = -2;
117,826✔
2572
                        else         n1 = -1;
117,826✔
2573
                }
2574
                else {
2575
                        x1[0] = (UWORD)ma2;
311,294✔
2576
                        x1[1] = (UWORD)(ma2 >> BITSINWORD);
311,294✔
2577
                        if ( x1[1] ) n1 = 2;
311,294✔
2578
                        else         n1 = 1;
311,294✔
2579
                }
2580
                if ( MulLong(b,nb,x1,n1,x3,&n3) ) goto GcdErr;
429,120✔
2581
                if ( AddLong(x2,n2,x3,n3,c,&n4) ) goto GcdErr;
429,120✔
2582
                if ( mb1 < 0 ) {
429,120✔
2583
                        mb1 = -mb1;
117,826✔
2584
                        x1[0] = (UWORD)mb1;
117,826✔
2585
                        x1[1] = (UWORD)(mb1 >> BITSINWORD);
117,826✔
2586
                        if ( x1[1] ) n1 = -2;
117,826✔
2587
                        else         n1 = -1;
117,826✔
2588
                }
2589
                else {
2590
                        x1[0] = (UWORD)mb1;
311,294✔
2591
                        x1[1] = (UWORD)(mb1 >> BITSINWORD);
311,294✔
2592
                        if ( x1[1] ) n1 = 2;
311,294✔
2593
                        else         n1 = 1;
311,294✔
2594
                }
2595
                if ( MulLong(a,na,x1,n1,x2,&n2) ) goto GcdErr;
429,120✔
2596
                if ( mb2 < 0 ) {
429,120✔
2597
                        mb2 = -mb2;
311,294✔
2598
                        x1[0] = (UWORD)mb2;
311,294✔
2599
                        x1[1] = (UWORD)(mb2 >> BITSINWORD);
311,294✔
2600
                        if ( x1[1] ) n1 = -2;
311,294✔
2601
                        else         n1 = -1;
311,294✔
2602
                }
2603
                else {
2604
                        x1[0] = (UWORD)mb2;
117,826✔
2605
                        x1[1] = (UWORD)(mb2 >> BITSINWORD);
117,826✔
2606
                        if ( x1[1] ) n1 = 2;
117,826✔
2607
                        else         n1 = 1;
117,826✔
2608
                }
2609
                if ( MulLong(b,nb,x1,n1,x3,&n3) ) goto GcdErr;
429,120✔
2610
                if ( AddLong(x2,n2,x3,n3,x5,&n5) ) goto GcdErr;
429,120✔
2611
                a = c; na = n4; b = x5; nb = n5;
429,120✔
2612
                if ( nb == 0 ) { *nc = n4; goto normalend; }
429,120✔
2613
                x4 = GLscrat9; 
2614
                for ( i = 0; i < na; i++ ) x4[i] = a[i];
1,023,283✔
2615
                a = x4;
255,860✔
2616
                if ( na < 0 ) na = -na;
255,860✔
2617
                if ( nb < 0 ) nb = -nb;
255,860✔
2618
/*
2619
                The typical case now is that in a we have the last step to go
2620
                to loose the leading word, while in b we have lost the leading word.
2621
                We could go to DivLong now but we can also add an extra step that
2622
                is less wasteful.
2623
                In the case that the new leading word of b is extrememly short (like 1)
2624
                we make a rather large error of course. In the worst case the whole
2625
                will be intercepted by DivLong after all, but that is so rare that
2626
                it shouldn't influence any timing in a measurable way.
2627
*/
2628
                if ( nb >= GCDMAX && na == nb+1 && b[nb-1] >= HALFMAX && b[nb-1] > a[na-1] ) {
255,860✔
2629
                        lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
×
2630
                        x1[0] = lx/b[nb-1]; n1 = 1;
×
2631
                        MulLong(b,nb,x1,n1,x2,&n2);
×
2632
                        n2 = -n2;
×
2633
                        AddLong(a,na,x2,n2,x4,&n4);
×
2634
                        if ( n4 == 0 ) {
×
2635
                                *nc = nb;
×
2636
                                for ( i = 0; i < nb; i++ ) c[i] = b[i];
×
2637
                                goto normalend;
×
2638
                        }
2639
                        if ( n4 < 0 ) n4 = -n4;
×
2640
                        a = b; na = nb; b = x4; nb = n4;
×
2641
                }
2642
                goto restart;
255,860✔
2643
/*
2644
          #] New code : 
2645
*/
2646
        }
2647
normalend:
3,565,990✔
2648
        NumberFree(GLscrat6,"GcdLong"); NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
3,565,990✔
2649
        NumberFree(GLscrat9,"GcdLong"); NumberFree(GLscrat10,"GcdLong");
3,565,990✔
2650
        return(0);
3,565,990✔
2651
GcdErr:
×
2652
        MLOCK(ErrorMessageLock);
×
2653
        MesCall("GcdLong");
×
2654
        MUNLOCK(ErrorMessageLock);
×
2655
        NumberFree(GLscrat6,"GcdLong"); NumberFree(GLscrat7,"GcdLong"); NumberFree(GLscrat8,"GcdLong");
×
2656
        NumberFree(GLscrat9,"GcdLong"); NumberFree(GLscrat10,"GcdLong");
×
2657
        SETERROR(-1)
×
2658
}
2659

2660
#endif
2661

2662
/*
2663
                 #] GcdLong : 
2664
                 #[ GetBinom :                WORD GetBinom(a,na,i1,i2)
2665
*/
2666

2667
WORD GetBinom(UWORD *a, WORD *na, WORD i1, WORD i2)
12✔
2668
{
2669
        GETIDENTITY
8✔
2670
        WORD j, k, l;
12✔
2671
        UWORD *GBscrat3, *GBscrat4;
12✔
2672
        if ( i1-i2 < i2 ) i2 = i1-i2;
12✔
2673
        if ( i2 == 0 ) { *a = 1; *na = 1; return(0); }
12✔
2674
        if ( i2 > i1 ) { *a = 0; *na = 0; return(0); }
6✔
2675
        *a = i1; *na = 1;
6✔
2676
        GBscrat3 = NumberMalloc("GetBinom"); GBscrat4 = NumberMalloc("GetBinom");
6✔
2677
        for ( j = 2; j <= i2; j++ ) {
6✔
2678
                GBscrat3[0] = i1+1-j;
×
2679
                if ( MulLong(a,*na,GBscrat3,(WORD)1,GBscrat4,&k) ) goto CalledFrom;
×
2680
                GBscrat3[0] = j;
×
2681
                if ( DivLong(GBscrat4,k,GBscrat3,(WORD)1,a,na,GBscrat3,&l) ) goto CalledFrom;
×
2682
        }
2683
        NumberFree(GBscrat3,"GetBinom"); NumberFree(GBscrat4,"GetBinom");
6✔
2684
        return(0);
6✔
2685
CalledFrom:
×
2686
        MLOCK(ErrorMessageLock);
×
2687
        MesCall("GetBinom");
×
2688
        MUNLOCK(ErrorMessageLock);
×
2689
        NumberFree(GBscrat3,"GetBinom"); NumberFree(GBscrat4,"GetBinom");
×
2690
        SETERROR(-1)
×
2691
}
2692

2693
/*
2694
                 #] GetBinom : 
2695
                 #[ LcmLong :                WORD LcmLong(a,na,b,nb)
2696

2697
                Computes the LCM of the long numbers a and b and puts the result
2698
                in c. c is allowed to be equal to a.
2699
*/
2700

2701
WORD LcmLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
24✔
2702
{
2703
        WORD error = 0;
24✔
2704
        UWORD *d = NumberMalloc("LcmLong");
24✔
2705
        UWORD *e = NumberMalloc("LcmLong");
24✔
2706
        UWORD *f = NumberMalloc("LcmLong");
24✔
2707
        WORD nd, ne, nf;
24✔
2708
        GcdLong(BHEAD a, na, b, nb, d, &nd);
24✔
2709
        DivLong(a,na,d,nd,e,&ne,f,&nf);
24✔
2710
        if ( MulLong(b,nb,e,ne,c,nc) ) {
24✔
2711
                MLOCK(ErrorMessageLock);
×
2712
                MesCall("LcmLong");
×
2713
                MUNLOCK(ErrorMessageLock);
×
2714
                error = -1;
×
2715
        }
2716
        NumberFree(f,"LcmLong");
24✔
2717
        NumberFree(e,"LcmLong");
24✔
2718
        NumberFree(d,"LcmLong");
24✔
2719
        return(error);
24✔
2720
}
2721

2722
/*
2723
                 #] LcmLong : 
2724
                 #[ TakeLongRoot:        int TakeLongRoot(a,n,power)
2725

2726
        Takes the 'power'-root of the long number in a.
2727
        If the root could be taken the return value is zero.
2728
        If the root could not be taken, the return value is 1.
2729
        The root will be in a if it could be taken, otherwise there will be garbage
2730
        Algorithm: (assume b is guess of root, b' better guess)
2731
                b' = (a-(power-1)*b^power)/(n*b^(power-1))
2732
        Note: power should be positive!
2733
*/
2734

2735
int TakeLongRoot(UWORD *a, WORD *n, WORD power)
101,448✔
2736
{
2737
        GETIDENTITY
67,632✔
2738
        int numbits, guessbits, i, retval = 0;
101,448✔
2739
        UWORD x, *b, *c, *d, *e;
101,448✔
2740
        WORD na, nb, nc, nd, ne;
101,448✔
2741
        if ( *n < 0 && ( power & 1 ) == 0 ) return(1);
101,448✔
2742
        if ( power == 1 ) return(0);
101,448✔
2743
        if ( *n < 0 ) { na = -*n; }
101,448✔
2744
        else          { na =  *n; }
2745
        if ( na == 1 ) {
101,448✔
2746
/*                        Special cases that are the most frequent */
2747
                if ( a[0] == 1 ) return(0);
97,389✔
2748
                if ( power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<power) ) {
97,389✔
2749
                        a[0] = 2; return(0);
×
2750
                }
2751
                if ( 2*power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<(2*power)) ) {
97,389✔
2752
                        a[0] = 4; return(0);
×
2753
                }
2754
        }
2755
/*
2756
        Step 1: make a guess. We count the number of bits.
2757
        numbits will be the 1+2log(a)
2758
*/
2759
        numbits = BITSINWORD*(na-1);
101,448✔
2760
        x = a[na-1];
101,448✔
2761
        while ( ( x >> 8 ) != 0 ) { numbits += 8; x >>= 8; }
198,936✔
2762
        if ( ( x >> 4 ) != 0 ) { numbits += 4; x >>= 4; }
101,448✔
2763
        if ( ( x >> 2 ) != 0 ) { numbits += 2; x >>= 2; }
101,448✔
2764
        if ( ( x >> 1 ) != 0 ) numbits++;
101,448✔
2765
        guessbits = numbits / power;
101,448✔
2766
        if ( guessbits <= 0 ) return(1); /* root < 2 and 1 we did already */
101,448✔
2767
        nb = guessbits/BITSINWORD;
101,448✔
2768
/*
2769
        The recursion is:
2770
        (b'-b) = (a/b^(power-1)-b)/n
2771
               = (a/c-b)/n
2772
               = (d-b)/n    (remainder of a/c is e)
2773
               = c/n  (we reuse the scratch array c)
2774
        Termination can be tricky. When a/c has no remainder and = b we have a root.
2775
        When d = b but the remainder of a/c != 0, there is definitely no root.
2776
*/
2777
        b = NumberMalloc("TakeLongRoot"); c = NumberMalloc("TakeLongRoot");
101,448✔
2778
        d = NumberMalloc("TakeLongRoot"); e = NumberMalloc("TakeLongRoot"); 
101,448✔
2779
        for ( i = 0; i < nb; i++ ) { b[i] = 0; }
101,448✔
2780
        b[nb] = 1 << (guessbits%BITSINWORD);
101,448✔
2781
        nb++;
101,448✔
2782
        for(;;) {
244,116✔
2783
                nc = nb;
244,116✔
2784
                for ( i = 0; i < nb; i++ ) c[i] = b[i];
488,232✔
2785
                if ( RaisPow(BHEAD c,&nc,power-1) ) goto TLcall;
244,116✔
2786
                if ( DivLong(a,na,c,nc,d,&nd,e,&ne) ) goto TLcall;
244,116✔
2787
                nb = -nb;
244,116✔
2788
                if ( AddLong(d,nd,b,nb,c,&nc) ) goto TLcall;
244,116✔
2789
                nb = -nb;
244,116✔
2790
                if ( nc == 0 ) {
244,116✔
2791
                        if ( ne == 0 ) break;
97,551✔
2792
                        retval = 1; break;
28,296✔
2793
/*
2794
                        else {
2795
                                NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2796
                                NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2797
                                return(1);
2798
                        }
2799
*/
2800
                }
2801
                DivLong(c,nc,(UWORD *)(&power),1,d,&nd,e,&ne);
146,565✔
2802
                if ( nd == 0 ) {
146,565✔
2803
                        retval = 1;
2804
                        break;
2805
/*
2806
                        NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2807
                        NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2808
                        return(1);
2809
*/
2810
/*
2811
                        This code tries b+1 as a final possibility.
2812
                        We believe this is not needed
2813
                        UWORD one = 1;
2814
                        if ( AddLong(b,nb,&one,1,c,&nc) ) goto TLcall;
2815
                        if ( RaisPow(BHEAD c,&nc,power-1) ) goto TLcall;
2816
                        if ( DivLong(a,na,c,nc,d,&nd,e,&ne) ) goto TLcall;
2817
                        if ( ne != 0 ) return(1);
2818
                        nb = -nb;
2819
                        if ( SubLong(d,nd,b,nb,c,&nc) ) goto TLcall;
2820
                        nb = -nb;
2821
                        if ( nc != 0 ) {
2822
                                NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
2823
                                NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
2824
                                return(1);
2825
                        }
2826
                        break;
2827
*/
2828
                }
2829
                if ( AddLong(b,nb,d,nd,b,&nb) ) goto TLcall;
142,668✔
2830
        }
2831
        for ( i = 0; i < nb; i++ ) a[i] = b[i];
202,896✔
2832
        if ( *n < 0 ) *n = -nb;
101,448✔
2833
        else          *n =  nb;
101,448✔
2834
        NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
101,448✔
2835
        NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
101,448✔
2836
        return(retval);
101,448✔
2837
TLcall:
×
2838
        MLOCK(ErrorMessageLock);
×
2839
        MesCall("TakeLongRoot");
×
2840
        MUNLOCK(ErrorMessageLock);
×
2841
        NumberFree(b,"TakeLongRoot"); NumberFree(c,"TakeLongRoot");
×
2842
        NumberFree(d,"TakeLongRoot"); NumberFree(e,"TakeLongRoot");
×
2843
        Terminate(-1);
×
2844
        return(-1);
×
2845
}
2846

2847
/*
2848
                 #] TakeLongRoot: 
2849
                 #[ MakeRational:
2850

2851
                Makes the integer a mod m into a traction b/c with |b|,|c| < sqrt(m)
2852
                For the algorithm, see MakeLongRational.
2853
*/
2854

2855
int MakeRational(WORD a,WORD m, WORD *b, WORD *c)
6✔
2856
{
2857
        LONG x1,x2,x3,x4,y1,y2;
6✔
2858
        if ( a < 0 ) { a = a+m; }
6✔
2859
        if ( a <= 1 ) {
6✔
2860
                if ( a > m/2 ) a = a-m;
×
2861
                *b = a; *c = 1; return(0);
×
2862
        }
2863
        x1 = m; x2 = a;
6✔
2864
        if ( x2*x2 >= m ) {
6✔
2865
                y1 = x1/x2; y2 = x1%x2; x3 = 1; x4 = -y1; x1 = x2; x2 = y2;
6✔
2866
                while ( x2*x2 >= m ) {
48✔
2867
                        y1 = x1/x2; y2 = x1%x2; x1 = x2; x2 = y2; y2 = x3-y1*x4; x3 = x4; x4 = y2;
42✔
2868
                }
2869
        }
2870
        else x4 = 1;
2871
        if ( x2 == 0 ) { return(1); }
6✔
2872
        if ( x2 > m/2 ) *b = x2-m;
6✔
2873
        else            *b = x2;
6✔
2874
        if ( x4 > m/2 ) { *c = x4-m; *c = -*c; *b = -*b; }
6✔
2875
        else if ( x4 <= -m/2 ) { x4 += m; *c = x4; }
6✔
2876
        else if ( x4 < 0 ) { x4 = -x4; *c = x4; *b = -*b; }
6✔
2877
        else            *c = x4;
6✔
2878
        return(0);
2879
}
2880

2881
/*
2882
                 #] MakeRational: 
2883
                 #[ MakeLongRational:
2884

2885
                Converts the long number a mod m into the fraction b
2886
                One of the properties of b is that num,den < sqrt(m)
2887
                The algorithm: Start with:   m 0
2888
                                             a 1
2889
                Make now c=m%a, c1=m/a       c c2=0-c1*1
2890
                Make now d=a%c  d1=a/c       d d2=1-d1*c2
2891
                Make now e=c%d  e1=c/d       e e2=1-e1*d2
2892
                        etc till in the first column we get a number < sqrt(m)
2893
                        We have then f,f2 and the fraction is f/f2.
2894
                If at any moment we get a zero, m contained an unlucky prime.
2895

2896
                Note that this can be made a lot faster when we make the same
2897
                improvements as in the GCD routine. That is something for later.
2898
#ifdef WITHMAKERATIONAL
2899
*/
2900

2901
#define COPYLONG(x1,nx1,x2,nx2) { int i; for(i=0;i<ABS(nx2);i++)x1[i]=x2[i];nx1=nx2; }
2902

2903
int MakeLongRational(PHEAD UWORD *a, WORD na, UWORD *m, WORD nm, UWORD *b, WORD *nb)
101,448✔
2904
{
2905
        UWORD *root = NumberMalloc("MakeRational");
101,448✔
2906
        UWORD *x1 = NumberMalloc("MakeRational");
101,448✔
2907
        UWORD *x2 = NumberMalloc("MakeRational");
101,448✔
2908
        UWORD *x3 = NumberMalloc("MakeRational");
101,448✔
2909
        UWORD *x4 = NumberMalloc("MakeRational");
101,448✔
2910
        UWORD *y1 = NumberMalloc("MakeRational");
101,448✔
2911
        UWORD *y2 = NumberMalloc("MakeRational");
101,448✔
2912
        WORD nroot,nx1,nx2,nx3,nx4,ny1,ny2 = 0,retval = 0;
101,448✔
2913
        WORD sign = 1;
101,448✔
2914
/*
2915
        Step 1: Take the square root of m
2916
*/
2917
        COPYLONG(root,nroot,m,nm)
206,955✔
2918
        TakeLongRoot(root,&nroot,2);
101,448✔
2919
/*
2920
        Step 2: Set the start values
2921
*/
2922
        if ( na < 0 ) { na = -na; sign = -sign; }
101,448✔
2923
        COPYLONG(x1,nx1,m,nm)
206,955✔
2924
        COPYLONG(x2,nx2,a,na)
202,896✔
2925
/*
2926
        x3[0] = 0, nx3 = 0;
2927
        x4[0] = 1, nx4 = 1;
2928
*/
2929
/*
2930
        The start operation needs some special attention because of the zero.
2931
*/
2932
        if ( BigLong(x2,nx2,root,nroot) <= 0 ) {
101,448✔
2933
                x4[0] = 1, nx4 = 1;
54,045✔
2934
                goto gottheanswer;
54,045✔
2935
        }
2936
        DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
47,403✔
2937
        if ( ny2 == 0 ) { retval = 1; goto cleanup; }
47,403✔
2938
        COPYLONG(x1,nx1,x2,nx2)
94,806✔
2939
        COPYLONG(x2,nx2,y2,ny2)
94,806✔
2940
        x3[0] = 1; nx3 = 1;
47,403✔
2941
        COPYLONG(x4,nx4,y1,ny1)
94,806✔
2942
        nx4 = -nx4;
47,403✔
2943
/*
2944
        Now the loop.
2945
*/
2946
        while ( BigLong(x2,nx2,root,nroot) > 0 ) {
79,668✔
2947
                DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
32,265✔
2948
                if ( ny2 == 0 ) { retval = 1; goto cleanup; }
32,265✔
2949
                COPYLONG(x1,nx1,x2,nx2)
64,530✔
2950
                COPYLONG(x2,nx2,y2,ny2)
64,530✔
2951
                MulLong(y1,ny1,x4,nx4,y2,&ny2);
32,265✔
2952
                ny2 = -ny2;
32,265✔
2953
                AddLong(x3,nx3,y2,ny2,y1,&ny1);
32,265✔
2954
                COPYLONG(x3,nx3,x4,nx4)
96,795✔
2955
                COPYLONG(x4,nx4,y1,ny1)
64,530✔
2956
        }
2957
/*
2958
        Now we have the answer. It is x2/x4. It has to be packed into b.
2959
*/
2960
gottheanswer:
47,403✔
2961
        if ( nx4 < 0 ) { sign = -sign; nx4 = -nx4; }
101,448✔
2962
        COPYLONG(b,*nb,x2,nx2)
202,896✔
2963
        Pack(b,nb,x4,nx4);
101,448✔
2964
        if ( sign < 0 ) *nb = -*nb;
101,448✔
2965
cleanup:
50,517✔
2966
        NumberFree(y2,"MakeRational");
101,448✔
2967
        NumberFree(y1,"MakeRational");
101,448✔
2968
        NumberFree(x4,"MakeRational");
101,448✔
2969
        NumberFree(x3,"MakeRational");
101,448✔
2970
        NumberFree(x2,"MakeRational");
101,448✔
2971
        NumberFree(x1,"MakeRational");
101,448✔
2972
        NumberFree(root,"MakeRational");
101,448✔
2973
        return(retval);
101,448✔
2974
}
2975

2976
/*
2977
#endif
2978
                 #] MakeLongRational: 
2979
                 #[ ChineseRemainder:
2980
*/
2981
/**
2982
 *                Routine takes a1 mod m1 and a2 mod m2 and returns a mod m1*m2 with
2983
 *                a mod m1 = a1 and a mod m2 = a2
2984
 *        Chinese remainder:
2985
 *                a%(m1*m2) = q1*m1+a1
2986
 *                a%(m1*m2) = q2*m2+a2
2987
 *        Compute n1 such that (n1*m1)%m2 is one
2988
 *        Compute n2 such that (n2*m2)%m1 is one
2989
 *        Then (a1*n2*m2+a2*n1*m1)%(m1*m2) is a%(m1*m2)
2990
 *
2991
 */
2992
#ifdef WITHCHINESEREMAINDER
2993

2994
int ChineseRemainder(PHEAD MODNUM *a1, MODNUM *a2, MODNUM *a)
2995
{
2996
        UWORD *inv1 = NumberMalloc("ChineseRemainder");
2997
        UWORD *inv2 = NumberMalloc("ChineseRemainder");
2998
        UWORD *fac1 = NumberMalloc("ChineseRemainder");
2999
        UWORD *fac2 = NumberMalloc("ChineseRemainder");
3000
        UWORD two[1];
3001
        WORD ninv1, ninv2, nfac1, nfac2;
3002
        if ( a1->na < 0 ) {
3003
                AddLong(a1->a,a1->na,a1->m,a1->nm,a1->a,&(a1->na));
3004
        }
3005
        if ( a2->na < 0 ) {
3006
                AddLong(a2->a,a2->na,a2->m,a2->nm,a2->a,&(a2->na));
3007
        }
3008
        MulLong(a1->m,a1->nm,a2->m,a2->nm,a->m,&(a->nm));
3009

3010
        GetLongModInverses(BHEAD a1->m,a1->nm,a2->m,a2->nm,inv1,&ninv1,inv2,&ninv2);
3011
        MulLong(inv1,ninv1,a1->m,a1->nm,fac1,&nfac1);
3012
        MulLong(inv2,ninv2,a2->m,a2->nm,fac2,&nfac2);
3013

3014
        MulLong(fac1,nfac1,a2->a,a2->na,inv1,&ninv1);
3015
        MulLong(fac2,nfac2,a1->a,a1->na,inv2,&ninv2);
3016
        AddLong(inv1,ninv1,inv2,ninv2,a->a,&(a->na));
3017

3018
        two[0] = 2;
3019
        MulLong(a->a,a->na,two,1,fac1,&nfac1);
3020
        if ( BigLong(fac1,nfac1,a->m,a->nm) > 0 ) {
3021
                a->nm = -a->nm;
3022
                AddLong(a->a,a->na,a->m,a->nm,a->a,&(a->na));
3023
                a->nm = -a->nm;
3024
        }
3025
        NumberFree(fac2,"ChineseRemainder");
3026
        NumberFree(fac1,"ChineseRemainder");
3027
        NumberFree(inv2,"ChineseRemainder");
3028
        NumberFree(inv1,"ChineseRemainder");
3029
        return(0);
3030
}
3031

3032
#endif
3033

3034
/*
3035
                 #] ChineseRemainder: 
3036
          #] RekenLong : 
3037
          #[ RekenTerms :
3038
                 #[ CompCoef :                WORD CompCoef(term1,term2)
3039

3040
        Compares the coefficients of term1 and term2 by subtracting them.
3041
        This does more work than needed but this routine is only called
3042
        when sorting functions and function arguments.
3043
        (and comparing values 
3044
*/
3045
/* #define 64SAVE */
3046

3047
WORD CompCoef(WORD *term1, WORD *term2)
2,651,945✔
3048
{
3049
        GETIDENTITY
1,770,937✔
3050
        UWORD *c;
2,651,945✔
3051
        WORD n1,n2,n3,*a;
2,651,945✔
3052
        GETCOEF(term1,n1);
2,651,945✔
3053
        GETCOEF(term2,n2);
2,651,945✔
3054
        if ( term1[1] == 0 && n1 == 1 ) {
2,651,945✔
3055
                if ( term2[1] == 0 && n2 == 1 ) return(0);
×
3056
                if ( n2 < 0 ) return(1);
×
3057
                return(-1);
×
3058
        }
3059
        else if ( term2[1] == 0 && n2 == 1 ) {
2,651,945✔
3060
                if ( n1 < 0 ) return(-1);
×
3061
                return(1);
×
3062
        }
3063
        if ( n1 > 0 ) {
2,651,945✔
3064
                if ( n2 < 0 ) return(1);
1,573,202✔
3065
        }
3066
        else {
3067
                if ( n2 > 0 ) return(-1);
1,078,743✔
3068
                a = term1; term1 = term2; term2 = a;
1,078,416✔
3069
                n3 = -n1; n1 = -n2; n2 = n3;
1,078,416✔
3070
        }
3071
        if ( term1[1] == 1 && term2[1] == 1 && n1 == 1 && n2 == 1 ) {
2,651,513✔
3072
                if ( (UWORD)*term1 > (UWORD)*term2 ) return(1);
2,461,931✔
3073
                else if ( (UWORD)*term1 < (UWORD)*term2 ) return(-1);
2,444,958✔
3074
                else return(0);
2,444,502✔
3075
        }
3076

3077
/*
3078
        The next call should get dedicated code, as AddRat does more than
3079
        strictly needed. Also more attention should be given to overflow.
3080
*/
3081
        c = NumberMalloc("CompCoef");
189,582✔
3082
        if ( AddRat(BHEAD (UWORD *)term1,n1,(UWORD *)term2,-n2,c,&n3) ) {
189,582✔
3083
                MLOCK(ErrorMessageLock);
×
3084
                MesCall("CompCoef");
×
3085
                MUNLOCK(ErrorMessageLock);
×
3086
                NumberFree(c,"CompCoef");
×
3087
                SETERROR(-1)
×
3088
        }
3089
        NumberFree(c,"CompCoef");
189,582✔
3090
        return(n3);
189,582✔
3091
}
3092

3093
/*
3094
                 #] CompCoef : 
3095
                 #[ Modulus :                WORD Modulus(term)
3096

3097
        Routine takes the coefficient of term modulus b. The answer
3098
        is in term again and the length of term is adjusted.
3099

3100
*/
3101

3102
WORD Modulus(WORD *term)
6✔
3103
{
3104
        WORD *t;
6✔
3105
        WORD n1;
6✔
3106
        t = term;
6✔
3107
        GETCOEF(t,n1);
6✔
3108
        if ( TakeModulus((UWORD *)t,&n1,AC.cmod,AC.ncmod,UNPACK) ) {
6✔
3109
                MLOCK(ErrorMessageLock);
×
3110
                MesCall("Modulus");
×
3111
                MUNLOCK(ErrorMessageLock);
×
3112
                SETERROR(-1)
×
3113
        }
3114
        if ( !n1 ) {
6✔
3115
                *term = 0;
×
3116
                return(0);
×
3117
        }
3118
        else if ( n1 > 0 ) {
6✔
3119
                n1 *= 2;
6✔
3120
                t += n1;                /* Note that n1 >= 0 */
6✔
3121
                n1++;
6✔
3122
        }
3123
        else if ( n1 < 0 ) {
×
3124
                n1 *= 2;
×
3125
                t += -n1;
×
3126
                n1--;
×
3127
        }
3128
        *t++ = n1;
6✔
3129
        *term = WORDDIF(t,term);
6✔
3130
        return(0);
6✔
3131
}
3132

3133
/*
3134
                 #] Modulus : 
3135
                 #[ TakeModulus :        WORD TakeModulus(a,na,cmodvec,ncmod,par)
3136

3137
                Routine gets the rational number in a with reduced length na.
3138
                It is called when AC.ncmod != 0 and the number in AC.cmod is the
3139
                number wrt which we need the modulus.
3140
                The result is returned in a and na again.
3141

3142
                If par == NOUNPACK we only do a single number, not a fraction.
3143
                In addition we don't do fancy. We want a positive number and
3144
                the input was supposed to be positive.
3145
                We don't pack the result. The calling routine is responsible for that.
3146
                This may not be a good idea. To be checked.
3147
*/
3148

3149
WORD TakeModulus(UWORD *a, WORD *na, UWORD *cmodvec, WORD ncmod, WORD par)
5,790,659✔
3150
{
3151
        GETIDENTITY
3,863,448✔
3152
        UWORD *c, *d, *e, *f, *g, *h;
5,790,659✔
3153
        UWORD *x4,*x2;
5,790,659✔
3154
        UWORD *x3,*x1,*x5,*x6,*x7,*x8;
5,790,659✔
3155
        WORD y3,y1,y5,y6;
5,790,659✔
3156
        WORD n1, i, y2, y4;
5,790,659✔
3157
        WORD nh, tdenom, tnumer, nmod;
5,790,659✔
3158
        LONG x;
5,790,659✔
3159
        if ( ncmod == 0 ) return(0);                /* No modulus operation */
5,790,659✔
3160
        nmod = ABS(ncmod);
5,790,659✔
3161
        n1 = *na;
5,790,659✔
3162
        if ( ( par & UNPACK ) != 0 ) UnPack(a,n1,&tdenom,&tnumer);
5,790,659✔
3163
        else { tnumer = n1; }
5,790,641✔
3164
/*
3165
        We fish out the special case that the coefficient is short as well. 
3166
        There is no need to make lots of calls etc
3167
*/
3168
        if ( ( ( par & UNPACK ) == 0 ) && nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
5,790,659✔
3169
                goto simplecase;
1,816,204✔
3170
        }
3171
        else if ( nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
2,091,449✔
3172
                if ( a[1] != 1 ) {
18✔
3173
                        a[1] = a[1] % cmodvec[0];
18✔
3174
                        if ( a[1] == 0 ) {
18✔
3175
                                MesPrint("Division by zero in short modulus arithmetic");
×
3176
                                return(-1);
×
3177
                        }
3178
                        y1 = 0;
18✔
3179
                        if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 ) ) {
18✔
3180
                                y1 = AC.modinverses[a[1]];
×
3181
                        }
3182
                        else {
3183
                                GetModInverses(a[1],cmodvec[0],&y1,&y2);
18✔
3184
                        }
3185
                        x = a[0];
18✔
3186
                        a[0] = (x*y1) % cmodvec[0];
18✔
3187
                        a[1] = 1;
18✔
3188
                }
3189
                else {
3190
simplecase:
×
3191
                        a[0] = a[0] % cmodvec[0];
1,816,204✔
3192
                }
3193
                if ( a[0] == 0 ) { *na = 0; return(0); }
1,816,222✔
3194
                if ( ( AC.modmode & POSNEG ) != 0 ) {
1,597,185✔
3195
                        if ( a[0] > (UWORD)(cmodvec[0]/2) ) {
×
3196
                                a[0] =  cmodvec[0] - a[0];
×
3197
                                *na = -*na;
×
3198
                        }
3199
                }
3200
                else if ( *na < 0 ) {
1,597,185✔
3201
                        *na = 1; a[0] = cmodvec[0] - a[0];
788,412✔
3202
                }
3203
                return(0);
1,597,185✔
3204
        }
3205
        c = NumberMalloc("TakeModulus"); d = NumberMalloc("TakeModulus"); e = NumberMalloc("TakeModulus");
3,974,437✔
3206
        f = NumberMalloc("TakeModulus"); g = NumberMalloc("TakeModulus"); h = NumberMalloc("TakeModulus");
3,974,437✔
3207
        n1 = ABS(n1);
3,974,437✔
3208
        if ( DivLong(a,tnumer,(UWORD *)cmodvec,nmod,
3,974,437✔
3209
                c,&nh,a,&tnumer) ) goto ModErr;
×
3210
        if ( tnumer == 0 ) { *na = 0; goto normalreturn; }
3,974,437✔
3211
        if ( ( par & UNPACK ) == 0 ) {
3,612,633✔
3212
                if ( ( AC.modmode & POSNEG ) != 0 ) {
3,612,633✔
3213
                        NormalModulus(a,&tnumer);
×
3214
                }
3215
                else if ( tnumer < 0 ) {
3,612,633✔
3216
                        SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
1,209,327✔
3217
                }
3218
                *na = tnumer;
3,612,633✔
3219
                goto normalreturn;
3,612,633✔
3220
        }
3221
        if ( tdenom == 1 && a[n1] == 1 ) {
×
3222
                if ( ( AC.modmode & POSNEG ) != 0 ) {
×
3223
                        NormalModulus(a,&tnumer);
×
3224
                }
3225
                else if ( tnumer < 0 ) {
×
3226
                        SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
×
3227
                }
3228
                *na = tnumer;
×
3229
                i = ABS(tnumer);
×
3230
                a += i;
×
3231
                *a++ = 1;
×
3232
                while ( --i > 0 ) *a++ = 0;
×
3233
                goto normalreturn;
×
3234
        }
3235
        if ( DivLong(a+n1,tdenom,(UWORD *)cmodvec,nmod,c,&nh,a+n1,&tdenom) ) goto ModErr;
×
3236
        if ( !tdenom ) {
×
3237
                MLOCK(ErrorMessageLock);
×
3238
                MesPrint("Division by zero in modulus arithmetic");
×
3239
                if ( AP.DebugFlag ) {
×
3240
                        AO.OutSkip = 3;
×
3241
                        FiniLine();
×
3242
                        i = *na;
×
3243
                        if ( i < 0 ) i = -i;
×
3244
                        while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)"  "); }
×
3245
                        i = *na;
×
3246
                        if ( i < 0 ) i = -i;
×
3247
                        while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)"  "); }
×
3248
                        TalToLine((UWORD)(*na));
×
3249
                        AO.OutSkip = 0;
×
3250
                        FiniLine();
×
3251
                }
3252
                MUNLOCK(ErrorMessageLock);
×
3253
                NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
×
3254
                NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
×
3255
                return(-1);
×
3256
        }
3257
        if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 )
×
3258
        && ( tdenom == 1 || tdenom == -1 ) ) {
×
3259
                *d = AC.modinverses[a[n1]]; y1 = 1; y2 = tdenom;
×
3260
                if ( MulLong(a,tnumer,d,y1,c,&y3) ) goto ModErr;
×
3261
                if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) ) goto ModErr;
×
3262
                if ( y2 < 0 ) tdenom = -tdenom;
×
3263
        }
3264
        else {
3265
          x2 = (UWORD *)cmodvec; x1 = c; i = nmod; while ( --i >= 0 ) *x1++ = *x2++;
×
3266
          x1 = c; x2 = a+n1; x3 = d; x4 = e; x5 = f; x6 = g;
×
3267
          y1 = nmod; y2 = tdenom; y4 = 0; y5 = 1; *x5 = 1;
×
3268
          for(;;) {
×
3269
                if ( DivLong(x1,y1,x2,y2,h,&nh,x3,&y3) ) goto ModErr;
×
3270
                if ( MulLong(x5,y5,h,nh,x6,&y6) ) goto ModErr;
×
3271
                if ( AddLong(x4,y4,x6,-y6,x6,&y6) ) goto ModErr;
×
3272
                if ( !y3 ) {
×
3273
                        if ( y2 != 1 || *x2 != 1 ) {
×
3274
                                MLOCK(ErrorMessageLock);
×
3275
                                MesPrint("Inverse in modulus arithmetic doesn't exist");
×
3276
                                MesPrint("Denominator and modulus are not relative prime");
×
3277
                                MUNLOCK(ErrorMessageLock);
×
3278
                                goto ModErr;
×
3279
                        }
3280
                        break;
×
3281
                }
3282
                x7 = x1; x1 = x2; y1 = y2; x2 = x3; y2 = y3; x3 = x7;
×
3283
                x8 = x4; x4 = x5; y4 = y5; x5 = x6; y5 = y6; x6 = x8;
×
3284
          }
3285
          if ( y5 < 0 && AddLong((UWORD *)cmodvec,nmod,x5,y5,x5,&y5) ) goto ModErr;
×
3286
          if ( MulLong(a,tnumer,x5,y5,c,&y3) ) goto ModErr;
×
3287
          if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) ) goto ModErr;
×
3288
        }
3289
        if ( !tdenom ) { *na = 0; goto normalreturn; }
×
3290
        if ( ( ( AC.modmode & POSNEG ) != 0 ) && ( ( par & FROMFUNCTION ) == 0 ) ) {
×
3291
                NormalModulus(a,&tdenom);
×
3292
        }
3293
        else if ( tdenom < 0 ) {
×
3294
                SubPLon((UWORD *)cmodvec,nmod,a,-tdenom,a,&tdenom);
×
3295
        }
3296
        *na = tdenom;
×
3297
        i = ABS(tdenom);
×
3298
        a += i;
×
3299
        *a++ = 1;
×
3300
        while ( --i > 0 ) *a++ = 0;
×
3301
normalreturn:
×
3302
        NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
3,974,437✔
3303
        NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
3,974,437✔
3304
        return(0);
3,974,437✔
3305
ModErr:
×
3306
        MLOCK(ErrorMessageLock);
×
3307
        MesCall("TakeModulus");
×
3308
        MUNLOCK(ErrorMessageLock);
×
3309
        NumberFree(c,"TakeModulus"); NumberFree(d,"TakeModulus"); NumberFree(e,"TakeModulus");
×
3310
        NumberFree(f,"TakeModulus"); NumberFree(g,"TakeModulus"); NumberFree(h,"TakeModulus");
×
3311
        SETERROR(-1)
×
3312
}
3313

3314
/*
3315
                 #] TakeModulus : 
3316
                 #[ TakeNormalModulus :  WORD TakeNormalModulus(a,na,par)
3317

3318
                added by Jan [01-09-2010]
3319
*/
3320

3321
WORD TakeNormalModulus (UWORD *a, WORD *na, UWORD *c, WORD nc, WORD par)
16,687,203✔
3322
{
3323
        WORD n;
16,687,203✔
3324
        WORD nhalfc;
16,687,203✔
3325
        UWORD *halfc;
16,687,203✔
3326

3327
        GETIDENTITY;
16,687,203✔
3328
        
3329
        /* determine c/2 by right shifting */
3330
        halfc = NumberMalloc("TakeNormalModulus");
16,687,203✔
3331
        nhalfc=nc;
16,687,203✔
3332
        WCOPY(halfc,c,nc);
74,114,951✔
3333

3334
        for (n=0; n<nhalfc; n++) {
74,114,951✔
3335
                halfc[n] /= 2;
57,427,748✔
3336
                if (n+1<nc) halfc[n] |= c[n+1] << (BITSINWORD-1);
57,427,748✔
3337
        }
3338

3339
        if (halfc[nhalfc-1]==0)
16,687,203✔
3340
                nhalfc--;
5,538✔
3341
                                 
3342
        /* takes care of the number never expanding, e.g., -1(mod 100) -> 99 -> -1 */
3343
        if (BigLong(a,ABS(*na),halfc,nhalfc) > 0) {
16,687,203✔
3344
        
3345
                TakeModulus(a,na,c,nc,par);
5,790,641✔
3346
        
3347
                n = ABS(*na);
5,790,641✔
3348
                if (BigLong(a,n,halfc,nhalfc) > 0) {
5,790,641✔
3349
                        SubPLon(c,nc,a,n,a,&n);
2,609,975✔
3350
                        *na = (*na > 0 ? -n : n);
2,609,975✔
3351
                }
3352
        }
3353

3354
        NumberFree(halfc,"TakeNormalModulus");
16,687,203✔
3355
        return(0);
16,687,203✔
3356
}
3357

3358
/*
3359
                 #] TakeNormalModulus : 
3360
                 #[ MakeModTable :        WORD MakeModTable()
3361
*/
3362

NEW
3363
WORD MakeModTable(void)
×
3364
{
3365
        LONG size, i, j, n;
×
3366
        n = ABS(AC.ncmod);
×
3367
        if ( AC.modpowers ) {
×
3368
                M_free(AC.modpowers,"AC.modpowers");
×
3369
                AC.modpowers = NULL;
×
3370
        }
3371
        if ( n > 2 ) {
×
3372
                MLOCK(ErrorMessageLock);
×
3373
                MesPrint("&No memory for modulus generator power table");
×
3374
                MUNLOCK(ErrorMessageLock);
×
3375
                Terminate(-1);
×
3376
        }
3377
        if ( n == 0 ) return(0);
×
3378
        size = (LONG)(*AC.cmod);
×
3379
        if ( n == 2 ) size += (((LONG)AC.cmod[1])<<BITSINWORD);
×
3380
        AC.modpowers = (UWORD *)Malloc1(size*n*sizeof(UWORD),"table for powers of modulus");
×
3381
        if ( n == 1 ) {
×
3382
                j = 1;
×
3383
                for ( i = 0; i < size; i++ ) AC.modpowers[i] = 0;
×
3384
                for ( i = 0; i < size; i++ ) {
×
3385
                        AC.modpowers[j] = (WORD)i;
×
3386
                        j *= *AC.powmod;
×
3387
                        j %= *AC.cmod;
×
3388
                }
3389
                for ( i = 2; i < size; i++ ) {
×
3390
                        if ( AC.modpowers[i] == 0 ) {
×
3391
                                MLOCK(ErrorMessageLock);
×
3392
                                MesPrint("&improper generator for this modulus");
×
3393
                                MUNLOCK(ErrorMessageLock);
×
3394
                                M_free(AC.modpowers,"AC.modpowers");
×
3395
                                return(-1);
×
3396
                        }
3397
                }
3398
                AC.modpowers[1] = 0;
×
3399
        }
3400
        else {
3401
                GETIDENTITY
3402
                WORD nScrat, n2;
×
3403
                UWORD *MMscrat7 = NumberMalloc("MakeModTable"), *MMscratC = NumberMalloc("MakeModTable");
×
3404
                *MMscratC = 1;
×
3405
                nScrat = 1;
×
3406
                j = size * 2;
×
3407
                for ( i = 0; i < j; i+=2 ) { AC.modpowers[i] = 0; AC.modpowers[i+1] = 0; }
×
3408
                for ( i = 0; i < size; i++ ) {
×
3409
                        j = *MMscratC + (((LONG)MMscratC[1])<<BITSINWORD);
×
3410
                        j *= 2;
×
3411
                        AC.modpowers[j] = (WORD)(i & WORDMASK);
×
3412
                        AC.modpowers[j+1] = (WORD)(i >> BITSINWORD);
×
3413
                        MulLong((UWORD *)MMscratC,nScrat,(UWORD *)AC.powmod,
×
3414
                        AC.npowmod,(UWORD *)MMscrat7,&n2);
3415
                        TakeModulus(MMscrat7,&n2,AC.cmod,AC.ncmod,NOUNPACK);
×
3416
                        *MMscratC = *MMscrat7; MMscratC[1] = MMscrat7[1]; nScrat = n2;
×
3417
                }
3418
                NumberFree(MMscrat7,"MakeModTable"); NumberFree(MMscratC,"MakeModTable");
×
3419
                j = size * 2;
×
3420
                for ( i = 4; i < j; i+=2 ) {
×
3421
                        if ( AC.modpowers[i] == 0 && AC.modpowers[i+1] == 0 ) {
×
3422
                                MLOCK(ErrorMessageLock);
×
3423
                                MesPrint("&improper generator for this modulus");
×
3424
                                MUNLOCK(ErrorMessageLock);
×
3425
                                M_free(AC.modpowers,"AC.modpowers");
×
3426
                                return(-1);
×
3427
                        }
3428
                }
3429
                AC.modpowers[2] = AC.modpowers[3] = 0;
×
3430
        }
3431
        return(0);
3432
}
3433

3434
/*
3435
                 #] MakeModTable : 
3436
          #] RekenTerms : 
3437
          #[ Functions :
3438
                 #[ Factorial :                WORD Factorial(n,a,na)
3439

3440
        Starts with only the value of fac_(0).
3441
        Builds up what is needed and remembers it for the next time.
3442

3443
        We have:
3444
                AT.nfac: the number of the highest stored factorial
3445
                AT.pfac: the array of locations in the array of stored factorials
3446
                AT.factorials: the array with stored factorials
3447
*/
3448

3449
int Factorial(PHEAD WORD n, UWORD *a, WORD *na)
42✔
3450
{
3451
        GETBIDENTITY
3452
        UWORD *b, *c;
42✔
3453
        WORD nc;
42✔
3454
        int i, j;
42✔
3455
        LONG ii;
42✔
3456
        if ( n > AT.nfac ) {
42✔
3457
                if ( AT.factorials == 0 ) {
6✔
3458
                        AT.nfac = 0; AT.mfac = 50; AT.sfact = 400;
6✔
3459
                        AT.pfac = (LONG *)Malloc1((AT.mfac+2)*sizeof(LONG),"factorials");
6✔
3460
                        AT.factorials = (UWORD *)Malloc1(AT.sfact*sizeof(UWORD),"factorials");
6✔
3461
                        AT.factorials[0] = 1; AT.pfac[0] = 0; AT.pfac[1] = 1;
6✔
3462
                }
3463
                b = a;
6✔
3464
                c = AT.factorials+AT.pfac[AT.nfac];
6✔
3465
                nc = i = AT.pfac[AT.nfac+1] - AT.pfac[AT.nfac];
6✔
3466
                while ( --i >= 0 ) *b++ = *c++;
12✔
3467
                for ( j = AT.nfac+1; j <= n; j++ ) {
42✔
3468
                        Product(a,&nc,j);
36✔
3469
                        if ( nc > AM.MaxTal ) {
36✔
3470
                                MLOCK(ErrorMessageLock);
×
3471
                                MesPrint("Overflow in factorial. MaxTal = %d",AM.MaxTal);
×
3472
                                MesPrint("Increase MaxTerm in %s",setupfilename);
×
3473
                                MUNLOCK(ErrorMessageLock);
×
3474
                                return(-1);
×
3475
                        }
3476
                        if ( j > AT.mfac ) {  /* double the pfac buffer */
36✔
3477
                                LONG *p;
×
3478
                                p = (LONG *)Malloc1((AT.mfac*2+2)*sizeof(LONG),"factorials");
×
3479
                                i = AT.mfac;
×
3480
                                for ( i = AT.mfac+1; i >= 0; i-- ) p[i] = AT.pfac[i];
×
3481
                                M_free(AT.pfac,"factorial offsets"); AT.pfac = p; AT.mfac *= 2;
×
3482
                        }
3483
                        if ( AT.pfac[j] + nc >= AT.sfact ) { /* double the factorials buffer */
36✔
3484
                                UWORD *f;
×
3485
                                f = (UWORD *)Malloc1(AT.sfact*2*sizeof(UWORD),"factorials");
×
3486
                                ii = AT.sfact;
×
3487
                                c = AT.factorials; b = f;
×
3488
                                while ( --ii >= 0 ) *b++ = *c++;
×
3489
                                M_free(AT.factorials,"factorials");
×
3490
                                AT.factorials = f;
×
3491
                                AT.sfact *= 2;
×
3492
                        }
3493
                        b = a; c = AT.factorials + AT.pfac[j]; i = nc;
36✔
3494
                        while ( --i >= 0 ) *c++ = *b++;
72✔
3495
                        AT.pfac[j+1] = AT.pfac[j] + nc;
36✔
3496
                }
3497
                *na = nc;
6✔
3498
                AT.nfac = n;
6✔
3499
        }
3500
        else if ( n == 0 ) {
36✔
3501
                *a = 1; *na = 1;
18✔
3502
        }
3503
        else {
3504
                *na = i = AT.pfac[n+1] - AT.pfac[n];
18✔
3505
                b = AT.factorials + AT.pfac[n];
18✔
3506
                while ( --i >= 0 ) *a++ = *b++;
36✔
3507
        }
3508
        return(0);
3509
}
3510

3511
/*
3512
                 #] Factorial : 
3513
                 #[ Bernoulli :                WORD Bernoulli(n,a,na)
3514

3515
        Starts with only the value of bernoulli_(0).
3516
        Builds up what is needed and remembers it for the next time.
3517
        b_0 = 1
3518
        (n+1)*b_n = -b_{n-1}-sum_(i,1,n-1,b_i*b_{n-i})
3519
        The n-1 plays only a role for b_2.
3520
        We have hard coded b_0,b_1,b_2 and b_odd. After that:
3521
        (2n+1)*b_2n = -sum_(i,1,n-1,b_2i*b_{2n-2i})
3522

3523
        We have:
3524
                AT.nBer: the number of the highest stored Bernoulli number
3525
                AT.pBer: the array of locations in the array of stored Bernoulli numbers
3526
                AT.bernoullis: the array with stored Bernoulli numbers
3527
*/
3528

3529
int Bernoulli(WORD n, UWORD *a, WORD *na)
×
3530
{
3531
        GETIDENTITY
3532
        UWORD *b, *c, *scrib, *ntop, *ntop1;
×
3533
        WORD i, i1, i2, nhalf, nqua, nscrib, nntop, nntop1, *oldworkpointer;
×
3534
        UWORD twee = 2, twonplus1;
×
3535
        int j;
×
3536
        LONG ii;
×
3537
        if ( n <= 1 ) {
×
3538
                if ( n == 0 ) { a[0] = a[1] = 1; *na = 3; }
×
3539
                else if ( n == 1 ) { a[0] = 1; a[1] = 2; *na = 3; }
×
3540
                return(0);
×
3541
        }
3542
        if ( ( n & 1 ) != 0 ) { a[0] = a[1] = 0; *na = 0; return(0); }
×
3543
        nhalf = n/2;
×
3544
        if ( nhalf > AT.nBer ) {
×
3545
                oldworkpointer = AT.WorkPointer;
×
3546
                if ( AT.bernoullis == 0 ) {
×
3547
                        AT.nBer = 1; AT.mBer = 50; AT.sBer = 400;
×
3548
                        AT.pBer = (LONG *)Malloc1((AT.mBer+2)*sizeof(LONG),"bernoullis");
×
3549
                        AT.bernoullis = (UWORD *)Malloc1(AT.sBer*sizeof(UWORD),"bernoullis");
×
3550
                        AT.pBer[1] = 0; AT.pBer[2] = 3;
×
3551
                        AT.bernoullis[0] = 3; AT.bernoullis[1] = 1; AT.bernoullis[2] = 12;
×
3552
                        if ( nhalf == 1 ) {
×
3553
                                a[0] = 1; a[1] = 12; *na = 3; return(0);
×
3554
                        }
3555
                }
3556
                while ( nhalf > AT.mBer ) {
×
3557
                        LONG *p;
×
3558
                        p = (LONG *)Malloc1((AT.mBer*2+1)*sizeof(LONG),"bernoullis");
×
3559
                        i = AT.mBer;
×
3560
                        for ( i = AT.mBer; i >= 0; i-- ) p[i] = AT.pBer[i];
×
3561
                        M_free(AT.pBer,"factorial pointers"); AT.pBer = p; AT.mBer *= 2;
×
3562
                }
3563
                for ( n = AT.nBer+1; n <= nhalf; n++ ) {
×
3564
                        scrib = (UWORD *)(AT.WorkPointer);
×
3565
                        nqua = n/2;
×
3566
                        if ( ( n & 1 ) == 1 ) {
×
3567
                                nscrib = 0; ntop = scrib;
×
3568
                        }
3569
                        else {
3570
                                b = AT.bernoullis + AT.pBer[nqua];
×
3571
                                nscrib = *b++;
×
3572
                                i = (WORD)(REDLENG(nscrib));
×
3573
                                MulRat(BHEAD b,i,b,i,scrib,&nscrib);
×
3574
                                ntop = scrib + 2*nscrib;
×
3575
                                nqua--;
×
3576
                        }
3577
                        for ( j = 1; j <= nqua; j++ ) {
×
3578
                                b = AT.bernoullis + AT.pBer[j];
×
3579
                                c = AT.bernoullis + AT.pBer[n-j];
×
3580
                                i1 = (WORD)(*b); i2 = (WORD)(*c);
×
3581
                                i1 = REDLENG(i1);
×
3582
                                i2 = REDLENG(i2);
×
3583
                                MulRat(BHEAD b+1,i1,c+1,i2,ntop,&nntop);
×
3584
                                Mully(BHEAD ntop,&nntop,&twee,1);
×
3585
                                if ( nscrib ) {
×
3586
                                        i = (WORD)nntop; if ( i < 0 ) i = -i;
×
3587
                                        ntop1 = ntop + 2*i;
×
3588
                                        AddRat(BHEAD ntop,nntop,scrib,nscrib,ntop1,&nntop1);
×
3589
                                }
3590
                                else {
3591
                                        ntop1 = ntop; nntop1 = nntop;
×
3592
                                }
3593
                                nscrib = i1 = (WORD)nntop1;
×
3594
                                if ( i1 < 0 ) i1 = - i1;
×
3595
                                i1 = 2*i1;
×
3596
                                for ( i = 0; i < i1; i++ ) scrib[i] = ntop1[i];
×
3597
                                ntop = scrib + i1; 
×
3598
                        }
3599
                        twonplus1 = 2*n+1;
×
3600
                        Divvy(BHEAD scrib,&nscrib,&twonplus1,-1);
×
3601
                        i1 = INCLENG(nscrib);
×
3602
                        i2 = i1; if ( i2 < 0 ) i2 = -i2;
×
3603
                        i = (WORD)(AT.bernoullis[AT.pBer[n-1]]);
×
3604
                        if ( i < 0 ) i = -i;
×
3605
                        AT.pBer[n] = AT.pBer[n-1]+i;
×
3606
                        if ( AT.pBer[n] + i2 >= AT.sBer ) {
×
3607
                                UWORD *f;
×
3608
                                f = (UWORD *)Malloc1(AT.sBer*2*sizeof(UWORD),"bernoullis");
×
3609
                                ii = AT.sBer;
×
3610
                                c = AT.bernoullis; b = f;
×
3611
                                while ( --ii >= 0 ) *b++ = *c++;
×
3612
                                M_free(AT.bernoullis,"bernoullis");
×
3613
                                AT.bernoullis = f;
×
3614
                                AT.sBer *= 2;
×
3615
                        }
3616
                        c = AT.bernoullis + AT.pBer[n]; b = scrib;
×
3617
                        *c++ = i1;
×
3618
                        for ( i = 1; i < i2; i++ ) *c++ = *b++;
×
3619
                }
3620
                AT.nBer = nhalf;
×
3621
                AT.WorkPointer = oldworkpointer;
×
3622
        }
3623
        b = AT.bernoullis + AT.pBer[nhalf];
×
3624
        *na = i = (WORD)(*b++);
×
3625
        if ( i < 0 ) i = -i;
×
3626
        i--;
×
3627
        while ( --i >= 0 ) *a++ = *b++;
×
3628
        return(0);
3629
}
3630

3631
/*
3632
                 #] Bernoulli : 
3633
                 #[ NextPrime :
3634
*/
3635
/**
3636
 *        Gives the next prime number in the list of prime numbers.
3637
 *
3638
 *        If the list isn't long enough we expand it.
3639
 *        For ease in ParForm and because these lists shouldn't be very big
3640
 *        we let each worker keep its own list.
3641
 *
3642
 *        The list is cut off at MAXPOWER, because we don't want to get into
3643
 *        trouble that the power of a variable gets larger than the prime number.
3644
 */
3645

3646
#if ( BITSINWORD == 32 )
3647

3648
void StartPrimeList(PHEAD0)
106✔
3649
{
3650
        int i, j;
106✔
3651
        AR.PrimeList[AR.numinprimelist++] = 3;
106✔
3652
        for ( i = 5; i < 46340; i += 2 ) {
2,455,914✔
3653
                for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*AR.PrimeList[j] <= i; j++ ) {
25,884,564✔
3654
                        if ( i % AR.PrimeList[j] == 0 ) goto nexti;
25,376,824✔
3655
                }
3656
                AR.PrimeList[AR.numinprimelist++] = i;
507,740✔
3657
nexti:;
2,455,808✔
3658
        }
3659
        AR.notfirstprime = 1;
106✔
3660
}
106✔
3661

3662
#endif
3663

3664
WORD NextPrime(PHEAD WORD num)
8,150✔
3665
{
3666
        int i, j;
8,150✔
3667
        WORD *newpl;
8,150✔
3668
        LONG newsize, x;
8,150✔
3669
#if ( BITSINWORD == 32 )
3670
        if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
8,150✔
3671
#endif
3672
        if ( num > AT.inprimelist ) {
8,150✔
3673
                while ( AT.inprimelist < num ) {
220✔
3674
                        if ( num >= AT.sizeprimelist ) {
116✔
3675
                                if ( AT.sizeprimelist == 0 ) newsize = 32;
86✔
3676
                                else newsize = 2*AT.sizeprimelist;
×
3677
                                while ( num >= newsize ) newsize = newsize*2;
86✔
3678
                                newpl = (WORD *)Malloc1(newsize*sizeof(WORD),"NextPrime");
86✔
3679
                                for ( i = 0; i < AT.sizeprimelist; i++ ) {
172✔
3680
                                        newpl[i] = AT.primelist[i];
×
3681
                                }
3682
                                if ( AT.sizeprimelist > 0 ) {
86✔
3683
                                        M_free(AT.primelist,"NextPrime");
×
3684
                                }
3685
                                AT.sizeprimelist = newsize;
86✔
3686
                                AT.primelist = newpl;
86✔
3687
                        }
3688
                        if ( AT.inprimelist < 0 ) { i = MAXPOSITIVE; }
116✔
3689
                        else { i = AT.primelist[AT.inprimelist]; }
30✔
3690
                        while ( i > MAXPOWER ) {
1,140✔
3691
                                i -= 2; x = i;
1,140✔
3692
#if ( BITSINWORD == 32 )
3693
                                for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*(LONG)(AR.PrimeList[j]) <= x; j++ ) {
726,022✔
3694
                                        if ( x % AR.PrimeList[j] == 0 ) goto nexti;
725,906✔
3695
                                }
3696
#else
3697
                                for ( j = 3; j*((LONG)j) <= x; j += 2 ) {
3698
                                        if ( x % j == 0 ) goto nexti;
3699
                                }
3700
#endif
3701
                                AT.inprimelist++;
116✔
3702
                                AT.primelist[AT.inprimelist] = i;
116✔
3703
                                break;
116✔
3704
nexti:;
1,140✔
3705
                        }
3706
                        if ( i < MAXPOWER ) {
116✔
3707
                                MLOCK(ErrorMessageLock);
×
3708
                                MesPrint("There are not enough short prime numbers for this calculation");
×
3709
                                MesPrint("Try to use a computer with a %d-bits architecture",
×
3710
                                        (int)(BITSINWORD*4));
3711
                                MUNLOCK(ErrorMessageLock);
×
3712
                                Terminate(-1);
220✔
3713
                        }
3714
                }
3715
        }
3716
        return(AT.primelist[num]);
8,150✔
3717
}
3718
 
3719
/*
3720
                 #] NextPrime : 
3721
                 #[ Moebius :
3722

3723
                Returns the value of the Moebius function if n fits inside
3724
                a WORD.
3725
                The method we use is a bit like the sieve of Erathostenes.
3726
*/
3727

3728
WORD Moebius(PHEAD WORD nn)
2,280✔
3729
{
3730
        WORD i,n = nn, x;
2,280✔
3731
        LONG newsize;
2,280✔
3732
        SBYTE *newtable, mu;
2,280✔
3733
#if ( BITSINWORD == 32 )
3734
        if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
2,280✔
3735
#endif
3736
/*
3737
        First we make sure that:
3738
                a: the table is big enough.
3739
                b: the number is not already in the table.
3740
*/
3741
        if ( nn >= AR.moebiustablesize ) {
2,280✔
3742
                if ( AR.moebiustablesize <= 0 ) { newsize = (LONG)nn + 20; }
58✔
3743
                else { newsize = (LONG)nn*2; }
38✔
3744
                if ( newsize > MAXPOSITIVE ) newsize = MAXPOSITIVE;
58✔
3745
                newtable = (SBYTE *)Malloc1(newsize*sizeof(SBYTE),"Moebius");
58✔
3746
                for ( i = 0; i < AR.moebiustablesize; i++ ) newtable[i] = AR.moebiustable[i];
142,300✔
3747
                for ( ; i < newsize; i++ ) newtable[i] = 2;
562,102✔
3748
                if ( AR.moebiustablesize > 0 ) M_free(AR.moebiustable,"Moebius");
58✔
3749
                AR.moebiustable = newtable;                        
58✔
3750
                AR.moebiustablesize = newsize;
58✔
3751
        }
3752
        /* NOTE: nn == MAXPOSITIVE never fits in moebiustable. */
3753
        if ( nn != MAXPOSITIVE && AR.moebiustable[nn] != 2 ) return((WORD)AR.moebiustable[nn]);
2,280✔
3754
        mu = 1;
2,856✔
3755
        if ( n == 1 ) goto putvalue;
1,431✔
3756
        if ( n % 2 == 0 ) {
1,425✔
3757
                n /= 2;
714✔
3758
                if ( n % 2 == 0 ) { mu = 0; goto putvalue; }
714✔
3759
                if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n]; goto putvalue; }
371✔
3760
                mu = -mu;
38✔
3761
                if ( n == 1 ) goto putvalue;
38✔
3762
        }
3763
#if ( BITSINWORD == 32 )
3764
        for ( i = 0; i < AR.numinprimelist; i++ ) {
3,850✔
3765
                x = AR.PrimeList[i];
3,850✔
3766
#else
3767
        for ( x = 3; x < MAXPOSITIVE; x += 2 ) {
3768
#endif
3769
                if ( n % x == 0 ) {
3,850✔
3770
                        n /= x;
528✔
3771
                        if ( n % x == 0 ) { mu = 0; goto putvalue; }
528✔
3772
                        if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n]; goto putvalue; }
414✔
3773
                        mu = -mu;
186✔
3774
                        if ( n == 1 ) goto putvalue;
186✔
3775
                }
3776
                if ( n < x*x ) break; /* notice that x*x always fits inside a WORD */
3,508✔
3777
        }
3778
        mu = -mu;
407✔
3779
putvalue:
1,425✔
3780
        if ( nn != MAXPOSITIVE ) AR.moebiustable[nn] = mu;
1,431✔
3781
        return((WORD)mu);
1,431✔
3782
}
3783

3784
/*
3785
                 #] Moebius : 
3786
                 #[ wranf :
3787

3788
                A random number generator that generates random WORDs with a very
3789
                long sequence. It is based on the Knuth generator.
3790

3791
                We take some care that each thread can run its own, but each
3792
                uses its own startup. Hence the seed includes the identity of
3793
                the thread.
3794

3795
                For NPAIR1, NPAIR2 we can use any pair from the table on page 28.
3796
                Candidates are 24,55 (the example on the pages 171,172)
3797
                or (33,97) or (38,89)
3798
                These values are defined in fsizes.h and used in startup.c and threads.c
3799
*/
3800

3801
#define WARMUP 6
3802

3803
static void wranfnew(PHEAD0)
29,244✔
3804
{
3805
        int i;
29,244✔
3806
        LONG j;
29,244✔
3807
        for ( i = 0; i < AR.wranfnpair1; i++ ) {
1,140,516✔
3808
                j = AR.wranfia[i] - AR.wranfia[i+(AR.wranfnpair2-AR.wranfnpair1)];
1,111,272✔
3809
                if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
1,111,272✔
3810
                AR.wranfia[i] = j;
1,111,272✔
3811
        }
3812
        for ( i = AR.wranfnpair1; i < AR.wranfnpair2; i++ ) {
1,520,688✔
3813
                j = AR.wranfia[i] - AR.wranfia[i-AR.wranfnpair1];
1,491,444✔
3814
                if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
1,491,444✔
3815
                AR.wranfia[i] = j;
1,491,444✔
3816
        }
3817
}
29,244✔
3818

3819
void iniwranf(PHEAD0)
403✔
3820
{
3821
        int imax = AR.wranfnpair2-1;
403✔
3822
        ULONG i, ii, seed = AR.wranfseed;
403✔
3823
        LONG j, k;
403✔
3824
        ULONG offset = 12345;
403✔
3825
#ifdef PARALLELCODE
3826
        int id;
323✔
3827
#if defined(WITHPTHREADS)
3828
        id = AT.identity;
323✔
3829
#elif defined(WITHMPI)
3830
        id = PF.me;
3831
#endif
3832
        seed += id;
323✔
3833
        i = id + 1;
323✔
3834
        if ( i > 1 ) {
323✔
3835
                ULONG pow, accu;
3836
                pow = offset; accu = 1;
3837
                while ( i ) {
671✔
3838
                        if ( ( i & 1 ) != 0 ) accu *= pow;
467✔
3839
                        i /= 2; pow = pow*pow;
467✔
3840
                }
3841
                offset = accu;
3842
        }
3843
#endif
3844
        if ( seed < ((LONG)1<<(BITSINWORD-1)) ) {
403✔
3845
                j = ( (seed+31459L) << (BITSINWORD-2))+offset;
403✔
3846
        }
3847
        else if ( seed < ((LONG)1<<(BITSINWORD+10-1)) ) {
×
3848
                j = ( (seed+31459L) << (BITSINWORD-10-2))+offset;
×
3849
        }
3850
        else {
3851
                j = ( (seed+31459L) << 1)+offset;
×
3852
        }
3853
        if ( ( seed & 1 ) == 1 ) seed++;
403✔
3854
        j += seed;
403✔
3855
        AR.wranfia[imax] = j;
403✔
3856
        k = 1;
403✔
3857
        for ( i = 0; i <= (ULONG)(imax); i++ ) {
36,270✔
3858
                ii = (AR.wranfnpair1*i)%AR.wranfnpair2;
35,867✔
3859
                AR.wranfia[ii] = k;
35,867✔
3860
                k = ULongToLong((ULONG)j - (ULONG)k);
35,867✔
3861
                if ( k < 0 ) k += (LONG)1 << (2*BITSINWORD-2);
35,867✔
3862
                j = AR.wranfia[ii];
35,867✔
3863
        }
3864
        for ( i = 0; i < WARMUP; i++ ) wranfnew(BHEAD0);
2,821✔
3865
        AR.wranfcall = 0;
403✔
3866
}
403✔
3867

3868
UWORD wranf(PHEAD0)
2,401,604✔
3869
{
3870
        UWORD wval;
2,401,604✔
3871
        if ( AR.wranfia == 0 ) {
2,401,604✔
3872
                AR.wranfia = (ULONG *)Malloc1(AR.wranfnpair2*sizeof(ULONG),"wranf");
403✔
3873
                iniwranf(BHEAD0);
403✔
3874
        }
3875
        if ( AR.wranfcall >= AR.wranfnpair2) {
2,401,604✔
3876
                wranfnew(BHEAD0);
26,826✔
3877
                AR.wranfcall = 0;
26,826✔
3878
        }
3879
        wval = (UWORD)(AR.wranfia[AR.wranfcall++]>>(BITSINWORD-1));
2,401,604✔
3880
        return(wval);
2,401,604✔
3881
}
3882

3883
/*
3884
        Returns a random UWORD in the range (0,...,imax-1)
3885
*/
3886

3887
UWORD iranf(PHEAD UWORD imax)
11,934✔
3888
{
3889
        UWORD i;
11,934✔
3890
        ULONG x, xmax;
11,934✔
3891
        if (imax < 2) return 0;
11,934✔
3892
        x = (LONG)1 << BITSINWORD;
11,934✔
3893
        xmax = x - x%imax;
11,934✔
3894
        while ( ( i = wranf(BHEAD0) ) >= xmax ) {}
11,934✔
3895
        return(i%imax);
11,934✔
3896
}
3897

3898
/*
3899
                 #] wranf : 
3900
                 #[ PreRandom :
3901

3902
                The random number generator of the preprocessor.
3903
                This one is completely different from the execution time generator
3904
                random_(number). In the preprocessor we generate a floating point
3905
                number in a string according to a distribution.
3906
                Currently allowed are:
3907
                        RANDOM_(log,min,max)
3908
                        RANDOM_(lin,min,max)
3909
                The return value is a string with the floating point number.
3910
*/
3911

3912
UBYTE *PreRandom(UBYTE *s)
×
3913
{
3914
        GETIDENTITY
3915
        UBYTE *mode,*mins = 0,*maxs = 0, *outval;
×
3916
        float num;
×
3917
        double minval, maxval, value = 0;
×
3918
        int linlog = -1;
×
3919
        mode = s;
×
3920
        while ( FG.cTable[*s] <= 1 ) s++;
×
3921
        if ( *s == ',' ) { *s = 0; s++; }
×
3922
        mins = s;
×
3923
        while ( *s && *s != ',' ) s++;
×
3924
        if ( *s == ',' ) { *s = 0; s++; }
×
3925
        maxs = s;
×
3926
        while ( *s && *s != ',' ) s++;
×
3927
        if ( *s || *maxs == 0 || *mins == 0 ) {
×
3928
                MesPrint("@Illegal arguments in macro RANDOM_");
×
3929
                Terminate(-1);
×
3930
        }
3931
        if ( StrICmp(mode,(UBYTE *)"lin") == 0 ) {
×
3932
                linlog = 0;
3933
        }
3934
        else if ( StrICmp(mode,(UBYTE *)"log") == 0 ) {
×
3935
                linlog = 1;
3936
        }
3937
        else {
3938
                MesPrint("@Illegal mode argument in macro RANDOM_");
×
3939
                Terminate(-1);
×
3940
        }
3941

3942
        sscanf((char *)mins,"%f",&num); minval = num;
×
3943
        sscanf((char *)maxs,"%f",&num); maxval = num;
×
3944

3945
        /*
3946
         * Note on ParFORM: we should use the same random number on all the
3947
         * processes in the complication phase. The random number is generated
3948
         * on the master and broadcast to the other processes.
3949
         */
3950
        {
3951
                UWORD x;
×
3952
                double xx;
×
3953
#ifdef WITHMPI
3954
                x = 0;
3955
                if ( PF.me == MASTER ) {
3956
                        x = wranf(BHEAD0);
3957
                }
3958
                x = (UWORD)PF_BroadcastNumber((LONG)x);
3959
#else
3960
                x = wranf(BHEAD0);
×
3961
#endif
3962
                xx = x/pow(2.0,(double)(BITSINWORD-1));
×
3963
                if ( linlog == 0 ) {
×
3964
                        value = minval + (maxval-minval)*xx;
×
3965
                }
3966
                else if ( linlog == 1 ) {
×
3967
                        value = minval * pow(maxval/minval,xx);
×
3968
                }
3969
        }
3970

3971
        outval = (UBYTE *)Malloc1(64,"PreRandom");
×
3972
        if ( ABS(value) < 0.00001 || ABS(value) > 1000000. ) {
×
3973
                snprintf((char *)outval,64,"%e",value);
×
3974
        }
3975
        else if ( ABS(value) < 0.0001 ) { snprintf((char *)outval,64,"%10f",value); }
×
3976
        else if ( ABS(value) < 0.001 ) { snprintf((char *)outval,64,"%9f",value); }
×
3977
        else if ( ABS(value) < 0.01 ) { snprintf((char *)outval,64,"%8f",value); }
×
3978
        else if ( ABS(value) < 0.1 ) { snprintf((char *)outval,64,"%7f",value); }
×
3979
        else if ( ABS(value) < 1. ) { snprintf((char *)outval,64,"%6f",value); }
×
3980
        else if ( ABS(value) < 10. ) { snprintf((char *)outval,64,"%5f",value); }
×
3981
        else if ( ABS(value) < 100. ) { snprintf((char *)outval,64,"%4f",value); }
×
3982
        else if ( ABS(value) < 1000. ) { snprintf((char *)outval,64,"%3f",value); }
×
3983
        else if ( ABS(value) < 10000. ) { snprintf((char *)outval,64,"%2f",value); }
×
3984
        else { snprintf((char *)outval,64,"%1f",value); }
×
3985
        return(outval);
×
3986
}
3987

3988
/*
3989
                 #] PreRandom : 
3990
          #] Functions : 
3991
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc