Annotation of OpenXM_contrib2/asir2000/engine/igcdhack.c, Revision 1.1
1.1 ! noro 1: /* $OpenXM: OpenXM/src/asir99/engine/igcdhack.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
! 2: #if 0
! 3: #include "base.h"
! 4:
! 5: #define SWAP(a,b,Type) { Type temp=a; a = b; b = temp; }
! 6: #define SIGNED_VAL(a,s) ((s)>0?(a): -(a))
! 7: #endif
! 8:
! 9: #undef FULLSET
! 10:
! 11:
! 12: static int negate_nbd( b, l )
! 13: int *b, l;
! 14: /* It is assumed that l > 0 and b[0] != 0 */
! 15: {
! 16: int i, nz;
! 17:
! 18: *b = BASE - *b;
! 19: for ( nz = i = 1 ; i < l; ) {
! 20: b++, i++;
! 21: if ( (*b ^= BMASK) != 0 ) nz = i;
! 22: }
! 23: return nz;
! 24: }
! 25:
! 26: /****************/
! 27: /****************/
! 28:
! 29: static int abs_U_V_maxrshift( u, lu, v, lv, a )
! 30: int *u, lu, *v, lv, *a;
! 31: /*
! 32: * Compute | U - V | >> (as much as possible) in a[], where U = u[0:lu-1]
! 33: * and V = v[0:lv-1]. Value returned is the length of the result
! 34: * multiplied by the sign of (U-V).
! 35: */
! 36: {
! 37: int sign, rsh, t, b, i, i_1, l, *p = a;
! 38:
! 39: /* first, determine U <, ==, > V */
! 40: sign = 1;
! 41: if ( lu == lv ) {
! 42: int i;
! 43:
! 44: for ( i = lu -1; i >= 0; i-- ) {
! 45: if ( u[i] == v[i] ) continue;
! 46: lu = lv = i + 1;
! 47: if ( u[i] > v[i] ) goto U_V;
! 48: else goto swap;
! 49: }
! 50: return 0;
! 51: } else if ( lu > lv ) goto U_V;
! 52: swap:
! 53: SWAP( lu, lv, int ); SWAP( u, v, int * );
! 54: sign = -1;
! 55: U_V: /* U > V, i.e., (lu > lv) || (lu == lv && u[lu-1] > v[lv-1]) */
! 56: for ( i = 0; i < lv; i++ ) if ( u[i] != v[i] ) break;
! 57: if ( i != 0 ) u += i, lu -= i, v += i, lv -= i;
! 58: if ( lv == 0 ) { /* no more pv[], and lu > 0 */
! 59: i = trailingzeros_nbd( u, &rsh );
! 60: i = rshift_nbd( u, lu, rsh, i, a );
! 61: return SIGNED_VAL( i, sign );
! 62: }
! 63: /**/
! 64: if ( (t = u[0] - v[0]) >= 0 ) b = 0;
! 65: else b = 1, t += BASE;
! 66: TRAILINGZEROS( t, rsh );
! 67: /**/
! 68: if ( rsh != 0 ) {
! 69: int w, lsh = BSH - rsh;
! 70:
! 71: /* subtract v[*] from u[*] */
! 72: for ( i = 1, l = 0; i < lv; i++, t = w >> rsh ) {
! 73: if ( (w = u[i] - v[i] - b) >= 0 ) b = 0;
! 74: else b = 1, w += BASE;
! 75: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
! 76: }
! 77: /* subtraction of V completed. Note there may exist non-0 borrow b */
! 78: if ( i >= lu ) /* lu == lv, and b==0 is implied */ goto chk_nz;
! 79: /* we still have (lu-i) elms in U */
! 80: if ( b != 0 ) { /* non-zero borrow */
! 81: if ( (w = u[i++] -1) != 0 ) t |= ((w << lsh) & BMASK);
! 82: if ( i >= lu ) { /* lu == lv+1. The M.S. word w may beome 0 */
! 83: if ( w != 0 ) {
! 84: *p++ = t;
! 85: l = lv;
! 86: t = w >> rsh;
! 87: } else lu--;
! 88: goto chk_nz;
! 89: }
! 90: *p++ = t;
! 91: if ( w < 0 ) {
! 92: while ( (w = u[i++]) == 0 ) *p++ = BMASK;
! 93: w -= 1;
! 94: *p++ = (BMASK >> rsh) | ((w << lsh) & BMASK);
! 95: }
! 96: t = w >> rsh;
! 97: }
! 98: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
! 99: l = i -1;
! 100: chk_nz:
! 101: if ( t != 0 ) *p = t, l = /*1 + (p - a)*/ lu;
! 102: goto ret_nz;
! 103: }
! 104: /* rsh == 0 : need not be right-shifted */
! 105: *p++ = t, l = 1;
! 106: for ( i = 1; i < lv; ) {
! 107: if ( (t = u[i] - v[i] - b) >= 0 ) b = 0;
! 108: else b = 1, t += BASE;
! 109: i++;
! 110: if ( (*p++ = t) != 0 ) l = i;
! 111: }
! 112: if ( i >= lu ) /* lu == lv, and b==0 is implied */ goto ret_nz;
! 113: if ( b != 0 ) { /* non-zero borrow */
! 114: t = u[i++] -1;
! 115: if ( i >= lu ) /* lu == lv+1. The M.S. word w may beome 0 */ goto chk_nz;
! 116: if ( t < 0 ) {
! 117: do *p++ = BMASK; while ( (t = u[i++]) == 0 );
! 118: t -= 1;
! 119: if ( i >= lu ) {
! 120: l = lu;
! 121: if ( t == 0 ) l--;
! 122: else *p = t;
! 123: goto ret_nz;
! 124: }
! 125: }
! 126: *p++ = t;
! 127: }
! 128: for ( ; i < lu; i++ ) *p++ = u[i];
! 129: l = lu;
! 130: /**/
! 131: ret_nz:
! 132: return SIGNED_VAL( l, sign );
! 133: }
! 134:
! 135: /****************/
! 136: /****************/
! 137:
! 138: #ifdef CALL
! 139: static int aV_plus_c(), aV_plus_c_sh();
! 140: #endif
! 141: static int abs_U_aV_c(), abs_U_aV_c_sh();
! 142: static int abs_aVplusc_U(), abs_aVplusc_U_sh();
! 143:
! 144: static int abs_U_aV_maxrshift( u, lu, a, v, lv, ans )
! 145: int *u, lu, a, *v, lv, *ans;
! 146: {
! 147: int i, t, c, rsh, l, *p = ans, w, lsh;
! 148: int hi;
! 149:
! 150: if ( a == 1 ) return( (l = abs_U_V_maxrshift( u, lu, v, lv, ans )) >= 0 ? l : -l );
! 151: /**/
! 152: for ( l = lu <= lv ? lu : lv, i = c = 0; i < l; ) {
! 153: DMA( a, v[i], c, hi, t, not_used );
! 154: c = hi;
! 155: if ( (t -= u[i++]) != 0 ) goto non0w;
! 156: }
! 157: /**/
! 158: if ( i < lv ) { /* no more u[] elm.'s, and we still have non-zero v[] elm's */
! 159: do {
! 160: DMA( a, v[i], c, hi, t, not_used );
! 161: i++, c = hi;
! 162: } while ( t == 0 );
! 163: TRAILINGZEROS( t, rsh );
! 164: v += i, lv -= i;
! 165: #ifdef CALL
! 166: if ( rsh == 0 ) {
! 167: *p++ = t;
! 168: return( aV_plus_c( a, v, lv, c, p ) + 1 );
! 169: } else return aV_plus_c_sh( a, v, lv, c, rsh, t, ans );
! 170: #else
! 171: i = 0;
! 172: if ( rsh == 0 ) {
! 173: *p++ = t;
! 174: for ( ; i < lv; i++, c = hi, *p++ = t ) { DMA( a, v[i], c, hi, t, not_used ); }
! 175: if ( c == 0 ) return( i + 1 );
! 176: *p = c;
! 177: return( i + 2 );
! 178: } else {
! 179: for ( lsh = BSH - rsh; i < lv; i++, c = hi, t = w >> rsh ) {
! 180: DMA( a, v[i], c, hi, w, not_used );
! 181: *p++ = t | ((w << lsh) & BMASK);
! 182: }
! 183: if ( c != 0 ) {
! 184: *p++ = t | ((c << lsh) & BMASK);
! 185: i++;
! 186: t = c >> rsh;
! 187: }
! 188: if ( t == 0 ) return i;
! 189: *p = t;
! 190: return( i + 1 );
! 191: }
! 192: #endif
! 193: }
! 194: /* no more v[] elm.'s */
! 195: if ( i >= lu ) {
! 196: if ( c == 0 ) return 0;
! 197: c_sh:
! 198: while ( (c&1) == 0 ) c >>= 1;
! 199: *p = c;
! 200: return 1;
! 201: }
! 202: t = u[i++] - c;
! 203: if ( i >= lu ) {
! 204: if ( t == 0 ) return 0;
! 205: c = t < 0 ? -t : t;
! 206: goto c_sh;
! 207: } else if ( t == 0 ) {
! 208: while ( (t = u[i++]) == 0 ) ;
! 209: c = 0;
! 210: } else if ( t < 0 ) t += BASE, c = 1;
! 211: else c = 0;
! 212: /* diff turned out to be > 0 */
! 213: u += i, lu -= i;
! 214: TRAILINGZEROS( t, rsh );
! 215: i = 0;
! 216: if ( rsh == 0 ) {
! 217: *p++ = t;
! 218: if ( c != 0 ) {
! 219: for ( ; i < lu; *p++ = BMASK ) if ( (t = u[i++]) != 0 ) break;
! 220: t--;
! 221: if ( i >= lu && t == 0 ) return i;
! 222: *p++ = t;
! 223: }
! 224: for ( ; i < lu; i++ ) *p++ = u[i];
! 225: } else { /* rsh != 0 */
! 226: lsh = BSH - rsh;
! 227: if ( c != 0 ) { /* there still exists u[] elms.'s because diff is known to be > 0 */
! 228: if ( (w = u[i++]) == 0 ) {
! 229: *p++ = t | ((BMASK << lsh) & BMASK);
! 230: for ( ; (w = u[i++]) == 0; *p++ = BMASK ) ;
! 231: t = BMASK >> rsh;
! 232: }
! 233: w--;
! 234: *p++ = t | ((w << lsh) & BMASK);
! 235: t = w >> rsh;
! 236: }
! 237: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
! 238: if ( t == 0 ) return( i );
! 239: *p = t;
! 240: }
! 241: return( i + 1 );
! 242: /**/
! 243: non0w:
! 244: u += i, lu -= i, v += i, lv -= i;
! 245: /* | t + BASE*(c + a*v[0:lv-1] - u[0:lu-1] | */
! 246: if ( lv < lu ) { /* a*V < U if lv<lu-1, and very likely if lv==lu-1 */
! 247: t = -t; /* We shall compute U - a*V */
! 248: if ( t < 0 ) t += BASE, c++;
! 249: } else /* a*V > U if lv>lu, and very likely even if lv==lu */
! 250: if ( t < 0 ) t += BASE, c--;
! 251: TRAILINGZEROS( t, rsh );
! 252: return( rsh == 0 ? (lv < lu ? abs_U_aV_c( t, u, lu, a, v, lv, c, ans ) :
! 253: abs_aVplusc_U( t, a, v, lv, c, u, lu, ans )) :
! 254: lv < lu ? abs_U_aV_c_sh( t, u, lu, a, v, lv, c, rsh, ans ) :
! 255: abs_aVplusc_U_sh( t, a, v, lv, c, u, lu, rsh, ans ) );
! 256: }
! 257:
! 258: /*********/
! 259:
! 260: static int aV_plus_c( a, v, lv, c, p )
! 261: int a, *v, lv, c, *p;
! 262: /*
! 263: * Compute (a*V + c) in p[], where V = v[0:lv-1].
! 264: */
! 265: {
! 266: int i, t;
! 267: int hi;
! 268:
! 269: for ( i = 0; i < lv; i++, *p++ = t, c = hi ) { DMA( a, v[i], c, hi, t, not_used); }
! 270: if ( c == 0 ) return i;
! 271: *p = c;
! 272: return( i + 1 );
! 273: }
! 274:
! 275: static int aV_plus_c_sh( a, v, lv, c, rsh, t, p )
! 276: int a, *v, lv, c, rsh, *p;
! 277: /*
! 278: * Compute (t + BASE*((a*V + c) >> rsh)) in p[], where V = v[0:lv-1].
! 279: */
! 280: {
! 281: int i, w, lsh = BSH - rsh;
! 282: int hi;
! 283:
! 284: for ( i = 0; i < lv; i++, c = hi, t = w >> rsh ) {
! 285: DMA( a, v[i], c, hi, w, not_used );
! 286: *p++ = t | ((w << lsh) & BMASK);
! 287: }
! 288: if ( c != 0 ) {
! 289: *p++ = t | ((c << lsh) & BMASK);
! 290: i++;
! 291: t = c >> rsh;
! 292: }
! 293: if ( t == 0 ) return i;
! 294: *p = t;
! 295: return( i + 1 );
! 296: }
! 297:
! 298: /*********/
! 299:
! 300: static int abs_aVplusc_U( t, a, v, lv, c, u, lu, ans )
! 301: int t, a, *v, lv, c, *u, lu, *ans;
! 302: /* compute | t + BASE*(a*V+c - U) | in ans[], where V=v[0:lv-1], U=u[0:lu-1],
! 303: * and a > 1, -1 <= c < BASE, lv >= lu >=0 && t != 0 are assumed.
! 304: */
! 305: {
! 306: int i, l, b, *p = ans;
! 307: int hi;
! 308:
! 309: *p++ = t, l = 1;
! 310: if ( c < 0 ) c = 0, b = 1;
! 311: else b = 0;
! 312: for ( i = 0; i < lu; *p++ = t ) {
! 313: DMA( a, v[i], c, hi, t, not_used );
! 314: t -= u[i++], c = hi;
! 315: if ( b != 0 ) t--;
! 316: b = 0;
! 317: if ( t > 0 ) l = i + 1;
! 318: else if ( t < 0 ) {
! 319: t += BASE, l = i + 1;
! 320: if ( c != 0 ) c--;
! 321: else b = 1;
! 322: }
! 323: }
! 324: /* at this point, i == lu and we have written (i+1) entries in ans[] */
! 325: if ( i >= lv ) { /* no more elms in v[] */
! 326: if ( b != 0 ) {
! 327: if ( i == 0 ) { ans[i] = BASE - t; return 1; }
! 328: l = negate_nbd( ans, i ); /* <================ */
! 329: /* if ( (t = BMASK ^ ans[i]) == 0 ) return l;*/
! 330: if ( (t ^= BMASK) == 0 ) return l;
! 331: ans[i] = t;
! 332: return( i + 1 );
! 333: }
! 334: if ( c == 0 ) return l;
! 335: *p = c;
! 336: return( i + 2 );
! 337: }
! 338: /* diff turned out to be > 0 */
! 339: if ( b != 0 ) { /* c == 0 */
! 340: while ( (b = v[i++]) == 0 ) *p++ = BMASK;
! 341: DM( a, b, hi, t );
! 342: if ( t != 0 ) t--, c = hi;
! 343: else t = BMASK, c = hi - 1;
! 344: *p++ - t;
! 345: }
! 346: #ifdef CALL
! 347: return( aV_plus_c( a, &v[i], lv - i, c, p ) + i +1 );
! 348: #else
! 349: for ( ; i < lv; i++, *p++ = t, c = hi ) { DMA( a, v[i], c, hi, t, not_used );}
! 350: if ( c == 0 ) return( i + 1 );
! 351: *p = c;
! 352: return( i + 2 );
! 353: #endif
! 354: }
! 355:
! 356: static int abs_aVplusc_U_sh( t, a, v, lv, c, u, lu, rsh, ans )
! 357: int t, a, *v, lv, c, *u, lu, rsh, *ans;
! 358: {
! 359: int i, l, w, b, lsh = BSH - rsh, *p = ans;
! 360: int hi;
! 361:
! 362: if ( c < 0 ) c = 0, b = 1;
! 363: else b = 0;
! 364: for ( i = 0; i < lu; t = w >> rsh ) {
! 365: DMA( a, v[i], c, hi, w, not_used );
! 366: w -= u[i++], c = hi;
! 367: if ( b != 0 ) w--;
! 368: b = 0;
! 369: if ( w < 0 ) {
! 370: w += BASE;
! 371: if ( c != 0 ) c--;
! 372: else b = 1;
! 373: }
! 374: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
! 375: }
! 376: /* at this point, i == lu and we have written i entries in ans[] */
! 377: if ( i >= lv ) {
! 378: if ( b != 0 ) { /* diff turned out to be < 0 */
! 379: if ( i == 0 ) {
! 380: *p = (BASE >> rsh) - t;
! 381: return 1;
! 382: }
! 383: l = negate_nbd( ans, i ); /* <================ */
! 384: if ( (t ^= (BMASK >> rsh)) == 0 ) return l;
! 385: *p = t;
! 386: return( i + 1 );
! 387: }
! 388: if ( c == 0 ) {
! 389: if ( t == 0 ) return l;
! 390: *p = t;
! 391: return( i + 1 );
! 392: }
! 393: *p++ = t | ((c << lsh) & BMASK);
! 394: if ( (t = c >> rsh) == 0 ) return( i + 1 );
! 395: *p = t;
! 396: return( i + 2 );
! 397: }
! 398: /* lv >= lu+1 = i+1, and diff is > 0 */
! 399: if ( b != 0 ) { /* c == 0 */
! 400: if ( (w = v[i++]) == 0 ) {
! 401: *p++ = t | ((BMASK << lsh) & BMASK);
! 402: while ( (w = v[i++]) == 0 ) *p++ = BMASK;
! 403: t = BMASK >> rsh;
! 404: } else {
! 405: DM( a, w, c, b );
! 406: if ( b != 0 ) b--;
! 407: else b = BMASK, c--;
! 408: *p++ = t | ((b << lsh) & BMASK);
! 409: t = b >> rsh;
! 410: }
! 411: }
! 412: /**/
! 413: #ifdef CALL
! 414: return( aV_plus_c_sh( a, &v[i], lv - i, c, rsh, t, p ) + i );
! 415: #else
! 416: for ( ; i < lv; i++, t = w >> rsh, c = hi ) {
! 417: DMA( a, v[i], c, hi, w, not_used );
! 418: *p++ = t | ((w << lsh) & BMASK);
! 419: }
! 420: if ( c != 0 ) {
! 421: *p++ = t | ((c << lsh) & BMASK);
! 422: i++, t = c >> rsh;
! 423: }
! 424: if ( t == 0 ) return i;
! 425: *p = t;
! 426: return( i + 1 );
! 427: #endif
! 428: }
! 429:
! 430: /*********/
! 431:
! 432: static int abs_U_aV_c( t, u, lu, a, v, lv, c, ans )
! 433: int t, *u, lu, a, *v, lv, c, *ans;
! 434: /* compute | t + BASE*(U - a*V - c) | in ans[], where U = u[0:lu-1], V = v[0:lv-1],
! 435: * c is <= BASE-1, and lu >= lv+1 && t != 0 assumed.
! 436: */
! 437: {
! 438: int i, w, l, *p = ans;
! 439: int hi;
! 440:
! 441: *p++ = t, l = 1;
! 442: for ( i = 0; i < lv; *p++ = t ) {
! 443: DMA( a, v[i], c, hi, w, not_used );
! 444: t = u[i] - w;
! 445: i++, c = hi;
! 446: if ( t != 0 ) l = i + 1;
! 447: if ( t < 0 ) t += BASE, c++;
! 448: }
! 449: /* at this point, i == lv */
! 450: if ( lu == lv+1 ) {
! 451: if ( (t = u[i]) == c ) return l;
! 452: else if ( t > c ) { *p = t - c; return( lu + 1 ); }
! 453: l = negate_nbd( ans, lu ); /* <================ */
! 454: if ( (c -= (t + 1)) == 0 ) return l;
! 455: *p = c;
! 456: return( lu + 1 );
! 457: }
! 458: /* lu >= lv+2 and the diff turned out to be >= 0 */
! 459: if ( c != 0 ) {
! 460: /* note c <= BASE. If c == BASE, we must care about the length of the result
! 461: of the case when lu == lv+2 && u[lu-2:lu-1]=u[i:i+1] == BASE */
! 462: if ( c >= BASE && i+2 == lu && u[i+1] == 1 ) {
! 463: /* m.s. word of the diff becomes 0 */
! 464: if ( (t = u[i] - (c & BMASK)) == 0 ) return l;
! 465: *p = t;
! 466: return lu;
! 467: }
! 468: for ( ; 1; c = 1, *p++ = t + BASE ) if ( (t = u[i++] - c) >= 0 ) break;
! 469: if ( t == 0 && i >= lu ) return lu;
! 470: *p++ = t;
! 471: }
! 472: for ( ; i < lu; i++ ) *p++ = u[i];
! 473: return( lu + 1 );
! 474: }
! 475:
! 476: static int abs_U_aV_c_sh( t, u, lu, a, v, lv, c, rsh, ans )
! 477: int t, *u, lu, a, *v, lv, c, rsh, *ans;
! 478: /* r-shift version of the above */
! 479: {
! 480: int i, w, l, lsh = BSH - rsh, *p = ans;
! 481: int hi;
! 482:
! 483: for ( l = i = 0; i < lv; t = w >> rsh ) {
! 484: DMA( a, v[i], c, hi, w, not_used );
! 485: w = u[i] - w, c = hi;
! 486: i++;
! 487: if ( w < 0 ) w += BASE, c++;
! 488: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
! 489: }
! 490: /* at this point, i == lv, and we have written lv elm.s in ans[] */
! 491: if ( lu == lv+1 ) {
! 492: if ( (w = u[i] - c) == 0 ) {
! 493: if ( t == 0 ) return l;
! 494: *p = t;
! 495: return lu; /* == lv+1 */
! 496: } else if ( w > 0 ) {
! 497: l0: *p++ = t | ((w << lsh) & BMASK);
! 498: if ( (w >>= rsh) == 0 ) return lu; /* == lv+1 */
! 499: *p = w;
! 500: return( lu + 1 );
! 501: }
! 502: /* diff turned out to be < 0 */
! 503: w = - w - 1;
! 504: if ( lv == 0 ) { /* lu == 1 */
! 505: t = (BASE >> rsh) - t;
! 506: if ( w != 0 ) goto l0;
! 507: *p = t;
! 508: return 1;
! 509: }
! 510: l = negate_nbd( ans, lv ); /* <================ */
! 511: t ^= (BMASK >> rsh);
! 512: if ( w != 0 ) goto l0;
! 513: if ( t == 0 ) return l;
! 514: *p = t;
! 515: return lu; /* == lv + 1 */
! 516: }
! 517: /* now, lu >= lv+2 == i+2 */
! 518: if ( c != 0 ) {
! 519: /* note c <= BASE. If c == BASE, we must care about the length of the result
! 520: of the case when lu == lv+2 && u[lu-2:lu-1]=u[i:i+1] == BASE */
! 521: if ( c >= BASE && i+2 == lu && t == 0 && u[i] == 0 && u[i+1] == 1 )
! 522: return l; /* m.s. word of the diff has become 0 */
! 523: for ( ; 1; t = w >> rsh, c = 1 ) {
! 524: if ( (w = u[i++] - c) >= 0 ) break;
! 525: w += BASE;
! 526: *p++ = t | ((w << lsh) & BMASK);
! 527: }
! 528: t |= ((w << lsh) & BMASK);
! 529: w >>= rsh;
! 530: if ( i >= lu ) {
! 531: if ( w != 0 ) {
! 532: *p++ = t;
! 533: *p = w;
! 534: return( lu + 1 );
! 535: } else if ( t == 0 ) return( i - 1 );
! 536: else { *p = t; return i; }
! 537: }
! 538: *p++ = t;
! 539: t = w;
! 540: }
! 541: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
! 542: if ( t == 0 ) return i;
! 543: *p = t;
! 544: return( i + 1 );
! 545: }
! 546:
! 547: /****************/
! 548: /****************/
! 549: #ifdef FULLSET
! 550: static int abs_axU_V_maxrshift(), abs_axU_bxV_maxrshift();
! 551:
! 552: static int abs_aU_bV_maxrshift( a, u, lu, b, v, lv, ans )
! 553: int a, *u, lu, b, *v, lv, *ans;
! 554: /*
! 555: * Compute | a*U - b*V | >> (as much as possible) in ans[], where U=u[0:lu-1]
! 556: * and V=v[0:lv-1].
! 557: */
! 558: {
! 559: if ( a == 1 ) return abs_U_aV_maxrshift( u, lu, b, v, lv, ans );
! 560: else if ( b == 1 ) return abs_U_aV_maxrshift( v, lv, a, u, lu, ans );
! 561: else if ( a == b ) return abs_axU_V_maxrshift( a, u, lu, v, lv, ans );
! 562: return abs_axU_bxV_maxrshift( a, u, lu, b, v, lv, ans );
! 563: }
! 564:
! 565: static int abs_axU_V_maxrshift( a, u, lu, v, lv, ans )
! 566: int a, *u, lu, *v, lv, *ans;
! 567: /*
! 568: * Compute a*| U - V | >> (as much as possible) in ans[], where U=u[0:lu-1]
! 569: * and V=v[0:lv-1], 0 < a < 2^BASE.
! 570: */
! 571: {
! 572: int i, l, b, c, t, rsh, *p = ans, lsh, w, x;
! 573: int hi;
! 574:
! 575: if ( lu > lv ) goto U_V;
! 576: else if ( lu < lv ) goto swap;
! 577: else {
! 578: for ( i = lu; i-- > 0; ) {
! 579: if ( u[i] == v[i] ) continue;
! 580: lu = lv = i + 1;
! 581: if ( u[i] > v[i] ) goto U_V;
! 582: else goto swap;
! 583: }
! 584: return 0;
! 585: }
! 586: swap:
! 587: SWAP( lu, lv, int ); SWAP( u, v, int * );
! 588: U_V:
! 589: for ( b = c = i = 0; i < lv; ) {
! 590: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
! 591: else b = 0;
! 592: DMA( a, w, c, hi, t, not_used );
! 593: i++, c = hi;
! 594: if ( t != 0 ) goto non0w;
! 595: }
! 596: while ( i < lu ) {
! 597: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
! 598: else b = 0;
! 599: DMA( a, w, c, hi, t, not_used );
! 600: i++, c = hi;
! 601: if ( t != 0 ) goto non0w;
! 602: }
! 603: if ( b != 0 ) c -= a;
! 604: else if ( c == 0 ) return 0;
! 605: while ( (c&1) == 0 ) c >>= 1;
! 606: *p = c;
! 607: return 1;
! 608: /**/
! 609: non0w:
! 610: u += i, lu -= i, v += i, lv -= i;
! 611: TRAILINGZEROS( t, rsh );
! 612: i = 0;
! 613: if ( rsh == 0 ) {
! 614: *p++ = t, l = 0;
! 615: for ( ; i < lv; c = hi ) {
! 616: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
! 617: else b = 0;
! 618: DMA( a, w, c, hi, t, not_used );
! 619: i++;
! 620: if ( (*p++ = t) != 0 ) l = i;
! 621: }
! 622: for ( ; i < lu; c = hi ) {
! 623: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
! 624: else b = 1;
! 625: DMA( a, w, c, hi, t, not_used );
! 626: i++;
! 627: if ( (*p++ = t) != 0 ) l = i;
! 628: }
! 629: if ( b != 0 ) c -= a;
! 630: if ( c == 0 ) return( l + 1 );
! 631: *p = c;
! 632: return( i + 2 );
! 633: } else {
! 634: for ( lsh = BSH - rsh, l = 0; i < lv; c = hi, t = x >> rsh ) {
! 635: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
! 636: else b = 0;
! 637: DMA( a, w, c, hi, x, not_used );
! 638: i++;
! 639: if ( (*p++ = t | ((x << lsh) & BMASK)) != 0 ) l = i;
! 640: }
! 641: for ( ; i < lu; i++, c = hi, t = x >> rsh ) {
! 642: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
! 643: else b = 0;
! 644: DMA( a, w, c, hi, x, not_used );
! 645: i++;
! 646: if ( (*p++ = t | ((x << lsh) & BMASK)) != 0 ) l = i;
! 647: }
! 648: if ( b != 0 ) c -= a;
! 649: if ( c != 0 ) {
! 650: *p++ = t | ((c << lsh) & BMASK);
! 651: i++, t = c >> rsh;
! 652: } else if ( t == 0 ) return l;
! 653: if ( t == 0 ) return( i );
! 654: *p = t;
! 655: return( i + 1 );
! 656: }
! 657: }
! 658: #endif /* FULLSET */
! 659:
! 660: static int abs_axU_bxV_maxrshift( a, u, lu, b, v, lv, ans )
! 661: int a, *u, lu, b, *v, lv, *ans;
! 662: /*
! 663: * Compute | a*U - b*V | >> (as much as possible) in ans[], where U=u[0:lu-1]
! 664: * and V=v[0:lv-1], 0 < a, b < 2^BASE.
! 665: */
! 666: {
! 667: int i, l, c, d, s, t, w, rsh, *p = ans, lsh;
! 668: int hi;
! 669: static int bw_int32();
! 670:
! 671: BitWidth( a, c ); BitWidth( u[lu -1], s );
! 672: BitWidth( b, d ); BitWidth( v[lv -1], t );
! 673: if ( lu < lv || lu == lv && (c + s) < (d + t) ) {
! 674: SWAP( a, b, int ); SWAP( lu, lv, int ); SWAP( u, v, int * );
! 675: }
! 676: for ( i = c = d = 0; i < lv; ) {
! 677: DMA( a, u[i], c, hi, t, not_used ); /* 0 <= c <= 2^BSH -2 */
! 678: c = hi;
! 679: DMA( b, v[i], d, hi, s, not_used ); /* 0 <= d <= 2^BSH -1 */
! 680: i++, d = hi;
! 681: if ( (t -= s) == 0 ) continue;
! 682: else if ( t < 0 ) {
! 683: t += BASE;
! 684: if ( c != 0 ) c--;
! 685: else d++;
! 686: }
! 687: goto non0w;
! 688: }
! 689: if ( i >= lu ) { /* no more elm.'s in u[] and v[] */
! 690: only_c:
! 691: if ( (c -= d) == 0 ) return 0;
! 692: else if ( c < 0 ) c = -c;
! 693: sh_onlyc:
! 694: /* TRAILINGZEROS( c, rsh ); */
! 695: while ( (c&1) == 0 ) c >>= 1;
! 696: *p = c;
! 697: return 1;
! 698: }
! 699: /* there is at least one more elm. in u[] */
! 700: DMA( a, u[i], c, hi, t, not_used );
! 701: i++, c = hi;
! 702: if ( i >= lu ) { /* in this case, diff still can be <= 0 */
! 703: if ( hi == 0 ) { c = t; goto only_c; }
! 704: if ( (t -= d) == 0 ) { c = hi; goto sh_onlyc; }
! 705: else if ( t < 0 ) t += BASE, hi--;
! 706: TRAILINGZEROS( t, rsh );
! 707: if ( rsh == 0 ) *p++ = t;
! 708: else {
! 709: *p++ = t | ((hi << (BSH - rsh)) & BMASK);
! 710: hi >>= rsh;
! 711: }
! 712: if ( hi == 0 ) return 1;
! 713: *p = hi;
! 714: return 2;
! 715: } /* diff turned out to be > 0 */ else if ( (t -= d) > 0 ) d = 0;
! 716: else if ( t < 0 ) t += BASE, d = 1;
! 717: else {
! 718: while ( i < lu ) {
! 719: DMA( a, u[i], c, hi, t, not_used );
! 720: i++, c = hi;
! 721: if ( t != 0 ) break;
! 722: }
! 723: }
! 724: u += i, lu -= i;
! 725: TRAILINGZEROS( t, rsh );
! 726: l = i = 0;
! 727: if ( rsh == 0 ) {
! 728: *p++ = t;
! 729: goto no_more_v;
! 730: } else goto no_more_v_sh;
! 731: /**/
! 732: non0w:
! 733: u += i, lu -= i, v += i, lv -= i;
! 734: TRAILINGZEROS( t, rsh );
! 735: i = 0;
! 736: if ( rsh == 0 ) {
! 737: *p++ = t, l = 0;
! 738: for ( ; i < lv; *p++ = t ) {
! 739: DMA( a, u[i], c, hi, t, not_used );
! 740: c = hi;
! 741: DMA( b, v[i], d, hi, s, not_used );
! 742: i++, d = hi;
! 743: if ( (t -= s) == 0 ) continue;
! 744: else if ( t < 0 ) {
! 745: t += BASE;
! 746: if ( c != 0 ) c--;
! 747: else d++;
! 748: }
! 749: l = i;
! 750: }
! 751: no_more_v:
! 752: if ( i >= lu ) {
! 753: final_c_d:
! 754: if ( (c -= d) == 0 ) return( l + 1 );
! 755: else if ( c < 0 ) {
! 756: l = negate_nbd( ans, i + 1 ); /* <================ */
! 757: if ( (c = -c - 1) == 0 ) return l;
! 758: }
! 759: *p = c;
! 760: return( i + 2 );
! 761: }
! 762: /* a*u[i:lu-1] + c - d */
! 763: if ( c >= d ) c -= d;
! 764: else {
! 765: DMA( a, u[i], c, hi, t, not_used );
! 766: if ( i+1 >= lu ) {
! 767: if ( hi == 0 ) { c = t; goto final_c_d; }
! 768: if ( (t -= d) < 0 ) t += BASE, c = hi - 1;
! 769: else c = hi;
! 770: i++, *p++ = t;
! 771: goto final_c;
! 772: }
! 773: i++, c = hi;
! 774: if ( (t -= d) >= 0 ) *p++ = t;
! 775: else {
! 776: *p++ = t + BASE;
! 777: if ( c != 0 ) c--;
! 778: else {
! 779: for ( ; i < lu; *p++ = BMASK ) {
! 780: DMA( a, u[i], c, hi, t, not_used );
! 781: i++, c = hi;
! 782: if ( t == 0 ) continue;
! 783: *p++ = t - 1;
! 784: goto aU;
! 785: }
! 786: c--;
! 787: goto final_c;
! 788: }
! 789: }
! 790: }
! 791: /*** return( aV_plus_c( a, &u[i], lu - i, c, p ) + i + 1 ); ***/
! 792: aU:
! 793: for ( ; i < lu; i++, c = hi, *p++ = t ) { DMA( a, u[i], c, hi, t, not_used ); }
! 794: final_c:
! 795: if ( c == 0 ) return( i + 1 );
! 796: *p = c;
! 797: return( i + 2 );
! 798: } else { /* rsh != 0 */
! 799: for ( lsh = BSH - rsh; i < lv; t = w >> rsh ) {
! 800: DMA( a, u[i], c, hi, w, not_used );
! 801: c = hi;
! 802: DMA( b, v[i], d, hi, s, not_used );
! 803: i++, d = hi;
! 804: if ( (w -= s) < 0 ) {
! 805: w += BASE;
! 806: if ( c != 0 ) c--;
! 807: else d++;
! 808: }
! 809: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
! 810: }
! 811: no_more_v_sh:
! 812: if ( i >= lu ) {
! 813: final_c_d_sh:
! 814: if ( (c -= d) == 0 )
! 815: if ( t == 0 ) return l;
! 816: else { *p = t; return( i + 1 ); }
! 817: else if ( c < 0 ) {
! 818: if ( i == 0 ) t = (BASE >> rsh) - t;
! 819: else {
! 820: l = negate_nbd( ans, i ); /* <================ */
! 821: /* t = (BASE >> rsh) - t;*/
! 822: t ^= ((BMASK >> rsh));
! 823: }
! 824: c = -c -1;
! 825: }
! 826: *p++ = t | ((c << lsh) & BMASK);
! 827: if ( (c >>= rsh) == 0 ) return( i + 1 );
! 828: *p = c;
! 829: return( i + 2 );
! 830: } else if ( c >= d ) c -= d;
! 831: else {
! 832: DMA( a, u[i], c, hi, w, not_used );
! 833: if ( i+1 >= lu ) {
! 834: if ( hi == 0 ) { c = w; goto final_c_d_sh; }
! 835: if ( (w -= d) < 0 ) w += BASE, c = hi - 1;
! 836: else c = hi;
! 837: i++, *p++ = t | ((w << lsh) & BMASK);
! 838: t = w >> rsh;
! 839: goto final_c_sh;
! 840: }
! 841: i++, c = hi;
! 842: if ( (w -= d) >= 0 ) { *p++ = t | ((w << lsh) & BMASK); t = w >> rsh; }
! 843: else {
! 844: w += BASE;
! 845: *p++ = t | ((w << lsh) & BMASK);
! 846: t = w >> rsh;
! 847: if ( c != 0 ) c--;
! 848: else {
! 849: while ( i < lu ) {
! 850: DMA( a, u[i], c, hi, w, not_used );
! 851: i++, c = hi;
! 852: if ( w == 0 ) {
! 853: *p++ = t | ((BMASK << lsh) & BMASK);
! 854: t = BMASK >> rsh;
! 855: continue;
! 856: } else {
! 857: w--;
! 858: *p++ = t | ((w << lsh) & BMASK);
! 859: t = w >> rsh;
! 860: goto aU_sh;
! 861: }
! 862: }
! 863: c--;
! 864: goto final_c_sh;
! 865: }
! 866: }
! 867: }
! 868: /*** return( aV_plus_c_sh( a, &u[i], lu - i, c, rsh, t ) + i ); ***/
! 869: aU_sh:
! 870: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
! 871: DMA( a, u[i], c, hi, w, not_used );
! 872: *p++ = t | ((w << lsh) & BMASK);
! 873: }
! 874: final_c_sh:
! 875: if ( c != 0 ) {
! 876: *p++ = t | ((c << lsh) & BMASK);
! 877: i++, t = c >> rsh;
! 878: }
! 879: if ( t == 0 ) return i;
! 880: *p = t;
! 881: return( i + 1 );
! 882: }
! 883: }
! 884: /****************/
! 885: /****************/
! 886: #ifdef FULLSET
! 887: static int UplusV_maxrshift(), aUplusV_maxrshift(), axUplusV_maxrshift(), aUplusbV_maxrshift();
! 888:
! 889: static int aU_plus_bV_maxrshift( a, u, lu, b, v, lv, ans )
! 890: int a, *u, lu, b, *v, lv, *ans;
! 891: {
! 892: if ( a == 1 )
! 893: return( b == 1 ? UplusV_maxrshift( u, lu, v, lv, ans ) :
! 894: aUplusV_maxrshift( b, v, lv, u, lu, ans ) );
! 895: else if ( b == 1 ) return aUplusV_maxrshift( a, u, lu, v, lv, ans );
! 896: else if ( a == b ) return axUplusV_maxrshift( a, u, lu, v, lv, ans );
! 897: return aUplusbV_maxrshift( a, u, lu, b, v, lv, ans );
! 898: }
! 899:
! 900: static int UplusV_maxrshift( u, lu, v, lv, ans )
! 901: int *u, lu, *v, lv, *ans;
! 902: /*
! 903: * Compute ( (U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
! 904: * V=v[0:lv-1], and 0 < a < BASE.
! 905: */
! 906: {
! 907: int i, t, c, rsh, *p = ans;
! 908: int hi;
! 909:
! 910: if ( lu < lv ) { SWAP( lu, lv, int ); SWAP( u, v, int * ); }
! 911: for ( c = i = 0; i < lv; ) {
! 912: t = (c += (u[i] + v[i])) & BMASK;
! 913: /* 0 <= c <= 2*(2^BSH -1) + 1 = 2^BSH + (2^BSH -1) */
! 914: i++, c >>= BSH;
! 915: if ( t != 0 ) goto non0w;
! 916: }
! 917: while ( i < lu ) {
! 918: t = (c += u[i]) & BMASK;
! 919: i++, c >>= BSH;
! 920: if ( t != 0 ) goto non0w;
! 921: }
! 922: *p = c;
! 923: return 1;
! 924: /**/
! 925: non0w:
! 926: u += i, lu -= i, v += i, lv -= i;
! 927: TRAILINGZEROS( t, rsh );
! 928: i = 0;
! 929: if ( rsh == 0 ) {
! 930: *p++ = t;
! 931: for ( ; i < lv; i++, c >>= BSH ) *p++ = (c += (u[i] + v[i])) & BMASK;
! 932: if ( c != 0 ) {
! 933: while ( i < lu )
! 934: if ( (c = u[i++] + 1) >= BASE ) *p++ = c & BMASK;
! 935: else {
! 936: *p++ = c;
! 937: goto cpu;
! 938: }
! 939: *p = 1; /* == c */
! 940: return( lu + 2 );
! 941: }
! 942: cpu:
! 943: for ( ; i < lu; i++ ) *p++ = u[i];
! 944: return( lu + 1 );
! 945: } else {
! 946: int lsh = BSH - rsh;
! 947:
! 948: for ( ; i < lv; i++, c >>= BSH ) {
! 949: c += (u[i] + v[i]);
! 950: *p++ = t | ((c << lsh) & BMASK);
! 951: t = (c & BMASK) >> rsh;
! 952: }
! 953: if ( c != 0 ) {
! 954: while ( i < lu ) {
! 955: c = u[i++] + 1;
! 956: *p++ = t | ((c << lsh) & BMASK);
! 957: t = (c & BMASK) >> rsh;
! 958: if ( (c >>= BSH) == 0 ) goto cpu_sh;
! 959: }
! 960: *p = t | (1 << lsh);
! 961: return( lu + 1 );
! 962: }
! 963: cpu_sh:
! 964: for ( ; i < lu; t = c >> rsh ) *p++ = t | (((c = u[i++]) << lsh) & BMASK);
! 965: if ( t == 0 ) return( lu );
! 966: *p = t;
! 967: return( lu + 1 );
! 968: }
! 969: }
! 970:
! 971: static int aUplusV_maxrshift( a, u, lu, v, lv, ans )
! 972: int a, *u, lu, *v, lv, *ans;
! 973: /*
! 974: * Compute ( (a*U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
! 975: * V=v[0:lv-1], and 1 < a < BASE.
! 976: */
! 977: {
! 978: int i, l, t, c, rsh, *p = ans, w, lsh;
! 979: int hi;
! 980:
! 981: for ( l = lu < lv ? lu : lv, c = i = 0; i < l; ) {
! 982: /* Note that (carry in a*U[*]) <= 2^BSH-2 because {(2^j-1)}^2 + (2^j-2)
! 983: * = 2^j*(2^j -2)+(2^j -1), and the following c is <= 2^j -1 because
! 984: * {(2^j -1)}^2 + (2^j -1) + (2^j -1) = 2^j*(2^j -1) + (2^j -1).
! 985: * ^^^^^^carry^^^^^^ pv[?].
! 986: */
! 987: c += v[i];
! 988: DMA( a, u[i], c, hi, t, not_used );
! 989: i++, c = hi;
! 990: if ( t != 0 ) goto non0sum;
! 991: }
! 992: if ( i >= lu ) { /* compute (c + v[i:lv-1]) */
! 993: while ( i < lv ) {
! 994: t = (c += v[i++]) & BMASK;
! 995: c >>= BSH;
! 996: if ( t != 0 ) goto non0w_v;
! 997: }
! 998: *p = 1;
! 999: return 1;
! 1000: non0w_v:
! 1001: v += i, lv -= i;
! 1002: i = 0;
! 1003: TRAILINGZEROS( t, rsh );
! 1004: if ( rsh == 0 ) {
! 1005: *p++ = t;
! 1006: L_addv:
! 1007: if ( c != 0 ) {
! 1008: while ( i < lv )
! 1009: if ( (c = u[i++] + 1) >= BASE ) *p++ = c & BMASK;
! 1010: else {
! 1011: *p++ = c;
! 1012: goto cpv;
! 1013: }
! 1014: *p = 1; /* == c */
! 1015: return( lv + 2 );
! 1016: }
! 1017: cpv:
! 1018: for ( ; i < lv; i++ ) *p++ = v[i];
! 1019: return( lv + 1 );
! 1020: } else {
! 1021: lsh = BSH - rsh;
! 1022: L_addv_sh:
! 1023: if ( c != 0 ) {
! 1024: while ( i < lv ) {
! 1025: c += v[i++];
! 1026: *p++ = t | ((c << lsh) & BMASK);
! 1027: t = (c & BMASK) >> rsh;
! 1028: if ( (c >>= BSH) == 0 ) goto cpv_sh;
! 1029: }
! 1030: *p = t | (1 << lsh);
! 1031: return( lv + 1 );
! 1032: }
! 1033: cpv_sh:
! 1034: for ( ; i < lv; t = c >> rsh ) *p++ = t | (((c = v[i++]) << lsh) & BMASK);
! 1035: if ( t == 0 ) return( lv );
! 1036: *p = t;
! 1037: return( lv + 1 );
! 1038: }
! 1039: } else { /* i >= lv, and compute (c + a*u[i:lu-1]) */
! 1040: while ( i < lu ) {
! 1041: DMA( a, u[i], c, hi, t, not_used );
! 1042: i++, c = hi;
! 1043: if ( t != 0 ) goto non0w_u;
! 1044: }
! 1045: TRAILINGZEROS( c, rsh );
! 1046: *p = c;
! 1047: return 1;
! 1048: /**/
! 1049: non0w_u:
! 1050: u += i, lu -= i;
! 1051: TRAILINGZEROS( t, rsh );
! 1052: i = 0;
! 1053: if ( rsh == 0 ) {
! 1054: *p++ = t;
! 1055: L_addu:
! 1056: #ifdef CALL
! 1057: return( aV_plus_c( a, u, lv, c, p ) + 1 );
! 1058: #else
! 1059: for ( ; i < lu; i++, *p++ = t, c = hi ) { DMA( a, u[i], c, hi, t, not_used ); }
! 1060: if ( c == 0 ) return( lu + 1 );
! 1061: *p = c;
! 1062: return( lu + 2 );
! 1063: #endif
! 1064: } else {
! 1065: lsh = BSH - rsh;
! 1066: L_addu_sh:
! 1067: #ifdef CALL
! 1068: return aV_plus_c_sh( a, u, lu, c, rsh, t, p );
! 1069: #else
! 1070: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
! 1071: DMA( a, u[i], c, hi, w, not_used );
! 1072: *p++ = t | ((w << lsh) & BMASK);
! 1073: }
! 1074: if ( c != 0 ) {
! 1075: *p++ = t | ((c << lsh) & BMASK);
! 1076: i++, t = c >> rsh;
! 1077: }
! 1078: if ( t == 0 ) return i;
! 1079: *p = t;
! 1080: return( i + 1 );
! 1081: #endif
! 1082: }
! 1083: }
! 1084: /**/
! 1085: non0sum:
! 1086: u += i, lu -= i, v += i, lv -= i, l -= i;
! 1087: TRAILINGZEROS( t, rsh );
! 1088: i = 0;
! 1089: if ( rsh == 0 ) {
! 1090: *p++ = t;
! 1091: for ( ; i < l; i++, *p++ = t, c = hi ) {
! 1092: c += v[i];
! 1093: DMA( a, u[i], c, hi, t, not_used );
! 1094: }
! 1095: if ( i >= lu ) /* compute (c + v[i:lv-1]). note i may be >= lv */ goto L_addv;
! 1096: else /* i >= lv, and compute (c + u[i:lu-1]) */ goto L_addu;
! 1097: } else {
! 1098: lsh = BSH - rsh;
! 1099: for ( ; i < l; i++, c = hi, t = w >> rsh ) {
! 1100: c += v[i];
! 1101: DMA( a, u[i], c, hi, w, not_used );
! 1102: *p++ = t | ((w << lsh) & BMASK);
! 1103: }
! 1104: if ( i >= lu ) /* compute (c + v[i:lv-1]) >> rsh. note i may be >= lv */ goto L_addv_sh;
! 1105: else /* i >= lv, and compute (c + u[i:lu-1]) >> rsh */ goto L_addu_sh;
! 1106: }
! 1107: }
! 1108:
! 1109:
! 1110: static int axUplusV_maxrshift( a, u, lu, v, lv, ans )
! 1111: int a, *u, lu, *v, lv, *ans;
! 1112: /*
! 1113: * Compute ( a*(U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
! 1114: * V=v[0:lv-1], and 1 < a < BASE.
! 1115: */
! 1116: {
! 1117: int i, t, c, d, rsh, w, *p = ans, lsh, x;
! 1118: int hi;
! 1119:
! 1120: if ( lu < lv ) { SWAP( lu, lv, int ); SWAP( u, v, int * ); }
! 1121: for ( i = c = d = 0; i < lv; ) {
! 1122: w = (d += (u[i] + v[i])) & BMASK;
! 1123: DMA( a, w, c, hi, t, not_used );
! 1124: i++, d >>= BSH, c = hi;
! 1125: if ( t != 0 ) goto non0w;
! 1126: }
! 1127: while ( i < lu ) {
! 1128: w = (d += u[i++]) & BMASK;
! 1129: DMA( a, w, c, hi, t, not_used );
! 1130: d >>= BSH, c = hi;
! 1131: if ( t != 0 ) goto non0w;
! 1132: }
! 1133: if ( d != 0 ) c += a;
! 1134: TRAILINGZEROS( c, rsh );
! 1135: if ( rsh != 0 || c <= BMASK ) { *p = c; return 1; }
! 1136: *p++ = c & BMASK;
! 1137: *p = c >> BSH;
! 1138: return 2;
! 1139: /**/
! 1140: non0w:
! 1141: u += i, lu -= i, v += i, lv -= i;
! 1142: TRAILINGZEROS( t, rsh );
! 1143: i = 0;
! 1144: if ( rsh == 0 ) {
! 1145: *p++ = t;
! 1146: for ( ; i < lv; i++, d >>= BSH, *p++ = t, c = hi ) {
! 1147: w = (d += (u[i] + v[i])) & BMASK;
! 1148: DMA( a, w, c, hi, t, not_used );
! 1149: }
! 1150: for ( ; i < lu; d >>= BSH, *p++ = t, c = hi ) {
! 1151: w = (d += u[i++]) & BMASK;
! 1152: DMA( a, w, c, hi, t, not_used );
! 1153: }
! 1154: if ( d != 0 ) c += a;
! 1155: if ( c == 0 ) return( lu + 1 );
! 1156: *p++ = c & BMASK;
! 1157: if ( (c >>= BSH) == 0 ) return( lu + 2 );
! 1158: *p = c;
! 1159: return( lu + 3 );
! 1160: } else {
! 1161: for ( lsh = BSH - rsh; i < lv; i++, d >>= BSH, t = x >> rsh, c = hi ) {
! 1162: w = (d += (u[i] + v[i])) & BMASK;
! 1163: DMA( a, w, c, hi, x, not_used );
! 1164: *p++ = t | ((x << lsh) & BMASK);
! 1165: }
! 1166: for ( ; i < lu; d >>= BSH, t = x >> rsh, c = hi ) {
! 1167: w = (d += u[i++]) & BMASK;
! 1168: DMA( a, w, c, hi, x, not_used );
! 1169: *p++ = t | ((x << lsh) & BMASK);
! 1170: }
! 1171: if ( d != 0 ) c += a;
! 1172: t |= ((c << lsh) & BMASK);
! 1173: c >>= rsh;
! 1174: if ( c != 0 ) {
! 1175: *p++ = t;
! 1176: *p = c;
! 1177: return( lu + 2 );
! 1178: } else if ( t == 0 ) return lu;
! 1179: *p = t;
! 1180: return( lu + 1 );
! 1181: }
! 1182: }
! 1183: #endif /* FULLSET */
! 1184:
! 1185: static int aUplusbV_maxrshift( a, u, lu, b, v, lv, ans )
! 1186: int a, *u, lu, b, *v, lv, *ans;
! 1187: /*
! 1188: * Compute ( (a*U + b*V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
! 1189: * V=v[0:lv-1], and 0 < a,b < BASE.
! 1190: */
! 1191: {
! 1192: int i, c, d, s, t, w, rsh, *p = ans, lsh;
! 1193: int hi;
! 1194:
! 1195: if ( lu < lv ) { SWAP( a, b, int ); SWAP( lu, lv, int ); SWAP( u, v, int * ); }
! 1196: for ( c = d = i = 0; i < lv; ) {
! 1197: DMA( a, u[i], c, hi, t, not_used ); /* 0 <= c <= 2^BSH -1 */
! 1198: c = hi;
! 1199: DMA( b, v[i], d, hi, s, not_used ); /* 0 <= d <= 2^BSH -2 */
! 1200: i++, d = hi, t += s;
! 1201: if ( t > BMASK ) c++, t &= BMASK;
! 1202: if ( t != 0 ) goto non0w;
! 1203: }
! 1204: c += d;
! 1205: for ( d = 0; i < lu; ) {
! 1206: DMA( a, u[i], c, hi, t, not_used );
! 1207: i++, c = hi;
! 1208: if ( t != 0 ) goto non0w;
! 1209: }
! 1210: TRAILINGZEROS( c, rsh );
! 1211: if ( rsh != 0 || c <= BMASK ) { *p = c; return 1; }
! 1212: *p++ = c & BMASK;
! 1213: *p = 1;
! 1214: return 2;
! 1215: /**/
! 1216: non0w:
! 1217: u += i, lu -= i, v += i, lv -= i;
! 1218: TRAILINGZEROS( t, rsh );
! 1219: i = 0;
! 1220: if ( rsh == 0 ) {
! 1221: *p++ = t;
! 1222: for ( ; i < lv; i++, *p++ = t ) {
! 1223: DMA( a, u[i], c, hi, t, not_used );
! 1224: c = hi;
! 1225: DMA( b, v[i], d, hi, s, not_used );
! 1226: d = hi, t += s;
! 1227: if ( t > BMASK ) c++, t &= BMASK;
! 1228: }
! 1229: c += d;
! 1230: for ( ; i < lu; i++, *p++ = t, c = hi ) {
! 1231: DMA( a, u[i], c, hi, t, not_used );
! 1232: }
! 1233: if ( c == 0 ) return( lu + 1 );
! 1234: else if ( c <= BMASK ) { *p = c; return( lu + 2 ); }
! 1235: *p++ = c & BMASK;
! 1236: *p = 1;
! 1237: return( lu + 3 );
! 1238: } else {
! 1239: for ( lsh = BSH - rsh; i < lv; i++, t = w >> rsh ) {
! 1240: DMA( a, u[i], c, hi, w, not_used );
! 1241: c = hi;
! 1242: DMA( b, v[i], d, hi, s, not_used );
! 1243: d = hi, w += s;
! 1244: if ( w > BMASK ) c++, w &= BMASK;
! 1245: *p++ = t | ((w << lsh) & BMASK);
! 1246: }
! 1247: c += d; /* <= 2^BSH + (2^BSH - 3) */
! 1248: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
! 1249: DMA( a, u[i], c, hi, w, not_used );
! 1250: *p++ = t | ((w << lsh) & BMASK);
! 1251: }
! 1252: if ( c == 0 ) {
! 1253: if ( t == 0 ) return lu;
! 1254: *p = t;
! 1255: return( lu + 1 );
! 1256: }
! 1257: *p++ = t | ((c << lsh) & BMASK);
! 1258: if ( (c >>= rsh) == 0 ) return( lu + 1 );
! 1259: *p = c;
! 1260: return( lu + 2 );
! 1261: }
! 1262: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>