Annotation of OpenXM_contrib2/asir2000/engine/Ngcd.c, Revision 1.4
1.1 murao 1: /*
1.4 ! noro 2: * $OpenXM: OpenXM_contrib2/asir2000/engine/Ngcd.c,v 1.3 2001/10/09 01:36:11 noro Exp $
1.1 murao 3: */
4: /*
5: #include "ca.h"
6: #include "base.h"
7: */
8:
9: #undef CALL
10:
11: /**** Machine specific ****/
12: #define BIT_WIDTH_OF_INT 32
13:
14:
15: #if BSH == BIT_WIDTH_OF_INT
1.3 noro 16: #if defined(BMASK)
17: #undef BMASK
18: #endif
1.1 murao 19: #define BMask ((unsigned)(-1))
20: #define BMASK BMask
21: #endif
22:
23:
24: int igcd_algorithm = 0;
1.4 ! noro 25: /* == 0 : Euclid,
! 26: * == 1 : binary,
! 27: * == 2 : bmod,
! 28: * >= 3 : (Weber's accelerated)/(Jebelean's generalized binary) algorithm,
1.1 murao 29: */
30: int igcd_thre_inidiv = 50;
31: /*
32: * In the non-Euclidean algorithms, if the ratio of the lengths (number
33: * of words) of two integers is >= igcd_thre_inidiv, we first perform
34: * remainder calculation.
35: * If == 0, this remainder calculation is not performed.
36: */
37: int igcdacc_thre = 10;
38: /*
39: * In the accelerated algorithm, if the bit-lengths of two integers is
40: * > igcdacc_thre, "bmod" reduction is done.
41: */
42:
43: #include "inline.h"
44:
45: #define TRAILINGZEROS(t,cntr) for(cntr=0;(t&1)==0;t>>=1)cntr++;
46:
47: #define W_NALLOC(d) ((N)ALLOCA(TRUESIZE(oN,(d)-1,int)))
48:
49: #define ShouldCompRemInit(n1,n2) (igcd_thre_inidiv != 0 && PL(n1) >= igcd_thre_inidiv*PL(n2))
50:
51: #define IniDiv(n1,n2) \
1.4 ! noro 52: if ( ShouldCompRemInit(n1,n2) ) {\
! 53: N q, r; int w, b; \
! 54: divn(n1,n2,&q,&r); \
! 55: if ( !r ) return(n2); \
! 56: b = trailingzerosn( r, &w ); \
! 57: q = n1; n1 = n2; n2 = q; \
! 58: rshiftn( r, w, b, n2 ); \
! 59: }
! 60:
1.1 murao 61: /*
1.4 ! noro 62: * Binary GCD algorithm by J.Stein
! 63: * [J. Comp. Phys. Vol. 1 (1967), pp. 397-405)]:
! 64: * The right-shift binary algorithm is used.
1.1 murao 65: */
66:
67:
68: /*
1.4 ! noro 69: * subsidiary routines for gcdbinn below.
1.1 murao 70: */
71: static int /* number of bits */ trailingzeros_nbd( /* BD of N */ nbd, pnw )
72: int *nbd, *pnw /* number of zero words */;
73: {
74: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 75: unsigned
1.1 murao 76: #endif
1.4 ! noro 77: int nw, nb, w;
1.1 murao 78:
1.4 ! noro 79: for ( nw = 0; (w = *nbd) == 0; nbd++ ) nw++;
! 80: TRAILINGZEROS(w,nb);
! 81: *pnw = nw;
! 82: return nb;
1.1 murao 83: }
84:
85: #define trailingzerosn(n,pnw) trailingzeros_nbd(BD(n),pnw)
86:
87: static int /* PL of N */ rshift_nbd( /* BD of N */ nbd, /* PL of N */ nl,
1.4 ! noro 88: /* # words */ shw, /* # bits */ shb, /* BD of N */ p )
1.1 murao 89: #if BSH == BIT_WIDTH_OF_INT
90: unsigned
91: #endif
92: int *nbd, nl, shw, shb, *p;
93: {
1.4 ! noro 94: unsigned int i, v, w, lshb; /* <---- */
1.1 murao 95:
1.4 ! noro 96: nbd += shw, i = (nl -= shw);
! 97: if ( shb == 0 ) {
! 98: for ( ; nl > 0; nl-- ) *p++ = *nbd++;
! 99: return i;
! 100: } else if ( nl < 2 ) {
! 101: *p = (*nbd) >> shb;
! 102: return 1;
! 103: }
! 104: for ( lshb = BSH - shb, v = *nbd++; --nl > 0; v = w ) {
! 105: w = *nbd++;
! 106: #if BSH == BIT_WIDTH_OF_INT
! 107: *p++ = (v >> shb) | (w << lshb); /********/
! 108: #else
! 109: *p++ = (v >> shb) | ((w << lshb)&BMASK);
! 110: #endif
! 111: }
! 112: if ( (v >>= shb) == 0 ) return( i-1 );
! 113: *p = v;
! 114: return i;
1.1 murao 115: }
116:
117: #define rshiftn(ns,shw,shb,nd) (PL(nd)=rshift_nbd(BD(ns),PL(ns),shw,shb,BD(nd)))
118: /* nd <= ns << (shb + shw*BSH), returns PL of the result */
119:
120: #ifdef FULLSET
121: static N N_of_i_lshifted_by_wb( i, gw, gb )
122: int i, gw, gb;
1.4 ! noro 123: /*
! 124: * returns pointer to a new struct (N)(((int)i) >> (gb + gw*BSH))
! 125: */
! 126: {
! 127: unsigned int j, l, *p; /* <---- */
! 128: N n;
! 129:
! 130: j = i >> (BSH - gb);
! 131: #if BSH == BIT_WIDTH_OF_INT
! 132: i = (i << gb); /********/
! 133: #else
! 134: i = (i << gb)&BMASK;
! 135: #endif
! 136: l = j != 0 ? gw + 2 : gw + 1;
! 137: n = NALLOC(l);
! 138: PL(n) = l;
! 139: for ( p = BD(n); gw-- > 0; ) *p++ = 0;
! 140: *p++ = i;
! 141: if ( j != 0 ) *p = j;
! 142: return n;
1.1 murao 143: }
144: #endif /* FULLSET */
145:
146: /*
1.4 ! noro 147: * routines to make a new struct
! 148: * (N)(((BD of N)(b[0],...,b[lb-1])) << (gb + gw*BSH))
1.1 murao 149: */
150: static N N_of_nbd_lshifted_by_wb( /* BD of N */ b, /* PL of N */ lb, gw, gb )
151: int *b, lb, gw, gb;
1.4 ! noro 152: /*
! 153: * returns pointer to a new struct
! 154: * (N)(((BD of N)(b[0],...,b[lb-1])) << (gb + gw*BSH))
! 155: */
! 156: {
! 157: unsigned int rsh, s, t, *p, l; /* <---- */
! 158: N n;
! 159:
! 160: l = lb + gw;
! 161: if ( gb == 0 ) {
! 162: n = NALLOC(l);
! 163: PL(n) = l;
! 164: for ( p = BD(n); gw-- > 0; ) *p++ = 0;
! 165: while ( lb-- > 0 ) *p++ = *b++;
! 166: return n;
! 167: }
! 168: rsh = BSH - gb; s = b[lb-1];
! 169: if ( (t = s >> rsh) != 0 ) {
! 170: n = NALLOC(l+1);
! 171: PL(n) = l+1;
! 172: (p = BD(n))[l] = t;
! 173: } else {
! 174: n = NALLOC(l);
! 175: PL(n) = l;
! 176: p = BD(n);
! 177: }
! 178: while ( gw-- > 0 ) *p++ = 0;
! 179: #if BSH == BIT_WIDTH_OF_INT
! 180: *p++ = (t = *b++) << gb; /********/
! 181: for ( ; --lb > 0; t = s )
! 182: *p++ = (t >> rsh) | ((s = *b++) << gb); /********/
! 183: #else
! 184: *p++ = ((t = *b++) << gb)&BMASK;
! 185: for ( ; --lb > 0; t = s )
! 186: *p++ = (t >> rsh) | (((s = *b++) << gb)&BMASK);
1.1 murao 187: #endif
1.4 ! noro 188: return n;
1.1 murao 189: }
190:
191: #define N_of_n_lshifted_by_wb(a,gw,gb) N_of_nbd_lshifted_by_wb(BD(a),PL(a),gw,gb)
192:
193: #define SWAP(a,b,Type) { Type temp=a;a=b;b=temp;}
194: #define SIGNED_VAL(a,s) ((s)>0?(a):-(a))
195:
196:
197: #ifdef CALL
198: static int bw_int32( n )
1.4 ! noro 199: unsigned int n; /* <---- */
1.1 murao 200: {
1.4 ! noro 201: int w;
1.1 murao 202:
1.4 ! noro 203: w = 0;
1.1 murao 204: #if BSH > 32
1.4 ! noro 205: if ( n > 0xffffffff ) w += 32, n >>= 32;
1.1 murao 206: #endif
1.4 ! noro 207: if ( n >= 0x10000 ) w += 16, n >>= 16;
! 208: if ( n >= 0x100 ) w += 8, n >>= 8;
! 209: if ( n >= 0x10 ) w += 4, n >>= 4;
! 210: if ( n >= 0x4 ) w += 2, n >>= 2;
! 211: if ( n >= 0x2 ) w += 1, n >>= 1;
! 212: if ( n != 0 ) ++w;
! 213: return w;
1.1 murao 214: }
215: #define BitWidth(n,bw) bw = bw_int32( n )
216: #else
217:
218: #if BSH > 32
219: #define BitWidth(n,bw) {\
1.4 ! noro 220: unsigned int k = (n); \
! 221: bw = 0; \
! 222: if ( k > 0xffffffff ) bw += 32, k >>= 32; \
! 223: if ( k >= 0x10000 ) bw += 16, k >>= 16; \
! 224: if ( k >= 0x100 ) bw += 8, k >>= 8; \
! 225: if ( k >= 0x10 ) bw += 4, k >>= 4; \
! 226: if ( k >= 0x4 ) bw += 2, k >>= 2; \
! 227: if ( k >= 0x2 ) bw += 1, k >>= 1; \
! 228: if ( k != 0 ) bw++; \
1.1 murao 229: }
230: #else
231: #define BitWidth(n,bw) {\
1.4 ! noro 232: unsigned int k = (n); \
! 233: bw = 0; \
! 234: if ( k >= 0x10000 ) bw += 16, k >>= 16; \
! 235: if ( k >= 0x100 ) bw += 8, k >>= 8; \
! 236: if ( k >= 0x10 ) bw += 4, k >>= 4; \
! 237: if ( k >= 0x4 ) bw += 2, k >>= 2; \
! 238: if ( k >= 0x2 ) bw += 1, k >>= 1; \
! 239: if ( k != 0 ) bw++; \
1.1 murao 240: }
241: #endif
242: #endif
243:
244: #include "igcdhack.c"
245:
246: /*
1.4 ! noro 247: * Implementation of the binary GCD algorithm for two oN structs
! 248: * (big-integers) in risa.
1.1 murao 249: *
1.4 ! noro 250: * The major operations in the following algorithms are the binary-shifts
! 251: * and the updates of (u, v) by (min(u,v), |u-v|), and are to be open-coded
! 252: * without using routines for oN structures just as in addn() or subn().
1.1 murao 253: */
254:
255: static int igcd_binary_2w( u, lu, v, lv, pans )
256: #if BSH == BIT_WIDTH_OF_INT
257: unsigned
258: #endif
1.4 ! noro 259: int *u, lu, *v, lv, *pans; /* <---- */
! 260: /* both u[0:lu-1] and v[0:lv-1] are assumed to be odd */
1.1 murao 261: {
262: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 263: unsigned
1.1 murao 264: #endif
1.4 ! noro 265: int i, h1, l1, h2, l2; /* <---- */
1.1 murao 266:
1.4 ! noro 267: l1 = u[0], l2 = v[0];
! 268: h1 = lu <= 1 ? 0 : u[1];
! 269: h2 = lv <= 1 ? 0 : v[1];
! 270: /**/
! 271: loop: if ( h1 == 0 ) {
! 272: no_hi1: if ( h2 == 0 ) goto one_word;
! 273: no_hi1n:if ( l1 == 1 ) return 0;
! 274: #if BSH == BIT_WIDTH_OF_INT
! 275: if ( l2 == l1 ) {
! 276: for ( l2 = h2; (l2&1) == 0; l2 >>= 1 ) ;
! 277: goto one_word;
! 278: } else if ( l2 < l1 ) {
! 279: l2 -= l1, h2--;
! 280: } else l2 -= l1;
! 281: i = 0; do { l2 >>= 1, i++; } while ( (l2&1) == 0 );
! 282: l2 |= (h2 << (BSH - i));
! 283: #else
! 284: if ( (l2 -= l1) == 0 ) {
! 285: for ( l2 = h2; (l2&1) == 0; l2 >>= 1 ) ;
! 286: goto one_word;
! 287: } else if ( l2 < 0 ) h2--, l2 += BASE;
! 288: i = 0; do { l2 >>= 1, i++; } while ( (l2&1) == 0 );
! 289: l2 |= ((h2 << (BSH - i)) & BMASK);
! 290: #endif
! 291: h2 >>= i;
! 292: goto no_hi1;
! 293: } else if ( h2 == 0 ) {
! 294: no_hi2: if ( l2 == 1 ) return 0;
! 295: #if BSH == BIT_WIDTH_OF_INT
! 296: if ( l1 == l2 ) {
! 297: for ( l1 = h1; (l1&1) == 0; l1 >>= 1 ) ;
! 298: goto one_word;
! 299: } else if ( l1 < l2 ) {
! 300: l1 -= l2, h1--;
! 301: } else l1 -= l2;
! 302: i = 0; do { l1 >>= 1, i++; } while ( (l1&1) == 0 );
! 303: l1 |= (h1 << (BSH - i));
! 304: #else
! 305: if ( (l1 -= l2) == 0 ) {
! 306: for ( l1 = h1; (l1&1) == 0; l1 >>= 1 ) ;
! 307: goto one_word;
! 308: } else if ( l1 < 0 ) h1--, l1 += BASE;
! 309: i = 0; do { l1 >>= 1, i++; } while ( (l1&1) == 0 );
! 310: l1 |= ((h1 << (BSH - i)) & BMASK);
! 311: #endif
! 312: if ( (h1 >>= i) == 0 ) goto one_word;
! 313: goto no_hi2;
! 314: } else if ( l1 == l2 ) {
! 315: if ( h1 == h2 ) {
! 316: pans[0] = l1, pans[1] = h1;
! 317: return 2;
! 318: } else if ( h1 > h2 ) {
! 319: for ( l1 = h1 - h2; (l1&1) == 0; l1 >>= 1 ) ;
! 320: goto no_hi1n;
! 321: } else {
! 322: for ( l2 = h2 - h1; (l2&1) == 0; l2 >>= 1 ) ;
! 323: goto no_hi2;
! 324: }
! 325: } else if ( h1 == h2 ) {
! 326: if ( l1 > l2 ) {
! 327: for ( l1 -= l2; (l1&1) == 0; l1 >>= 1 ) ;
! 328: goto no_hi1n;
! 329: } else {
! 330: for ( l2 -= l1; (l2&1) == 0; l2 >>= 1 ) ;
! 331: goto no_hi2;
! 332: }
! 333: } else if ( h1 > h2 ) {
! 334: h1 -= h2;
! 335: #if BSH == BIT_WIDTH_OF_INT
! 336: if ( l1 < l2 ) l1 -= l2, h1--;
! 337: else l1 -= l2;
! 338: i = 0; do { l1 >>= 1, i++; } while ( (l1&1) == 0 );
! 339: l1 |= (h1 << (BSH - i));
! 340: #else
! 341: if ( (l1 -= l2) < 0 ) h1--, l1 += BASE;
! 342: i = 0; do { l1 >>= 1, i++; } while ( (l1&1) == 0 );
! 343: l1 |= ((h1 << (BSH - i)) & BMASK);
! 344: #endif
! 345: h1 >>= i;
! 346: } else {
! 347: h2 -= h1;
! 348: #if BSH == BIT_WIDTH_OF_INT
! 349: if ( l2 < l1 ) l2 -= l1, h2--;
! 350: else l2 -= l1;
! 351: i = 0; do { l2 >>= 1, i++; } while ( (l2&1) == 0 );
! 352: l2 |= (h2 << (BSH - i));
! 353: #else
! 354: if ( (l2 -= l1) < 0 ) h2--, l2 += BASE;
! 355: i = 0; do { l2 >>= 1, i++; } while ( (l2&1) == 0 );
! 356: l2 |= ((h2 << (BSH - i)) & BMASK);
! 357: #endif
! 358: h2 >>= i;
! 359: }
! 360: goto loop;
1.1 murao 361: one_word:
1.4 ! noro 362: if ( l1 == 1 || l2 == 1 ) return 0;
! 363: else if ( l1 == l2 ) {
! 364: pans[0] = l1;
! 365: return 1;
! 366: }
1.1 murao 367: one_word_neq:
1.4 ! noro 368: if ( l1 > l2 ) {
! 369: l1 -= l2;
! 370: do { l1 >>= 1; } while ( (l1&1) == 0 );
! 371: goto one_word;
! 372: } else {
! 373: l2 -= l1;
! 374: do { l2 >>= 1; } while ( (l2&1) == 0 );
! 375: goto one_word;
! 376: }
1.1 murao 377: }
378:
379: static N igcd_binary( n1, n2, nt )
380: N n1, n2, nt;
1.4 ! noro 381: /* both n1 and n2 are assumed to be odd */
1.1 murao 382: {
1.4 ! noro 383: int l1, *b1, l2, *b2, *bt = BD(nt);
! 384: int l;
1.1 murao 385:
1.4 ! noro 386: if ( (l = cmpn( n1, n2 )) == 0 ) return n1;
! 387: else if ( l < 0 ) { SWAP( n1, n2, N ); }
! 388: IniDiv( n1, n2 );
! 389: if ( UNIN(n2) ) return 0;
! 390: l1 = PL(n1), b1 = BD(n1), l2 = PL(n2), b2 = BD(n2);
1.1 murao 391: loop:
392: #if 0000
393: {
394: int i, b, w;
395:
396: printf( "===============\n" );
397: for ( i = 0; i < l1; i++ ) printf( "0x%08x ", b1[i] );
398: printf( "\n" );
399: for ( i = 0; i < l2; i++ ) printf( "0x%08x ", b2[i] );
400: printf( "\n" );
401: }
402: #endif
1.4 ! noro 403: if ( l1 <= 2 && l2 <= 2 ) {
! 404: l = igcd_binary_2w( b1, l1, b2, l2, bt );
! 405: if ( l == 0 ) return 0;
! 406: PL(nt) = l;
! 407: return nt;
! 408: }
! 409: /**/
! 410: l = abs_U_V_maxrshift( b1, l1, b2, l2, bt );
! 411: /**/
! 412: if ( l == 0 ) {
! 413: PL(n1) = l1;
! 414: return n1;
! 415: } else if ( l > 0 ) {
! 416: l1 = l;
! 417: SWAP( b1, bt, int * ); SWAP( n1, nt, N );
! 418: } else {
! 419: l2 = -l;
! 420: SWAP( b2, bt, int * ); SWAP( n2, nt, N );
! 421: }
! 422: goto loop;
1.1 murao 423: }
424:
425: #define RetTrueGCD(p,gw,gb,nr,l0) \
426: if (p==0) { l0: if (gw==0&&gb==0) { *(nr)=ONEN; return; } else p=ONEN; } \
427: *(nr) = N_of_n_lshifted_by_wb(p,gw,gb); \
428: return;
429:
430: void gcdbinn( n1, n2, nr )
431: N n1, n2, *nr;
432: {
1.4 ! noro 433: int s1, s2, gw, gb, t1, t2;
! 434: int w1, w2;
! 435: N tn1, tn2, tnt, p;
! 436:
! 437: if ( !n1 ) {
! 438: *nr = n2;
! 439: return;
! 440: } else if ( !n2 ) {
! 441: *nr = n1;
! 442: return;
! 443: }
! 444: s1 = trailingzerosn( n1, &w1 );
! 445: s2 = trailingzerosn( n2, &w2 );
! 446: if ( w1 == w2 ) gw = w1, gb = s1 <= s2 ? s1 : s2;
! 447: else if ( w1 < w2 ) gw = w1, gb = s1;
! 448: else gw = w2, gb = s2;
! 449: /*
! 450: * true GCD must be multiplied by 2^{gw*BSH+gb}.
! 451: */
! 452: t1 = PL(n1) - w1;
! 453: t2 = PL(n2) - w2;
! 454: if ( t1 < t2 ) t1 = t2;
! 455: tn1 = W_NALLOC(t1); tn2 = W_NALLOC(t1); tnt = W_NALLOC(t1);
! 456: rshiftn( n1, w1, s1, tn1 );
! 457: rshiftn( n2, w2, s2, tn2 );
! 458: p = igcd_binary( tn1, tn2, tnt );
! 459: RetTrueGCD( p, gw, gb, nr, L0 )
1.1 murao 460: }
461:
462:
463: /*
1.4 ! noro 464: * The bmod gcd algorithm stated briefly in K.Weber's paper
! 465: * [ACM TOMS, Vol.21, No. 1 (1995), pp. 111-122].
! 466: * It replaces the subtraction (n1 - n2) in the binary algorithm
! 467: * by (n1 - S*n2) with such an S that (n1 - S*n2) \equiv 0 \bmod 2^BSH,
! 468: * which should improve the efficiency when n1 \gg n2.
1.1 murao 469: */
470:
471: /* subsidiary routines */
472: #if BSH == BIT_WIDTH_OF_INT
473: #ifdef CALL
474: static int u_div_v_mod_2toBSH( u, v )
475: unsigned int u, v;
1.4 ! noro 476: /*
! 477: * u/v mod 2^BSH.
! 478: */
! 479: {
! 480: unsigned int i, lsh_i, m;
! 481:
! 482: lsh_i = (sizeof(int) << 3) - 1;
! 483: m = i = 0;
! 484: do {
! 485: if ( u == 0 ) break;
! 486: if ( (u << lsh_i) != 0 ) {
! 487: m += (1 << i);
! 488: u -= (v << i);
! 489: }
! 490: lsh_i--;
! 491: } while ( ++i != BSH );
! 492: return m;
1.1 murao 493: }
494:
495: #define Comp_U_div_V_mod_BASE(U,V,R) R = u_div_v_mod_2toBSH(U,V)
496: #else /* CALL */
497: #define Comp_U_div_V_mod_BASE(U,V,R) {\
1.4 ! noro 498: unsigned int u = (U), v = (V), i, lsh; \
! 499: /* U and V are assumed to be odd */ \
! 500: i = R = 1, lsh = (sizeof(int) << 3) - 2; u = (u - v); \
! 501: do { if ( u == 0 ) break; \
! 502: if ( (u << lsh) != 0 ) R += (1 << i), u = (u - (v << i)); \
! 503: i++, lsh--; \
! 504: } while ( i < BSH ); \
1.1 murao 505: }
506: #endif /* CALL */
507: #else
508: #ifdef CALL
509: static int u_div_v_mod_2tos( u, v, s )
510: int u, v, s;
1.4 ! noro 511: /*
! 512: * u/v mod 2^s.
! 513: */
! 514: {
! 515: int i, lsh_i, mask, m;
! 516:
! 517: mask = (1 << s) - 1;
! 518: lsh_i = (sizeof(int) << 3) - 1;
! 519: m = i = 0;
! 520: u &= mask, v &= mask;
! 521: do {
! 522: if ( u == 0 ) break;
! 523: if ( (u << lsh_i) != 0 ) {
! 524: m += (1 << i);
! 525: u -= (v << i);
! 526: u &= mask;
! 527: }
! 528: lsh_i--;
! 529: } while ( ++i != s );
! 530: return m;
1.1 murao 531: }
532:
533: #define Comp_U_div_V_mod_BASE(U,V,R) R = u_div_v_mod_2tos(U,V,BSH)
534: #else
535: #define Comp_U_div_V_mod_BASE(U,V,R) {\
1.4 ! noro 536: int u = (U), v = (V), i, lsh; \
! 537: /* U and V are assumed to be odd */ \
! 538: i = R = 1, lsh = (sizeof(int) << 3) - 2; u = (u - v) & BMASK; \
! 539: do { if ( u == 0 ) break; \
! 540: if ( (u << lsh) != 0 ) R += (1 << i), u = (u - (v << i)) & BMASK; \
! 541: i++, lsh--; \
! 542: } while ( i < BSH ); \
1.1 murao 543: }
544: #endif
545: #endif
546:
547:
548: static int bmod_n( nu, nv, na )
549: N nu, nv, na;
1.4 ! noro 550: /*
! 551: * Computes (u[] \bmod v[]) >> (as much as possible) in r[].
! 552: */
! 553: {
! 554: #if BSH == BIT_WIDTH_OF_INT
! 555: unsigned int *u = BD(nu), *v = BD(nv), *r = BD(na);
! 556: unsigned int *p, a, t, l, v0, vh, bv, v0r;
! 557: int lu = PL(nu), lv = PL(nv), z;
! 558: #else
! 559: int *u = BD(nu), lu = PL(nu), *v = BD(nv), lv = PL(nv),
! 560: *r = BD(na);
! 561: int *p, a, t, l, z, v0, vh, bv, v0r;
! 562: #endif
! 563:
! 564: v0 = v[0];
! 565: if ( lv == 1 ) {
! 566: if ( lu == 1 ) a = u[0] % v0;
! 567: else {
! 568: p = &u[--lu];
! 569: #if BSH == BIT_WIDTH_OF_INT
! 570: a = (*p) % v0, t = (unsigned)(-((int)v0)) % v0;
! 571: #else
! 572: a = (*p) % v0, t = BASE % v0;
! 573: #endif
! 574: for ( ; --lu >= 0; a = l ) {
! 575: --p;
! 576: DMAR(a,t,*p,v0,l);
! 577: /* l <= (a*t + p[0])%v0 */
! 578: }
! 579: }
! 580: if ( a == 0 ) return 0;
! 581: while ( (a&1) == 0 ) a >>= 1;
! 582: *r = a;
! 583: return( PL(na) = 1 );
! 584: }
! 585: Comp_U_div_V_mod_BASE( 1, v0, v0r );
! 586: vh = v[lv -1];
! 587: BitWidth( vh, bv );
! 588: bv--;
! 589: t = 1 << bv;
! 590: l = lv + 1;
! 591: for ( z = -1; lu > l || lu == l && u[lu-1] >= t; z = -z ) {
1.1 murao 592: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 593: a = (v0r*u[0]);
1.1 murao 594: #else
1.4 ! noro 595: a = (v0r*u[0])&BMASK;
1.1 murao 596: #endif
1.4 ! noro 597: /**/
1.1 murao 598: #if 0000
599: {
600: int i;
601: for ( i = 0; i < lu; i++ ) printf( "0x%08x ", u[i] );
602: printf( "\n- a=0x%08x, %u*\n", a, a );
603: for ( i = 0; i < lv; i++ ) printf( "0x%08x ", v[i] );
604: printf( "\n=>\n" );
605: }
606: #endif
1.4 ! noro 607: lu = abs_U_aV_maxrshift( u, lu, a, v, lv, r );
! 608: /**/
1.1 murao 609: #if 0000
610: printf( "***lu=%d\n", lu );
611: if ( lu != 0 ) {
612: int i;
613: for ( i = 0; i < lu; i++ ) printf( "0x%08x ", r[i] );
614: printf( "\n" );
615: }
616: #endif
1.4 ! noro 617: if ( lu == 0 ) return 0;
! 618: p = r;
! 619: r = u;
! 620: u = p;
! 621: }
! 622: if ( lu < lv ) goto ret;
! 623: t = u[lu-1];
! 624: if ( lu > lv ) l = BSH;
! 625: else if ( t < vh ) goto ret;
! 626: else l = 0;
! 627: BitWidth( t, a );
! 628: l += (a - bv);
1.1 murao 629: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 630: a = (v0r*u[0])&((unsigned)(-1) >> (BSH - l));
1.1 murao 631: #else
1.4 ! noro 632: a = (v0r*u[0])&(BMASK >> (BSH - l));
1.1 murao 633: #endif
634: #if 0000
635: {
636: int i;
637: for ( i = 0; i < lu; i++ ) printf( "0x%08x ", u[i] );
638: printf( "\n - a=0x%08x, %u*\n", a, a );
639: for ( i = 0; i < lv; i++ ) printf( "0x%08x ", v[i] );
640: printf( "\n =>\n" );
641: }
642: #endif
1.4 ! noro 643: /**/
! 644: lu = abs_U_aV_maxrshift( u, lu, a, v, lv, r );
! 645: /**/
1.1 murao 646: #if 0000
647: printf( "::: lu=%d\n", lu );
648: if ( lu != 0 ) {
649: int i;
650: for ( i = 0; i < lu; i++ ) printf( "0x%08x ", r[i] );
651: printf( "\n" );
652: }
653: #endif
1.4 ! noro 654: if ( lu == 0 ) return 0;
! 655: z = -z;
! 656: ret: if ( z > 0 ) return( PL(na) = lu );
! 657: PL(nu) = lu;
! 658: return( -lu );
1.1 murao 659: }
660:
661:
662: static N igcd_bmod( n1, n2, nt )
663: N n1, n2, nt;
1.4 ! noro 664: /* both n1 and n2 are assumed to be odd */
1.1 murao 665: {
1.4 ! noro 666: int l1, l2;
! 667: int l;
1.1 murao 668:
1.4 ! noro 669: if ( (l = cmpn( n1, n2 )) == 0 ) return n1;
! 670: else if ( l < 0 ) { SWAP( n1, n2, N ); }
! 671: IniDiv( n1, n2 );
! 672: if ( UNIN(n2) ) return 0;
! 673: loop: if ( (l1 = PL(n1)) <= 2 && (l2 = PL(n2)) <= 2 ) {
! 674: l = igcd_binary_2w( BD(n1), l1, BD(n2), l2, BD(nt) );
! 675: if ( l == 0 ) return 0;
! 676: PL(nt) = l;
! 677: return nt;
! 678: }
! 679: /**/
! 680: l = bmod_n( n1, n2, nt );
! 681: /**/
! 682: if ( l == 0 ) return n2;
! 683: else if ( l > 0 ) {
! 684: N tmp = n1;
! 685:
! 686: n1 = n2;
! 687: n2 = nt;
! 688: nt = tmp;
! 689: } else SWAP( n1, n2, N );
! 690: goto loop;
1.1 murao 691: }
692:
693: void gcdbmodn( n1, n2, nr )
694: N n1, n2, *nr;
695: {
1.4 ! noro 696: int s1, s2, gw, gb, t1, t2;
! 697: int w1, w2;
! 698: N tn1, tn2, tnt, p;
! 699:
! 700: if ( !n1 ) {
! 701: *nr = n2;
! 702: return;
! 703: } else if ( !n2 ) {
! 704: *nr = n1;
! 705: return;
! 706: }
! 707: s1 = trailingzerosn( n1, &w1 );
! 708: s2 = trailingzerosn( n2, &w2 );
! 709: if ( w1 == w2 ) gw = w1, gb = s1 <= s2 ? s1 : s2;
! 710: else if ( w1 < w2 ) gw = w1, gb = s1;
! 711: else gw = w2, gb = s2;
! 712: /*
! 713: * true GCD must be multiplied by 2^{gw*BSH+gs}.
! 714: */
! 715: t1 = PL(n1) - w1;
! 716: t2 = PL(n2) - w2;
! 717: if ( t1 < t2 ) t1 = t2;
! 718: tn1 = W_NALLOC(t1); tn2 = W_NALLOC(t1); tnt = W_NALLOC(t1);
! 719: rshiftn( n1, w1, s1, tn1 );
! 720: rshiftn( n2, w2, s2, tn2 );
! 721: p = igcd_bmod( tn1, tn2, tnt );
! 722: RetTrueGCD( p, gw, gb, nr, L0 )
1.1 murao 723: }
724:
725: /*
1.4 ! noro 726: * The accelerated integer GCD algorithm by K.Weber
! 727: * [ACM TOMS, Vol.21, No. 1 (1995), pp. 111-122]:
1.1 murao 728: */
729:
730: static int ReducedRatMod( x, y, pn, pd )
731: N x, y;
732: #if BSH == BIT_WIDTH_OF_INT
733: unsigned
734: #endif
735: int *pn, *pd;
1.4 ! noro 736: /*
! 737: * Let m = 2^{2*BSH} = 2*BASE. We assume x, y > 0 and \gcd(x,m)
! 738: * = \gcd(y,m) = 1. This routine computes n and d (resp. returned
! 739: * in *pn and *pd) such that 0 < n, |d| < \sqrt{m} and
! 740: * n*y \equiv x*d \bmod m.
! 741: */
1.1 murao 742: {
743: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 744: unsigned int n1h, n1l, d1h, d1l, n2h, n2l, d2h, d2l;
! 745: unsigned int th, tl, l1, l2, i, ir;
! 746: int s1, s2;
1.1 murao 747: #else
1.4 ! noro 748: int n1h, n1l, d1h, d1l, n2h, n2l, d2h, d2l;
! 749: int th, tl, l1, l2, i, ir;
! 750: int s1, s2;
1.1 murao 751: #endif
752:
1.4 ! noro 753: {
1.1 murao 754: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 755: unsigned
1.1 murao 756: #endif
1.4 ! noro 757: int xh, xl, yh, yl, lsh_i;
1.1 murao 758:
1.4 ! noro 759: xl = BD(x)[0];
! 760: xh = PL(x) > 1 ? BD(x)[1] : 0;
! 761: yl = BD(y)[0];
! 762: yh = PL(y) > 1 ? BD(y)[1] : 0;
1.1 murao 763: #if 0000
764: printf( "*** RedRatMod: (0x%08x:0x%08x=%u*2^%d+%u)\n /(0x%08x:0x%08x=%u*2^%d+%u) mod 2^%d\n",
765: xh,xl, xh,BSH,xl, yh,yl, yh,BSH,yl, BSH );
766: #endif
1.4 ! noro 767: Comp_U_div_V_mod_BASE( xl, yl, n2l );
! 768: DM(n2l,yl,th,tl) /* n2l*yl = tl+th*BASE, where tl==xl. */;
1.1 murao 769: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 770: xh -= th;
1.1 murao 771: #else
1.4 ! noro 772: if ( xh > th ) xh -= th;
! 773: else xh += (BASE - th);
1.1 murao 774: #endif
1.4 ! noro 775: DM(n2l,yh,th,tl) /* n2l*yh = tl+th*BASE. */;
! 776: #if BSH == BIT_WIDTH_OF_INT
! 777: xh -= tl;
! 778: #else
! 779: if ( xh > tl ) xh -= tl;
! 780: else xh += (BASE - tl);
! 781: #endif
! 782: /* n2h = i = 0, lsh_i = 31;*/
! 783: n2h = i = 0, lsh_i = BIT_WIDTH_OF_INT -1;
! 784: do {
! 785: if ( xh == 0 ) break;
! 786: if ( (xh << lsh_i) != 0 ) {
! 787: n2h += (1 << i);
! 788: #if BSH == BIT_WIDTH_OF_INT
! 789: tl = yl << i;
! 790: xh -= tl;
! 791: #else
! 792: tl = (yl << i)&BMASK;
! 793: if ( xh > tl ) xh -= tl;
! 794: else xh += (BASE - tl);
! 795: #endif
! 796: }
! 797: lsh_i--;
! 798: } while ( ++i != BSH );
! 799: }
! 800: /*
! 801: * n2l + n2h*BASE = x/y mod 2^{2*BSH}.
! 802: */
1.1 murao 803: #if 0000
804: printf( "=====> 0x%08x(%u) + 2^%d*0x%08x(%u)\n", n2l, n2l, BSH, n2h, n2h );
805: #endif
1.4 ! noro 806: d2h = 0, d2l = 1, s2 = 1;
1.1 murao 807: #if BSH == BIT_WIDTH_OF_INT
1.4 ! noro 808: if ( n2h == 0 ) goto done;
! 809: BitWidth( n2h, l2 );
! 810: if ( l2 == BSH ) {
! 811: d1h = 0, d1l = 1, s1 = -1;
! 812: th = n2h, tl = n2l;
! 813: } else {
! 814: i = BSH - l2;
! 815: d1h = 0, d1l = 1 << i, s1 = -1;
! 816: th = (n2h << i) | (n2l >> l2);
! 817: tl = n2l << i;
! 818: }
! 819: if ( tl == 0 ) n1h = - th, n1l = 0;
! 820: else n1h = BMASK - th, n1l = - tl;
! 821: /**/
! 822: if ( n1h < n2h || (n1h == n2h && n1l < n2l) ) goto swap12;
! 823: BitWidth( n1h, l1 );
! 824: goto sub12;
! 825: #else
! 826: n1h = BASE, n1l = 0, l1 = BSH,
! 827: d1h = d1l = 0, s1 = 0;
! 828: #endif
! 829: /**/
! 830: while ( n2h != 0 ) {
! 831: BitWidth( n2h, l2 );
! 832: sub12: ir = BSH - (i = l1 - l2);
! 833: do {
! 834: if ( i == 0 ) th = n2h, tl = n2l;
! 835: else
! 836: th = (n2h << i) | (n2l >> ir),
! 837: #if BSH == BIT_WIDTH_OF_INT
! 838: tl = n2l << i;
! 839: #else
! 840: tl = (n2l << i) & BMASK;
! 841: #endif
! 842: if ( th > n1h || (th == n1h && tl > n1l) ) goto next_i;
! 843: #if BSH == BIT_WIDTH_OF_INT
! 844: if ( tl > n1l ) n1h--;
! 845: n1l -= tl;
! 846: #else
! 847: if ( tl <= n1l ) n1l -= tl;
! 848: else n1l += (BASE - tl), n1h--;
! 849: #endif
! 850: n1h -= th;
! 851: /* (s1:d1h,d1l) -= ((s2:d2h,d2l) << i); */
! 852: if ( s2 != 0 ) {
! 853: if ( i == 0 ) th = d2h, tl = d2l;
! 854: else
! 855: #if BSH == BIT_WIDTH_OF_INT
! 856: th = (d2h << i) | (d2l >> ir),
! 857: tl = (d2l << i);
! 858: #else
! 859: th = (d2h << i)&BMASK | (d2l >> ir),
! 860: tl = (d2l << i)&BMASK;
! 861: #endif
! 862: if ( s1 == 0 )
! 863: s1 = -s2, d1h = th, d1l = tl;
! 864: else if ( s1 != s2 ) {
! 865: #if BSH == BIT_WIDTH_OF_INT
! 866: d1l += tl,
! 867: d1h += th;
! 868: if ( d1l < tl ) d1h++;
! 869: #else
! 870: tl += d1l;
! 871: d1l = tl&BMASK;
! 872: d1h = (d1h + th + (tl >> BSH))&BMASK;
! 873: #endif
! 874: if ( d1h == 0 && d1l == 0 ) s1 = 0;
! 875: } else if ( d1h > th ) {
! 876: #if BSH == BIT_WIDTH_OF_INT
! 877: if ( d1l < tl ) d1h--;
! 878: d1l -= tl;
! 879: #else
! 880: if ( d1l >= tl ) d1l -= tl;
! 881: else d1l += (BASE - tl), d1h--;
! 882: #endif
! 883: d1h -= th;
! 884: } else if ( d1h == th ) {
! 885: d1h = 0;
! 886: if ( d1l == tl ) s1 = d2h = 0;
! 887: else if ( d1l > tl ) d1l -= tl;
! 888: else d1l = tl - d1l, s1 = -s1;
! 889: } else {
! 890: #if BSH == BIT_WIDTH_OF_INT
! 891: if ( tl < d1l ) th--;
! 892: d1l = tl - d1l;
! 893: #else
! 894: if ( tl >= d1l ) d1l = tl - d1l;
! 895: else d1l = tl + (BASE - d1l), th--;
! 896: #endif
! 897: d1h = th - d1h;
! 898: s1 = -s1;
! 899: }
! 900: }
! 901: next_i: i--, ir++;
! 902: } while ( n1h > n2h || (n1h == n2h && n1l >= n2l) );
! 903: swap12: /* swap 1 and 2 */
! 904: th = n1h, tl = n1l;
! 905: n1h = n2h, n1l = n2l;
! 906: n2h = th, n2l = tl;
! 907: l1 = l2;
! 908: th = d1h, tl = d1l, i = s1;
! 909: d1h = d2h, d1l = d2l, s1 = s2;
! 910: d2h = th, d2l = tl, s2 = i;
! 911: }
! 912: /**/
! 913: done: *pn = n2l, *pd = d2l;
! 914: return s2;
1.1 murao 915: }
916:
917: static int igcd_spurious_factor;
918:
919: #define SaveN(s,d) {\
1.4 ! noro 920: int i, l; \
! 921: for ( l = PL(d) = PL(s), i = 0; i < l; i++ ) BD(d)[i] = BD(s)[i]; \
1.1 murao 922: }
923:
924: static N igcd_acc( n1, n2, nt )
925: N n1, n2, nt;
1.4 ! noro 926: /* both n1 and n2 are assumed to be odd */
1.1 murao 927: {
1.4 ! noro 928: int l1, l2, *b1, *b2, bw1, bw2;
! 929: int l;
! 930: int n, d;
! 931: N p, s1, s2;
! 932:
! 933: if ( (l = cmpn( n1, n2 )) == 0 ) return n1;
! 934: else if ( l < 0 ) { SWAP( n1, n2, N ); }
! 935: if ( ShouldCompRemInit(n1,n2) ) {
! 936: int w, b;
! 937:
! 938: divn( n1, n2, &s1, &s2 );
! 939: if ( !s2 ) return n2;
! 940: b = trailingzerosn( s2, &w );
! 941: p = n1; n1 = n2; n2 = p;
! 942: rshiftn( s2, w, b, n2 );
! 943: if ( UNIN(n2) ) return 0;
! 944: l1 = PL(n1);
! 945: if ( !s1 || PL(s1) < l1 ) s1 = NALLOC(l1);
! 946: } else if ( UNIN(n2) ) return 0;
! 947: else {
! 948: s1 = NALLOC(PL(n1));
! 949: s2 = NALLOC(PL(n2));
! 950: }
! 951: SaveN( n1, s1 );
! 952: SaveN( n2, s2 );
! 953: igcd_spurious_factor = 0;
! 954: loop: l1 = PL(n1), l2 = PL(n2);
! 955: if ( l1 <= 2 && l2 <= 2 ) {
! 956: l = igcd_binary_2w( BD(n1), l1, BD(n2), l2, BD(nt) );
! 957: if ( l == 0 ) return 0;
! 958: PL(nt) = l;
! 959: SWAP( n2, nt, N );
! 960: goto ret;
! 961: }
! 962: /**/
! 963: b1 = BD(n1), b2 = BD(n2);
! 964: BitWidth( b1[l1 -1], bw1 );
! 965: BitWidth( b2[l2 -1], bw2 );
! 966: if ( (l1*BSH + bw1) - (l2*BSH + bw2) <= igcdacc_thre ) {
! 967: l = ReducedRatMod( n1, n2, &n, &d );
! 968: l = l < 0 ? aUplusbV_maxrshift( n, b2, l2, d, b1, l1, BD(nt) ) :
! 969: abs_axU_bxV_maxrshift( n, b2, l2, d, b1, l1, BD(nt) );
! 970: igcd_spurious_factor++;
! 971: if ( l == 0 ) goto ret;
! 972: PL(nt) = l;
! 973: } else {
! 974: l = bmod_n( n1, n2, nt );
! 975: if ( l == 0 ) goto ret;
! 976: else if ( l < 0 ) {
! 977: SWAP( n1, n2, N );
! 978: goto loop;
! 979: }
! 980: }
! 981: p = n1;
! 982: n1 = n2;
! 983: n2 = nt;
! 984: nt = p;
! 985: goto loop;
! 986: /**/
! 987: ret: if ( igcd_spurious_factor != 0 && !UNIN(n2) ) {
! 988: if ( (p = igcd_bmod( n2, s1, n1 )) == 0 ) return 0;
! 989: if ( (p = igcd_bmod( p, s2, nt )) == 0 ) return 0;
! 990: return p;
! 991: } else return n2;
1.1 murao 992: }
993:
994: void gcdaccn( n1, n2, nr )
995: N n1, n2, *nr;
996: {
1.4 ! noro 997: int s1, s2, gw, gb, t1, t2;
! 998: int w1, w2;
! 999: N tn1, tn2, tnt, p;
! 1000:
! 1001: if ( !n1 ) {
! 1002: *nr = n2;
! 1003: return;
! 1004: } else if ( !n2 ) {
! 1005: *nr = n1;
! 1006: return;
! 1007: }
! 1008: s1 = trailingzerosn( n1, &w1 );
! 1009: s2 = trailingzerosn( n2, &w2 );
! 1010: if ( w1 == w2 ) gw = w1, gb = s1 <= s2 ? s1 : s2;
! 1011: else if ( w1 < w2 ) gw = w1, gb = s1;
! 1012: else gw = w2, gb = s2;
! 1013: /*
! 1014: * true GCD must be multiplied by 2^{gw*BSH+gs}.
! 1015: */
! 1016: t1 = PL(n1) - w1;
! 1017: t2 = PL(n2) - w2;
! 1018: if ( t1 < t2 ) t1 = t2;
! 1019: tn1 = W_NALLOC(t1); tn2 = W_NALLOC(t1); tnt = W_NALLOC(t1);
! 1020: rshiftn( n1, w1, s1, tn1 );
! 1021: rshiftn( n2, w2, s2, tn2 );
! 1022: /**/
! 1023: p = igcd_acc( tn1, tn2, tnt );
! 1024: /**/
! 1025: if ( p == 0 ) goto L0;
! 1026: RetTrueGCD( p, gw, gb, nr, L0 )
1.1 murao 1027: }
1028:
1029:
1030: /********************************/
1031:
1032: void gcdn_HMEXT( n1, n2, nr )
1033: N n1, n2, *nr;
1034: {
1.4 ! noro 1035: int b1, b2, w1, w2, gw, gb;
! 1036: int l1, l2;
! 1037: N tn1, tn2, tnt, a;
! 1038:
! 1039: if ( !n1 ) {
! 1040: *nr = n2; return;
! 1041: } else if ( !n2 ) {
! 1042: *nr = n1; return;
! 1043: }
! 1044: b1 = trailingzerosn( n1, &w1 );
! 1045: b2 = trailingzerosn( n2, &w2 );
! 1046: if ( w1 == w2 ) gw = w1, gb = b1 <= b2 ? b1 : b2;
! 1047: else if ( w1 < w2 ) gw = w1, gb = b1;
! 1048: else gw = w2, gb = b2;
! 1049: /*
! 1050: * true GCD must be multiplied by 2^{gw*BSH+gb}.
! 1051: */
! 1052: l1 = PL(n1) - w1;
! 1053: l2 = PL(n2) - w2;
! 1054: if ( l1 < l2 ) l1 = l2;
! 1055: tn1 = W_NALLOC( l1 ); tn2 = W_NALLOC( l1 ); tnt = W_NALLOC( l1 );
! 1056: rshiftn( n1, w1, b1, tn1 );
! 1057: rshiftn( n2, w2, b2, tn2 );
! 1058: /**/
! 1059: if ( igcd_algorithm == 1 ) {
! 1060: a = igcd_binary( tn1, tn2, tnt );
! 1061: } else if ( igcd_algorithm == 2 ) {
! 1062: a = igcd_bmod( tn1, tn2, tnt );
! 1063: } else {
! 1064: a = igcd_acc( tn1, tn2, tnt );
! 1065: if ( igcd_spurious_factor != 0 ) {
! 1066: }
! 1067: }
! 1068: RetTrueGCD( a, gw, gb, nr, L0 )
1.1 murao 1069: }
1070:
1071:
1072: /**************************/
1073: #if 111
1074: N maxrshn( n, p )
1075: N n;
1076: int *p;
1077: {
1.4 ! noro 1078: int nw, nb, c, l;
! 1079: N new;
1.1 murao 1080:
1.4 ! noro 1081: nb = trailingzerosn( n, &nw );
! 1082: l = PL(n);
! 1083: c = BD(n)[l -1];
! 1084: l -= nw;
! 1085: if ( (c >> nb) == 0 ) l--;
! 1086: new = NALLOC(l);
! 1087: rshiftn( n, nw, nb, new );
! 1088: *p = nb + nw*BSH;
! 1089: return new;
1.1 murao 1090: }
1091: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>