46#define GMPSPREAD (GMP_LIMB_BITS/BITSINWORD)
62void Pack(UWORD *a, WORD *na, UWORD *b, WORD nb)
66 if ( (c = *na) == 0 ) {
68 MLOCK(ErrorMessageLock);
69 MesPrint(
"!>Caught a zero in Pack");
70 MUNLOCK(ErrorMessageLock);
76 MLOCK(ErrorMessageLock);
77 MesPrint(
"!>Division by zero in Pack");
78 MUNLOCK(ErrorMessageLock);
82 if ( *na < 0 ) { sgn = -sgn; c = -c; }
83 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
87 while ( --i >= 0 ) *to++ = 0;
91 while ( --i >= 0 ) *to++ = 0;
92 if ( sgn < 0 ) *na = -*na;
104void UnPack(UWORD *a, WORD na, WORD *denom, WORD *numer)
108 if ( na < 0 ) { na = -na; }
114 while ( !(*a) ) { i--; a--; }
115 while ( !(*pos) ) { na--; pos--; }
118 if ( sgn < 0 ) i = -i;
130int Mully(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
135 WORD nd, ne, adenom, anumer;
136 if ( !nb ) { *na = 0;
return(0); }
137 else if ( *b == 1 ) {
138 if ( nb == 1 )
return(0);
139 else if ( nb == -1 ) { *na = -*na;
return(0); }
141 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
142 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
143 UnPack(a,*na,&adenom,&anumer);
144 d = NumberMalloc(
"Mully"); e = NumberMalloc(
"Mully");
145 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
147 if ( Simplify(BHEAD a+*na,&adenom,e,&ne) )
goto MullyEr;
148 if ( MulLong(a,anumer,e,ne,d,&nd) )
goto MullyEr;
150 for ( i = 0; i < *na; i++ ) { e[i] = *b++; }
155 for ( i = 0; i < *na; i++ ) { a[i] = *b++; }
157 if ( sgn < 0 ) *na = -*na;
158 NumberFree(d,
"Mully"); NumberFree(e,
"Mully");
161 MLOCK(ErrorMessageLock);
163 MUNLOCK(ErrorMessageLock);
164 NumberFree(d,
"Mully"); NumberFree(e,
"Mully");
176int Divvy(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
181 WORD nd, ne, adenom, anumer;
184 MLOCK(ErrorMessageLock);
185 MesPrint(
"!>Division by zero in Divvy");
186 MUNLOCK(ErrorMessageLock);
190 d = NumberMalloc(
"Divvy"); e = NumberMalloc(
"Divvy");
191 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
192 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
193 UnPack(a,*na,&adenom,&anumer);
194 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
196 if ( Simplify(BHEAD a,&anumer,e,&ne) )
goto DivvyEr;
197 if ( MulLong(a+*na,adenom,e,ne,d,&nd) )
goto DivvyEr;
200 if ( sgn < 0 ) *na = -*na;
201 NumberFree(d,
"Divvy"); NumberFree(e,
"Divvy");
204 MLOCK(ErrorMessageLock);
206 MUNLOCK(ErrorMessageLock);
207 NumberFree(d,
"Divvy"); NumberFree(e,
"Divvy");
216int AddRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
219 UWORD *d, *e, *f, *g;
220 WORD nd, ne, nf, ng, adenom, anumer, bdenom, bnumer;
224 if ( nb < 0 ) nb = -nb;
226 for ( i = 0; i < nb; i++ ) *c++ = *b++;
232 if ( na < 0 ) na = -na;
234 for ( i = 0; i < na; i++ ) *c++ = *a++;
237 else if ( b[1] == 1 && a[1] == 1 ) {
242 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = 2; }
246 else if ( nb == -1 ) {
248 *c = *b - *a; *nc = -1;
250 else if ( *b < *a ) {
251 *c = *a - *b; *nc = 1;
258 else if ( na == -1 ){
262 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = -2; }
266 else if ( nb == 1 ) {
268 *c = *b - *a; *nc = 1;
270 else if ( *b < *a ) {
271 *c = *a - *b; *nc = -1;
279 UnPack(a,na,&adenom,&anumer);
280 UnPack(b,nb,&bdenom,&bnumer);
281 if ( na < 0 ) na = -na;
282 if ( nb < 0 ) nb = -nb;
283 if ( na == 1 && nb == 1 ) {
285 t3 = ((RLONG)a[1])*((RLONG)b[1]);
286 t1 = ((RLONG)a[0])*((RLONG)b[1]);
287 t2 = ((RLONG)a[1])*((RLONG)b[0]);
288 if ( ( anumer > 0 && bnumer > 0 ) || ( anumer < 0 && bnumer < 0 ) ) {
289 if ( ( t1 = t1 + t2 ) < t2 ) {
292 c[1] = (UWORD)(t1 >> BITSINWORD);
297 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
302 if ( t1 == t2 ) { *nc = 0;
return(0); }
311 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
314 if ( anumer < 0 ) *nc = -*nc;
315 d = NumberMalloc(
"AddRat");
317 if ( ( d[1] = (UWORD)(t3 >> BITSINWORD) ) != 0 ) nd = 2;
319 if ( Simplify(BHEAD c,nc,d,&nd) )
goto AddRer1;
330 d = NumberMalloc(
"AddRat"); e = NumberMalloc(
"AddRat");
331 f = NumberMalloc(
"AddRat"); g = NumberMalloc(
"AddRat");
332 if ( GcdLong(BHEAD a+na,adenom,b+nb,bdenom,d,&nd) )
goto AddRer;
333 if ( *d == 1 && nd == 1 ) nd = 0;
335 if ( DivLong(a+na,adenom,d,nd,e,&ne,c,nc) )
goto AddRer;
336 if ( DivLong(b+nb,bdenom,d,nd,f,&nf,c,nc) )
goto AddRer;
337 if ( MulLong(a,anumer,f,nf,c,nc) )
goto AddRer;
338 if ( MulLong(b,bnumer,e,ne,g,&ng) )
goto AddRer;
341 if ( MulLong(a+na,adenom,b,bnumer,c,nc) )
goto AddRer;
342 if ( MulLong(b+nb,bdenom,a,anumer,g,&ng) )
goto AddRer;
344 if ( AddLong(c,*nc,g,ng,c,nc) )
goto AddRer;
346 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat");
347 NumberFree(e,
"AddRat"); NumberFree(d,
"AddRat");
351 if ( Simplify(BHEAD c,nc,d,&nd) )
goto AddRer;
352 if ( MulLong(e,ne,d,nd,g,&ng) )
goto AddRer;
353 if ( MulLong(g,ng,f,nf,d,&nd) )
goto AddRer;
356 if ( MulLong(a+na,adenom,b+nb,bdenom,d,&nd) )
goto AddRer;
358 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat"); NumberFree(e,
"AddRat");
361 NumberFree(d,
"AddRat");
364 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat"); NumberFree(e,
"AddRat");
366 NumberFree(d,
"AddRat");
368 MLOCK(ErrorMessageLock);
370 MUNLOCK(ErrorMessageLock);
384int MulRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
388 if ( *b == 1 && b[1] == 1 ) {
392 while ( --i >= 0 ) *c++ = *a++;
395 else if ( nb == -1 ) {
398 while ( --i >= 0 ) *c++ = *a++;
402 if ( *a == 1 && a[1] == 1 ) {
406 while ( --i >= 0 ) *c++ = *b++;
409 else if ( na == -1 ) {
412 while ( --i >= 0 ) *c++ = *b++;
416 if ( na < 0 ) { na = -na; sgn = -sgn; }
417 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
418 if ( !na || !nb ) { *nc = 0;
return(0); }
419 if ( na != 1 || nb != 1 ) {
421 UWORD *xd,*xe, *xf,*xg;
422 WORD dden, dnumr, eden, enumr;
423 UnPack(a,na,&dden,&dnumr);
424 UnPack(b,nb,&eden,&enumr);
425 xd = NumberMalloc(
"MulRat"); xf = NumberMalloc(
"MulRat");
426 for ( i = 0; i < dnumr; i++ ) xd[i] = a[i];
428 for ( i = 0; i < dden; i++ ) xf[i] = a[i];
429 xe = NumberMalloc(
"MulRat"); xg = NumberMalloc(
"MulRat");
430 for ( i = 0; i < enumr; i++ ) xe[i] = b[i];
432 for ( i = 0; i < eden; i++ ) xg[i] = b[i];
433 if ( Simplify(BHEAD xd,&dnumr,xg,&eden) ||
434 Simplify(BHEAD xe,&enumr,xf,&dden) ||
435 MulLong(xd,dnumr,xe,enumr,c,nc) ||
436 MulLong(xf,dden,xg,eden,xd,&dnumr) ) {
437 MLOCK(ErrorMessageLock);
439 MUNLOCK(ErrorMessageLock);
440 NumberFree(xd,
"MulRat"); NumberFree(xe,
"MulRat"); NumberFree(xf,
"MulRat"); NumberFree(xg,
"MulRat");
444 NumberFree(xd,
"MulRat"); NumberFree(xe,
"MulRat"); NumberFree(xf,
"MulRat"); NumberFree(xg,
"MulRat");
451 do { a0 = y % b1; y = b1; }
while ( ( b1 = a0 ) != 0 );
461 do { b0 = y % a1; y = a1; }
while ( ( a1 = b0 ) != 0 );
471 if ( xx & AWORDMASK ) {
474 c[1] = (UWORD)(xx >> BITSINWORD);
477 c[3] = (UWORD)(xx >> BITSINWORD);
482 if ( xx & AWORDMASK ) {
485 c[3] = (UWORD)(xx >> BITSINWORD);
494 if ( sgn < 0 ) *nc = -*nc;
506int DivRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
514 MLOCK(ErrorMessageLock);
515 MesPrint(
"!>Rational division by zero");
516 MUNLOCK(ErrorMessageLock);
520 j = i = (nb >= 0)? nb: -nb;
522 do { xx = *xd; *xd++ = *xe; *xe++ = xx; }
while ( --j > 0 );
523 ret = MulRat(BHEAD a,na,b,nb,c,nc);
525 do { xx = *xd; *xd++ = *xe; *xe++ = xx; }
while ( --i > 0 );
539int Simplify(PHEAD UWORD *a, WORD *na, UWORD *b, WORD *nb)
544 WORD n1,n2,n3,n4,sgn = 1;
546 UWORD *Siscrat5, *Siscrat6, *Siscrat7, *Siscrat8;
547 if ( *na < 0 ) { *na = -*na; sgn = -sgn; }
548 if ( *nb < 0 ) { *nb = -*nb; sgn = -sgn; }
549 Siscrat5 = NumberMalloc(
"Simplify"); Siscrat6 = NumberMalloc(
"Simplify");
550 Siscrat7 = NumberMalloc(
"Simplify"); Siscrat8 = NumberMalloc(
"Simplify");
551 x1 = Siscrat8; x2 = Siscrat7;
554 if ( DivLong(a,*na,b,*nb,x1,&n1,x2,&n2) )
goto SimpErr;
556 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
564 do { y1 = y2 % y3; y2 = y3; }
while ( ( y3 = y1 ) != 0 );
565 if ( ( *x2 = y2 ) != 1 ) {
567 if ( DivLong(a,*na,x2,(WORD)1,x1,&n1,x3,&n3) )
goto SimpErr;
568 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
574 else if ( *na >= GCDMAX && *nb >= GCDMAX ) {
575 n1 = i = *na; x3 = a;
577 x3 = b; n2 = i = *nb;
582 if ( GcdLong(BHEAD Siscrat8,n1,Siscrat7,n2,x2,&n3) )
goto SimpErr;
584 if ( *x2 != 1 || n2 != 1 ) {
585 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
588 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
596 n1 = i = *na; x3 = a;
598 x3 = b; n2 = i = *nb;
600 x1 = Siscrat8; x2 = Siscrat7; x3 = Siscrat6;
602 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto SimpErr;
605 while ( ( *x1 = (*x2) % (*x3) ) != 0 ) { *x2 = *x3; *x3 = *x1; }
609 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto SimpErr;
610 if ( !n1 ) { x2 = x3; n2 = n3; x3 = Siscrat7;
break; }
612 while ( ( *x2 = (*x3) % (*x1) ) != 0 ) { *x3 = *x1; *x1 = *x2; }
617 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto SimpErr;
618 if ( !n2 ) { x2 = x1; n2 = n1; x1 = Siscrat7;
break; }
620 while ( ( *x3 = (*x1) % (*x2) ) != 0 ) { *x1 = *x2; *x2 = *x3; }
624 if ( *x2 != 1 || n2 != 1 ) {
625 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
628 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
633 if ( sgn < 0 ) *na = -*na;
634 NumberFree(Siscrat5,
"Simplify"); NumberFree(Siscrat6,
"Simplify");
635 NumberFree(Siscrat7,
"Simplify"); NumberFree(Siscrat8,
"Simplify");
638 MLOCK(ErrorMessageLock);
640 MUNLOCK(ErrorMessageLock);
641 NumberFree(Siscrat5,
"Simplify"); NumberFree(Siscrat6,
"Simplify");
642 NumberFree(Siscrat7,
"Simplify"); NumberFree(Siscrat8,
"Simplify");
656int AccumGCD(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
659 WORD nna,nnb,numa,numb,dena,denb,numc,denc;
660 UWORD *GCDbuffer = NumberMalloc(
"AccumGCD");
662 nna = *na;
if ( nna < 0 ) nna = -nna; nna = (nna-1)/2;
663 nnb = nb;
if ( nnb < 0 ) nnb = -nnb; nnb = (nnb-1)/2;
664 UnPack(a,nna,&dena,&numa);
665 UnPack(b,nnb,&denb,&numb);
666 if ( GcdLong(BHEAD a,numa,b,numb,GCDbuffer,&numc) )
goto AccErr;
668 for ( i = 0; i < numa; i++ ) a[i] = GCDbuffer[i];
669 if ( GcdLong(BHEAD a+nna,dena,b+nnb,denb,GCDbuffer,&denc) )
goto AccErr;
671 for ( i = 0; i < dena; i++ ) a[i+nna] = GCDbuffer[i];
672 Pack(a,&numa,a+nna,dena);
674 NumberFree(GCDbuffer,
"AccumGCD");
677 MLOCK(ErrorMessageLock);
679 MUNLOCK(ErrorMessageLock);
680 NumberFree(GCDbuffer,
"AccumGCD");
689int TakeRatRoot(UWORD *a, WORD *n, WORD power)
691 WORD numer,denom, nn;
692 if ( ( power & 1 ) == 0 && *n < 0 )
return(1);
693 if ( ABS(*n) == 1 && a[0] == 1 && a[1] == 1 )
return(0);
695 UnPack(a,nn,&denom,&numer);
696 if ( TakeLongRoot(a+nn,&denom,power) )
return(1);
697 if ( TakeLongRoot(a,&numer,power) )
return(1);
698 Pack(a,&numer,a+nn,denom);
699 if ( *n < 0 ) *n = -numer;
714int AddLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
719 if ( AddPLon(a,-na,b,-nb,c,nc) )
return(-1);
733 else {
return( AddPLon(a,na,b,nb,c,nc) ); }
735 if ( ( res = BigLong(a,na,b,nb) ) > 0 ) {
736 SubPLon(a,na,b,nb,c,nc);
737 if ( sgn < 0 ) *nc = -*nc;
739 else if ( res < 0 ) {
740 SubPLon(b,nb,a,na,c,nc);
741 if ( sgn > 0 ) *nc = -*nc;
759int AddPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
761 UWORD carry = 0, e, nd = 0;
766 if ( e < *c ) carry = 0;
769 if ( e > *c ) carry = 1;
771 a++; b++; c++; nd++; na--; nb--;
776 if ( *c++ ) carry = 0;
784 if ( *c++ ) carry = 0;
791 if ( nd > (UWORD)AM.MaxTal ) {
792 MLOCK(ErrorMessageLock);
793 MesPrint(
"Overflow in addition");
794 MUNLOCK(ErrorMessageLock);
812void SubPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
814 UWORD borrow = 0, e, nd = 0;
818 *c = e - *b - borrow;
819 if ( *c < e ) borrow = 0;
823 if ( *c > e ) borrow = 1;
825 a++; b++; c++; na--; nb--; nd++;
829 if ( *a ) { *c++ = *a++ - 1; borrow = 0; }
830 else { *c++ = (UWORD)(-1); a++; }
835 while ( nd && !*--c ) { nd--; }
850int MulLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
855 if ( !na || !nb ) { *nc = 0;
return(0); }
856 if ( na < 0 ) { na = -na; sgn = -sgn; }
857 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
859 if ( i > (UWORD)(AM.MaxTal+1) )
goto MulLov;
865 if (na > 3 && nb > 3) {
870 UWORD *DLscrat9 = NumberMalloc(
"MulLong"), *DLscratA = NumberMalloc(
"MulLong"), *DLscratB = NumberMalloc(
"MulLong");
871#if ( GMPSPREAD != 1 )
873 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
878 if ( (LONG)a & (
sizeof(mp_limb_t)-1) ) {
879 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
882#if ( GMPSPREAD != 1 )
884 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
889 if ( (LONG)b & (
sizeof(mp_limb_t)-1) ) {
890 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
893 if ( ( *nc > (WORD)i ) || ( (LONG)c & (LONG)(
sizeof(mp_limb_t)-1) ) ) {
898 mpn_mul((mp_ptr)ic, (mp_srcptr)b, nb/GMPSPREAD, (mp_srcptr)a, na/GMPSPREAD);
901 mpn_mul((mp_ptr)ic, (mp_srcptr)a, na/GMPSPREAD, (mp_srcptr)b, nb/GMPSPREAD);
903 while ( ic[i-1] == 0 ) i--;
910 j = *nc; NCOPY(c, ic, j);
912 if ( sgn < 0 ) *nc = -(*nc);
913 NumberFree(DLscrat9,
"MulLong"); NumberFree(DLscratA,
"MulLong"); NumberFree(DLscratB,
"MulLong");
920 do { *ic++ = 0; }
while ( --i > 0 );
928 t = (*ia++) * bb + t + *ic;
932 if ( t ) *ic = (UWORD)t;
933 }
while ( --nb > 0 );
935 if ( *nc > AM.MaxTal )
goto MulLov;
936 if ( sgn < 0 ) *nc = -(*nc);
939 MLOCK(ErrorMessageLock);
940 MesPrint(
"Overflow in Multiplication");
941 MUNLOCK(ErrorMessageLock);
953int BigLong(UWORD *a, WORD na, UWORD *b, WORD nb)
957 while ( na && !*--a ) na--;
958 while ( nb && !*--b ) nb--;
959 if ( nb < na )
return(1);
960 if ( nb > na )
return(-1);
961 while ( --na >= 0 ) {
962 if ( *a > *b )
return(1);
963 else if ( *b > *a )
return(-1);
981int DivLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c,
982 WORD *nc, UWORD *d, WORD *nd)
984 WORD sgna = 1, sgnb = 1, ne, nf, ng, nh;
988 UWORD *e, *f, *ff, *g, norm, estim;
990 UWORD *DLscrat9, *DLscratA, *DLscratB, *DLscratC;
994 MLOCK(ErrorMessageLock);
995 MesPrint(
"Division by zero");
996 MUNLOCK(ErrorMessageLock);
999 if ( !na ) { *nc = *nd = 0;
return(0); }
1000 if ( na < 0 ) { sgna = -sgna; na = -na; }
1001 if ( nb < 0 ) { sgnb = -sgnb; nb = -nb; }
1003 for ( i = 0; i < na; i++ ) *d++ = *a++;
1007 else if ( nb == na && ( i = BigLong(b,nb,a,na) ) >= 0 ) {
1009 for ( i = 0; i < na; i++ ) *d++ = *a++;
1019 else if ( nb == 1 ) {
1021 for ( i = 0; i < na; i++ ) *c++ = *a++;
1032 while ( --ni >= 0 ) {
1040 if ( ( *d = (UWORD)t ) == 0 ) *nd = 0;
1041 if ( !*(c+na-1) ) (*nc)--;
1056 if ( na > 4 && nb > 3 ) {
1057 UWORD *ic, *id, *to, *from;
1059 DLscrat9 = NumberMalloc(
"DivLong"); DLscratA = NumberMalloc(
"DivLong");
1060 DLscratB = NumberMalloc(
"DivLong"); DLscratC = NumberMalloc(
"DivLong");
1062#if ( GMPSPREAD != 1 )
1064 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1068 if ( (LONG)a & (
sizeof(mp_limb_t)-1) ) {
1069 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1072#if ( GMPSPREAD != 1 )
1074 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1078 if ( ( (LONG)b & (
sizeof(mp_limb_t)-1) ) != 0 ) {
1079 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1081#if ( GMPSPREAD != 1 )
1088 ic = DLscratB;
id = DLscratC;
1090 if ( ( (LONG)c & (
sizeof(mp_limb_t)-1) ) != 0 ) ic = DLscratB;
1093 if ( ( (LONG)d & (
sizeof(mp_limb_t)-1) ) != 0 )
id = DLscratC;
1096 mpn_tdiv_qr((mp_limb_t *)ic,(mp_limb_t *)
id,(mp_size_t)0,
1097 (
const mp_limb_t *)a,(mp_size_t)(na/GMPSPREAD),
1098 (
const mp_limb_t *)b,(mp_size_t)(nb/GMPSPREAD));
1099 while ( j >= 0 && ic[j] == 0 ) j--;
1101 if ( c != ic ) { NCOPY(c,ic,j); }
1103 while ( j >= 0 &&
id[j] == 0 ) j--;
1105 if ( d !=
id ) { NCOPY(d,
id,j); }
1106 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1107 if ( sgnb < 0 ) { *nc = -(*nc); }
1108 NumberFree(DLscrat9,
"DivLong"); NumberFree(DLscratA,
"DivLong");
1109 NumberFree(DLscratB,
"DivLong"); NumberFree(DLscratC,
"DivLong");
1118 e = NumberMalloc(
"DivLong"); f = NumberMalloc(
"DivLong"); g = NumberMalloc(
"DivLong");
1119 if ( b[nb-1] == (FULLMAX-1) ) norm = 1;
1121 norm = (UWORD)(((ULONG)FULLMAX) / (ULONG)((b[nb-1]+1L)));
1124 if ( MulLong(b,nb,&norm,1,e,&ne) ||
1125 MulLong(a,na,&norm,1,f,&nf) ) {
1126 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1129 if ( BigLong(f+nf-ne,ne,e,ne) >= 0 ) {
1130 SubPLon(f+nf-ne,ne,e,ne,f+nf-ne,&nh);
1139 w2 = c; i = *nc;
do { *w2++ = 0; }
while ( --i > 0 );
1142 esthelp = (RLONG)(e[ne-1]) + 1L;
1143 while ( nf >= ne ) {
1144 if ( (WORD)esthelp == 0 ) {
1145 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])>>BITSINWORD);
1148 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])/esthelp);
1152 MulLong(e,ne,&estim,1,g,&ng);
1153 nh = ne + 1;
if ( !f[ni+ne] ) nh--;
1154 SubPLon(f+ni,nh,g,ng,f+ni,&nh);
1157 w2 = f+ni+ne; nh = ne+1;
1158 while ( ( nh > 0 ) && !*w2 ) { nh--; w2--; }
1160 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1162 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1163 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1165 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1166 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1168 MLOCK(ErrorMessageLock);
1169 MesPrint(
"!>Problems in DivLong");
1173 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
1176 while ( --i >= 0 ) { TalToLine((UWORD)(*b++)); TokenToLine((UBYTE *)
" "); }
1179 MUNLOCK(ErrorMessageLock);
1180 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1196 *nd = i = nh; ff = f;
1205 while ( --ni >= 0 ) {
1215 MLOCK(ErrorMessageLock);
1216 MesPrint(
"!>Error in DivLong");
1217 MUNLOCK(ErrorMessageLock);
1218 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1222 if ( !*(d+nh-1) ) (*nd)--;
1226 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1228 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1229 if ( sgnb < 0 ) { *nc = -(*nc); }
1241int RaisPow(PHEAD UWORD *a, WORD *na, UWORD b)
1248 nmod = ABS(AN.ncmod);
1249 if ( !*na || ( ( *na == 1 ) && ( *a == 1 ) ) )
return(0);
1250 if ( !b ) { *na=1; *a=1;
return(0); }
1251 is = NumberMalloc(
"RaisPow");
1252 it = NumberMalloc(
"RaisPow");
1253 for ( i = 0; i < ABS(*na); i++ ) is[i] = a[i];
1256 for ( i = 0; i < BITSINWORD; i++ ) {
1262 while ( --i >= 0 ) {
1264 if(MulLong(is,ns,is,ns,it,&nt))
goto RaisOvl;
1266 if ( MulLong(it,nt,a,*na,is,&ns) )
goto RaisOvl;
1269 iu = is; is = it; it = iu;
1270 nu = ns; ns = nt; nt = nu;
1273 if ( DivLong(is,ns,(UWORD *)AC.cmod,nmod,it,&nt,is,&ns) )
goto RaisOvl;
1276 if ( ( nmod != 0 ) && ( ( AC.modmode & POSNEG ) != 0 ) ) {
1279 if ( ( *na = i = ns ) != 0 ) { iss = is; i=ABS(i); NCOPY(a,iss,i); }
1280 NumberFree(is,
"RaisPow"); NumberFree(it,
"RaisPow");
1283 MLOCK(ErrorMessageLock);
1285 MUNLOCK(ErrorMessageLock);
1286 NumberFree(is,
"RaisPow"); NumberFree(it,
"RaisPow");
1312 WORD new_small_power_maxx, new_small_power_maxn, ID;
1313 WORD *new_small_power_n;
1314 UWORD **new_small_power;
1317 if (x>=AT.small_power_maxx || n>=AT.small_power_maxn) {
1319 new_small_power_maxx = AT.small_power_maxx;
1320 if (x>=AT.small_power_maxx)
1321 new_small_power_maxx = MaX(2*AT.small_power_maxx, x+1);
1323 new_small_power_maxn = AT.small_power_maxn;
1324 if (n>=AT.small_power_maxn)
1325 new_small_power_maxn = MaX(2*AT.small_power_maxn, n+1);
1327 new_small_power_n = (WORD*) Malloc1(new_small_power_maxx*new_small_power_maxn*
sizeof(WORD),
"RaisPowCached");
1328 new_small_power = (UWORD **) Malloc1(new_small_power_maxx*new_small_power_maxn*
sizeof(UWORD *),
"RaisPowCached");
1330 for (i=0; i<new_small_power_maxx * new_small_power_maxn; i++) {
1331 new_small_power_n[i] = 0;
1332 new_small_power [i] = NULL;
1335 for (i=0; i<AT.small_power_maxx; i++)
1336 for (j=0; j<AT.small_power_maxn; j++) {
1337 new_small_power_n[i*new_small_power_maxn+j] = AT.small_power_n[i*AT.small_power_maxn+j];
1338 new_small_power [i*new_small_power_maxn+j] = AT.small_power [i*AT.small_power_maxn+j];
1341 if (AT.small_power_n != NULL) {
1342 M_free(AT.small_power_n,
"RaisPowCached");
1343 M_free(AT.small_power,
"RaisPowCached");
1346 AT.small_power_maxx = new_small_power_maxx;
1347 AT.small_power_maxn = new_small_power_maxn;
1348 AT.small_power_n = new_small_power_n;
1349 AT.small_power = new_small_power;
1353 ID = x * AT.small_power_maxn + n;
1355 if (AT.small_power[ID] == NULL) {
1356#ifdef OLDRAISPOWCACHED
1357 AT.small_power[ID] = NumberMalloc(
"RaisPowCached");
1358 AT.small_power_n[ID] = 1;
1359 AT.small_power[ID][0] = x;
1360 RaisPow(BHEAD AT.small_power[ID],&AT.small_power_n[ID],n);
1362 UWORD *c = NumberMalloc(
"RaisPowCached");
1365 RaisPow(BHEAD c,&k,n);
1369 if ( AT.InNumMem < k ) {
1370 AT.InNumMem = 5*AM.MaxTal;
1371 AT.NumMem = (UWORD *)Malloc1(AT.InNumMem*
sizeof(UWORD),
"RaisPowCached");
1376 for ( i = 0; i < k; i++ ) AT.NumMem[i] = c[i];
1377 AT.small_power[ID] = AT.NumMem;
1378 AT.small_power_n[ID] = k;
1381 NumberFree(c,
"RaisPowCached");
1386 *c = AT.small_power[ID];
1387 *nc = AT.small_power_n[ID];
1396WORD RaisPowMod (WORD x, WORD n, WORD m) {
1399 if (n&1) { y*=z; y%=m; }
1419 if ( AC.halfmod == 0 ) {
1420 LOCK(AC.halfmodlock);
1421 if ( AC.halfmod == 0 ) {
1422 UWORD two[1],remain[1];
1425 AC.halfmod = (UWORD *)Malloc1((ABS(AC.ncmod))*
sizeof(UWORD),
"halfmod");
1426 DivLong((UWORD *)AC.cmod,(ABS(AC.ncmod)),two,1
1427 ,(UWORD *)AC.halfmod,&(AC.nhalfmod),remain,&dummy);
1429 UNLOCK(AC.halfmodlock);
1432 if ( BigLong(a,n,AC.halfmod,AC.nhalfmod) > 0 ) {
1433 SubPLon((UWORD *)AC.cmod,(ABS(AC.ncmod)),a,n,a,&n);
1434 if ( *na > 0 ) { *na = -n; }
1455 WORD n = AC.cmod[0], i, inv2;
1456 if ( AC.ncmod != 1 )
return(1);
1457 if ( AC.modinverses == 0 ) {
1458 LOCK(AC.halfmodlock);
1459 if ( AC.modinverses == 0 ) {
1460 AC.modinverses = (UWORD *)Malloc1(n*
sizeof(UWORD),
"modinverses");
1461 AC.modinverses[0] = 0;
1462 AC.modinverses[1] = 1;
1463 for ( i = 2; i < n; i++ ) {
1465 (WORD *)(&(AC.modinverses[i])),&inv2) ) {
1470 UNLOCK(AC.halfmodlock);
1493 WORD x = m1, y, c, d = m2;
1494 if ( x < 1 || d <= 1 )
goto somethingwrong;
1499 if ( y == 0 )
break;
1500 a3 = a1-c*a2; a1 = a2; a2 = a3;
1501 b3 = b1-c*b2; b1 = b2; b2 = b3;
1504 if ( x != 1 )
goto somethingwrong;
1505 if ( a2 < 0 ) a2 += m2;
1506 if ( b2 < 0 ) b2 += m1;
1507 if (im1!=NULL) *im1 = a2;
1508 if (im2!=NULL) *im2 = b2;
1512 MLOCK(ErrorMessageLock);
1513 MesPrint(
"!>Error trying to determine inverses in GetModInverses");
1514 MUNLOCK(ErrorMessageLock);
1523int GetLongModInverses(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *ia, WORD *nia, UWORD *ib, WORD *nib) {
1525 UWORD *s, *t, *sa, *sb, *ta, *tb, *x, *y, *swap1;
1526 WORD ns, nt, nsa, nsb, nta, ntb, nx, ny, swap2;
1528 s = NumberMalloc(
"GetLongModInverses");
1530 WCOPY(s, a, ABS(ns));
1532 t = NumberMalloc(
"GetLongModInverses");
1534 WCOPY(t, b, ABS(nt));
1536 sa = NumberMalloc(
"GetLongModInverses");
1540 sb = NumberMalloc(
"GetLongModInverses");
1543 ta = NumberMalloc(
"GetLongModInverses");
1546 tb = NumberMalloc(
"GetLongModInverses");
1550 x = NumberMalloc(
"GetLongModInverses");
1551 y = NumberMalloc(
"GetLongModInverses");
1554 DivLong(s,ns,t,nt,x,&nx,y,&ny);
1555 swap1=s; s=y; y=swap1;
1557 MulLong(x,nx,ta,nta,y,&ny);
1558 AddLong(sa,nsa,y,-ny,sa,&nsa);
1559 MulLong(x,nx,tb,ntb,y,&ny);
1560 AddLong(sb,nsb,y,-ny,sb,&nsb);
1562 swap1=s; s=t; t=swap1;
1563 swap2=ns; ns=nt; nt=swap2;
1564 swap1=sa; sa=ta; ta=swap1;
1565 swap2=nsa; nsa=nta; nta=swap2;
1566 swap1=sb; sb=tb; tb=swap1;
1567 swap2=nsb; nsb=ntb; ntb=swap2;
1572 WCOPY(ia,sa,ABS(*nia));
1577 WCOPY(ib,sb,ABS(*nib));
1580 NumberFree(s,
"GetLongModInverses");
1581 NumberFree(t,
"GetLongModInverses");
1582 NumberFree(sa,
"GetLongModInverses");
1583 NumberFree(sb,
"GetLongModInverses");
1584 NumberFree(ta,
"GetLongModInverses");
1585 NumberFree(tb,
"GetLongModInverses");
1586 NumberFree(x,
"GetLongModInverses");
1587 NumberFree(y,
"GetLongModInverses");
1600int Product(UWORD *a, WORD *na, WORD b)
1604 if ( *na < 0 ) { *na = -(*na); sgn = -sgn; }
1605 if ( b < 0 ) { b = -b; sgn = -sgn; }
1608 for ( i = 0; i < *na; i++ ) {
1614 if ( ++(*na) > AM.MaxTal ) {
1615 MLOCK(ErrorMessageLock);
1616 MesPrint(
"Overflow in Product");
1617 MUNLOCK(ErrorMessageLock);
1622 if ( sgn < 0 ) *na = -(*na);
1635UWORD Quotient(UWORD *a, WORD *na, WORD b)
1639 if ( ( i = *na ) < 0 ) { sgn = -1; i = -i; }
1640 if ( b < 0 ) { b = -b; sgn = -sgn; }
1642 if ( ( *a /= (UWORD)b ) == 0 ) *na = 0;
1643 if ( sgn < 0 ) *na = -*na;
1650 while ( --i >= 0 ) {
1660 if ( sgn < 0 ) j = -j;
1674WORD Remain10(UWORD *a, WORD *na)
1682 while ( --i >= 0 ) {
1686 if ( i > 0 ) t <<= BITSINWORD;
1688 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1701WORD Remain4(UWORD *a, WORD *na)
1709 while ( --i >= 0 ) {
1711 *b-- = u = t / 10000;
1713 if ( i > 0 ) t <<= BITSINWORD;
1715 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1727void PrtLong(UWORD *a, WORD na, UBYTE *s)
1740 b = NumberMalloc(
"PrtLong");
1742 i = na;
while ( --i >= 0 ) *bb++ = *a++;
1748 *sa++ = (UBYTE)(
'0' + (q%10));
1750 *sa++ = (UBYTE)(
'0' + (q%10));
1752 *sa++ = (UBYTE)(
'0' + (q%10));
1754 *sa++ = (UBYTE)(
'0' + (q%10));
1756 while ( sa[-1] ==
'0' ) sa--;
1760 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1765 q = Remain10(a,&na);
1766 *sa++ = (UBYTE)(
'0' + q);
1771 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1775 NumberFree(b,
"PrtLong");
1789int GetLong(UBYTE *s, UWORD *a, WORD *na)
1802 UWORD digit, x = 0, y = 0;
1805 while ( FG.cTable[*s] == 1 ) {
1807 if ( FG.cTable[*s] != 1 ) { y = 10;
break; }
1808 x = 10*x + *s++ -
'0';
1809 if ( FG.cTable[*s] != 1 ) { y = 100;
break; }
1810 x = 10*x + *s++ -
'0';
1811 if ( FG.cTable[*s] != 1 ) { y = 1000;
break; }
1812 x = 10*x + *s++ -
'0';
1813 if ( *na && Product(a,na,(WORD)10000) )
return(-1);
1814 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1819 if ( *na && Product(a,na,(WORD)y) )
return(-1);
1820 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1840#define Convert(ia,aa,naa) \
1841 if ( (LONG)ia < 0 ) { \
1842 ia = (ULONG)(-(LONG)ia); \
1844 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = -2; \
1847 else if ( ia == 0 ) { aa[0] = 0; naa = 0; } \
1850 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = 2; \
1854void GCD(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1856 int ja = 0, jb = 0, j;
1858 UWORD *x1, *x2, *x3;
1860 ULONG ia,ib,ic,id,u,v,w,q,T;
1865 while ( a[0] == 0 ) { na--; ja++; a++; }
1866 while ( b[0] == 0 ) { nb--; jb++; b++; }
1867 if ( ja > jb ) ja = jb;
1870 do { *c++ = 0; }
while ( --j > 0 );
1876 jb = na; na = nb; nb = jb;
1878 r = a; a = b; b = r;
1880 else if ( na == nb ) {
1884 while ( --j >= 0 ) {
1885 if ( *--r > *--t )
break;
1886 if ( *r < *t )
goto exch;
1917 r = x1 = NumberMalloc(
"GCD"); t = x2 = NumberMalloc(
"GCD"); x3 = NumberMalloc(
"GCD");
1927 DivLong(x1,na,x2,nb,c,nc,x3,&nd);
1928 if ( nd == 0 ) { b = x2;
goto out; }
1929 t = x1; x1 = x2; x2 = x3; x3 = t; na = nb; nb = nd;
1930 if ( na == 2 )
break;
1936 v = x1[0] + ( ((ULONG)x1[1]) << BITSINWORD );
1938 if ( nb == 2 ) w += ((ULONG)x2[1]) << BITSINWORD;
1942 do { u = v%w; v = w; w = u; }
while ( w );
1945 if ( ( c[1] = (UWORD)(v >> BITSINWORD) ) != 0 ) *nc = 2+ja;
1947 NumberFree(x1,
"GCD"); NumberFree(x2,
"GCD"); NumberFree(x3,
"GCD");
1952 ui = x1[0]; uj = x2[0];
1954 ui = (UWORD)GCD2((ULONG)ui,(ULONG)uj);
1956 do { nd = ui%uj; ui = uj; uj = nd; }
while ( nd );
1960 NumberFree(x1,
"GCD"); NumberFree(x2,
"GCD"); NumberFree(x3,
"GCD");
1963 ia = 1; ib = 0; ic = 0;
id = 1;
1964 u = ( ((ULONG)x1[na-1]) << BITSINWORD ) + x1[na-2];
1965 v = ( ((ULONG)x2[nb-1]) << BITSINWORD ) + x2[nb-2];
1967 while ( v+ic != 0 && v+
id != 0 &&
1968 ( q = (u+ia)/(v+ic) ) == (u+ib)/(v+
id) ) {
1969 T = ia-q*ic; ia = ic; ic = T;
1970 T = ib-q*id; ib = id;
id = T;
1971 T = u - q*v; u = v; v = T;
1973 if ( ib == 0 )
goto toobad;
1976 MulLong(x1,na,aa,naa,x3,&nd);
1977 MulLong(x2,nb,bb,nbb,c,nc);
1978 AddLong(x3,nd,c,*nc,c,nc);
1981 MulLong(x1,na,aa,naa,x3,&nd);
1982 t = c; na = j = *nc; r = x1;
1984 MulLong(x2,nb,bb,nbb,c,nc);
1985 AddLong(x3,nd,c,*nc,x2,&nb);
2006int GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2012 MLOCK(ErrorMessageLock);
2013 MesPrint(
"!>Cannot take gcd");
2014 MUNLOCK(ErrorMessageLock);
2031 if ( na < 0 ) na = -na;
2032 if ( nb < 0 ) nb = -nb;
2033 if ( na == 1 && nb == 1 ) {
2035 *c = (UWORD)GCD2((ULONG)*a,(ULONG)*b);
2040 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2045 else if ( na <= 2 && nb <= 2 ) {
2047 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2049 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2055 do { lz = lx % ly; lx = ly; }
while ( ( ly = lz ) != 0 );
2058 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2060 lz = lx % ly; lx = ly;
2061 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2063 do { *c = ((UWORD)lx)%((UWORD)ly); lx = ly; }
while ( ( ly = *c ) != 0 );
2071 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2077 GCD(a,na,b,nb,c,nc);
2080 UWORD *x3,*x1,*x2, *GLscrat7, *GLscrat8;
2083 x1 = c; x3 = a; n1 = i = na;
2085 GLscrat7 = NumberMalloc(
"GcdLong"); GLscrat8 = NumberMalloc(
"GcdLong");
2086 x2 = GLscrat8; x3 = b; n2 = i = nb;
2089 while ( x1[0] == 0 ) { i += BITSINWORD; x1++; n1--; }
2090 while ( ( x1[0] & 1 ) == 0 ) { i++; SCHUIF(x1,n1) }
2091 x2 = GLscrat8; j = 0;
2092 while ( x2[0] == 0 ) { j += BITSINWORD; x2++; n2--; }
2093 while ( ( x2[0] & 1 ) == 0 ) { j++; SCHUIF(x2,n2) }
2098 SubPLon(x1,n1,x2,n2,x1,&n3);
2102 n1 = i = n2; NCOPY(x1,x2,i);
2105 while ( ( x1[0] & 1 ) == 0 ) SCHUIF(x1,n1)
2107 if ( DivLong(x2,n2,x1,n1,GLscrat7,&n3,x2,&n4) )
goto GcdErr;
2110 i = n1; x2 = c; NCOPY(x2,x1,i);
2114 *c = (UWORD)GCD2((ULONG)x1[0],(ULONG)x2[0]);
2120 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2128 else if ( n1 < n2 ) {
2130 SubPLon(x2,n2,x1,n1,x2,&n3);
2133 i = n1; x2 = c; NCOPY(x2,x1,i);
2136 while ( ( x2[0] & 1 ) == 0 ) SCHUIF(x2,n2)
2138 if ( DivLong(x1,n1,x2,n2,GLscrat7,&n3,x1,&n4) )
goto GcdErr;
2142 n1 = i = n2; NCOPY(x1,x2,i);
2146 *c = (UWORD)GCD2((ULONG)x2[0],(ULONG)x1[0]);
2152 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2161 for ( i = n1-1; i >= 0; i-- ) {
2162 if ( x1[i] > x2[i] )
goto firstbig;
2163 else if ( x1[i] < x2[i] )
goto lastbig;
2165 i = n1; x2 = c; NCOPY(x2,x1,i);
2173 while ( j >= BITSINWORD ) {
2174 for ( i = n1; i > 0; i-- ) x1[i] = x1[i-1];
2180 for ( i = 0; i < n1; i++ ) {
2181 a1 = x1[i]; a1 <<= j;
2191 NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2193 UWORD *x1,*x2,*x3,*x4,*c1,*c2;
2195 x1 = c; x3 = a; n1 = i = na;
2197 x1 = c; c1 = x2 = NumberMalloc(
"GcdLong"); x3 = NumberMalloc(
"GcdLong"); x4 = NumberMalloc(
"GcdLong");
2198 c2 = b; n2 = i = nb;
2201 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto GcdErr;
2202 if ( !n3 ) { x1 = x2; n1 = n2;
break; }
2203 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto GcdErr;
2204 if ( !n1 ) { x1 = x3; n1 = n3;
break; }
2205 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto GcdErr;
2208 NumberFree(x2,
"GcdLong"); NumberFree(x3,
"GcdLong"); NumberFree(x4,
"GcdLong");
2214 NumberFree(x2,
"GcdLong"); NumberFree(x3,
"GcdLong"); NumberFree(x4,
"GcdLong");
2220 MLOCK(ErrorMessageLock);
2222 MUNLOCK(ErrorMessageLock);
2293int GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2297 UWORD *x1,*x2,*x3,*x4,*x5,*d;
2298 UWORD *GLscrat6, *GLscrat7, *GLscrat8, *GLscrat9, *GLscrat10;
2299 WORD n1,n2,n3,n4,n5,i;
2301 LONG ma1, ma2, mb1, mb2, mc1, mc2, m;
2305 MLOCK(ErrorMessageLock);
2306 MesPrint(
"!>Cannot take gcd");
2307 MUNLOCK(ErrorMessageLock);
2324 if ( na < 0 ) na = -na;
2325 if ( nb < 0 ) nb = -nb;
2330 if ( na > 3 && nb > 3 ) {
2332 mp_limb_t *upa, *upb, *upc, xx;
2333 UWORD *uw, *u1, *u2;
2334 unsigned int tcounta, tcountb, tcounta1, tcountb1;
2335 mp_size_t ana, anb, anc;
2337 u1 = uw = NumberMalloc(
"GcdLong");
2338 upa = (mp_limb_t *)u1;
2339 ana = na; tcounta1 = 0;
2340 while ( a[0] == 0 ) { a++; ana--; tcounta1++; }
2341 for ( ii = 0; ii < ana; ii++ ) { *uw++ = *a++; }
2342 if ( ( ana & 1 ) != 0 ) { *uw = 0; ana++; }
2345 u2 = uw = NumberMalloc(
"GcdLong");
2346 upb = (mp_limb_t *)u2;
2347 anb = nb; tcountb1 = 0;
2348 while ( b[0] == 0 ) { b++; anb--; tcountb1++; }
2349 for ( ii = 0; ii < anb; ii++ ) { *uw++ = *b++; }
2350 if ( ( anb & 1 ) != 0 ) { *uw = 0; anb++; }
2353 xx = upa[0]; tcounta = 0;
2354 while ( ( xx & 15 ) == 0 ) { tcounta += 4; xx >>= 4; }
2355 while ( ( xx & 1 ) == 0 ) { tcounta += 1; xx >>= 1; }
2356 xx = upb[0]; tcountb = 0;
2357 while ( ( xx & 15 ) == 0 ) { tcountb += 4; xx >>= 4; }
2358 while ( ( xx & 1 ) == 0 ) { tcountb += 1; xx >>= 1; }
2361 mpn_rshift(upa,upa,ana,tcounta);
2362 if ( upa[ana-1] == 0 ) ana--;
2365 mpn_rshift(upb,upb,anb,tcountb);
2366 if ( upb[anb-1] == 0 ) anb--;
2369 upc = (mp_limb_t *)(NumberMalloc(
"GcdLong"));
2370 if ( ( ana > anb ) || ( ( ana == anb ) && ( upa[ana-1] >= upb[ana-1] ) ) ) {
2371 anc = mpn_gcd(upc,upa,ana,upb,anb);
2374 anc = mpn_gcd(upc,upb,anb,upa,ana);
2377 tcounta = tcounta1*BITSINWORD + tcounta;
2378 tcountb = tcountb1*BITSINWORD + tcountb;
2379 if ( tcountb > tcounta ) tcountb = tcounta;
2380 tcounta = tcountb/BITSINWORD;
2381 tcountb = tcountb%BITSINWORD;
2384 xx = mpn_lshift(upc,upc,anc,tcountb);
2385 if ( xx ) { upc[anc] = xx; anc++; }
2388 uw = (UWORD *)upc; anc *= 2;
2389 while ( uw[anc-1] == 0 ) anc--;
2390 for ( ii = 0; ii < (int)tcounta; ii++ ) *c++ = 0;
2391 for ( ii = 0; ii < anc; ii++ ) *c++ = *uw++;
2392 *nc = anc + tcounta;
2393 NumberFree(u1,
"GcdLong"); NumberFree(u2,
"GcdLong"); NumberFree((UWORD *)(upc),
"GcdLong");
2403 if ( na == 1 && nb == 1 ) {
2406 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2411 else if ( na <= 2 && nb <= 2 ) {
2412 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2414 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2416 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2417#if ( BITSINWORD == 16 )
2419 lz = lx % ly; lx = ly;
2420 }
while ( ( ly = lz ) != 0 );
2423 lz = lx % ly; lx = ly;
2424 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2426 x = (UWORD)lx; y = (UWORD)ly;
2427 do { *c = x % y; x = y; }
while ( ( y = *c ) != 0 );
2435 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2443 GLscrat6 = NumberMalloc(
"GcdLong"); GLscrat7 = NumberMalloc(
"GcdLong");
2444 GLscrat8 = NumberMalloc(
"GcdLong");
2445 GLscrat9 = NumberMalloc(
"GcdLong"); GLscrat10 = NumberMalloc(
"GcdLong");
2450 if ( na == 1 && nb == 1 ) {
2453 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2457 else if ( na <= 2 && nb <= 2 ) {
2458 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2460 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2462 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2463#if ( BITSINWORD == 16 )
2465 lz = lx % ly; lx = ly;
2466 }
while ( ( ly = lz ) != 0 );
2469 lz = lx % ly; lx = ly;
2470 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2472 x = (UWORD)lx; y = (UWORD)ly;
2473 do { *c = x % y; x = y; }
while ( ( y = *c ) != 0 );
2481 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2489 else if ( na < GCDMAX || nb < GCDMAX || na != nb ) {
2491 x2 = GLscrat8; x3 = a; n2 = i = na;
2493 x1 = c; x3 = b; n1 = i = nb;
2497 x1 = c; x3 = a; n1 = i = na;
2499 x2 = GLscrat8; x3 = b; n2 = i = nb;
2502 x1 = c; x2 = GLscrat8; x3 = GLscrat7; x4 = GLscrat6;
2504 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto GcdErr;
2505 if ( !n3 ) { x1 = x2; n1 = n2;
break; }
2506 if ( n2 <= 2 ) { a = x2; b = x3; na = n2; nb = n3;
goto restart; }
2507 if ( n3 >= GCDMAX && n2 == n3 ) {
2508 a = GLscrat9; b = GLscrat10; na = n2; nb = n3;
2509 for ( i = 0; i < na; i++ ) a[i] = x2[i];
2510 for ( i = 0; i < nb; i++ ) b[i] = x3[i];
2513 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto GcdErr;
2514 if ( !n1 ) { x1 = x3; n1 = n3;
break; }
2515 if ( n3 <= 2 ) { a = x3; b = x1; na = n3; nb = n1;
goto restart; }
2516 if ( n1 >= GCDMAX && n1 == n3 ) {
2517 a = GLscrat9; b = GLscrat10; na = n3; nb = n1;
2518 for ( i = 0; i < na; i++ ) a[i] = x3[i];
2519 for ( i = 0; i < nb; i++ ) b[i] = x1[i];
2522 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto GcdErr;
2523 if ( !n2 ) { *nc = n1;
goto normalend; }
2524 if ( n1 <= 2 ) { a = x1; b = x2; na = n1; nb = n2;
goto restart; }
2525 if ( n2 >= GCDMAX && n2 == n1 ) {
2526 a = GLscrat9; b = GLscrat10; na = n1; nb = n2;
2527 for ( i = 0; i < na; i++ ) a[i] = x1[i];
2528 for ( i = 0; i < nb; i++ ) b[i] = x2[i];
2552 ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2553 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2554 ly = (((RLONG)(b[nb-1]))<<BITSINWORD) + b[nb-2];
2555 if ( ly > lx ) { lz = lx; lx = ly; ly = lz; d = a; a = b; b = d; }
2558 mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2559 ma1 = mb1; ma2 = mb2; mb1 = mc1; mb2 = mc2;
2560 lz = lx - m*ly; lx = ly; ly = lz;
2561 }
while ( ly >= FULLMAX );
2575 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2576 if ( x1[1] ) n1 = -2;
2581 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2582 if ( x1[1] ) n1 = 2;
2585 if ( MulLong(a,na,x1,n1,x2,&n2) )
goto GcdErr;
2589 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2590 if ( x1[1] ) n1 = -2;
2595 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2596 if ( x1[1] ) n1 = 2;
2599 if ( MulLong(b,nb,x1,n1,x3,&n3) )
goto GcdErr;
2600 if ( AddLong(x2,n2,x3,n3,c,&n4) )
goto GcdErr;
2604 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2605 if ( x1[1] ) n1 = -2;
2610 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2611 if ( x1[1] ) n1 = 2;
2614 if ( MulLong(a,na,x1,n1,x2,&n2) )
goto GcdErr;
2618 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2619 if ( x1[1] ) n1 = -2;
2624 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2625 if ( x1[1] ) n1 = 2;
2628 if ( MulLong(b,nb,x1,n1,x3,&n3) )
goto GcdErr;
2629 if ( AddLong(x2,n2,x3,n3,x5,&n5) )
goto GcdErr;
2630 a = c; na = n4; b = x5; nb = n5;
2631 if ( nb == 0 ) { *nc = n4;
goto normalend; }
2633 for ( i = 0; i < na; i++ ) x4[i] = a[i];
2635 if ( na < 0 ) na = -na;
2636 if ( nb < 0 ) nb = -nb;
2647 if ( nb >= GCDMAX && na == nb+1 && b[nb-1] >= HALFMAX && b[nb-1] > a[na-1] ) {
2648 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2649 x1[0] = lx/b[nb-1]; n1 = 1;
2650 MulLong(b,nb,x1,n1,x2,&n2);
2652 AddLong(a,na,x2,n2,x4,&n4);
2655 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2658 if ( n4 < 0 ) n4 = -n4;
2659 a = b; na = nb; b = x4; nb = n4;
2667 NumberFree(GLscrat6,
"GcdLong"); NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2668 NumberFree(GLscrat9,
"GcdLong"); NumberFree(GLscrat10,
"GcdLong");
2671 MLOCK(ErrorMessageLock);
2673 MUNLOCK(ErrorMessageLock);
2674 NumberFree(GLscrat6,
"GcdLong"); NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2675 NumberFree(GLscrat9,
"GcdLong"); NumberFree(GLscrat10,
"GcdLong");
2686int GetBinom(UWORD *a, WORD *na, WORD i1, WORD i2)
2690 UWORD *GBscrat3, *GBscrat4;
2691 if ( i1-i2 < i2 ) i2 = i1-i2;
2692 if ( i2 == 0 ) { *a = 1; *na = 1;
return(0); }
2693 if ( i2 > i1 ) { *a = 0; *na = 0;
return(0); }
2695 GBscrat3 = NumberMalloc(
"GetBinom"); GBscrat4 = NumberMalloc(
"GetBinom");
2696 for ( j = 2; j <= i2; j++ ) {
2697 GBscrat3[0] = i1+1-j;
2698 if ( MulLong(a,*na,GBscrat3,(WORD)1,GBscrat4,&k) )
goto CalledFrom;
2700 if ( DivLong(GBscrat4,k,GBscrat3,(WORD)1,a,na,GBscrat3,&l) )
goto CalledFrom;
2702 NumberFree(GBscrat3,
"GetBinom"); NumberFree(GBscrat4,
"GetBinom");
2705 MLOCK(ErrorMessageLock);
2706 MesCall(
"GetBinom");
2707 MUNLOCK(ErrorMessageLock);
2708 NumberFree(GBscrat3,
"GetBinom"); NumberFree(GBscrat4,
"GetBinom");
2720int LcmLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2723 UWORD *d = NumberMalloc(
"LcmLong");
2724 UWORD *e = NumberMalloc(
"LcmLong");
2725 UWORD *f = NumberMalloc(
"LcmLong");
2727 GcdLong(BHEAD a, na, b, nb, d, &nd);
2728 DivLong(a,na,d,nd,e,&ne,f,&nf);
2729 if ( MulLong(b,nb,e,ne,c,nc) ) {
2730 MLOCK(ErrorMessageLock);
2732 MUNLOCK(ErrorMessageLock);
2735 NumberFree(f,
"LcmLong");
2736 NumberFree(e,
"LcmLong");
2737 NumberFree(d,
"LcmLong");
2754int TakeLongRoot(UWORD *a, WORD *n, WORD power)
2757 int numbits, guessbits, i, retval = 0;
2758 UWORD x, *b, *c, *d, *e;
2759 WORD na, nb, nc, nd, ne;
2760 if ( *n < 0 && ( power & 1 ) == 0 )
return(1);
2761 if ( power == 1 )
return(0);
2762 if ( *n < 0 ) { na = -*n; }
2766 if ( a[0] == 1 )
return(0);
2767 if ( power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<power) ) {
2768 a[0] = 2;
return(0);
2770 if ( 2*power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<(2*power)) ) {
2771 a[0] = 4;
return(0);
2778 numbits = BITSINWORD*(na-1);
2780 while ( ( x >> 8 ) != 0 ) { numbits += 8; x >>= 8; }
2781 if ( ( x >> 4 ) != 0 ) { numbits += 4; x >>= 4; }
2782 if ( ( x >> 2 ) != 0 ) { numbits += 2; x >>= 2; }
2783 if ( ( x >> 1 ) != 0 ) numbits++;
2784 guessbits = numbits / power;
2785 if ( guessbits <= 0 )
return(1);
2786 nb = guessbits/BITSINWORD;
2796 b = NumberMalloc(
"TakeLongRoot"); c = NumberMalloc(
"TakeLongRoot");
2797 d = NumberMalloc(
"TakeLongRoot"); e = NumberMalloc(
"TakeLongRoot");
2798 for ( i = 0; i < nb; i++ ) { b[i] = 0; }
2799 b[nb] = 1 << (guessbits%BITSINWORD);
2803 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2804 if ( RaisPow(BHEAD c,&nc,power-1) )
goto TLcall;
2805 if ( DivLong(a,na,c,nc,d,&nd,e,&ne) )
goto TLcall;
2807 if ( AddLong(d,nd,b,nb,c,&nc) )
goto TLcall;
2810 if ( ne == 0 )
break;
2820 DivLong(c,nc,(UWORD *)(&power),1,d,&nd,e,&ne);
2848 if ( AddLong(b,nb,d,nd,b,&nb) )
goto TLcall;
2850 for ( i = 0; i < nb; i++ ) a[i] = b[i];
2851 if ( *n < 0 ) *n = -nb;
2853 NumberFree(b,
"TakeLongRoot"); NumberFree(c,
"TakeLongRoot");
2854 NumberFree(d,
"TakeLongRoot"); NumberFree(e,
"TakeLongRoot");
2857 MLOCK(ErrorMessageLock);
2858 MesCall(
"TakeLongRoot");
2859 MUNLOCK(ErrorMessageLock);
2860 NumberFree(b,
"TakeLongRoot"); NumberFree(c,
"TakeLongRoot");
2861 NumberFree(d,
"TakeLongRoot"); NumberFree(e,
"TakeLongRoot");
2874int MakeRational(WORD a,WORD m, WORD *b, WORD *c)
2876 LONG x1,x2,x3,x4,y1,y2;
2877 if ( a < 0 ) { a = a+m; }
2879 if ( a > m/2 ) a = a-m;
2880 *b = a; *c = 1;
return(0);
2884 y1 = x1/x2; y2 = x1%x2; x3 = 1; x4 = -y1; x1 = x2; x2 = y2;
2885 while ( x2*x2 >= m ) {
2886 y1 = x1/x2; y2 = x1%x2; x1 = x2; x2 = y2; y2 = x3-y1*x4; x3 = x4; x4 = y2;
2890 if ( x2 == 0 ) {
return(1); }
2891 if ( x2 > m/2 ) *b = x2-m;
2893 if ( x4 > m/2 ) { *c = x4-m; *c = -*c; *b = -*b; }
2894 else if ( x4 <= -m/2 ) { x4 += m; *c = x4; }
2895 else if ( x4 < 0 ) { x4 = -x4; *c = x4; *b = -*b; }
2920#define COPYLONG(x1,nx1,x2,nx2) { int i; for(i=0;i<ABS(nx2);i++)x1[i]=x2[i];nx1=nx2; }
2922int MakeLongRational(PHEAD UWORD *a, WORD na, UWORD *m, WORD nm, UWORD *b, WORD *nb)
2924 UWORD *root = NumberMalloc(
"MakeRational");
2925 UWORD *x1 = NumberMalloc(
"MakeRational");
2926 UWORD *x2 = NumberMalloc(
"MakeRational");
2927 UWORD *x3 = NumberMalloc(
"MakeRational");
2928 UWORD *x4 = NumberMalloc(
"MakeRational");
2929 UWORD *y1 = NumberMalloc(
"MakeRational");
2930 UWORD *y2 = NumberMalloc(
"MakeRational");
2931 WORD nroot,nx1,nx2,nx3,nx4,ny1,ny2 = 0,retval = 0;
2936 COPYLONG(root,nroot,m,nm)
2937 TakeLongRoot(root,&nroot,2);
2941 if ( na < 0 ) { na = -na; sign = -sign; }
2942 COPYLONG(x1,nx1,m,nm)
2943 COPYLONG(x2,nx2,a,na)
2951 if ( BigLong(x2,nx2,root,nroot) <= 0 ) {
2955 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2956 if ( ny2 == 0 ) { retval = 1;
goto cleanup; }
2957 COPYLONG(x1,nx1,x2,nx2)
2958 COPYLONG(x2,nx2,y2,ny2)
2960 COPYLONG(x4,nx4,y1,ny1)
2965 while ( BigLong(x2,nx2,root,nroot) > 0 ) {
2966 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2967 if ( ny2 == 0 ) { retval = 1;
goto cleanup; }
2968 COPYLONG(x1,nx1,x2,nx2)
2969 COPYLONG(x2,nx2,y2,ny2)
2970 MulLong(y1,ny1,x4,nx4,y2,&ny2);
2972 AddLong(x3,nx3,y2,ny2,y1,&ny1);
2973 COPYLONG(x3,nx3,x4,nx4)
2974 COPYLONG(x4,nx4,y1,ny1)
2980 if ( nx4 < 0 ) { sign = -sign; nx4 = -nx4; }
2981 COPYLONG(b,*nb,x2,nx2)
2983 if ( sign < 0 ) *nb = -*nb;
2985 NumberFree(y2,
"MakeRational");
2986 NumberFree(y1,
"MakeRational");
2987 NumberFree(x4,
"MakeRational");
2988 NumberFree(x3,
"MakeRational");
2989 NumberFree(x2,
"MakeRational");
2990 NumberFree(x1,
"MakeRational");
2991 NumberFree(root,
"MakeRational");
3011#ifdef WITHCHINESEREMAINDER
3015 UWORD *inv1 = NumberMalloc(
"ChineseRemainder");
3016 UWORD *inv2 = NumberMalloc(
"ChineseRemainder");
3017 UWORD *fac1 = NumberMalloc(
"ChineseRemainder");
3018 UWORD *fac2 = NumberMalloc(
"ChineseRemainder");
3020 WORD ninv1, ninv2, nfac1, nfac2;
3022 AddLong(a1->a,a1->na,a1->m,a1->nm,a1->a,&(a1->na));
3025 AddLong(a2->a,a2->na,a2->m,a2->nm,a2->a,&(a2->na));
3027 MulLong(a1->m,a1->nm,a2->m,a2->nm,a->m,&(a->nm));
3029 GetLongModInverses(BHEAD a1->m,a1->nm,a2->m,a2->nm,inv1,&ninv1,inv2,&ninv2);
3030 MulLong(inv1,ninv1,a1->m,a1->nm,fac1,&nfac1);
3031 MulLong(inv2,ninv2,a2->m,a2->nm,fac2,&nfac2);
3033 MulLong(fac1,nfac1,a2->a,a2->na,inv1,&ninv1);
3034 MulLong(fac2,nfac2,a1->a,a1->na,inv2,&ninv2);
3035 AddLong(inv1,ninv1,inv2,ninv2,a->a,&(a->na));
3038 MulLong(a->a,a->na,two,1,fac1,&nfac1);
3039 if ( BigLong(fac1,nfac1,a->m,a->nm) > 0 ) {
3041 AddLong(a->a,a->na,a->m,a->nm,a->a,&(a->na));
3044 NumberFree(fac2,
"ChineseRemainder");
3045 NumberFree(fac1,
"ChineseRemainder");
3046 NumberFree(inv2,
"ChineseRemainder");
3047 NumberFree(inv1,
"ChineseRemainder");
3073 if ( term1[1] == 0 && n1 == 1 ) {
3074 if ( term2[1] == 0 && n2 == 1 )
return(0);
3075 if ( n2 < 0 )
return(1);
3078 else if ( term2[1] == 0 && n2 == 1 ) {
3079 if ( n1 < 0 )
return(-1);
3083 if ( n2 < 0 )
return(1);
3086 if ( n2 > 0 )
return(-1);
3087 a = term1; term1 = term2; term2 = a;
3088 n3 = -n1; n1 = -n2; n2 = n3;
3090 if ( term1[1] == 1 && term2[1] == 1 && n1 == 1 && n2 == 1 ) {
3091 if ( (UWORD)*term1 > (UWORD)*term2 )
return(1);
3092 else if ( (UWORD)*term1 < (UWORD)*term2 )
return(-1);
3100 c = NumberMalloc(
"CompCoef");
3101 if ( AddRat(BHEAD (UWORD *)term1,n1,(UWORD *)term2,-n2,c,&n3) ) {
3102 MLOCK(ErrorMessageLock);
3103 MesCall(
"CompCoef");
3104 MUNLOCK(ErrorMessageLock);
3105 NumberFree(c,
"CompCoef");
3108 NumberFree(c,
"CompCoef");
3121int Modulus(WORD *term)
3127 if ( TakeModulus((UWORD *)t,&n1,AC.cmod,AC.ncmod,UNPACK) ) {
3128 MLOCK(ErrorMessageLock);
3130 MUNLOCK(ErrorMessageLock);
3137 else if ( n1 > 0 ) {
3142 else if ( n1 < 0 ) {
3148 *term = WORDDIF(t,term);
3168int TakeModulus(UWORD *a, WORD *na, UWORD *cmodvec, WORD ncmod, WORD par)
3171 UWORD *c, *d, *e, *f, *g, *h;
3173 UWORD *x3,*x1,*x5,*x6,*x7,*x8;
3176 WORD nh, tdenom, tnumer, nmod;
3178 if ( ncmod == 0 )
return(0);
3181 if ( ( par & UNPACK ) != 0 ) UnPack(a,n1,&tdenom,&tnumer);
3182 else { tnumer = n1; }
3187 if ( ( ( par & UNPACK ) == 0 ) && nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3190 else if ( nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3192 a[1] = a[1] % cmodvec[0];
3194 MesPrint(
"Division by zero in short modulus arithmetic");
3198 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 ) ) {
3199 y1 = AC.modinverses[a[1]];
3205 a[0] = (x*y1) % cmodvec[0];
3210 a[0] = a[0] % cmodvec[0];
3212 if ( a[0] == 0 ) { *na = 0;
return(0); }
3213 if ( ( AC.modmode & POSNEG ) != 0 ) {
3214 if ( a[0] > (UWORD)(cmodvec[0]/2) ) {
3215 a[0] = cmodvec[0] - a[0];
3219 else if ( *na < 0 ) {
3220 *na = 1; a[0] = cmodvec[0] - a[0];
3224 c = NumberMalloc(
"TakeModulus"); d = NumberMalloc(
"TakeModulus"); e = NumberMalloc(
"TakeModulus");
3225 f = NumberMalloc(
"TakeModulus"); g = NumberMalloc(
"TakeModulus"); h = NumberMalloc(
"TakeModulus");
3227 if ( DivLong(a,tnumer,(UWORD *)cmodvec,nmod,
3228 c,&nh,a,&tnumer) )
goto ModErr;
3229 if ( tnumer == 0 ) { *na = 0;
goto normalreturn; }
3230 if ( ( par & UNPACK ) == 0 ) {
3231 if ( ( AC.modmode & POSNEG ) != 0 ) {
3234 else if ( tnumer < 0 ) {
3235 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3240 if ( tdenom == 1 && a[n1] == 1 ) {
3241 if ( ( AC.modmode & POSNEG ) != 0 ) {
3244 else if ( tnumer < 0 ) {
3245 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3251 while ( --i > 0 ) *a++ = 0;
3254 if ( DivLong(a+n1,tdenom,(UWORD *)cmodvec,nmod,c,&nh,a+n1,&tdenom) )
goto ModErr;
3256 MLOCK(ErrorMessageLock);
3257 MesPrint(
"Division by zero in modulus arithmetic");
3258 if ( AP.DebugFlag ) {
3262 if ( i < 0 ) i = -i;
3263 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
3265 if ( i < 0 ) i = -i;
3266 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
3267 TalToLine((UWORD)(*na));
3271 MUNLOCK(ErrorMessageLock);
3272 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3273 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3276 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 )
3277 && ( tdenom == 1 || tdenom == -1 ) ) {
3278 *d = AC.modinverses[a[n1]]; y1 = 1; y2 = tdenom;
3279 if ( MulLong(a,tnumer,d,y1,c,&y3) )
goto ModErr;
3280 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) )
goto ModErr;
3281 if ( y2 < 0 ) tdenom = -tdenom;
3284 x2 = (UWORD *)cmodvec; x1 = c; i = nmod;
while ( --i >= 0 ) *x1++ = *x2++;
3285 x1 = c; x2 = a+n1; x3 = d; x4 = e; x5 = f; x6 = g;
3286 y1 = nmod; y2 = tdenom; y4 = 0; y5 = 1; *x5 = 1;
3288 if ( DivLong(x1,y1,x2,y2,h,&nh,x3,&y3) )
goto ModErr;
3289 if ( MulLong(x5,y5,h,nh,x6,&y6) )
goto ModErr;
3290 if ( AddLong(x4,y4,x6,-y6,x6,&y6) )
goto ModErr;
3292 if ( y2 != 1 || *x2 != 1 ) {
3293 MLOCK(ErrorMessageLock);
3294 MesPrint(
"Inverse in modulus arithmetic doesn't exist");
3295 MesPrint(
"Denominator and modulus are not relative prime");
3296 MUNLOCK(ErrorMessageLock);
3301 x7 = x1; x1 = x2; y1 = y2; x2 = x3; y2 = y3; x3 = x7;
3302 x8 = x4; x4 = x5; y4 = y5; x5 = x6; y5 = y6; x6 = x8;
3304 if ( y5 < 0 && AddLong((UWORD *)cmodvec,nmod,x5,y5,x5,&y5) )
goto ModErr;
3305 if ( MulLong(a,tnumer,x5,y5,c,&y3) )
goto ModErr;
3306 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) )
goto ModErr;
3308 if ( !tdenom ) { *na = 0;
goto normalreturn; }
3309 if ( ( ( AC.modmode & POSNEG ) != 0 ) && ( ( par & FROMFUNCTION ) == 0 ) ) {
3312 else if ( tdenom < 0 ) {
3313 SubPLon((UWORD *)cmodvec,nmod,a,-tdenom,a,&tdenom);
3319 while ( --i > 0 ) *a++ = 0;
3321 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3322 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3325 MLOCK(ErrorMessageLock);
3326 MesCall(
"TakeModulus");
3327 MUNLOCK(ErrorMessageLock);
3328 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3329 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3340int TakeNormalModulus (UWORD *a, WORD *na, UWORD *c, WORD nc, WORD par)
3349 halfc = NumberMalloc(
"TakeNormalModulus");
3353 for (n=0; n<nhalfc; n++) {
3355 if (n+1<nc) halfc[n] |= c[n+1] << (BITSINWORD-1);
3358 if (halfc[nhalfc-1]==0)
3362 if (BigLong(a,ABS(*na),halfc,nhalfc) > 0) {
3364 TakeModulus(a,na,c,nc,par);
3367 if (BigLong(a,n,halfc,nhalfc) > 0) {
3368 SubPLon(c,nc,a,n,a,&n);
3369 *na = (*na > 0 ? -n : n);
3373 NumberFree(halfc,
"TakeNormalModulus");
3382int MakeModTable(
void)
3386 if ( AC.modpowers ) {
3387 M_free(AC.modpowers,
"AC.modpowers");
3388 AC.modpowers = NULL;
3392 MLOCK(ErrorMessageLock);
3393 MesPrint(
"!>No memory for modulus generator power table");
3394 MUNLOCK(ErrorMessageLock);
3398 if ( n == 0 )
return(0);
3399 size = (LONG)(*AC.cmod);
3400 if ( n == 2 ) size += (((LONG)AC.cmod[1])<<BITSINWORD);
3401 AC.modpowers = (UWORD *)Malloc1(size*n*
sizeof(UWORD),
"table for powers of modulus");
3404 for ( i = 0; i < size; i++ ) AC.modpowers[i] = 0;
3405 for ( i = 0; i < size; i++ ) {
3406 AC.modpowers[j] = (WORD)i;
3410 for ( i = 2; i < size; i++ ) {
3411 if ( AC.modpowers[i] == 0 ) {
3412 MLOCK(ErrorMessageLock);
3413 MesPrint(
"&improper generator for this modulus");
3414 MUNLOCK(ErrorMessageLock);
3415 M_free(AC.modpowers,
"AC.modpowers");
3419 AC.modpowers[1] = 0;
3424 UWORD *MMscrat7 = NumberMalloc(
"MakeModTable"), *MMscratC = NumberMalloc(
"MakeModTable");
3428 for ( i = 0; i < j; i+=2 ) { AC.modpowers[i] = 0; AC.modpowers[i+1] = 0; }
3429 for ( i = 0; i < size; i++ ) {
3430 j = *MMscratC + (((LONG)MMscratC[1])<<BITSINWORD);
3432 AC.modpowers[j] = (WORD)(i & WORDMASK);
3433 AC.modpowers[j+1] = (WORD)(i >> BITSINWORD);
3434 MulLong((UWORD *)MMscratC,nScrat,(UWORD *)AC.powmod,
3435 AC.npowmod,(UWORD *)MMscrat7,&n2);
3436 TakeModulus(MMscrat7,&n2,AC.cmod,AC.ncmod,NOUNPACK);
3437 *MMscratC = *MMscrat7; MMscratC[1] = MMscrat7[1]; nScrat = n2;
3439 NumberFree(MMscrat7,
"MakeModTable"); NumberFree(MMscratC,
"MakeModTable");
3441 for ( i = 4; i < j; i+=2 ) {
3442 if ( AC.modpowers[i] == 0 && AC.modpowers[i+1] == 0 ) {
3443 MLOCK(ErrorMessageLock);
3444 MesPrint(
"&improper generator for this modulus");
3445 MUNLOCK(ErrorMessageLock);
3446 M_free(AC.modpowers,
"AC.modpowers");
3450 AC.modpowers[2] = AC.modpowers[3] = 0;
3470int Factorial(PHEAD WORD n, UWORD *a, WORD *na)
3477 if ( n > AT.nfac ) {
3478 if ( AT.factorials == 0 ) {
3479 AT.nfac = 0; AT.mfac = 50; AT.sfact = 400;
3480 AT.pfac = (LONG *)Malloc1((AT.mfac+2)*
sizeof(LONG),
"factorials");
3481 AT.factorials = (UWORD *)Malloc1(AT.sfact*
sizeof(UWORD),
"factorials");
3482 AT.factorials[0] = 1; AT.pfac[0] = 0; AT.pfac[1] = 1;
3485 c = AT.factorials+AT.pfac[AT.nfac];
3486 nc = i = AT.pfac[AT.nfac+1] - AT.pfac[AT.nfac];
3487 while ( --i >= 0 ) *b++ = *c++;
3488 for ( j = AT.nfac+1; j <= n; j++ ) {
3490 if ( nc > AM.MaxTal ) {
3491 MLOCK(ErrorMessageLock);
3492 MesPrint(
"Overflow in factorial. MaxTal = %d",AM.MaxTal);
3493 MesPrint(
"Increase MaxTerm in %s",setupfilename);
3494 MUNLOCK(ErrorMessageLock);
3497 if ( j > AT.mfac ) {
3499 p = (LONG *)Malloc1((AT.mfac*2+2)*
sizeof(LONG),
"factorials");
3501 for ( i = AT.mfac+1; i >= 0; i-- ) p[i] = AT.pfac[i];
3502 M_free(AT.pfac,
"factorial offsets"); AT.pfac = p; AT.mfac *= 2;
3504 if ( AT.pfac[j] + nc >= AT.sfact ) {
3506 f = (UWORD *)Malloc1(AT.sfact*2*
sizeof(UWORD),
"factorials");
3508 c = AT.factorials; b = f;
3509 while ( --ii >= 0 ) *b++ = *c++;
3510 M_free(AT.factorials,
"factorials");
3514 b = a; c = AT.factorials + AT.pfac[j]; i = nc;
3515 while ( --i >= 0 ) *c++ = *b++;
3516 AT.pfac[j+1] = AT.pfac[j] + nc;
3521 else if ( n == 0 ) {
3525 *na = i = AT.pfac[n+1] - AT.pfac[n];
3526 b = AT.factorials + AT.pfac[n];
3527 while ( --i >= 0 ) *a++ = *b++;
3550int Bernoulli(WORD n, UWORD *a, WORD *na)
3553 UWORD *b, *c, *scrib, *ntop, *ntop1;
3554 WORD i, i1, i2, nhalf, nqua, nscrib, nntop, nntop1, *oldworkpointer;
3555 UWORD twee = 2, twonplus1;
3559 if ( n == 0 ) { a[0] = a[1] = 1; *na = 3; }
3560 else if ( n == 1 ) { a[0] = 1; a[1] = 2; *na = 3; }
3563 if ( ( n & 1 ) != 0 ) { a[0] = a[1] = 0; *na = 0;
return(0); }
3565 if ( nhalf > AT.nBer ) {
3566 oldworkpointer = AT.WorkPointer;
3567 if ( AT.bernoullis == 0 ) {
3568 AT.nBer = 1; AT.mBer = 50; AT.sBer = 400;
3569 AT.pBer = (LONG *)Malloc1((AT.mBer+2)*
sizeof(LONG),
"bernoullis");
3570 AT.bernoullis = (UWORD *)Malloc1(AT.sBer*
sizeof(UWORD),
"bernoullis");
3571 AT.pBer[1] = 0; AT.pBer[2] = 3;
3572 AT.bernoullis[0] = 3; AT.bernoullis[1] = 1; AT.bernoullis[2] = 12;
3574 a[0] = 1; a[1] = 12; *na = 3;
return(0);
3577 while ( nhalf > AT.mBer ) {
3579 p = (LONG *)Malloc1((AT.mBer*2+1)*
sizeof(LONG),
"bernoullis");
3581 for ( i = AT.mBer; i >= 0; i-- ) p[i] = AT.pBer[i];
3582 M_free(AT.pBer,
"factorial pointers"); AT.pBer = p; AT.mBer *= 2;
3584 for ( n = AT.nBer+1; n <= nhalf; n++ ) {
3585 scrib = (UWORD *)(AT.WorkPointer);
3587 if ( ( n & 1 ) == 1 ) {
3588 nscrib = 0; ntop = scrib;
3591 b = AT.bernoullis + AT.pBer[nqua];
3593 i = (WORD)(REDLENG(nscrib));
3594 MulRat(BHEAD b,i,b,i,scrib,&nscrib);
3595 ntop = scrib + 2*nscrib;
3598 for ( j = 1; j <= nqua; j++ ) {
3599 b = AT.bernoullis + AT.pBer[j];
3600 c = AT.bernoullis + AT.pBer[n-j];
3601 i1 = (WORD)(*b); i2 = (WORD)(*c);
3604 MulRat(BHEAD b+1,i1,c+1,i2,ntop,&nntop);
3605 Mully(BHEAD ntop,&nntop,&twee,1);
3607 i = (WORD)nntop;
if ( i < 0 ) i = -i;
3609 AddRat(BHEAD ntop,nntop,scrib,nscrib,ntop1,&nntop1);
3612 ntop1 = ntop; nntop1 = nntop;
3614 nscrib = i1 = (WORD)nntop1;
3615 if ( i1 < 0 ) i1 = - i1;
3617 for ( i = 0; i < i1; i++ ) scrib[i] = ntop1[i];
3621 Divvy(BHEAD scrib,&nscrib,&twonplus1,-1);
3622 i1 = INCLENG(nscrib);
3623 i2 = i1;
if ( i2 < 0 ) i2 = -i2;
3624 i = (WORD)(AT.bernoullis[AT.pBer[n-1]]);
3625 if ( i < 0 ) i = -i;
3626 AT.pBer[n] = AT.pBer[n-1]+i;
3627 if ( AT.pBer[n] + i2 >= AT.sBer ) {
3629 f = (UWORD *)Malloc1(AT.sBer*2*
sizeof(UWORD),
"bernoullis");
3631 c = AT.bernoullis; b = f;
3632 while ( --ii >= 0 ) *b++ = *c++;
3633 M_free(AT.bernoullis,
"bernoullis");
3637 c = AT.bernoullis + AT.pBer[n]; b = scrib;
3639 for ( i = 1; i < i2; i++ ) *c++ = *b++;
3642 AT.WorkPointer = oldworkpointer;
3644 b = AT.bernoullis + AT.pBer[nhalf];
3645 *na = i = (WORD)(*b++);
3646 if ( i < 0 ) i = -i;
3648 while ( --i >= 0 ) *a++ = *b++;
3667#if ( BITSINWORD == 32 )
3669void StartPrimeList(PHEAD0)
3672 AR.PrimeList[AR.numinprimelist++] = 3;
3673 for ( i = 5; i < 46340; i += 2 ) {
3674 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*AR.PrimeList[j] <= i; j++ ) {
3675 if ( i % AR.PrimeList[j] == 0 )
goto nexti;
3677 AR.PrimeList[AR.numinprimelist++] = i;
3680 AR.notfirstprime = 1;
3690#if ( BITSINWORD == 32 )
3691 if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
3693 if ( num > AT.inprimelist ) {
3694 while ( AT.inprimelist < num ) {
3695 if ( num >= AT.sizeprimelist ) {
3696 if ( AT.sizeprimelist == 0 ) newsize = 32;
3697 else newsize = 2*AT.sizeprimelist;
3698 while ( num >= newsize ) newsize = newsize*2;
3699 newpl = (WORD *)Malloc1(newsize*
sizeof(WORD),
"NextPrime");
3700 for ( i = 0; i < AT.sizeprimelist; i++ ) {
3701 newpl[i] = AT.primelist[i];
3703 if ( AT.sizeprimelist > 0 ) {
3704 M_free(AT.primelist,
"NextPrime");
3706 AT.sizeprimelist = newsize;
3707 AT.primelist = newpl;
3709 if ( AT.inprimelist < 0 ) { i = MAXPOSITIVE; }
3710 else { i = AT.primelist[AT.inprimelist]; }
3711 while ( i > MAXPOWER ) {
3713#if ( BITSINWORD == 32 )
3714 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*(LONG)(AR.PrimeList[j]) <= x; j++ ) {
3715 if ( x % AR.PrimeList[j] == 0 )
goto nexti;
3718 for ( j = 3; j*((LONG)j) <= x; j += 2 ) {
3719 if ( x % j == 0 )
goto nexti;
3723 AT.primelist[AT.inprimelist] = i;
3727 if ( i < MAXPOWER ) {
3729 MLOCK(ErrorMessageLock);
3730 MesPrint(
"!>There are not enough short prime numbers for this calculation");
3731 MesPrint(
"Try to use a computer with a %d-bits architecture",
3732 (
int)(BITSINWORD*4));
3733 MUNLOCK(ErrorMessageLock);
3739 return(AT.primelist[num]);
3751WORD Moebius(PHEAD WORD nn)
3755 SBYTE *newtable, mu;
3756#if ( BITSINWORD == 32 )
3757 if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
3764 if ( nn >= AR.moebiustablesize ) {
3765 if ( AR.moebiustablesize <= 0 ) { newsize = (LONG)nn + 20; }
3766 else { newsize = (LONG)nn*2; }
3767 if ( newsize > MAXPOSITIVE ) newsize = MAXPOSITIVE;
3768 newtable = (SBYTE *)Malloc1(newsize*
sizeof(SBYTE),
"Moebius");
3769 for ( i = 0; i < AR.moebiustablesize; i++ ) newtable[i] = AR.moebiustable[i];
3770 for ( ; i < newsize; i++ ) newtable[i] = 2;
3771 if ( AR.moebiustablesize > 0 ) M_free(AR.moebiustable,
"Moebius");
3772 AR.moebiustable = newtable;
3773 AR.moebiustablesize = newsize;
3776 if ( nn != MAXPOSITIVE && AR.moebiustable[nn] != 2 )
return((WORD)AR.moebiustable[nn]);
3778 if ( n == 1 )
goto putvalue;
3781 if ( n % 2 == 0 ) { mu = 0;
goto putvalue; }
3782 if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n];
goto putvalue; }
3784 if ( n == 1 )
goto putvalue;
3786#if ( BITSINWORD == 32 )
3787 for ( i = 0; i < AR.numinprimelist; i++ ) {
3788 x = AR.PrimeList[i];
3790 for ( x = 3; x < MAXPOSITIVE; x += 2 ) {
3794 if ( n % x == 0 ) { mu = 0;
goto putvalue; }
3795 if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n];
goto putvalue; }
3797 if ( n == 1 )
goto putvalue;
3799 if ( n < x*x )
break;
3803 if ( nn != MAXPOSITIVE ) AR.moebiustable[nn] = mu;
3826static void wranfnew(PHEAD0)
3830 for ( i = 0; i < AR.wranfnpair1; i++ ) {
3831 j = AR.wranfia[i] - AR.wranfia[i+(AR.wranfnpair2-AR.wranfnpair1)];
3832 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3835 for ( i = AR.wranfnpair1; i < AR.wranfnpair2; i++ ) {
3836 j = AR.wranfia[i] - AR.wranfia[i-AR.wranfnpair1];
3837 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3842void iniwranf(PHEAD0)
3844 int imax = AR.wranfnpair2-1;
3845 ULONG i, ii, seed = AR.wranfseed;
3847 ULONG offset = 12345;
3850#if defined(WITHPTHREADS)
3852#elif defined(WITHMPI)
3859 pow = offset; accu = 1;
3861 if ( ( i & 1 ) != 0 ) accu *= pow;
3862 i /= 2; pow = pow*pow;
3867 if ( seed < ((LONG)1<<(BITSINWORD-1)) ) {
3868 j = ( (seed+31459L) << (BITSINWORD-2))+offset;
3870 else if ( seed < ((LONG)1<<(BITSINWORD+10-1)) ) {
3871 j = ( (seed+31459L) << (BITSINWORD-10-2))+offset;
3874 j = ( (seed+31459L) << 1)+offset;
3876 if ( ( seed & 1 ) == 1 ) seed++;
3878 AR.wranfia[imax] = j;
3880 for ( i = 0; i <= (ULONG)(imax); i++ ) {
3881 ii = (AR.wranfnpair1*i)%AR.wranfnpair2;
3883 k = ULongToLong((ULONG)j - (ULONG)k);
3884 if ( k < 0 ) k += (LONG)1 << (2*BITSINWORD-2);
3887 for ( i = 0; i < WARMUP; i++ ) wranfnew(BHEAD0);
3894 if ( AR.wranfia == 0 ) {
3895 AR.wranfia = (ULONG *)Malloc1(AR.wranfnpair2*
sizeof(ULONG),
"wranf");
3898 if ( AR.wranfcall >= AR.wranfnpair2) {
3902 wval = (UWORD)(AR.wranfia[AR.wranfcall++]>>(BITSINWORD-1));
3910UWORD iranf(PHEAD UWORD imax)
3914 if (imax < 2)
return 0;
3915 x = (LONG)1 << BITSINWORD;
3917 while ( ( i = wranf(BHEAD0) ) >= xmax ) {}
3935UBYTE *PreRandom(UBYTE *s)
3938 UBYTE *mode,*mins = 0,*maxs = 0, *outval;
3940 double minval, maxval, value = 0;
3943 while ( FG.cTable[*s] <= 1 ) s++;
3944 if ( *s ==
',' ) { *s = 0; s++; }
3946 while ( *s && *s !=
',' ) s++;
3947 if ( *s ==
',' ) { *s = 0; s++; }
3949 while ( *s && *s !=
',' ) s++;
3950 if ( *s || *maxs == 0 || *mins == 0 ) {
3951 MesPrint(
"@Illegal arguments in macro RANDOM_");
3954 if ( StrICmp(mode,(UBYTE *)
"lin") == 0 ) {
3957 else if ( StrICmp(mode,(UBYTE *)
"log") == 0 ) {
3961 MesPrint(
"@Illegal mode argument in macro RANDOM_");
3965 sscanf((
char *)mins,
"%f",&num); minval = num;
3966 sscanf((
char *)maxs,
"%f",&num); maxval = num;
3978 if ( PF.me == MASTER ) {
3985 xx = x/pow(2.0,(
double)(BITSINWORD-1));
3986 if ( linlog == 0 ) {
3987 value = minval + (maxval-minval)*xx;
3989 else if ( linlog == 1 ) {
3990 value = minval * pow(maxval/minval,xx);
3994 outval = (UBYTE *)Malloc1(64,
"PreRandom");
3995 if ( ABS(value) < 0.00001 || ABS(value) > 1000000. ) {
3996 snprintf((
char *)outval,64,
"%e",value);
3998 else if ( ABS(value) < 0.0001 ) { snprintf((
char *)outval,64,
"%10f",value); }
3999 else if ( ABS(value) < 0.001 ) { snprintf((
char *)outval,64,
"%9f",value); }
4000 else if ( ABS(value) < 0.01 ) { snprintf((
char *)outval,64,
"%8f",value); }
4001 else if ( ABS(value) < 0.1 ) { snprintf((
char *)outval,64,
"%7f",value); }
4002 else if ( ABS(value) < 1. ) { snprintf((
char *)outval,64,
"%6f",value); }
4003 else if ( ABS(value) < 10. ) { snprintf((
char *)outval,64,
"%5f",value); }
4004 else if ( ABS(value) < 100. ) { snprintf((
char *)outval,64,
"%4f",value); }
4005 else if ( ABS(value) < 1000. ) { snprintf((
char *)outval,64,
"%3f",value); }
4006 else if ( ABS(value) < 10000. ) { snprintf((
char *)outval,64,
"%2f",value); }
4007 else { snprintf((
char *)outval,64,
"%1f",value); }
LONG PF_BroadcastNumber(LONG x)
int GetModInverses(WORD m1, WORD m2, WORD *im1, WORD *im2)
void RaisPowCached(PHEAD WORD x, WORD n, UWORD **c, WORD *nc)
int NormalModulus(UWORD *a, WORD *na)
WORD NextPrime(PHEAD WORD num)
WORD CompCoef(WORD *term1, WORD *term2)