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