46#define GMPSPREAD (GMP_LIMB_BITS/BITSINWORD)
62void Pack(UWORD *a, WORD *na, UWORD *b, WORD nb)
66 if ( (c = *na) == 0 ) {
67 MLOCK(ErrorMessageLock);
68 MesPrint(
"Caught a zero in Pack");
69 MUNLOCK(ErrorMessageLock);
73 MLOCK(ErrorMessageLock);
74 MesPrint(
"Division by zero in Pack");
75 MUNLOCK(ErrorMessageLock);
78 if ( *na < 0 ) { sgn = -sgn; c = -c; }
79 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
83 while ( --i >= 0 ) *to++ = 0;
87 while ( --i >= 0 ) *to++ = 0;
88 if ( sgn < 0 ) *na = -*na;
100void UnPack(UWORD *a, WORD na, WORD *denom, WORD *numer)
104 if ( na < 0 ) { na = -na; }
110 while ( !(*a) ) { i--; a--; }
111 while ( !(*pos) ) { na--; pos--; }
114 if ( sgn < 0 ) i = -i;
126int Mully(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
131 WORD nd, ne, adenom, anumer;
132 if ( !nb ) { *na = 0;
return(0); }
133 else if ( *b == 1 ) {
134 if ( nb == 1 )
return(0);
135 else if ( nb == -1 ) { *na = -*na;
return(0); }
137 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
138 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
139 UnPack(a,*na,&adenom,&anumer);
140 d = NumberMalloc(
"Mully"); e = NumberMalloc(
"Mully");
141 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
143 if ( Simplify(BHEAD a+*na,&adenom,e,&ne) )
goto MullyEr;
144 if ( MulLong(a,anumer,e,ne,d,&nd) )
goto MullyEr;
146 for ( i = 0; i < *na; i++ ) { e[i] = *b++; }
151 for ( i = 0; i < *na; i++ ) { a[i] = *b++; }
153 if ( sgn < 0 ) *na = -*na;
154 NumberFree(d,
"Mully"); NumberFree(e,
"Mully");
157 MLOCK(ErrorMessageLock);
159 MUNLOCK(ErrorMessageLock);
160 NumberFree(d,
"Mully"); NumberFree(e,
"Mully");
172int Divvy(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
177 WORD nd, ne, adenom, anumer;
179 MLOCK(ErrorMessageLock);
180 MesPrint(
"Division by zero in Divvy");
181 MUNLOCK(ErrorMessageLock);
184 d = NumberMalloc(
"Divvy"); e = NumberMalloc(
"Divvy");
185 if ( nb < 0 ) { sgn = -sgn; nb = -nb; }
186 if ( *na < 0 ) { sgn = -sgn; *na = -*na; }
187 UnPack(a,*na,&adenom,&anumer);
188 for ( i = 0; i < nb; i++ ) { e[i] = *b++; }
190 if ( Simplify(BHEAD a,&anumer,e,&ne) )
goto DivvyEr;
191 if ( MulLong(a+*na,adenom,e,ne,d,&nd) )
goto DivvyEr;
194 if ( sgn < 0 ) *na = -*na;
195 NumberFree(d,
"Divvy"); NumberFree(e,
"Divvy");
198 MLOCK(ErrorMessageLock);
200 MUNLOCK(ErrorMessageLock);
201 NumberFree(d,
"Divvy"); NumberFree(e,
"Divvy");
210int AddRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
213 UWORD *d, *e, *f, *g;
214 WORD nd, ne, nf, ng, adenom, anumer, bdenom, bnumer;
218 if ( nb < 0 ) nb = -nb;
220 for ( i = 0; i < nb; i++ ) *c++ = *b++;
226 if ( na < 0 ) na = -na;
228 for ( i = 0; i < na; i++ ) *c++ = *a++;
231 else if ( b[1] == 1 && a[1] == 1 ) {
236 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = 2; }
240 else if ( nb == -1 ) {
242 *c = *b - *a; *nc = -1;
244 else if ( *b < *a ) {
245 *c = *a - *b; *nc = 1;
252 else if ( na == -1 ){
256 if ( *c < *a ) { c[2] = 1; c[3] = 0; *nc = -2; }
260 else if ( nb == 1 ) {
262 *c = *b - *a; *nc = 1;
264 else if ( *b < *a ) {
265 *c = *a - *b; *nc = -1;
273 UnPack(a,na,&adenom,&anumer);
274 UnPack(b,nb,&bdenom,&bnumer);
275 if ( na < 0 ) na = -na;
276 if ( nb < 0 ) nb = -nb;
277 if ( na == 1 && nb == 1 ) {
279 t3 = ((RLONG)a[1])*((RLONG)b[1]);
280 t1 = ((RLONG)a[0])*((RLONG)b[1]);
281 t2 = ((RLONG)a[1])*((RLONG)b[0]);
282 if ( ( anumer > 0 && bnumer > 0 ) || ( anumer < 0 && bnumer < 0 ) ) {
283 if ( ( t1 = t1 + t2 ) < t2 ) {
286 c[1] = (UWORD)(t1 >> BITSINWORD);
291 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
296 if ( t1 == t2 ) { *nc = 0;
return(0); }
305 if ( ( c[1] = (UWORD)(t1 >> BITSINWORD) ) != 0 ) *nc = 2;
308 if ( anumer < 0 ) *nc = -*nc;
309 d = NumberMalloc(
"AddRat");
311 if ( ( d[1] = (UWORD)(t3 >> BITSINWORD) ) != 0 ) nd = 2;
313 if ( Simplify(BHEAD c,nc,d,&nd) )
goto AddRer1;
324 d = NumberMalloc(
"AddRat"); e = NumberMalloc(
"AddRat");
325 f = NumberMalloc(
"AddRat"); g = NumberMalloc(
"AddRat");
326 if ( GcdLong(BHEAD a+na,adenom,b+nb,bdenom,d,&nd) )
goto AddRer;
327 if ( *d == 1 && nd == 1 ) nd = 0;
329 if ( DivLong(a+na,adenom,d,nd,e,&ne,c,nc) )
goto AddRer;
330 if ( DivLong(b+nb,bdenom,d,nd,f,&nf,c,nc) )
goto AddRer;
331 if ( MulLong(a,anumer,f,nf,c,nc) )
goto AddRer;
332 if ( MulLong(b,bnumer,e,ne,g,&ng) )
goto AddRer;
335 if ( MulLong(a+na,adenom,b,bnumer,c,nc) )
goto AddRer;
336 if ( MulLong(b+nb,bdenom,a,anumer,g,&ng) )
goto AddRer;
338 if ( AddLong(c,*nc,g,ng,c,nc) )
goto AddRer;
340 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat");
341 NumberFree(e,
"AddRat"); NumberFree(d,
"AddRat");
345 if ( Simplify(BHEAD c,nc,d,&nd) )
goto AddRer;
346 if ( MulLong(e,ne,d,nd,g,&ng) )
goto AddRer;
347 if ( MulLong(g,ng,f,nf,d,&nd) )
goto AddRer;
350 if ( MulLong(a+na,adenom,b+nb,bdenom,d,&nd) )
goto AddRer;
352 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat"); NumberFree(e,
"AddRat");
355 NumberFree(d,
"AddRat");
358 NumberFree(g,
"AddRat"); NumberFree(f,
"AddRat"); NumberFree(e,
"AddRat");
360 NumberFree(d,
"AddRat");
362 MLOCK(ErrorMessageLock);
364 MUNLOCK(ErrorMessageLock);
378int MulRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
382 if ( *b == 1 && b[1] == 1 ) {
386 while ( --i >= 0 ) *c++ = *a++;
389 else if ( nb == -1 ) {
392 while ( --i >= 0 ) *c++ = *a++;
396 if ( *a == 1 && a[1] == 1 ) {
400 while ( --i >= 0 ) *c++ = *b++;
403 else if ( na == -1 ) {
406 while ( --i >= 0 ) *c++ = *b++;
410 if ( na < 0 ) { na = -na; sgn = -sgn; }
411 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
412 if ( !na || !nb ) { *nc = 0;
return(0); }
413 if ( na != 1 || nb != 1 ) {
415 UWORD *xd,*xe, *xf,*xg;
416 WORD dden, dnumr, eden, enumr;
417 UnPack(a,na,&dden,&dnumr);
418 UnPack(b,nb,&eden,&enumr);
419 xd = NumberMalloc(
"MulRat"); xf = NumberMalloc(
"MulRat");
420 for ( i = 0; i < dnumr; i++ ) xd[i] = a[i];
422 for ( i = 0; i < dden; i++ ) xf[i] = a[i];
423 xe = NumberMalloc(
"MulRat"); xg = NumberMalloc(
"MulRat");
424 for ( i = 0; i < enumr; i++ ) xe[i] = b[i];
426 for ( i = 0; i < eden; i++ ) xg[i] = b[i];
427 if ( Simplify(BHEAD xd,&dnumr,xg,&eden) ||
428 Simplify(BHEAD xe,&enumr,xf,&dden) ||
429 MulLong(xd,dnumr,xe,enumr,c,nc) ||
430 MulLong(xf,dden,xg,eden,xd,&dnumr) ) {
431 MLOCK(ErrorMessageLock);
433 MUNLOCK(ErrorMessageLock);
434 NumberFree(xd,
"MulRat"); NumberFree(xe,
"MulRat"); NumberFree(xf,
"MulRat"); NumberFree(xg,
"MulRat");
438 NumberFree(xd,
"MulRat"); NumberFree(xe,
"MulRat"); NumberFree(xf,
"MulRat"); NumberFree(xg,
"MulRat");
445 do { a0 = y % b1; y = b1; }
while ( ( b1 = a0 ) != 0 );
455 do { b0 = y % a1; y = a1; }
while ( ( a1 = b0 ) != 0 );
465 if ( xx & AWORDMASK ) {
468 c[1] = (UWORD)(xx >> BITSINWORD);
471 c[3] = (UWORD)(xx >> BITSINWORD);
476 if ( xx & AWORDMASK ) {
479 c[3] = (UWORD)(xx >> BITSINWORD);
488 if ( sgn < 0 ) *nc = -*nc;
500int DivRat(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
507 MLOCK(ErrorMessageLock);
508 MesPrint(
"Rational division by zero");
509 MUNLOCK(ErrorMessageLock);
512 j = i = (nb >= 0)? nb: -nb;
514 do { xx = *xd; *xd++ = *xe; *xe++ = xx; }
while ( --j > 0 );
515 ret = MulRat(BHEAD a,na,b,nb,c,nc);
517 do { xx = *xd; *xd++ = *xe; *xe++ = xx; }
while ( --i > 0 );
531int Simplify(PHEAD UWORD *a, WORD *na, UWORD *b, WORD *nb)
536 WORD n1,n2,n3,n4,sgn = 1;
538 UWORD *Siscrat5, *Siscrat6, *Siscrat7, *Siscrat8;
539 if ( *na < 0 ) { *na = -*na; sgn = -sgn; }
540 if ( *nb < 0 ) { *nb = -*nb; sgn = -sgn; }
541 Siscrat5 = NumberMalloc(
"Simplify"); Siscrat6 = NumberMalloc(
"Simplify");
542 Siscrat7 = NumberMalloc(
"Simplify"); Siscrat8 = NumberMalloc(
"Simplify");
543 x1 = Siscrat8; x2 = Siscrat7;
546 if ( DivLong(a,*na,b,*nb,x1,&n1,x2,&n2) )
goto SimpErr;
548 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
556 do { y1 = y2 % y3; y2 = y3; }
while ( ( y3 = y1 ) != 0 );
557 if ( ( *x2 = y2 ) != 1 ) {
559 if ( DivLong(a,*na,x2,(WORD)1,x1,&n1,x3,&n3) )
goto SimpErr;
560 for ( i = 0; i < n1; i++ ) *a++ = *x1++;
566 else if ( *na >= GCDMAX && *nb >= GCDMAX ) {
567 n1 = i = *na; x3 = a;
569 x3 = b; n2 = i = *nb;
574 if ( GcdLong(BHEAD Siscrat8,n1,Siscrat7,n2,x2,&n3) )
goto SimpErr;
576 if ( *x2 != 1 || n2 != 1 ) {
577 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
580 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
588 n1 = i = *na; x3 = a;
590 x3 = b; n2 = i = *nb;
592 x1 = Siscrat8; x2 = Siscrat7; x3 = Siscrat6;
594 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto SimpErr;
597 while ( ( *x1 = (*x2) % (*x3) ) != 0 ) { *x2 = *x3; *x3 = *x1; }
601 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto SimpErr;
602 if ( !n1 ) { x2 = x3; n2 = n3; x3 = Siscrat7;
break; }
604 while ( ( *x2 = (*x3) % (*x1) ) != 0 ) { *x3 = *x1; *x1 = *x2; }
609 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto SimpErr;
610 if ( !n2 ) { x2 = x1; n2 = n1; x1 = Siscrat7;
break; }
612 while ( ( *x3 = (*x1) % (*x2) ) != 0 ) { *x1 = *x2; *x2 = *x3; }
616 if ( *x2 != 1 || n2 != 1 ) {
617 DivLong(a,*na,x2,n2,x1,&n1,x4,&n4);
620 DivLong(b,*nb,x2,n2,x3,&n3,x4,&n4);
625 if ( sgn < 0 ) *na = -*na;
626 NumberFree(Siscrat5,
"Simplify"); NumberFree(Siscrat6,
"Simplify");
627 NumberFree(Siscrat7,
"Simplify"); NumberFree(Siscrat8,
"Simplify");
630 MLOCK(ErrorMessageLock);
632 MUNLOCK(ErrorMessageLock);
633 NumberFree(Siscrat5,
"Simplify"); NumberFree(Siscrat6,
"Simplify");
634 NumberFree(Siscrat7,
"Simplify"); NumberFree(Siscrat8,
"Simplify");
648int AccumGCD(PHEAD UWORD *a, WORD *na, UWORD *b, WORD nb)
651 WORD nna,nnb,numa,numb,dena,denb,numc,denc;
652 UWORD *GCDbuffer = NumberMalloc(
"AccumGCD");
654 nna = *na;
if ( nna < 0 ) nna = -nna; nna = (nna-1)/2;
655 nnb = nb;
if ( nnb < 0 ) nnb = -nnb; nnb = (nnb-1)/2;
656 UnPack(a,nna,&dena,&numa);
657 UnPack(b,nnb,&denb,&numb);
658 if ( GcdLong(BHEAD a,numa,b,numb,GCDbuffer,&numc) )
goto AccErr;
660 for ( i = 0; i < numa; i++ ) a[i] = GCDbuffer[i];
661 if ( GcdLong(BHEAD a+nna,dena,b+nnb,denb,GCDbuffer,&denc) )
goto AccErr;
663 for ( i = 0; i < dena; i++ ) a[i+nna] = GCDbuffer[i];
664 Pack(a,&numa,a+nna,dena);
666 NumberFree(GCDbuffer,
"AccumGCD");
669 MLOCK(ErrorMessageLock);
671 MUNLOCK(ErrorMessageLock);
672 NumberFree(GCDbuffer,
"AccumGCD");
681int TakeRatRoot(UWORD *a, WORD *n, WORD power)
683 WORD numer,denom, nn;
684 if ( ( power & 1 ) == 0 && *n < 0 )
return(1);
685 if ( ABS(*n) == 1 && a[0] == 1 && a[1] == 1 )
return(0);
687 UnPack(a,nn,&denom,&numer);
688 if ( TakeLongRoot(a+nn,&denom,power) )
return(1);
689 if ( TakeLongRoot(a,&numer,power) )
return(1);
690 Pack(a,&numer,a+nn,denom);
691 if ( *n < 0 ) *n = -numer;
706int AddLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
711 if ( AddPLon(a,-na,b,-nb,c,nc) )
return(-1);
725 else {
return( AddPLon(a,na,b,nb,c,nc) ); }
727 if ( ( res = BigLong(a,na,b,nb) ) > 0 ) {
728 SubPLon(a,na,b,nb,c,nc);
729 if ( sgn < 0 ) *nc = -*nc;
731 else if ( res < 0 ) {
732 SubPLon(b,nb,a,na,c,nc);
733 if ( sgn > 0 ) *nc = -*nc;
751int AddPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
753 UWORD carry = 0, e, nd = 0;
758 if ( e < *c ) carry = 0;
761 if ( e > *c ) carry = 1;
763 a++; b++; c++; nd++; na--; nb--;
768 if ( *c++ ) carry = 0;
776 if ( *c++ ) carry = 0;
783 if ( nd > (UWORD)AM.MaxTal ) {
784 MLOCK(ErrorMessageLock);
785 MesPrint(
"Overflow in addition");
786 MUNLOCK(ErrorMessageLock);
804void SubPLon(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
806 UWORD borrow = 0, e, nd = 0;
810 *c = e - *b - borrow;
811 if ( *c < e ) borrow = 0;
815 if ( *c > e ) borrow = 1;
817 a++; b++; c++; na--; nb--; nd++;
821 if ( *a ) { *c++ = *a++ - 1; borrow = 0; }
822 else { *c++ = (UWORD)(-1); a++; }
827 while ( nd && !*--c ) { nd--; }
842int MulLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
847 if ( !na || !nb ) { *nc = 0;
return(0); }
848 if ( na < 0 ) { na = -na; sgn = -sgn; }
849 if ( nb < 0 ) { nb = -nb; sgn = -sgn; }
851 if ( i > (UWORD)(AM.MaxTal+1) )
goto MulLov;
857 if (na > 3 && nb > 3) {
862 UWORD *DLscrat9 = NumberMalloc(
"MulLong"), *DLscratA = NumberMalloc(
"MulLong"), *DLscratB = NumberMalloc(
"MulLong");
863#if ( GMPSPREAD != 1 )
865 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
870 if ( (LONG)a & (
sizeof(mp_limb_t)-1) ) {
871 from = a; a = to = DLscrat9; j = na; NCOPY(to, from, j);
874#if ( GMPSPREAD != 1 )
876 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
881 if ( (LONG)b & (
sizeof(mp_limb_t)-1) ) {
882 from = b; b = to = DLscratA; j = nb; NCOPY(to, from, j);
885 if ( ( *nc > (WORD)i ) || ( (LONG)c & (LONG)(
sizeof(mp_limb_t)-1) ) ) {
890 mpn_mul((mp_ptr)ic, (mp_srcptr)b, nb/GMPSPREAD, (mp_srcptr)a, na/GMPSPREAD);
893 mpn_mul((mp_ptr)ic, (mp_srcptr)a, na/GMPSPREAD, (mp_srcptr)b, nb/GMPSPREAD);
895 while ( ic[i-1] == 0 ) i--;
902 j = *nc; NCOPY(c, ic, j);
904 if ( sgn < 0 ) *nc = -(*nc);
905 NumberFree(DLscrat9,
"MulLong"); NumberFree(DLscratA,
"MulLong"); NumberFree(DLscratB,
"MulLong");
912 do { *ic++ = 0; }
while ( --i > 0 );
920 t = (*ia++) * bb + t + *ic;
924 if ( t ) *ic = (UWORD)t;
925 }
while ( --nb > 0 );
927 if ( *nc > AM.MaxTal )
goto MulLov;
928 if ( sgn < 0 ) *nc = -(*nc);
931 MLOCK(ErrorMessageLock);
932 MesPrint(
"Overflow in Multiplication");
933 MUNLOCK(ErrorMessageLock);
945int BigLong(UWORD *a, WORD na, UWORD *b, WORD nb)
949 while ( na && !*--a ) na--;
950 while ( nb && !*--b ) nb--;
951 if ( nb < na )
return(1);
952 if ( nb > na )
return(-1);
953 while ( --na >= 0 ) {
954 if ( *a > *b )
return(1);
955 else if ( *b > *a )
return(-1);
973int DivLong(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c,
974 WORD *nc, UWORD *d, WORD *nd)
976 WORD sgna = 1, sgnb = 1, ne, nf, ng, nh;
980 UWORD *e, *f, *ff, *g, norm, estim;
982 UWORD *DLscrat9, *DLscratA, *DLscratB, *DLscratC;
986 MLOCK(ErrorMessageLock);
987 MesPrint(
"Division by zero");
988 MUNLOCK(ErrorMessageLock);
991 if ( !na ) { *nc = *nd = 0;
return(0); }
992 if ( na < 0 ) { sgna = -sgna; na = -na; }
993 if ( nb < 0 ) { sgnb = -sgnb; nb = -nb; }
995 for ( i = 0; i < na; i++ ) *d++ = *a++;
999 else if ( nb == na && ( i = BigLong(b,nb,a,na) ) >= 0 ) {
1001 for ( i = 0; i < na; i++ ) *d++ = *a++;
1011 else if ( nb == 1 ) {
1013 for ( i = 0; i < na; i++ ) *c++ = *a++;
1024 while ( --ni >= 0 ) {
1032 if ( ( *d = (UWORD)t ) == 0 ) *nd = 0;
1033 if ( !*(c+na-1) ) (*nc)--;
1048 if ( na > 4 && nb > 3 ) {
1049 UWORD *ic, *id, *to, *from;
1051 DLscrat9 = NumberMalloc(
"DivLong"); DLscratA = NumberMalloc(
"DivLong");
1052 DLscratB = NumberMalloc(
"DivLong"); DLscratC = NumberMalloc(
"DivLong");
1054#if ( GMPSPREAD != 1 )
1056 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1060 if ( (LONG)a & (
sizeof(mp_limb_t)-1) ) {
1061 from = a; a = to = DLscrat9; i = na; NCOPY(to, from, i);
1064#if ( GMPSPREAD != 1 )
1066 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1070 if ( ( (LONG)b & (
sizeof(mp_limb_t)-1) ) != 0 ) {
1071 from = b; b = to = DLscratA; i = nb; NCOPY(to, from, i);
1073#if ( GMPSPREAD != 1 )
1080 ic = DLscratB;
id = DLscratC;
1082 if ( ( (LONG)c & (
sizeof(mp_limb_t)-1) ) != 0 ) ic = DLscratB;
1085 if ( ( (LONG)d & (
sizeof(mp_limb_t)-1) ) != 0 )
id = DLscratC;
1088 mpn_tdiv_qr((mp_limb_t *)ic,(mp_limb_t *)
id,(mp_size_t)0,
1089 (
const mp_limb_t *)a,(mp_size_t)(na/GMPSPREAD),
1090 (
const mp_limb_t *)b,(mp_size_t)(nb/GMPSPREAD));
1091 while ( j >= 0 && ic[j] == 0 ) j--;
1093 if ( c != ic ) { NCOPY(c,ic,j); }
1095 while ( j >= 0 &&
id[j] == 0 ) j--;
1097 if ( d !=
id ) { NCOPY(d,
id,j); }
1098 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1099 if ( sgnb < 0 ) { *nc = -(*nc); }
1100 NumberFree(DLscrat9,
"DivLong"); NumberFree(DLscratA,
"DivLong");
1101 NumberFree(DLscratB,
"DivLong"); NumberFree(DLscratC,
"DivLong");
1110 e = NumberMalloc(
"DivLong"); f = NumberMalloc(
"DivLong"); g = NumberMalloc(
"DivLong");
1111 if ( b[nb-1] == (FULLMAX-1) ) norm = 1;
1113 norm = (UWORD)(((ULONG)FULLMAX) / (ULONG)((b[nb-1]+1L)));
1116 if ( MulLong(b,nb,&norm,1,e,&ne) ||
1117 MulLong(a,na,&norm,1,f,&nf) ) {
1118 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1121 if ( BigLong(f+nf-ne,ne,e,ne) >= 0 ) {
1122 SubPLon(f+nf-ne,ne,e,ne,f+nf-ne,&nh);
1131 w2 = c; i = *nc;
do { *w2++ = 0; }
while ( --i > 0 );
1134 esthelp = (RLONG)(e[ne-1]) + 1L;
1135 while ( nf >= ne ) {
1136 if ( (WORD)esthelp == 0 ) {
1137 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])>>BITSINWORD);
1140 estim = (WORD)(((((RLONG)(f[nf]))<<BITSINWORD)+f[nf-1])/esthelp);
1144 MulLong(e,ne,&estim,1,g,&ng);
1145 nh = ne + 1;
if ( !f[ni+ne] ) nh--;
1146 SubPLon(f+ni,nh,g,ng,f+ni,&nh);
1149 w2 = f+ni+ne; nh = ne+1;
1150 while ( ( nh > 0 ) && !*w2 ) { nh--; w2--; }
1152 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1154 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1155 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1157 SubPLon(f+ni,nh,e,ne,f+ni,&nh);
1158 if ( BigLong(f+ni,nh,e,ne) >= 0 ) {
1159 MLOCK(ErrorMessageLock);
1160 MesPrint(
"Problems in DivLong");
1164 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
1167 while ( --i >= 0 ) { TalToLine((UWORD)(*b++)); TokenToLine((UBYTE *)
" "); }
1170 MUNLOCK(ErrorMessageLock);
1171 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1186 *nd = i = nh; ff = f;
1195 while ( --ni >= 0 ) {
1204 MLOCK(ErrorMessageLock);
1205 MesPrint(
"Error in DivLong");
1206 MUNLOCK(ErrorMessageLock);
1207 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1210 if ( !*(d+nh-1) ) (*nd)--;
1214 NumberFree(e,
"DivLong"); NumberFree(f,
"DivLong"); NumberFree(g,
"DivLong");
1216 if ( sgna < 0 ) { *nc = -(*nc); *nd = -(*nd); }
1217 if ( sgnb < 0 ) { *nc = -(*nc); }
1229int RaisPow(PHEAD UWORD *a, WORD *na, UWORD b)
1236 nmod = ABS(AN.ncmod);
1237 if ( !*na || ( ( *na == 1 ) && ( *a == 1 ) ) )
return(0);
1238 if ( !b ) { *na=1; *a=1;
return(0); }
1239 is = NumberMalloc(
"RaisPow");
1240 it = NumberMalloc(
"RaisPow");
1241 for ( i = 0; i < ABS(*na); i++ ) is[i] = a[i];
1244 for ( i = 0; i < BITSINWORD; i++ ) {
1250 while ( --i >= 0 ) {
1252 if(MulLong(is,ns,is,ns,it,&nt))
goto RaisOvl;
1254 if ( MulLong(it,nt,a,*na,is,&ns) )
goto RaisOvl;
1257 iu = is; is = it; it = iu;
1258 nu = ns; ns = nt; nt = nu;
1261 if ( DivLong(is,ns,(UWORD *)AC.cmod,nmod,it,&nt,is,&ns) )
goto RaisOvl;
1264 if ( ( nmod != 0 ) && ( ( AC.modmode & POSNEG ) != 0 ) ) {
1267 if ( ( *na = i = ns ) != 0 ) { iss = is; i=ABS(i); NCOPY(a,iss,i); }
1268 NumberFree(is,
"RaisPow"); NumberFree(it,
"RaisPow");
1271 MLOCK(ErrorMessageLock);
1273 MUNLOCK(ErrorMessageLock);
1274 NumberFree(is,
"RaisPow"); NumberFree(it,
"RaisPow");
1300 WORD new_small_power_maxx, new_small_power_maxn, ID;
1301 WORD *new_small_power_n;
1302 UWORD **new_small_power;
1305 if (x>=AT.small_power_maxx || n>=AT.small_power_maxn) {
1307 new_small_power_maxx = AT.small_power_maxx;
1308 if (x>=AT.small_power_maxx)
1309 new_small_power_maxx = MaX(2*AT.small_power_maxx, x+1);
1311 new_small_power_maxn = AT.small_power_maxn;
1312 if (n>=AT.small_power_maxn)
1313 new_small_power_maxn = MaX(2*AT.small_power_maxn, n+1);
1315 new_small_power_n = (WORD*) Malloc1(new_small_power_maxx*new_small_power_maxn*
sizeof(WORD),
"RaisPowCached");
1316 new_small_power = (UWORD **) Malloc1(new_small_power_maxx*new_small_power_maxn*
sizeof(UWORD *),
"RaisPowCached");
1318 for (i=0; i<new_small_power_maxx * new_small_power_maxn; i++) {
1319 new_small_power_n[i] = 0;
1320 new_small_power [i] = NULL;
1323 for (i=0; i<AT.small_power_maxx; i++)
1324 for (j=0; j<AT.small_power_maxn; j++) {
1325 new_small_power_n[i*new_small_power_maxn+j] = AT.small_power_n[i*AT.small_power_maxn+j];
1326 new_small_power [i*new_small_power_maxn+j] = AT.small_power [i*AT.small_power_maxn+j];
1329 if (AT.small_power_n != NULL) {
1330 M_free(AT.small_power_n,
"RaisPowCached");
1331 M_free(AT.small_power,
"RaisPowCached");
1334 AT.small_power_maxx = new_small_power_maxx;
1335 AT.small_power_maxn = new_small_power_maxn;
1336 AT.small_power_n = new_small_power_n;
1337 AT.small_power = new_small_power;
1341 ID = x * AT.small_power_maxn + n;
1343 if (AT.small_power[ID] == NULL) {
1344#ifdef OLDRAISPOWCACHED
1345 AT.small_power[ID] = NumberMalloc(
"RaisPowCached");
1346 AT.small_power_n[ID] = 1;
1347 AT.small_power[ID][0] = x;
1348 RaisPow(BHEAD AT.small_power[ID],&AT.small_power_n[ID],n);
1350 UWORD *c = NumberMalloc(
"RaisPowCached");
1353 RaisPow(BHEAD c,&k,n);
1357 if ( AT.InNumMem < k ) {
1358 AT.InNumMem = 5*AM.MaxTal;
1359 AT.NumMem = (UWORD *)Malloc1(AT.InNumMem*
sizeof(UWORD),
"RaisPowCached");
1364 for ( i = 0; i < k; i++ ) AT.NumMem[i] = c[i];
1365 AT.small_power[ID] = AT.NumMem;
1366 AT.small_power_n[ID] = k;
1369 NumberFree(c,
"RaisPowCached");
1374 *c = AT.small_power[ID];
1375 *nc = AT.small_power_n[ID];
1384WORD RaisPowMod (WORD x, WORD n, WORD m) {
1387 if (n&1) { y*=z; y%=m; }
1407 if ( AC.halfmod == 0 ) {
1408 LOCK(AC.halfmodlock);
1409 if ( AC.halfmod == 0 ) {
1410 UWORD two[1],remain[1];
1413 AC.halfmod = (UWORD *)Malloc1((ABS(AC.ncmod))*
sizeof(UWORD),
"halfmod");
1414 DivLong((UWORD *)AC.cmod,(ABS(AC.ncmod)),two,1
1415 ,(UWORD *)AC.halfmod,&(AC.nhalfmod),remain,&dummy);
1417 UNLOCK(AC.halfmodlock);
1420 if ( BigLong(a,n,AC.halfmod,AC.nhalfmod) > 0 ) {
1421 SubPLon((UWORD *)AC.cmod,(ABS(AC.ncmod)),a,n,a,&n);
1422 if ( *na > 0 ) { *na = -n; }
1443 WORD n = AC.cmod[0], i, inv2;
1444 if ( AC.ncmod != 1 )
return(1);
1445 if ( AC.modinverses == 0 ) {
1446 LOCK(AC.halfmodlock);
1447 if ( AC.modinverses == 0 ) {
1448 AC.modinverses = (UWORD *)Malloc1(n*
sizeof(UWORD),
"modinverses");
1449 AC.modinverses[0] = 0;
1450 AC.modinverses[1] = 1;
1451 for ( i = 2; i < n; i++ ) {
1453 (WORD *)(&(AC.modinverses[i])),&inv2) ) {
1458 UNLOCK(AC.halfmodlock);
1481 WORD x = m1, y, c, d = m2;
1482 if ( x < 1 || d <= 1 )
goto somethingwrong;
1487 if ( y == 0 )
break;
1488 a3 = a1-c*a2; a1 = a2; a2 = a3;
1489 b3 = b1-c*b2; b1 = b2; b2 = b3;
1492 if ( x != 1 )
goto somethingwrong;
1493 if ( a2 < 0 ) a2 += m2;
1494 if ( b2 < 0 ) b2 += m1;
1495 if (im1!=NULL) *im1 = a2;
1496 if (im2!=NULL) *im2 = b2;
1499 MLOCK(ErrorMessageLock);
1500 MesPrint(
"Error trying to determine inverses in GetModInverses");
1501 MUNLOCK(ErrorMessageLock);
1509int GetLongModInverses(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *ia, WORD *nia, UWORD *ib, WORD *nib) {
1511 UWORD *s, *t, *sa, *sb, *ta, *tb, *x, *y, *swap1;
1512 WORD ns, nt, nsa, nsb, nta, ntb, nx, ny, swap2;
1514 s = NumberMalloc(
"GetLongModInverses");
1516 WCOPY(s, a, ABS(ns));
1518 t = NumberMalloc(
"GetLongModInverses");
1520 WCOPY(t, b, ABS(nt));
1522 sa = NumberMalloc(
"GetLongModInverses");
1526 sb = NumberMalloc(
"GetLongModInverses");
1529 ta = NumberMalloc(
"GetLongModInverses");
1532 tb = NumberMalloc(
"GetLongModInverses");
1536 x = NumberMalloc(
"GetLongModInverses");
1537 y = NumberMalloc(
"GetLongModInverses");
1540 DivLong(s,ns,t,nt,x,&nx,y,&ny);
1541 swap1=s; s=y; y=swap1;
1543 MulLong(x,nx,ta,nta,y,&ny);
1544 AddLong(sa,nsa,y,-ny,sa,&nsa);
1545 MulLong(x,nx,tb,ntb,y,&ny);
1546 AddLong(sb,nsb,y,-ny,sb,&nsb);
1548 swap1=s; s=t; t=swap1;
1549 swap2=ns; ns=nt; nt=swap2;
1550 swap1=sa; sa=ta; ta=swap1;
1551 swap2=nsa; nsa=nta; nta=swap2;
1552 swap1=sb; sb=tb; tb=swap1;
1553 swap2=nsb; nsb=ntb; ntb=swap2;
1558 WCOPY(ia,sa,ABS(*nia));
1563 WCOPY(ib,sb,ABS(*nib));
1566 NumberFree(s,
"GetLongModInverses");
1567 NumberFree(t,
"GetLongModInverses");
1568 NumberFree(sa,
"GetLongModInverses");
1569 NumberFree(sb,
"GetLongModInverses");
1570 NumberFree(ta,
"GetLongModInverses");
1571 NumberFree(tb,
"GetLongModInverses");
1572 NumberFree(x,
"GetLongModInverses");
1573 NumberFree(y,
"GetLongModInverses");
1586int Product(UWORD *a, WORD *na, WORD b)
1590 if ( *na < 0 ) { *na = -(*na); sgn = -sgn; }
1591 if ( b < 0 ) { b = -b; sgn = -sgn; }
1594 for ( i = 0; i < *na; i++ ) {
1600 if ( ++(*na) > AM.MaxTal ) {
1601 MLOCK(ErrorMessageLock);
1602 MesPrint(
"Overflow in Product");
1603 MUNLOCK(ErrorMessageLock);
1608 if ( sgn < 0 ) *na = -(*na);
1621UWORD Quotient(UWORD *a, WORD *na, WORD b)
1625 if ( ( i = *na ) < 0 ) { sgn = -1; i = -i; }
1626 if ( b < 0 ) { b = -b; sgn = -sgn; }
1628 if ( ( *a /= (UWORD)b ) == 0 ) *na = 0;
1629 if ( sgn < 0 ) *na = -*na;
1636 while ( --i >= 0 ) {
1646 if ( sgn < 0 ) j = -j;
1660WORD Remain10(UWORD *a, WORD *na)
1668 while ( --i >= 0 ) {
1672 if ( i > 0 ) t <<= BITSINWORD;
1674 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1687WORD Remain4(UWORD *a, WORD *na)
1695 while ( --i >= 0 ) {
1697 *b-- = u = t / 10000;
1699 if ( i > 0 ) t <<= BITSINWORD;
1701 if ( ( *na > 0 ) && !a[*na-1] ) (*na)--;
1713void PrtLong(UWORD *a, WORD na, UBYTE *s)
1726 b = NumberMalloc(
"PrtLong");
1728 i = na;
while ( --i >= 0 ) *bb++ = *a++;
1734 *sa++ = (UBYTE)(
'0' + (q%10));
1736 *sa++ = (UBYTE)(
'0' + (q%10));
1738 *sa++ = (UBYTE)(
'0' + (q%10));
1740 *sa++ = (UBYTE)(
'0' + (q%10));
1742 while ( sa[-1] ==
'0' ) sa--;
1746 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1751 q = Remain10(a,&na);
1752 *sa++ = (UBYTE)(
'0' + q);
1757 while ( sa > sb ) { c = *sa; *sa = *sb; *sb = c; sa--; sb++; }
1761 NumberFree(b,
"PrtLong");
1775int GetLong(UBYTE *s, UWORD *a, WORD *na)
1788 UWORD digit, x = 0, y = 0;
1791 while ( FG.cTable[*s] == 1 ) {
1793 if ( FG.cTable[*s] != 1 ) { y = 10;
break; }
1794 x = 10*x + *s++ -
'0';
1795 if ( FG.cTable[*s] != 1 ) { y = 100;
break; }
1796 x = 10*x + *s++ -
'0';
1797 if ( FG.cTable[*s] != 1 ) { y = 1000;
break; }
1798 x = 10*x + *s++ -
'0';
1799 if ( *na && Product(a,na,(WORD)10000) )
return(-1);
1800 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1805 if ( *na && Product(a,na,(WORD)y) )
return(-1);
1806 if ( ( digit = x ) != 0 && AddLong(a,*na,&digit,(WORD)1,a,na) )
1826#define Convert(ia,aa,naa) \
1827 if ( (LONG)ia < 0 ) { \
1828 ia = (ULONG)(-(LONG)ia); \
1830 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = -2; \
1833 else if ( ia == 0 ) { aa[0] = 0; naa = 0; } \
1836 if ( ( aa[1] = ia >> BITSINWORD ) != 0 ) naa = 2; \
1840void GCD(UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1842 int ja = 0, jb = 0, j;
1844 UWORD *x1, *x2, *x3;
1846 ULONG ia,ib,ic,id,u,v,w,q,T;
1851 while ( a[0] == 0 ) { na--; ja++; a++; }
1852 while ( b[0] == 0 ) { nb--; jb++; b++; }
1853 if ( ja > jb ) ja = jb;
1856 do { *c++ = 0; }
while ( --j > 0 );
1862 jb = na; na = nb; nb = jb;
1864 r = a; a = b; b = r;
1866 else if ( na == nb ) {
1870 while ( --j >= 0 ) {
1871 if ( *--r > *--t )
break;
1872 if ( *r < *t )
goto exch;
1903 r = x1 = NumberMalloc(
"GCD"); t = x2 = NumberMalloc(
"GCD"); x3 = NumberMalloc(
"GCD");
1913 DivLong(x1,na,x2,nb,c,nc,x3,&nd);
1914 if ( nd == 0 ) { b = x2;
goto out; }
1915 t = x1; x1 = x2; x2 = x3; x3 = t; na = nb; nb = nd;
1916 if ( na == 2 )
break;
1922 v = x1[0] + ( ((ULONG)x1[1]) << BITSINWORD );
1924 if ( nb == 2 ) w += ((ULONG)x2[1]) << BITSINWORD;
1928 do { u = v%w; v = w; w = u; }
while ( w );
1931 if ( ( c[1] = (UWORD)(v >> BITSINWORD) ) != 0 ) *nc = 2+ja;
1933 NumberFree(x1,
"GCD"); NumberFree(x2,
"GCD"); NumberFree(x3,
"GCD");
1938 ui = x1[0]; uj = x2[0];
1940 ui = (UWORD)GCD2((ULONG)ui,(ULONG)uj);
1942 do { nd = ui%uj; ui = uj; uj = nd; }
while ( nd );
1946 NumberFree(x1,
"GCD"); NumberFree(x2,
"GCD"); NumberFree(x3,
"GCD");
1949 ia = 1; ib = 0; ic = 0;
id = 1;
1950 u = ( ((ULONG)x1[na-1]) << BITSINWORD ) + x1[na-2];
1951 v = ( ((ULONG)x2[nb-1]) << BITSINWORD ) + x2[nb-2];
1953 while ( v+ic != 0 && v+
id != 0 &&
1954 ( q = (u+ia)/(v+ic) ) == (u+ib)/(v+
id) ) {
1955 T = ia-q*ic; ia = ic; ic = T;
1956 T = ib-q*id; ib = id;
id = T;
1957 T = u - q*v; u = v; v = T;
1959 if ( ib == 0 )
goto toobad;
1962 MulLong(x1,na,aa,naa,x3,&nd);
1963 MulLong(x2,nb,bb,nbb,c,nc);
1964 AddLong(x3,nd,c,*nc,c,nc);
1967 MulLong(x1,na,aa,naa,x3,&nd);
1968 t = c; na = j = *nc; r = x1;
1970 MulLong(x2,nb,bb,nbb,c,nc);
1971 AddLong(x3,nd,c,*nc,x2,&nb);
1992int GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
1997 MLOCK(ErrorMessageLock);
1998 MesPrint(
"Cannot take gcd");
1999 MUNLOCK(ErrorMessageLock);
2015 if ( na < 0 ) na = -na;
2016 if ( nb < 0 ) nb = -nb;
2017 if ( na == 1 && nb == 1 ) {
2019 *c = (UWORD)GCD2((ULONG)*a,(ULONG)*b);
2024 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2029 else if ( na <= 2 && nb <= 2 ) {
2031 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2033 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2039 do { lz = lx % ly; lx = ly; }
while ( ( ly = lz ) != 0 );
2042 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2044 lz = lx % ly; lx = ly;
2045 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2047 do { *c = ((UWORD)lx)%((UWORD)ly); lx = ly; }
while ( ( ly = *c ) != 0 );
2055 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2061 GCD(a,na,b,nb,c,nc);
2064 UWORD *x3,*x1,*x2, *GLscrat7, *GLscrat8;
2067 x1 = c; x3 = a; n1 = i = na;
2069 GLscrat7 = NumberMalloc(
"GcdLong"); GLscrat8 = NumberMalloc(
"GcdLong");
2070 x2 = GLscrat8; x3 = b; n2 = i = nb;
2073 while ( x1[0] == 0 ) { i += BITSINWORD; x1++; n1--; }
2074 while ( ( x1[0] & 1 ) == 0 ) { i++; SCHUIF(x1,n1) }
2075 x2 = GLscrat8; j = 0;
2076 while ( x2[0] == 0 ) { j += BITSINWORD; x2++; n2--; }
2077 while ( ( x2[0] & 1 ) == 0 ) { j++; SCHUIF(x2,n2) }
2082 SubPLon(x1,n1,x2,n2,x1,&n3);
2086 n1 = i = n2; NCOPY(x1,x2,i);
2089 while ( ( x1[0] & 1 ) == 0 ) SCHUIF(x1,n1)
2091 if ( DivLong(x2,n2,x1,n1,GLscrat7,&n3,x2,&n4) )
goto GcdErr;
2094 i = n1; x2 = c; NCOPY(x2,x1,i);
2098 *c = (UWORD)GCD2((ULONG)x1[0],(ULONG)x2[0]);
2104 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2112 else if ( n1 < n2 ) {
2114 SubPLon(x2,n2,x1,n1,x2,&n3);
2117 i = n1; x2 = c; NCOPY(x2,x1,i);
2120 while ( ( x2[0] & 1 ) == 0 ) SCHUIF(x2,n2)
2122 if ( DivLong(x1,n1,x2,n2,GLscrat7,&n3,x1,&n4) )
goto GcdErr;
2126 n1 = i = n2; NCOPY(x1,x2,i);
2130 *c = (UWORD)GCD2((ULONG)x2[0],(ULONG)x1[0]);
2136 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2145 for ( i = n1-1; i >= 0; i-- ) {
2146 if ( x1[i] > x2[i] )
goto firstbig;
2147 else if ( x1[i] < x2[i] )
goto lastbig;
2149 i = n1; x2 = c; NCOPY(x2,x1,i);
2157 while ( j >= BITSINWORD ) {
2158 for ( i = n1; i > 0; i-- ) x1[i] = x1[i-1];
2164 for ( i = 0; i < n1; i++ ) {
2165 a1 = x1[i]; a1 <<= j;
2175 NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2177 UWORD *x1,*x2,*x3,*x4,*c1,*c2;
2179 x1 = c; x3 = a; n1 = i = na;
2181 x1 = c; c1 = x2 = NumberMalloc(
"GcdLong"); x3 = NumberMalloc(
"GcdLong"); x4 = NumberMalloc(
"GcdLong");
2182 c2 = b; n2 = i = nb;
2185 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto GcdErr;
2186 if ( !n3 ) { x1 = x2; n1 = n2;
break; }
2187 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto GcdErr;
2188 if ( !n1 ) { x1 = x3; n1 = n3;
break; }
2189 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto GcdErr;
2192 NumberFree(x2,
"GcdLong"); NumberFree(x3,
"GcdLong"); NumberFree(x4,
"GcdLong");
2198 NumberFree(x2,
"GcdLong"); NumberFree(x3,
"GcdLong"); NumberFree(x4,
"GcdLong");
2204 MLOCK(ErrorMessageLock);
2206 MUNLOCK(ErrorMessageLock);
2277int GcdLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2281 UWORD *x1,*x2,*x3,*x4,*x5,*d;
2282 UWORD *GLscrat6, *GLscrat7, *GLscrat8, *GLscrat9, *GLscrat10;
2283 WORD n1,n2,n3,n4,n5,i;
2285 LONG ma1, ma2, mb1, mb2, mc1, mc2, m;
2288 MLOCK(ErrorMessageLock);
2289 MesPrint(
"Cannot take gcd");
2290 MUNLOCK(ErrorMessageLock);
2306 if ( na < 0 ) na = -na;
2307 if ( nb < 0 ) nb = -nb;
2312 if ( na > 3 && nb > 3 ) {
2314 mp_limb_t *upa, *upb, *upc, xx;
2315 UWORD *uw, *u1, *u2;
2316 unsigned int tcounta, tcountb, tcounta1, tcountb1;
2317 mp_size_t ana, anb, anc;
2319 u1 = uw = NumberMalloc(
"GcdLong");
2320 upa = (mp_limb_t *)u1;
2321 ana = na; tcounta1 = 0;
2322 while ( a[0] == 0 ) { a++; ana--; tcounta1++; }
2323 for ( ii = 0; ii < ana; ii++ ) { *uw++ = *a++; }
2324 if ( ( ana & 1 ) != 0 ) { *uw = 0; ana++; }
2327 u2 = uw = NumberMalloc(
"GcdLong");
2328 upb = (mp_limb_t *)u2;
2329 anb = nb; tcountb1 = 0;
2330 while ( b[0] == 0 ) { b++; anb--; tcountb1++; }
2331 for ( ii = 0; ii < anb; ii++ ) { *uw++ = *b++; }
2332 if ( ( anb & 1 ) != 0 ) { *uw = 0; anb++; }
2335 xx = upa[0]; tcounta = 0;
2336 while ( ( xx & 15 ) == 0 ) { tcounta += 4; xx >>= 4; }
2337 while ( ( xx & 1 ) == 0 ) { tcounta += 1; xx >>= 1; }
2338 xx = upb[0]; tcountb = 0;
2339 while ( ( xx & 15 ) == 0 ) { tcountb += 4; xx >>= 4; }
2340 while ( ( xx & 1 ) == 0 ) { tcountb += 1; xx >>= 1; }
2343 mpn_rshift(upa,upa,ana,tcounta);
2344 if ( upa[ana-1] == 0 ) ana--;
2347 mpn_rshift(upb,upb,anb,tcountb);
2348 if ( upb[anb-1] == 0 ) anb--;
2351 upc = (mp_limb_t *)(NumberMalloc(
"GcdLong"));
2352 if ( ( ana > anb ) || ( ( ana == anb ) && ( upa[ana-1] >= upb[ana-1] ) ) ) {
2353 anc = mpn_gcd(upc,upa,ana,upb,anb);
2356 anc = mpn_gcd(upc,upb,anb,upa,ana);
2359 tcounta = tcounta1*BITSINWORD + tcounta;
2360 tcountb = tcountb1*BITSINWORD + tcountb;
2361 if ( tcountb > tcounta ) tcountb = tcounta;
2362 tcounta = tcountb/BITSINWORD;
2363 tcountb = tcountb%BITSINWORD;
2366 xx = mpn_lshift(upc,upc,anc,tcountb);
2367 if ( xx ) { upc[anc] = xx; anc++; }
2370 uw = (UWORD *)upc; anc *= 2;
2371 while ( uw[anc-1] == 0 ) anc--;
2372 for ( ii = 0; ii < (int)tcounta; ii++ ) *c++ = 0;
2373 for ( ii = 0; ii < anc; ii++ ) *c++ = *uw++;
2374 *nc = anc + tcounta;
2375 NumberFree(u1,
"GcdLong"); NumberFree(u2,
"GcdLong"); NumberFree((UWORD *)(upc),
"GcdLong");
2385 if ( na == 1 && nb == 1 ) {
2388 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2393 else if ( na <= 2 && nb <= 2 ) {
2394 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2396 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2398 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2399#if ( BITSINWORD == 16 )
2401 lz = lx % ly; lx = ly;
2402 }
while ( ( ly = lz ) != 0 );
2405 lz = lx % ly; lx = ly;
2406 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2408 x = (UWORD)lx; y = (UWORD)ly;
2409 do { *c = x % y; x = y; }
while ( ( y = *c ) != 0 );
2417 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2425 GLscrat6 = NumberMalloc(
"GcdLong"); GLscrat7 = NumberMalloc(
"GcdLong");
2426 GLscrat8 = NumberMalloc(
"GcdLong");
2427 GLscrat9 = NumberMalloc(
"GcdLong"); GLscrat10 = NumberMalloc(
"GcdLong");
2432 if ( na == 1 && nb == 1 ) {
2435 do { z = x % y; x = y; }
while ( ( y = z ) != 0 );
2439 else if ( na <= 2 && nb <= 2 ) {
2440 if ( na == 2 ) { lx = (((RLONG)(a[1]))<<BITSINWORD) + *a; }
2442 if ( nb == 2 ) { ly = (((RLONG)(b[1]))<<BITSINWORD) + *b; }
2444 if ( lx < ly ) { lz = lx; lx = ly; ly = lz; }
2445#if ( BITSINWORD == 16 )
2447 lz = lx % ly; lx = ly;
2448 }
while ( ( ly = lz ) != 0 );
2451 lz = lx % ly; lx = ly;
2452 }
while ( ( ly = lz ) != 0 && ( lx & AWORDMASK ) != 0 );
2454 x = (UWORD)lx; y = (UWORD)ly;
2455 do { *c = x % y; x = y; }
while ( ( y = *c ) != 0 );
2463 if ( ( *c = (UWORD)(lx >> BITSINWORD) ) != 0 ) *nc = 2;
2471 else if ( na < GCDMAX || nb < GCDMAX || na != nb ) {
2473 x2 = GLscrat8; x3 = a; n2 = i = na;
2475 x1 = c; x3 = b; n1 = i = nb;
2479 x1 = c; x3 = a; n1 = i = na;
2481 x2 = GLscrat8; x3 = b; n2 = i = nb;
2484 x1 = c; x2 = GLscrat8; x3 = GLscrat7; x4 = GLscrat6;
2486 if ( DivLong(x1,n1,x2,n2,x4,&n4,x3,&n3) )
goto GcdErr;
2487 if ( !n3 ) { x1 = x2; n1 = n2;
break; }
2488 if ( n2 <= 2 ) { a = x2; b = x3; na = n2; nb = n3;
goto restart; }
2489 if ( n3 >= GCDMAX && n2 == n3 ) {
2490 a = GLscrat9; b = GLscrat10; na = n2; nb = n3;
2491 for ( i = 0; i < na; i++ ) a[i] = x2[i];
2492 for ( i = 0; i < nb; i++ ) b[i] = x3[i];
2495 if ( DivLong(x2,n2,x3,n3,x4,&n4,x1,&n1) )
goto GcdErr;
2496 if ( !n1 ) { x1 = x3; n1 = n3;
break; }
2497 if ( n3 <= 2 ) { a = x3; b = x1; na = n3; nb = n1;
goto restart; }
2498 if ( n1 >= GCDMAX && n1 == n3 ) {
2499 a = GLscrat9; b = GLscrat10; na = n3; nb = n1;
2500 for ( i = 0; i < na; i++ ) a[i] = x3[i];
2501 for ( i = 0; i < nb; i++ ) b[i] = x1[i];
2504 if ( DivLong(x3,n3,x1,n1,x4,&n4,x2,&n2) )
goto GcdErr;
2505 if ( !n2 ) { *nc = n1;
goto normalend; }
2506 if ( n1 <= 2 ) { a = x1; b = x2; na = n1; nb = n2;
goto restart; }
2507 if ( n2 >= GCDMAX && n2 == n1 ) {
2508 a = GLscrat9; b = GLscrat10; na = n1; nb = n2;
2509 for ( i = 0; i < na; i++ ) a[i] = x1[i];
2510 for ( i = 0; i < nb; i++ ) b[i] = x2[i];
2534 ma1 = 1; ma2 = 0; mb1 = 0; mb2 = 1;
2535 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2536 ly = (((RLONG)(b[nb-1]))<<BITSINWORD) + b[nb-2];
2537 if ( ly > lx ) { lz = lx; lx = ly; ly = lz; d = a; a = b; b = d; }
2540 mc1 = ma1-m*mb1; mc2 = ma2-m*mb2;
2541 ma1 = mb1; ma2 = mb2; mb1 = mc1; mb2 = mc2;
2542 lz = lx - m*ly; lx = ly; ly = lz;
2543 }
while ( ly >= FULLMAX );
2557 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2558 if ( x1[1] ) n1 = -2;
2563 x1[1] = (UWORD)(ma1 >> BITSINWORD);
2564 if ( x1[1] ) n1 = 2;
2567 if ( MulLong(a,na,x1,n1,x2,&n2) )
goto GcdErr;
2571 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2572 if ( x1[1] ) n1 = -2;
2577 x1[1] = (UWORD)(ma2 >> BITSINWORD);
2578 if ( x1[1] ) n1 = 2;
2581 if ( MulLong(b,nb,x1,n1,x3,&n3) )
goto GcdErr;
2582 if ( AddLong(x2,n2,x3,n3,c,&n4) )
goto GcdErr;
2586 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2587 if ( x1[1] ) n1 = -2;
2592 x1[1] = (UWORD)(mb1 >> BITSINWORD);
2593 if ( x1[1] ) n1 = 2;
2596 if ( MulLong(a,na,x1,n1,x2,&n2) )
goto GcdErr;
2600 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2601 if ( x1[1] ) n1 = -2;
2606 x1[1] = (UWORD)(mb2 >> BITSINWORD);
2607 if ( x1[1] ) n1 = 2;
2610 if ( MulLong(b,nb,x1,n1,x3,&n3) )
goto GcdErr;
2611 if ( AddLong(x2,n2,x3,n3,x5,&n5) )
goto GcdErr;
2612 a = c; na = n4; b = x5; nb = n5;
2613 if ( nb == 0 ) { *nc = n4;
goto normalend; }
2615 for ( i = 0; i < na; i++ ) x4[i] = a[i];
2617 if ( na < 0 ) na = -na;
2618 if ( nb < 0 ) nb = -nb;
2629 if ( nb >= GCDMAX && na == nb+1 && b[nb-1] >= HALFMAX && b[nb-1] > a[na-1] ) {
2630 lx = (((RLONG)(a[na-1]))<<BITSINWORD) + a[na-2];
2631 x1[0] = lx/b[nb-1]; n1 = 1;
2632 MulLong(b,nb,x1,n1,x2,&n2);
2634 AddLong(a,na,x2,n2,x4,&n4);
2637 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2640 if ( n4 < 0 ) n4 = -n4;
2641 a = b; na = nb; b = x4; nb = n4;
2649 NumberFree(GLscrat6,
"GcdLong"); NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2650 NumberFree(GLscrat9,
"GcdLong"); NumberFree(GLscrat10,
"GcdLong");
2653 MLOCK(ErrorMessageLock);
2655 MUNLOCK(ErrorMessageLock);
2656 NumberFree(GLscrat6,
"GcdLong"); NumberFree(GLscrat7,
"GcdLong"); NumberFree(GLscrat8,
"GcdLong");
2657 NumberFree(GLscrat9,
"GcdLong"); NumberFree(GLscrat10,
"GcdLong");
2668int GetBinom(UWORD *a, WORD *na, WORD i1, WORD i2)
2672 UWORD *GBscrat3, *GBscrat4;
2673 if ( i1-i2 < i2 ) i2 = i1-i2;
2674 if ( i2 == 0 ) { *a = 1; *na = 1;
return(0); }
2675 if ( i2 > i1 ) { *a = 0; *na = 0;
return(0); }
2677 GBscrat3 = NumberMalloc(
"GetBinom"); GBscrat4 = NumberMalloc(
"GetBinom");
2678 for ( j = 2; j <= i2; j++ ) {
2679 GBscrat3[0] = i1+1-j;
2680 if ( MulLong(a,*na,GBscrat3,(WORD)1,GBscrat4,&k) )
goto CalledFrom;
2682 if ( DivLong(GBscrat4,k,GBscrat3,(WORD)1,a,na,GBscrat3,&l) )
goto CalledFrom;
2684 NumberFree(GBscrat3,
"GetBinom"); NumberFree(GBscrat4,
"GetBinom");
2687 MLOCK(ErrorMessageLock);
2688 MesCall(
"GetBinom");
2689 MUNLOCK(ErrorMessageLock);
2690 NumberFree(GBscrat3,
"GetBinom"); NumberFree(GBscrat4,
"GetBinom");
2702int LcmLong(PHEAD UWORD *a, WORD na, UWORD *b, WORD nb, UWORD *c, WORD *nc)
2705 UWORD *d = NumberMalloc(
"LcmLong");
2706 UWORD *e = NumberMalloc(
"LcmLong");
2707 UWORD *f = NumberMalloc(
"LcmLong");
2709 GcdLong(BHEAD a, na, b, nb, d, &nd);
2710 DivLong(a,na,d,nd,e,&ne,f,&nf);
2711 if ( MulLong(b,nb,e,ne,c,nc) ) {
2712 MLOCK(ErrorMessageLock);
2714 MUNLOCK(ErrorMessageLock);
2717 NumberFree(f,
"LcmLong");
2718 NumberFree(e,
"LcmLong");
2719 NumberFree(d,
"LcmLong");
2736int TakeLongRoot(UWORD *a, WORD *n, WORD power)
2739 int numbits, guessbits, i, retval = 0;
2740 UWORD x, *b, *c, *d, *e;
2741 WORD na, nb, nc, nd, ne;
2742 if ( *n < 0 && ( power & 1 ) == 0 )
return(1);
2743 if ( power == 1 )
return(0);
2744 if ( *n < 0 ) { na = -*n; }
2748 if ( a[0] == 1 )
return(0);
2749 if ( power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<power) ) {
2750 a[0] = 2;
return(0);
2752 if ( 2*power < BITSINWORD && na == 1 && a[0] == (UWORD)(1<<(2*power)) ) {
2753 a[0] = 4;
return(0);
2760 numbits = BITSINWORD*(na-1);
2762 while ( ( x >> 8 ) != 0 ) { numbits += 8; x >>= 8; }
2763 if ( ( x >> 4 ) != 0 ) { numbits += 4; x >>= 4; }
2764 if ( ( x >> 2 ) != 0 ) { numbits += 2; x >>= 2; }
2765 if ( ( x >> 1 ) != 0 ) numbits++;
2766 guessbits = numbits / power;
2767 if ( guessbits <= 0 )
return(1);
2768 nb = guessbits/BITSINWORD;
2778 b = NumberMalloc(
"TakeLongRoot"); c = NumberMalloc(
"TakeLongRoot");
2779 d = NumberMalloc(
"TakeLongRoot"); e = NumberMalloc(
"TakeLongRoot");
2780 for ( i = 0; i < nb; i++ ) { b[i] = 0; }
2781 b[nb] = 1 << (guessbits%BITSINWORD);
2785 for ( i = 0; i < nb; i++ ) c[i] = b[i];
2786 if ( RaisPow(BHEAD c,&nc,power-1) )
goto TLcall;
2787 if ( DivLong(a,na,c,nc,d,&nd,e,&ne) )
goto TLcall;
2789 if ( AddLong(d,nd,b,nb,c,&nc) )
goto TLcall;
2792 if ( ne == 0 )
break;
2802 DivLong(c,nc,(UWORD *)(&power),1,d,&nd,e,&ne);
2830 if ( AddLong(b,nb,d,nd,b,&nb) )
goto TLcall;
2832 for ( i = 0; i < nb; i++ ) a[i] = b[i];
2833 if ( *n < 0 ) *n = -nb;
2835 NumberFree(b,
"TakeLongRoot"); NumberFree(c,
"TakeLongRoot");
2836 NumberFree(d,
"TakeLongRoot"); NumberFree(e,
"TakeLongRoot");
2839 MLOCK(ErrorMessageLock);
2840 MesCall(
"TakeLongRoot");
2841 MUNLOCK(ErrorMessageLock);
2842 NumberFree(b,
"TakeLongRoot"); NumberFree(c,
"TakeLongRoot");
2843 NumberFree(d,
"TakeLongRoot"); NumberFree(e,
"TakeLongRoot");
2856int MakeRational(WORD a,WORD m, WORD *b, WORD *c)
2858 LONG x1,x2,x3,x4,y1,y2;
2859 if ( a < 0 ) { a = a+m; }
2861 if ( a > m/2 ) a = a-m;
2862 *b = a; *c = 1;
return(0);
2866 y1 = x1/x2; y2 = x1%x2; x3 = 1; x4 = -y1; x1 = x2; x2 = y2;
2867 while ( x2*x2 >= m ) {
2868 y1 = x1/x2; y2 = x1%x2; x1 = x2; x2 = y2; y2 = x3-y1*x4; x3 = x4; x4 = y2;
2872 if ( x2 == 0 ) {
return(1); }
2873 if ( x2 > m/2 ) *b = x2-m;
2875 if ( x4 > m/2 ) { *c = x4-m; *c = -*c; *b = -*b; }
2876 else if ( x4 <= -m/2 ) { x4 += m; *c = x4; }
2877 else if ( x4 < 0 ) { x4 = -x4; *c = x4; *b = -*b; }
2902#define COPYLONG(x1,nx1,x2,nx2) { int i; for(i=0;i<ABS(nx2);i++)x1[i]=x2[i];nx1=nx2; }
2904int MakeLongRational(PHEAD UWORD *a, WORD na, UWORD *m, WORD nm, UWORD *b, WORD *nb)
2906 UWORD *root = NumberMalloc(
"MakeRational");
2907 UWORD *x1 = NumberMalloc(
"MakeRational");
2908 UWORD *x2 = NumberMalloc(
"MakeRational");
2909 UWORD *x3 = NumberMalloc(
"MakeRational");
2910 UWORD *x4 = NumberMalloc(
"MakeRational");
2911 UWORD *y1 = NumberMalloc(
"MakeRational");
2912 UWORD *y2 = NumberMalloc(
"MakeRational");
2913 WORD nroot,nx1,nx2,nx3,nx4,ny1,ny2 = 0,retval = 0;
2918 COPYLONG(root,nroot,m,nm)
2919 TakeLongRoot(root,&nroot,2);
2923 if ( na < 0 ) { na = -na; sign = -sign; }
2924 COPYLONG(x1,nx1,m,nm)
2925 COPYLONG(x2,nx2,a,na)
2933 if ( BigLong(x2,nx2,root,nroot) <= 0 ) {
2937 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2938 if ( ny2 == 0 ) { retval = 1;
goto cleanup; }
2939 COPYLONG(x1,nx1,x2,nx2)
2940 COPYLONG(x2,nx2,y2,ny2)
2942 COPYLONG(x4,nx4,y1,ny1)
2947 while ( BigLong(x2,nx2,root,nroot) > 0 ) {
2948 DivLong(x1,nx1,x2,nx2,y1,&ny1,y2,&ny2);
2949 if ( ny2 == 0 ) { retval = 1;
goto cleanup; }
2950 COPYLONG(x1,nx1,x2,nx2)
2951 COPYLONG(x2,nx2,y2,ny2)
2952 MulLong(y1,ny1,x4,nx4,y2,&ny2);
2954 AddLong(x3,nx3,y2,ny2,y1,&ny1);
2955 COPYLONG(x3,nx3,x4,nx4)
2956 COPYLONG(x4,nx4,y1,ny1)
2962 if ( nx4 < 0 ) { sign = -sign; nx4 = -nx4; }
2963 COPYLONG(b,*nb,x2,nx2)
2965 if ( sign < 0 ) *nb = -*nb;
2967 NumberFree(y2,
"MakeRational");
2968 NumberFree(y1,
"MakeRational");
2969 NumberFree(x4,
"MakeRational");
2970 NumberFree(x3,
"MakeRational");
2971 NumberFree(x2,
"MakeRational");
2972 NumberFree(x1,
"MakeRational");
2973 NumberFree(root,
"MakeRational");
2993#ifdef WITHCHINESEREMAINDER
2997 UWORD *inv1 = NumberMalloc(
"ChineseRemainder");
2998 UWORD *inv2 = NumberMalloc(
"ChineseRemainder");
2999 UWORD *fac1 = NumberMalloc(
"ChineseRemainder");
3000 UWORD *fac2 = NumberMalloc(
"ChineseRemainder");
3002 WORD ninv1, ninv2, nfac1, nfac2;
3004 AddLong(a1->a,a1->na,a1->m,a1->nm,a1->a,&(a1->na));
3007 AddLong(a2->a,a2->na,a2->m,a2->nm,a2->a,&(a2->na));
3009 MulLong(a1->m,a1->nm,a2->m,a2->nm,a->m,&(a->nm));
3011 GetLongModInverses(BHEAD a1->m,a1->nm,a2->m,a2->nm,inv1,&ninv1,inv2,&ninv2);
3012 MulLong(inv1,ninv1,a1->m,a1->nm,fac1,&nfac1);
3013 MulLong(inv2,ninv2,a2->m,a2->nm,fac2,&nfac2);
3015 MulLong(fac1,nfac1,a2->a,a2->na,inv1,&ninv1);
3016 MulLong(fac2,nfac2,a1->a,a1->na,inv2,&ninv2);
3017 AddLong(inv1,ninv1,inv2,ninv2,a->a,&(a->na));
3020 MulLong(a->a,a->na,two,1,fac1,&nfac1);
3021 if ( BigLong(fac1,nfac1,a->m,a->nm) > 0 ) {
3023 AddLong(a->a,a->na,a->m,a->nm,a->a,&(a->na));
3026 NumberFree(fac2,
"ChineseRemainder");
3027 NumberFree(fac1,
"ChineseRemainder");
3028 NumberFree(inv2,
"ChineseRemainder");
3029 NumberFree(inv1,
"ChineseRemainder");
3055 if ( term1[1] == 0 && n1 == 1 ) {
3056 if ( term2[1] == 0 && n2 == 1 )
return(0);
3057 if ( n2 < 0 )
return(1);
3060 else if ( term2[1] == 0 && n2 == 1 ) {
3061 if ( n1 < 0 )
return(-1);
3065 if ( n2 < 0 )
return(1);
3068 if ( n2 > 0 )
return(-1);
3069 a = term1; term1 = term2; term2 = a;
3070 n3 = -n1; n1 = -n2; n2 = n3;
3072 if ( term1[1] == 1 && term2[1] == 1 && n1 == 1 && n2 == 1 ) {
3073 if ( (UWORD)*term1 > (UWORD)*term2 )
return(1);
3074 else if ( (UWORD)*term1 < (UWORD)*term2 )
return(-1);
3082 c = NumberMalloc(
"CompCoef");
3083 if ( AddRat(BHEAD (UWORD *)term1,n1,(UWORD *)term2,-n2,c,&n3) ) {
3084 MLOCK(ErrorMessageLock);
3085 MesCall(
"CompCoef");
3086 MUNLOCK(ErrorMessageLock);
3087 NumberFree(c,
"CompCoef");
3090 NumberFree(c,
"CompCoef");
3103int Modulus(WORD *term)
3109 if ( TakeModulus((UWORD *)t,&n1,AC.cmod,AC.ncmod,UNPACK) ) {
3110 MLOCK(ErrorMessageLock);
3112 MUNLOCK(ErrorMessageLock);
3119 else if ( n1 > 0 ) {
3124 else if ( n1 < 0 ) {
3130 *term = WORDDIF(t,term);
3150int TakeModulus(UWORD *a, WORD *na, UWORD *cmodvec, WORD ncmod, WORD par)
3153 UWORD *c, *d, *e, *f, *g, *h;
3155 UWORD *x3,*x1,*x5,*x6,*x7,*x8;
3158 WORD nh, tdenom, tnumer, nmod;
3160 if ( ncmod == 0 )
return(0);
3163 if ( ( par & UNPACK ) != 0 ) UnPack(a,n1,&tdenom,&tnumer);
3164 else { tnumer = n1; }
3169 if ( ( ( par & UNPACK ) == 0 ) && nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3172 else if ( nmod == 1 && ( n1 == 1 || n1 == -1 ) ) {
3174 a[1] = a[1] % cmodvec[0];
3176 MesPrint(
"Division by zero in short modulus arithmetic");
3180 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 ) ) {
3181 y1 = AC.modinverses[a[1]];
3187 a[0] = (x*y1) % cmodvec[0];
3192 a[0] = a[0] % cmodvec[0];
3194 if ( a[0] == 0 ) { *na = 0;
return(0); }
3195 if ( ( AC.modmode & POSNEG ) != 0 ) {
3196 if ( a[0] > (UWORD)(cmodvec[0]/2) ) {
3197 a[0] = cmodvec[0] - a[0];
3201 else if ( *na < 0 ) {
3202 *na = 1; a[0] = cmodvec[0] - a[0];
3206 c = NumberMalloc(
"TakeModulus"); d = NumberMalloc(
"TakeModulus"); e = NumberMalloc(
"TakeModulus");
3207 f = NumberMalloc(
"TakeModulus"); g = NumberMalloc(
"TakeModulus"); h = NumberMalloc(
"TakeModulus");
3209 if ( DivLong(a,tnumer,(UWORD *)cmodvec,nmod,
3210 c,&nh,a,&tnumer) )
goto ModErr;
3211 if ( tnumer == 0 ) { *na = 0;
goto normalreturn; }
3212 if ( ( par & UNPACK ) == 0 ) {
3213 if ( ( AC.modmode & POSNEG ) != 0 ) {
3216 else if ( tnumer < 0 ) {
3217 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3222 if ( tdenom == 1 && a[n1] == 1 ) {
3223 if ( ( AC.modmode & POSNEG ) != 0 ) {
3226 else if ( tnumer < 0 ) {
3227 SubPLon((UWORD *)cmodvec,nmod,a,-tnumer,a,&tnumer);
3233 while ( --i > 0 ) *a++ = 0;
3236 if ( DivLong(a+n1,tdenom,(UWORD *)cmodvec,nmod,c,&nh,a+n1,&tdenom) )
goto ModErr;
3238 MLOCK(ErrorMessageLock);
3239 MesPrint(
"Division by zero in modulus arithmetic");
3240 if ( AP.DebugFlag ) {
3244 if ( i < 0 ) i = -i;
3245 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
3247 if ( i < 0 ) i = -i;
3248 while ( --i >= 0 ) { TalToLine((UWORD)(*a++)); TokenToLine((UBYTE *)
" "); }
3249 TalToLine((UWORD)(*na));
3253 MUNLOCK(ErrorMessageLock);
3254 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3255 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3258 if ( ( AC.modinverses != 0 ) && ( ( par & NOINVERSES ) == 0 )
3259 && ( tdenom == 1 || tdenom == -1 ) ) {
3260 *d = AC.modinverses[a[n1]]; y1 = 1; y2 = tdenom;
3261 if ( MulLong(a,tnumer,d,y1,c,&y3) )
goto ModErr;
3262 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) )
goto ModErr;
3263 if ( y2 < 0 ) tdenom = -tdenom;
3266 x2 = (UWORD *)cmodvec; x1 = c; i = nmod;
while ( --i >= 0 ) *x1++ = *x2++;
3267 x1 = c; x2 = a+n1; x3 = d; x4 = e; x5 = f; x6 = g;
3268 y1 = nmod; y2 = tdenom; y4 = 0; y5 = 1; *x5 = 1;
3270 if ( DivLong(x1,y1,x2,y2,h,&nh,x3,&y3) )
goto ModErr;
3271 if ( MulLong(x5,y5,h,nh,x6,&y6) )
goto ModErr;
3272 if ( AddLong(x4,y4,x6,-y6,x6,&y6) )
goto ModErr;
3274 if ( y2 != 1 || *x2 != 1 ) {
3275 MLOCK(ErrorMessageLock);
3276 MesPrint(
"Inverse in modulus arithmetic doesn't exist");
3277 MesPrint(
"Denominator and modulus are not relative prime");
3278 MUNLOCK(ErrorMessageLock);
3283 x7 = x1; x1 = x2; y1 = y2; x2 = x3; y2 = y3; x3 = x7;
3284 x8 = x4; x4 = x5; y4 = y5; x5 = x6; y5 = y6; x6 = x8;
3286 if ( y5 < 0 && AddLong((UWORD *)cmodvec,nmod,x5,y5,x5,&y5) )
goto ModErr;
3287 if ( MulLong(a,tnumer,x5,y5,c,&y3) )
goto ModErr;
3288 if ( DivLong(c,y3,(UWORD *)cmodvec,nmod,d,&y5,a,&tdenom) )
goto ModErr;
3290 if ( !tdenom ) { *na = 0;
goto normalreturn; }
3291 if ( ( ( AC.modmode & POSNEG ) != 0 ) && ( ( par & FROMFUNCTION ) == 0 ) ) {
3294 else if ( tdenom < 0 ) {
3295 SubPLon((UWORD *)cmodvec,nmod,a,-tdenom,a,&tdenom);
3301 while ( --i > 0 ) *a++ = 0;
3303 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3304 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3307 MLOCK(ErrorMessageLock);
3308 MesCall(
"TakeModulus");
3309 MUNLOCK(ErrorMessageLock);
3310 NumberFree(c,
"TakeModulus"); NumberFree(d,
"TakeModulus"); NumberFree(e,
"TakeModulus");
3311 NumberFree(f,
"TakeModulus"); NumberFree(g,
"TakeModulus"); NumberFree(h,
"TakeModulus");
3322int TakeNormalModulus (UWORD *a, WORD *na, UWORD *c, WORD nc, WORD par)
3331 halfc = NumberMalloc(
"TakeNormalModulus");
3335 for (n=0; n<nhalfc; n++) {
3337 if (n+1<nc) halfc[n] |= c[n+1] << (BITSINWORD-1);
3340 if (halfc[nhalfc-1]==0)
3344 if (BigLong(a,ABS(*na),halfc,nhalfc) > 0) {
3346 TakeModulus(a,na,c,nc,par);
3349 if (BigLong(a,n,halfc,nhalfc) > 0) {
3350 SubPLon(c,nc,a,n,a,&n);
3351 *na = (*na > 0 ? -n : n);
3355 NumberFree(halfc,
"TakeNormalModulus");
3364int MakeModTable(
void)
3368 if ( AC.modpowers ) {
3369 M_free(AC.modpowers,
"AC.modpowers");
3370 AC.modpowers = NULL;
3373 MLOCK(ErrorMessageLock);
3374 MesPrint(
"&No memory for modulus generator power table");
3375 MUNLOCK(ErrorMessageLock);
3378 if ( n == 0 )
return(0);
3379 size = (LONG)(*AC.cmod);
3380 if ( n == 2 ) size += (((LONG)AC.cmod[1])<<BITSINWORD);
3381 AC.modpowers = (UWORD *)Malloc1(size*n*
sizeof(UWORD),
"table for powers of modulus");
3384 for ( i = 0; i < size; i++ ) AC.modpowers[i] = 0;
3385 for ( i = 0; i < size; i++ ) {
3386 AC.modpowers[j] = (WORD)i;
3390 for ( i = 2; i < size; i++ ) {
3391 if ( AC.modpowers[i] == 0 ) {
3392 MLOCK(ErrorMessageLock);
3393 MesPrint(
"&improper generator for this modulus");
3394 MUNLOCK(ErrorMessageLock);
3395 M_free(AC.modpowers,
"AC.modpowers");
3399 AC.modpowers[1] = 0;
3404 UWORD *MMscrat7 = NumberMalloc(
"MakeModTable"), *MMscratC = NumberMalloc(
"MakeModTable");
3408 for ( i = 0; i < j; i+=2 ) { AC.modpowers[i] = 0; AC.modpowers[i+1] = 0; }
3409 for ( i = 0; i < size; i++ ) {
3410 j = *MMscratC + (((LONG)MMscratC[1])<<BITSINWORD);
3412 AC.modpowers[j] = (WORD)(i & WORDMASK);
3413 AC.modpowers[j+1] = (WORD)(i >> BITSINWORD);
3414 MulLong((UWORD *)MMscratC,nScrat,(UWORD *)AC.powmod,
3415 AC.npowmod,(UWORD *)MMscrat7,&n2);
3416 TakeModulus(MMscrat7,&n2,AC.cmod,AC.ncmod,NOUNPACK);
3417 *MMscratC = *MMscrat7; MMscratC[1] = MMscrat7[1]; nScrat = n2;
3419 NumberFree(MMscrat7,
"MakeModTable"); NumberFree(MMscratC,
"MakeModTable");
3421 for ( i = 4; i < j; i+=2 ) {
3422 if ( AC.modpowers[i] == 0 && AC.modpowers[i+1] == 0 ) {
3423 MLOCK(ErrorMessageLock);
3424 MesPrint(
"&improper generator for this modulus");
3425 MUNLOCK(ErrorMessageLock);
3426 M_free(AC.modpowers,
"AC.modpowers");
3430 AC.modpowers[2] = AC.modpowers[3] = 0;
3450int Factorial(PHEAD WORD n, UWORD *a, WORD *na)
3457 if ( n > AT.nfac ) {
3458 if ( AT.factorials == 0 ) {
3459 AT.nfac = 0; AT.mfac = 50; AT.sfact = 400;
3460 AT.pfac = (LONG *)Malloc1((AT.mfac+2)*
sizeof(LONG),
"factorials");
3461 AT.factorials = (UWORD *)Malloc1(AT.sfact*
sizeof(UWORD),
"factorials");
3462 AT.factorials[0] = 1; AT.pfac[0] = 0; AT.pfac[1] = 1;
3465 c = AT.factorials+AT.pfac[AT.nfac];
3466 nc = i = AT.pfac[AT.nfac+1] - AT.pfac[AT.nfac];
3467 while ( --i >= 0 ) *b++ = *c++;
3468 for ( j = AT.nfac+1; j <= n; j++ ) {
3470 if ( nc > AM.MaxTal ) {
3471 MLOCK(ErrorMessageLock);
3472 MesPrint(
"Overflow in factorial. MaxTal = %d",AM.MaxTal);
3473 MesPrint(
"Increase MaxTerm in %s",setupfilename);
3474 MUNLOCK(ErrorMessageLock);
3477 if ( j > AT.mfac ) {
3479 p = (LONG *)Malloc1((AT.mfac*2+2)*
sizeof(LONG),
"factorials");
3481 for ( i = AT.mfac+1; i >= 0; i-- ) p[i] = AT.pfac[i];
3482 M_free(AT.pfac,
"factorial offsets"); AT.pfac = p; AT.mfac *= 2;
3484 if ( AT.pfac[j] + nc >= AT.sfact ) {
3486 f = (UWORD *)Malloc1(AT.sfact*2*
sizeof(UWORD),
"factorials");
3488 c = AT.factorials; b = f;
3489 while ( --ii >= 0 ) *b++ = *c++;
3490 M_free(AT.factorials,
"factorials");
3494 b = a; c = AT.factorials + AT.pfac[j]; i = nc;
3495 while ( --i >= 0 ) *c++ = *b++;
3496 AT.pfac[j+1] = AT.pfac[j] + nc;
3501 else if ( n == 0 ) {
3505 *na = i = AT.pfac[n+1] - AT.pfac[n];
3506 b = AT.factorials + AT.pfac[n];
3507 while ( --i >= 0 ) *a++ = *b++;
3530int Bernoulli(WORD n, UWORD *a, WORD *na)
3533 UWORD *b, *c, *scrib, *ntop, *ntop1;
3534 WORD i, i1, i2, nhalf, nqua, nscrib, nntop, nntop1, *oldworkpointer;
3535 UWORD twee = 2, twonplus1;
3539 if ( n == 0 ) { a[0] = a[1] = 1; *na = 3; }
3540 else if ( n == 1 ) { a[0] = 1; a[1] = 2; *na = 3; }
3543 if ( ( n & 1 ) != 0 ) { a[0] = a[1] = 0; *na = 0;
return(0); }
3545 if ( nhalf > AT.nBer ) {
3546 oldworkpointer = AT.WorkPointer;
3547 if ( AT.bernoullis == 0 ) {
3548 AT.nBer = 1; AT.mBer = 50; AT.sBer = 400;
3549 AT.pBer = (LONG *)Malloc1((AT.mBer+2)*
sizeof(LONG),
"bernoullis");
3550 AT.bernoullis = (UWORD *)Malloc1(AT.sBer*
sizeof(UWORD),
"bernoullis");
3551 AT.pBer[1] = 0; AT.pBer[2] = 3;
3552 AT.bernoullis[0] = 3; AT.bernoullis[1] = 1; AT.bernoullis[2] = 12;
3554 a[0] = 1; a[1] = 12; *na = 3;
return(0);
3557 while ( nhalf > AT.mBer ) {
3559 p = (LONG *)Malloc1((AT.mBer*2+1)*
sizeof(LONG),
"bernoullis");
3561 for ( i = AT.mBer; i >= 0; i-- ) p[i] = AT.pBer[i];
3562 M_free(AT.pBer,
"factorial pointers"); AT.pBer = p; AT.mBer *= 2;
3564 for ( n = AT.nBer+1; n <= nhalf; n++ ) {
3565 scrib = (UWORD *)(AT.WorkPointer);
3567 if ( ( n & 1 ) == 1 ) {
3568 nscrib = 0; ntop = scrib;
3571 b = AT.bernoullis + AT.pBer[nqua];
3573 i = (WORD)(REDLENG(nscrib));
3574 MulRat(BHEAD b,i,b,i,scrib,&nscrib);
3575 ntop = scrib + 2*nscrib;
3578 for ( j = 1; j <= nqua; j++ ) {
3579 b = AT.bernoullis + AT.pBer[j];
3580 c = AT.bernoullis + AT.pBer[n-j];
3581 i1 = (WORD)(*b); i2 = (WORD)(*c);
3584 MulRat(BHEAD b+1,i1,c+1,i2,ntop,&nntop);
3585 Mully(BHEAD ntop,&nntop,&twee,1);
3587 i = (WORD)nntop;
if ( i < 0 ) i = -i;
3589 AddRat(BHEAD ntop,nntop,scrib,nscrib,ntop1,&nntop1);
3592 ntop1 = ntop; nntop1 = nntop;
3594 nscrib = i1 = (WORD)nntop1;
3595 if ( i1 < 0 ) i1 = - i1;
3597 for ( i = 0; i < i1; i++ ) scrib[i] = ntop1[i];
3601 Divvy(BHEAD scrib,&nscrib,&twonplus1,-1);
3602 i1 = INCLENG(nscrib);
3603 i2 = i1;
if ( i2 < 0 ) i2 = -i2;
3604 i = (WORD)(AT.bernoullis[AT.pBer[n-1]]);
3605 if ( i < 0 ) i = -i;
3606 AT.pBer[n] = AT.pBer[n-1]+i;
3607 if ( AT.pBer[n] + i2 >= AT.sBer ) {
3609 f = (UWORD *)Malloc1(AT.sBer*2*
sizeof(UWORD),
"bernoullis");
3611 c = AT.bernoullis; b = f;
3612 while ( --ii >= 0 ) *b++ = *c++;
3613 M_free(AT.bernoullis,
"bernoullis");
3617 c = AT.bernoullis + AT.pBer[n]; b = scrib;
3619 for ( i = 1; i < i2; i++ ) *c++ = *b++;
3622 AT.WorkPointer = oldworkpointer;
3624 b = AT.bernoullis + AT.pBer[nhalf];
3625 *na = i = (WORD)(*b++);
3626 if ( i < 0 ) i = -i;
3628 while ( --i >= 0 ) *a++ = *b++;
3647#if ( BITSINWORD == 32 )
3649void StartPrimeList(PHEAD0)
3652 AR.PrimeList[AR.numinprimelist++] = 3;
3653 for ( i = 5; i < 46340; i += 2 ) {
3654 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*AR.PrimeList[j] <= i; j++ ) {
3655 if ( i % AR.PrimeList[j] == 0 )
goto nexti;
3657 AR.PrimeList[AR.numinprimelist++] = i;
3660 AR.notfirstprime = 1;
3670#if ( BITSINWORD == 32 )
3671 if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
3673 if ( num > AT.inprimelist ) {
3674 while ( AT.inprimelist < num ) {
3675 if ( num >= AT.sizeprimelist ) {
3676 if ( AT.sizeprimelist == 0 ) newsize = 32;
3677 else newsize = 2*AT.sizeprimelist;
3678 while ( num >= newsize ) newsize = newsize*2;
3679 newpl = (WORD *)Malloc1(newsize*
sizeof(WORD),
"NextPrime");
3680 for ( i = 0; i < AT.sizeprimelist; i++ ) {
3681 newpl[i] = AT.primelist[i];
3683 if ( AT.sizeprimelist > 0 ) {
3684 M_free(AT.primelist,
"NextPrime");
3686 AT.sizeprimelist = newsize;
3687 AT.primelist = newpl;
3689 if ( AT.inprimelist < 0 ) { i = MAXPOSITIVE; }
3690 else { i = AT.primelist[AT.inprimelist]; }
3691 while ( i > MAXPOWER ) {
3693#if ( BITSINWORD == 32 )
3694 for ( j = 0; j < AR.numinprimelist && AR.PrimeList[j]*(LONG)(AR.PrimeList[j]) <= x; j++ ) {
3695 if ( x % AR.PrimeList[j] == 0 )
goto nexti;
3698 for ( j = 3; j*((LONG)j) <= x; j += 2 ) {
3699 if ( x % j == 0 )
goto nexti;
3703 AT.primelist[AT.inprimelist] = i;
3707 if ( i < MAXPOWER ) {
3708 MLOCK(ErrorMessageLock);
3709 MesPrint(
"There are not enough short prime numbers for this calculation");
3710 MesPrint(
"Try to use a computer with a %d-bits architecture",
3711 (
int)(BITSINWORD*4));
3712 MUNLOCK(ErrorMessageLock);
3717 return(AT.primelist[num]);
3729WORD Moebius(PHEAD WORD nn)
3733 SBYTE *newtable, mu;
3734#if ( BITSINWORD == 32 )
3735 if ( AR.notfirstprime == 0 ) StartPrimeList(BHEAD0);
3742 if ( nn >= AR.moebiustablesize ) {
3743 if ( AR.moebiustablesize <= 0 ) { newsize = (LONG)nn + 20; }
3744 else { newsize = (LONG)nn*2; }
3745 if ( newsize > MAXPOSITIVE ) newsize = MAXPOSITIVE;
3746 newtable = (SBYTE *)Malloc1(newsize*
sizeof(SBYTE),
"Moebius");
3747 for ( i = 0; i < AR.moebiustablesize; i++ ) newtable[i] = AR.moebiustable[i];
3748 for ( ; i < newsize; i++ ) newtable[i] = 2;
3749 if ( AR.moebiustablesize > 0 ) M_free(AR.moebiustable,
"Moebius");
3750 AR.moebiustable = newtable;
3751 AR.moebiustablesize = newsize;
3754 if ( nn != MAXPOSITIVE && AR.moebiustable[nn] != 2 )
return((WORD)AR.moebiustable[nn]);
3756 if ( n == 1 )
goto putvalue;
3759 if ( n % 2 == 0 ) { mu = 0;
goto putvalue; }
3760 if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n];
goto putvalue; }
3762 if ( n == 1 )
goto putvalue;
3764#if ( BITSINWORD == 32 )
3765 for ( i = 0; i < AR.numinprimelist; i++ ) {
3766 x = AR.PrimeList[i];
3768 for ( x = 3; x < MAXPOSITIVE; x += 2 ) {
3772 if ( n % x == 0 ) { mu = 0;
goto putvalue; }
3773 if ( AR.moebiustable[n] != 2 ) { mu = -AR.moebiustable[n];
goto putvalue; }
3775 if ( n == 1 )
goto putvalue;
3777 if ( n < x*x )
break;
3781 if ( nn != MAXPOSITIVE ) AR.moebiustable[nn] = mu;
3804static void wranfnew(PHEAD0)
3808 for ( i = 0; i < AR.wranfnpair1; i++ ) {
3809 j = AR.wranfia[i] - AR.wranfia[i+(AR.wranfnpair2-AR.wranfnpair1)];
3810 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3813 for ( i = AR.wranfnpair1; i < AR.wranfnpair2; i++ ) {
3814 j = AR.wranfia[i] - AR.wranfia[i-AR.wranfnpair1];
3815 if ( j < 0 ) j += (LONG)1 << (2*BITSINWORD-2);
3820void iniwranf(PHEAD0)
3822 int imax = AR.wranfnpair2-1;
3823 ULONG i, ii, seed = AR.wranfseed;
3825 ULONG offset = 12345;
3828#if defined(WITHPTHREADS)
3830#elif defined(WITHMPI)
3837 pow = offset; accu = 1;
3839 if ( ( i & 1 ) != 0 ) accu *= pow;
3840 i /= 2; pow = pow*pow;
3845 if ( seed < ((LONG)1<<(BITSINWORD-1)) ) {
3846 j = ( (seed+31459L) << (BITSINWORD-2))+offset;
3848 else if ( seed < ((LONG)1<<(BITSINWORD+10-1)) ) {
3849 j = ( (seed+31459L) << (BITSINWORD-10-2))+offset;
3852 j = ( (seed+31459L) << 1)+offset;
3854 if ( ( seed & 1 ) == 1 ) seed++;
3856 AR.wranfia[imax] = j;
3858 for ( i = 0; i <= (ULONG)(imax); i++ ) {
3859 ii = (AR.wranfnpair1*i)%AR.wranfnpair2;
3861 k = ULongToLong((ULONG)j - (ULONG)k);
3862 if ( k < 0 ) k += (LONG)1 << (2*BITSINWORD-2);
3865 for ( i = 0; i < WARMUP; i++ ) wranfnew(BHEAD0);
3872 if ( AR.wranfia == 0 ) {
3873 AR.wranfia = (ULONG *)Malloc1(AR.wranfnpair2*
sizeof(ULONG),
"wranf");
3876 if ( AR.wranfcall >= AR.wranfnpair2) {
3880 wval = (UWORD)(AR.wranfia[AR.wranfcall++]>>(BITSINWORD-1));
3888UWORD iranf(PHEAD UWORD imax)
3892 if (imax < 2)
return 0;
3893 x = (LONG)1 << BITSINWORD;
3895 while ( ( i = wranf(BHEAD0) ) >= xmax ) {}
3913UBYTE *PreRandom(UBYTE *s)
3916 UBYTE *mode,*mins = 0,*maxs = 0, *outval;
3918 double minval, maxval, value = 0;
3921 while ( FG.cTable[*s] <= 1 ) s++;
3922 if ( *s ==
',' ) { *s = 0; s++; }
3924 while ( *s && *s !=
',' ) s++;
3925 if ( *s ==
',' ) { *s = 0; s++; }
3927 while ( *s && *s !=
',' ) s++;
3928 if ( *s || *maxs == 0 || *mins == 0 ) {
3929 MesPrint(
"@Illegal arguments in macro RANDOM_");
3932 if ( StrICmp(mode,(UBYTE *)
"lin") == 0 ) {
3935 else if ( StrICmp(mode,(UBYTE *)
"log") == 0 ) {
3939 MesPrint(
"@Illegal mode argument in macro RANDOM_");
3943 sscanf((
char *)mins,
"%f",&num); minval = num;
3944 sscanf((
char *)maxs,
"%f",&num); maxval = num;
3956 if ( PF.me == MASTER ) {
3963 xx = x/pow(2.0,(
double)(BITSINWORD-1));
3964 if ( linlog == 0 ) {
3965 value = minval + (maxval-minval)*xx;
3967 else if ( linlog == 1 ) {
3968 value = minval * pow(maxval/minval,xx);
3972 outval = (UBYTE *)Malloc1(64,
"PreRandom");
3973 if ( ABS(value) < 0.00001 || ABS(value) > 1000000. ) {
3974 snprintf((
char *)outval,64,
"%e",value);
3976 else if ( ABS(value) < 0.0001 ) { snprintf((
char *)outval,64,
"%10f",value); }
3977 else if ( ABS(value) < 0.001 ) { snprintf((
char *)outval,64,
"%9f",value); }
3978 else if ( ABS(value) < 0.01 ) { snprintf((
char *)outval,64,
"%8f",value); }
3979 else if ( ABS(value) < 0.1 ) { snprintf((
char *)outval,64,
"%7f",value); }
3980 else if ( ABS(value) < 1. ) { snprintf((
char *)outval,64,
"%6f",value); }
3981 else if ( ABS(value) < 10. ) { snprintf((
char *)outval,64,
"%5f",value); }
3982 else if ( ABS(value) < 100. ) { snprintf((
char *)outval,64,
"%4f",value); }
3983 else if ( ABS(value) < 1000. ) { snprintf((
char *)outval,64,
"%3f",value); }
3984 else if ( ABS(value) < 10000. ) { snprintf((
char *)outval,64,
"%2f",value); }
3985 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)