Annotation of OpenXM_contrib2/asir2000/engine/up.c, Revision 1.1
1.1 ! noro 1: /* $OpenXM: OpenXM/src/asir99/engine/up.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
! 2: #include "ca.h"
! 3: #include <math.h>
! 4:
! 5: struct oEGT eg_chrem,eg_fore,eg_back;
! 6:
! 7: /*
! 8: int up_kara_mag=15;
! 9: int up_tkara_mag=15;
! 10: */
! 11: /*
! 12: int up_kara_mag=30;
! 13: int up_tkara_mag=20;
! 14: */
! 15: int up_kara_mag=20;
! 16: int up_tkara_mag=15;
! 17:
! 18: #if defined(sparc)
! 19: int up_fft_mag=50;
! 20: #else
! 21: int up_fft_mag=80;
! 22: #endif
! 23:
! 24: int up_rem_mag=1;
! 25: int debug_up;
! 26: int up_lazy;
! 27: extern int lm_lazy;
! 28: extern int current_ff;
! 29: extern int GC_dont_gc;
! 30:
! 31: void monicup(a,b)
! 32: UP a;
! 33: UP *b;
! 34: {
! 35: UP w;
! 36:
! 37: if ( !a )
! 38: *b = 0;
! 39: else {
! 40: w = W_UPALLOC(0); w->d = 0;
! 41: divnum(0,(Num)ONE,(Num)a->c[a->d],(Num *)&w->c[0]);
! 42: mulup(a,w,b);
! 43: }
! 44: }
! 45:
! 46: void simpup(a,b)
! 47: UP a;
! 48: UP *b;
! 49: {
! 50: int i,d;
! 51: UP c;
! 52:
! 53: if ( !a )
! 54: *b = 0;
! 55: else {
! 56: d = a->d;
! 57: c = UPALLOC(d);
! 58:
! 59: for ( i = 0; i <= d; i++ )
! 60: simpnum(a->c[i],&c->c[i]);
! 61: for ( i = d; i >= 0 && !c->c[i]; i-- );
! 62: if ( i < 0 )
! 63: *b = 0;
! 64: else {
! 65: c->d = i;
! 66: *b = c;
! 67: }
! 68: }
! 69: }
! 70:
! 71: void simpnum(a,b)
! 72: Num a;
! 73: Num *b;
! 74: {
! 75: LM lm;
! 76: GF2N gf;
! 77: GFPN gfpn;
! 78:
! 79: if ( !a )
! 80: *b = 0;
! 81: else
! 82: switch ( NID(a) ) {
! 83: case N_LM:
! 84: simplm((LM)a,&lm); *b = (Num)lm; break;
! 85: case N_GF2N:
! 86: simpgf2n((GF2N)a,&gf); *b = (Num)gf; break;
! 87: case N_GFPN:
! 88: simpgfpn((GFPN)a,&gfpn); *b = (Num)gfpn; break;
! 89: default:
! 90: *b = a; break;
! 91: }
! 92: }
! 93:
! 94: void uremp(p1,p2,rp)
! 95: P p1,p2;
! 96: P *rp;
! 97: {
! 98: UP n1,n2,r;
! 99:
! 100: if ( !p1 || NUM(p1) )
! 101: *rp = p1;
! 102: else {
! 103: ptoup(p1,&n1); ptoup(p2,&n2);
! 104: remup(n1,n2,&r);
! 105: uptop(r,rp);
! 106: }
! 107: }
! 108:
! 109: void ugcdp(p1,p2,rp)
! 110: P p1,p2;
! 111: P *rp;
! 112: {
! 113: UP n1,n2,r;
! 114:
! 115: ptoup(p1,&n1); ptoup(p2,&n2);
! 116: gcdup(n1,n2,&r);
! 117: uptop(r,rp);
! 118: }
! 119:
! 120: void reversep(p1,d,rp)
! 121: P p1;
! 122: Q d;
! 123: P *rp;
! 124: {
! 125: UP n1,r;
! 126:
! 127: if ( !p1 )
! 128: *rp = 0;
! 129: else {
! 130: ptoup(p1,&n1);
! 131: reverseup(n1,QTOS(d),&r);
! 132: uptop(r,rp);
! 133: }
! 134: }
! 135:
! 136: void invmodp(p1,d,rp)
! 137: P p1;
! 138: Q d;
! 139: P *rp;
! 140: {
! 141: UP n1,r;
! 142:
! 143: if ( !p1 )
! 144: error("invmodp : invalid input");
! 145: else {
! 146: ptoup(p1,&n1);
! 147: invmodup(n1,QTOS(d),&r);
! 148: uptop(r,rp);
! 149: }
! 150: }
! 151:
! 152: void addup(n1,n2,nr)
! 153: UP n1,n2;
! 154: UP *nr;
! 155: {
! 156: UP r,t;
! 157: int i,d1,d2;
! 158: Num *c,*c1,*c2;
! 159:
! 160: if ( !n1 ) {
! 161: *nr = n2;
! 162: } else if ( !n2 ) {
! 163: *nr = n1;
! 164: } else {
! 165: if ( n2->d > n1->d ) {
! 166: t = n1; n1 = n2; n2 = t;
! 167: }
! 168: d1 = n1->d; d2 = n2->d;
! 169: *nr = r = UPALLOC(d1);
! 170: c1 = n1->c; c2 = n2->c; c = r->c;
! 171: for ( i = 0; i <= d2; i++ )
! 172: addnum(0,*c1++,*c2++,c++);
! 173: for ( ; i <= d1; i++ )
! 174: *c++ = *c1++;
! 175: for ( i = d1, c = r->c; i >=0 && !c[i]; i-- );
! 176: if ( i < 0 )
! 177: *nr = 0;
! 178: else
! 179: r->d = i;
! 180: }
! 181: }
! 182:
! 183: void subup(n1,n2,nr)
! 184: UP n1,n2;
! 185: UP *nr;
! 186: {
! 187: UP r;
! 188: int i,d1,d2,d;
! 189: Num *c,*c1,*c2;
! 190:
! 191: if ( !n1 ) {
! 192: chsgnup(n2,nr);
! 193: } else if ( !n2 ) {
! 194: *nr = n1;
! 195: } else {
! 196: d1 = n1->d; d2 = n2->d; d = MAX(d1,d2);
! 197: *nr = r = UPALLOC(d);
! 198: c1 = n1->c; c2 = n2->c; c = r->c;
! 199: if ( d1 >= d2 ) {
! 200: for ( i = 0; i <= d2; i++ )
! 201: subnum(0,*c1++,*c2++,c++);
! 202: for ( ; i <= d1; i++ )
! 203: *c++ = *c1++;
! 204: } else {
! 205: for ( i = 0; i <= d1; i++ )
! 206: subnum(0,*c1++,*c2++,c++);
! 207: for ( ; i <= d2; i++ )
! 208: chsgnnum(*c2++,c++);
! 209: }
! 210: for ( i = d, c = r->c; i >=0 && !c[i]; i-- );
! 211: if ( i < 0 )
! 212: *nr = 0;
! 213: else
! 214: r->d = i;
! 215: }
! 216: }
! 217:
! 218: void chsgnup(n1,nr)
! 219: UP n1;
! 220: UP *nr;
! 221: {
! 222: UP r;
! 223: int d1,i;
! 224: Num *c1,*c;
! 225:
! 226: if ( !n1 ) {
! 227: *nr = 0;
! 228: } else {
! 229: d1 = n1->d;
! 230: *nr = r = UPALLOC(d1); r->d = d1;
! 231: c1 = n1->c; c = r->c;
! 232: for ( i = 0; i <= d1; i++ )
! 233: chsgnnum(*c1++,c++);
! 234: }
! 235: }
! 236:
! 237: void hybrid_mulup(ff,n1,n2,nr)
! 238: int ff;
! 239: UP n1,n2;
! 240: UP *nr;
! 241: {
! 242: if ( !n1 || !n2 )
! 243: *nr = 0;
! 244: else if ( MAX(n1->d,n2->d) < up_fft_mag )
! 245: kmulup(n1,n2,nr);
! 246: else
! 247: switch ( ff ) {
! 248: case FF_GFP:
! 249: fft_mulup_lm(n1,n2,nr); break;
! 250: case FF_GF2N:
! 251: kmulup(n1,n2,nr); break;
! 252: default:
! 253: fft_mulup(n1,n2,nr); break;
! 254: }
! 255: }
! 256:
! 257: void hybrid_squareup(ff,n1,nr)
! 258: int ff;
! 259: UP n1;
! 260: UP *nr;
! 261: {
! 262: if ( !n1 )
! 263: *nr = 0;
! 264: else if ( n1->d < up_fft_mag )
! 265: ksquareup(n1,nr);
! 266: else
! 267: switch ( ff ) {
! 268: case FF_GFP:
! 269: fft_squareup_lm(n1,nr); break;
! 270: case FF_GF2N:
! 271: ksquareup(n1,nr); break;
! 272: default:
! 273: fft_squareup(n1,nr); break;
! 274: }
! 275: }
! 276:
! 277: void hybrid_tmulup(ff,n1,n2,d,nr)
! 278: int ff;
! 279: UP n1,n2;
! 280: int d;
! 281: UP *nr;
! 282: {
! 283: if ( !n1 || !n2 )
! 284: *nr = 0;
! 285: else if ( MAX(n1->d,n2->d) < up_fft_mag )
! 286: tkmulup(n1,n2,d,nr);
! 287: else
! 288: switch ( ff ) {
! 289: case FF_GFP:
! 290: trunc_fft_mulup_lm(n1,n2,d,nr); break;
! 291: case FF_GF2N:
! 292: tkmulup(n1,n2,d,nr); break;
! 293: default:
! 294: trunc_fft_mulup(n1,n2,d,nr); break;
! 295: }
! 296: }
! 297:
! 298: void mulup(n1,n2,nr)
! 299: UP n1,n2;
! 300: UP *nr;
! 301: {
! 302: UP r;
! 303: Num *pc1,*pc,*c1,*c2,*c;
! 304: Num mul,t,s;
! 305: int i,j,d1,d2;
! 306:
! 307: if ( !n1 || !n2 )
! 308: *nr = 0;
! 309: else {
! 310: d1 = n1->d; d2 = n2->d;
! 311: *nr = r = UPALLOC(d1+d2); r->d = d1+d2;
! 312: c1 = n1->c; c2 = n2->c; c = r->c;
! 313: lm_lazy = 1;
! 314: for ( i = 0; i <= d2; i++, c++ )
! 315: if ( mul = *c2++ )
! 316: for ( j = 0, pc1 = c1, pc = c; j <= d1; j++ ) {
! 317: mulnum(0,*pc1++,mul,&t); addnum(0,*pc,t,&s); *pc++ = s;
! 318: }
! 319: lm_lazy = 0;
! 320: if ( !up_lazy )
! 321: for ( i = 0, c = r->c; i <= r->d; i++ ) {
! 322: simpnum(c[i],&t); c[i] = t;
! 323: }
! 324: }
! 325: }
! 326:
! 327: /* nr = c*n1 */
! 328:
! 329: void mulcup(c,n1,nr)
! 330: Num c;
! 331: UP n1;
! 332: UP *nr;
! 333: {
! 334: int d;
! 335: UP r;
! 336: Num t;
! 337: Num *c1,*cr;
! 338: int i;
! 339:
! 340: if ( !c || !n1 )
! 341: *nr = 0;
! 342: else {
! 343: d = n1->d;
! 344: *nr = r = UPALLOC(d); r->d = d;
! 345: c1 = n1->c; cr = r->c;
! 346: lm_lazy = 1;
! 347: for ( i = 0; i <= d; i++ )
! 348: mulnum(0,c1[i],c,&cr[i]);
! 349: lm_lazy = 0;
! 350: if ( !up_lazy )
! 351: for ( i = 0; i <= d; i++ ) {
! 352: simpnum(cr[i],&t); cr[i] = t;
! 353: }
! 354: }
! 355: }
! 356:
! 357: void tmulup(n1,n2,d,nr)
! 358: UP n1,n2;
! 359: int d;
! 360: UP *nr;
! 361: {
! 362: UP r;
! 363: Num *pc1,*pc,*c1,*c2,*c;
! 364: Num mul,t,s;
! 365: int i,j,d1,d2,dr;
! 366:
! 367: if ( !n1 || !n2 )
! 368: *nr = 0;
! 369: else {
! 370: d1 = n1->d; d2 = n2->d;
! 371: dr = MAX(d-1,d1+d2);
! 372: *nr = r = UPALLOC(dr);
! 373: c1 = n1->c; c2 = n2->c; c = r->c;
! 374: lm_lazy = 1;
! 375: for ( i = 0; i <= d2; i++, c++ )
! 376: if ( mul = *c2++ )
! 377: for ( j = 0, pc1 = c1, pc = c; (j <= d1) && (i+j < d); j++ ) {
! 378: mulnum(0,*pc1++,mul,&t); addnum(0,*pc,t,&s); *pc++ = s;
! 379: }
! 380: lm_lazy = 0;
! 381: c = r->c;
! 382: if ( !up_lazy )
! 383: for ( i = 0; i < d; i++ ) {
! 384: simpnum(c[i],&t); c[i] = t;
! 385: }
! 386: for ( i = d-1; i >= 0 && !c[i]; i-- );
! 387: if ( i < 0 )
! 388: *nr = 0;
! 389: else
! 390: r->d = i;
! 391: }
! 392: }
! 393:
! 394: void squareup(n1,nr)
! 395: UP n1;
! 396: UP *nr;
! 397: {
! 398: UP r;
! 399: Num *c1,*c;
! 400: Num t,s,u;
! 401: int i,j,h,d1,d;
! 402:
! 403: if ( !n1 )
! 404: *nr = 0;
! 405: else if ( !n1->d ) {
! 406: *nr = r = UPALLOC(0); r->d = 0;
! 407: mulnum(0,n1->c[0],n1->c[0],&r->c[0]);
! 408: } else {
! 409: d1 = n1->d;
! 410: d = 2*d1;
! 411: *nr = r = UPALLOC(2*d); r->d = d;
! 412: c1 = n1->c; c = r->c;
! 413: lm_lazy = 1;
! 414: for ( i = 0; i <= d1; i++ )
! 415: mulnum(0,c1[i],c1[i],&c[2*i]);
! 416: for ( j = 1; j < d; j++ ) {
! 417: h = (j-1)/2;
! 418: for ( i = MAX(j-d1,0), s = 0; i <= h; i++ ) {
! 419: mulnum(0,c1[i],c1[j-i],&t); addnum(0,t,s,&u); s = u;
! 420: }
! 421: addnum(0,s,s,&t); addnum(0,t,c[j],&u); c[j] = u;
! 422: }
! 423: lm_lazy = 0;
! 424: if ( !up_lazy )
! 425: for ( i = 0, c = r->c; i <= d; i++ ) {
! 426: simpnum(c[i],&t); c[i] = t;
! 427: }
! 428: }
! 429: }
! 430:
! 431: void remup(n1,n2,nr)
! 432: UP n1,n2;
! 433: UP *nr;
! 434: {
! 435: UP w,r;
! 436:
! 437: if ( !n2 )
! 438: error("remup : division by 0");
! 439: else if ( !n1 || !n2->d )
! 440: *nr = 0;
! 441: else if ( n1->d < n2->d )
! 442: *nr = n1;
! 443: else {
! 444: w = W_UPALLOC(n1->d); copyup(n1,w);
! 445: remup_destructive(w,n2);
! 446: if ( w->d < 0 )
! 447: *nr = 0;
! 448: else {
! 449: *nr = r = UPALLOC(w->d); copyup(w,r);
! 450: }
! 451: }
! 452: }
! 453:
! 454: void remup_destructive(n1,n2)
! 455: UP n1,n2;
! 456: {
! 457: Num *c1,*c2;
! 458: int d1,d2,i,j;
! 459: Num m,t,s,mhc;
! 460:
! 461: c1 = n1->c; c2 = n2->c;
! 462: d1 = n1->d; d2 = n2->d;
! 463: chsgnnum(c2[d2],&mhc);
! 464: for ( i = d1; i >= d2; i-- ) {
! 465: simpnum(c1[i],&t); c1[i] = t;
! 466: if ( !c1[i] )
! 467: continue;
! 468: divnum(0,c1[i],mhc,&m);
! 469: lm_lazy = 1;
! 470: for ( j = d2; j >= 0; j-- ) {
! 471: mulnum(0,c2[j],m,&t); addnum(0,c1[i+j-d2],t,&s);
! 472: c1[i+j-d2] = s;
! 473: }
! 474: lm_lazy = 0;
! 475: }
! 476: for ( i = 0; i < d2; i++ ) {
! 477: simpnum(c1[i],&t); c1[i] = t;
! 478: }
! 479: for ( i = d2-1; i >= 0 && !c1[i]; i-- );
! 480: n1->d = i;
! 481: }
! 482:
! 483: void qrup(n1,n2,nq,nr)
! 484: UP n1,n2;
! 485: UP *nq,*nr;
! 486: {
! 487: UP w,r,q;
! 488: struct oUP t;
! 489: Num m;
! 490: int d;
! 491:
! 492: if ( !n2 )
! 493: error("qrup : division by 0");
! 494: else if ( !n1 ) {
! 495: *nq = 0; *nr = 0;
! 496: } else if ( !n2->d )
! 497: if ( !n1->d ) {
! 498: divnum(0,n1->c[0],n2->c[0],(Num *)nq); *nr = 0;
! 499: } else {
! 500: divnum(0,(Num)ONE,n2->c[0],&m);
! 501: t.d = 0; t.c[0] = m;
! 502: mulup(n1,&t,nq); *nr = 0;
! 503: }
! 504: else if ( n1->d < n2->d ) {
! 505: *nq = 0; *nr = n1;
! 506: } else {
! 507: w = W_UPALLOC(n1->d); copyup(n1,w);
! 508: qrup_destructive(w,n2);
! 509: d = n1->d-n2->d;
! 510: *nq = q = UPALLOC(d); q->d = d;
! 511: bcopy(w->c+n2->d,q->c,(d+1)*sizeof(Num));
! 512: if ( w->d < 0 )
! 513: *nr = 0;
! 514: else {
! 515: *nr = r = UPALLOC(w->d); copyup(w,r);
! 516: }
! 517: }
! 518: }
! 519:
! 520: void qrup_destructive(n1,n2)
! 521: UP n1,n2;
! 522: {
! 523: Num *c1,*c2;
! 524: int d1,d2,i,j;
! 525: Num q,t,s,hc;
! 526:
! 527: c1 = n1->c; c2 = n2->c;
! 528: d1 = n1->d; d2 = n2->d;
! 529: hc = c2[d2];
! 530: for ( i = d1; i >= d2; i-- ) {
! 531: simpnum(c1[i],&t); c1[i] = t;
! 532: if ( c1[i] ) {
! 533: divnum(0,c1[i],hc,&q);
! 534: lm_lazy = 1;
! 535: for ( j = d2; j >= 0; j-- ) {
! 536: mulnum(0,c2[j],q,&t); subnum(0,c1[i+j-d2],t,&s);
! 537: c1[i+j-d2] = s;
! 538: }
! 539: lm_lazy = 0;
! 540: } else
! 541: q = 0;
! 542: c1[i] = q;
! 543: }
! 544: for ( i = 0; i < d2; i++ ) {
! 545: simpnum(c1[i],&t); c1[i] = t;
! 546: }
! 547: for ( i = d2-1; i >= 0 && !c1[i]; i-- );
! 548: n1->d = i;
! 549: }
! 550:
! 551: void gcdup(n1,n2,nr)
! 552: UP n1,n2;
! 553: UP *nr;
! 554: {
! 555: UP w1,w2,t,r;
! 556: int d1,d2;
! 557:
! 558: if ( !n1 )
! 559: *nr = n2;
! 560: else if ( !n2 )
! 561: *nr = n1;
! 562: else if ( !n1->d || !n2->d ) {
! 563: *nr = r = UPALLOC(0); r->d = 0;
! 564: divnum(0,n1->c[n1->d],n1->c[n1->d],&r->c[0]);
! 565: } else {
! 566: d1 = n1->d; d2 = n2->d;
! 567: if ( d2 > d1 ) {
! 568: w1 = W_UPALLOC(d2); copyup(n2,w1);
! 569: w2 = W_UPALLOC(d1); copyup(n1,w2);
! 570: } else {
! 571: w1 = W_UPALLOC(d1); copyup(n1,w1);
! 572: w2 = W_UPALLOC(d2); copyup(n2,w2);
! 573: }
! 574: d1 = w1->d; d2 = w2->d;
! 575: while ( 1 ) {
! 576: remup_destructive(w1,w2);
! 577: if ( w1->d < 0 ) {
! 578: *nr = r = UPALLOC(w2->d); copyup(w2,r); return;
! 579: } else if ( !w1->d ) {
! 580: *nr = r = UPALLOC(0); r->d = 0;
! 581: divnum(0,n1->c[n1->d],n1->c[n1->d],&r->c[0]); return;
! 582: } else {
! 583: t = w1; w1 = w2; w2 = t;
! 584: }
! 585: }
! 586: }
! 587: }
! 588:
! 589: /* compute r s.t. a*r = 1 mod m */
! 590:
! 591: void extended_gcdup(a,m,r)
! 592: UP a,m;
! 593: UP *r;
! 594: {
! 595: UP one,g1,g2,a1,a2,a3,b1,b2,b3,inv,quo,rem,t;
! 596: Num i;
! 597:
! 598: one = UPALLOC(0); one->d = 0; one->c[0] = (Num)ONELM;
! 599: g1 = m; g2 = a;
! 600: a1 = one; a2 = 0;
! 601: b1 = 0; b2 = one;
! 602: /* a2*m+b2*a = g2 always holds */
! 603: while ( g2->d ) {
! 604: qrup(g1,g2,&quo,&rem); g1 = g2; g2 = rem;
! 605: mulup(a2,quo,&t); subup(a1,t,&a3); a1 = a2; a2 = a3;
! 606: mulup(b2,quo,&t); subup(b1,t,&b3); b1 = b2; b2 = b3;
! 607: }
! 608: /* now a2*m+b2*a = g2 (const) */
! 609: divnum(0,(Num)ONE,g2->c[0],&i);
! 610: inv = UPALLOC(0); inv->d = 0; inv->c[0] = i;
! 611: mulup(b2,inv,r);
! 612: }
! 613:
! 614: void reverseup(n1,d,nr)
! 615: UP n1;
! 616: int d;
! 617: UP *nr;
! 618: {
! 619: Num *c1,*c;
! 620: int i,d1;
! 621: UP r;
! 622:
! 623: if ( !n1 )
! 624: *nr = 0;
! 625: else if ( d < (d1 = n1->d) )
! 626: error("reverseup : invalid input");
! 627: else {
! 628: *nr = r = UPALLOC(d);
! 629: c = r->c;
! 630: bzero((char *)c,(d+1)*sizeof(Num));
! 631: c1 = n1->c;
! 632: for ( i = 0; i <= d1; i++ )
! 633: c[d-i] = c1[i];
! 634: for ( i = d; i >= 0 && !c[i]; i-- );
! 635: r->d = i;
! 636: if ( i < 0 )
! 637: *nr = 0;
! 638: }
! 639: }
! 640:
! 641: void invmodup(n1,d,nr)
! 642: UP n1;
! 643: int d;
! 644: UP *nr;
! 645: {
! 646: UP r;
! 647: Num s,t,u,hinv;
! 648: int i,j,dmin;
! 649: Num *w,*c,*cr;
! 650:
! 651: if ( !n1 || !n1->c[0] )
! 652: error("invmodup : invalid input");
! 653: else if ( !n1->d ) {
! 654: *nr = r = UPALLOC(0); r->d = 0;
! 655: divnum(0,(Num)ONE,n1->c[0],&r->c[0]);
! 656: } else {
! 657: *nr = r = UPALLOC(d);
! 658: w = (Num *)ALLOCA((d+1)*sizeof(Q));
! 659: bzero((char *)w,(d+1)*sizeof(Q));
! 660: dmin = MIN(d,n1->d);
! 661: divnum(0,(Num)ONE,n1->c[0],&hinv);
! 662: for ( i = 0, c = n1->c; i <= dmin; i++ )
! 663: mulnum(0,c[i],hinv,&w[i]);
! 664: cr = r->c;
! 665: cr[0] = w[0];
! 666: for ( i = 1; i <= d; i++ ) {
! 667: for ( j = 1, s = w[i]; j < i; j++ ) {
! 668: mulnum(0,cr[j],w[i-j],&t);
! 669: addnum(0,s,t,&u);
! 670: s = u;
! 671: }
! 672: chsgnnum(s,&cr[i]);
! 673: }
! 674: for ( i = 0; i <= d; i++ ) {
! 675: mulnum(0,cr[i],hinv,&t); cr[i] = t;
! 676: }
! 677: for ( i = d; i >= 0 && !cr[i]; i-- );
! 678: r->d = i;
! 679: }
! 680: }
! 681:
! 682: void pwrup(n,e,nr)
! 683: UP n;
! 684: Q e;
! 685: UP *nr;
! 686: {
! 687: UP y,z,t;
! 688: N en,qn;
! 689: int r;
! 690:
! 691: y = UPALLOC(0); y->d = 0; y->c[0] = (Num)ONE;
! 692: z = n;
! 693: if ( !e )
! 694: *nr = y;
! 695: else if ( UNIQ(e) )
! 696: *nr = n;
! 697: else {
! 698: en = NM(e);
! 699: while ( 1 ) {
! 700: r = divin(en,2,&qn); en = qn;
! 701: if ( r ) {
! 702: mulup(z,y,&t); y = t;
! 703: if ( !en ) {
! 704: *nr = y;
! 705: return;
! 706: }
! 707: }
! 708: mulup(z,z,&t); z = t;
! 709: }
! 710: }
! 711: }
! 712:
! 713: int compup(n1,n2)
! 714: UP n1,n2;
! 715: {
! 716: int i,r;
! 717:
! 718: if ( !n1 )
! 719: return n2 ? -1 : 0;
! 720: else if ( !n2 )
! 721: return 1;
! 722: else if ( n1->d > n2->d )
! 723: return 1;
! 724: else if ( n1->d < n2->d )
! 725: return -1;
! 726: else {
! 727: for ( i = n1->d; i >= 0; i-- ) {
! 728: r = compnum(CO,n1->c[i],n2->c[i]);
! 729: if ( r )
! 730: return r;
! 731: }
! 732: return 0;
! 733: }
! 734: }
! 735:
! 736: void kmulp(vl,n1,n2,nr)
! 737: VL vl;
! 738: P n1,n2;
! 739: P *nr;
! 740: {
! 741: UP b1,b2,br;
! 742:
! 743: if ( !n1 || !n2 )
! 744: *nr = 0;
! 745: else if ( OID(n1) == O_N || OID(n2) == O_N )
! 746: mulp(vl,n1,n2,nr);
! 747: else {
! 748: ptoup(n1,&b1); ptoup(n2,&b2);
! 749: kmulup(b1,b2,&br);
! 750: uptop(br,nr);
! 751: }
! 752: }
! 753:
! 754: void ksquarep(vl,n1,nr)
! 755: VL vl;
! 756: P n1;
! 757: P *nr;
! 758: {
! 759: UP b1,br;
! 760:
! 761: if ( !n1 )
! 762: *nr = 0;
! 763: else if ( OID(n1) == O_N )
! 764: mulp(vl,n1,n1,nr);
! 765: else {
! 766: ptoup(n1,&b1);
! 767: ksquareup(b1,&br);
! 768: uptop(br,nr);
! 769: }
! 770: }
! 771:
! 772: void kmulup(n1,n2,nr)
! 773: UP n1,n2,*nr;
! 774: {
! 775: UP n,t,s,m,carry;
! 776: int d,d1,d2,len,i,l;
! 777: pointer *r,*r0;
! 778:
! 779: if ( !n1 || !n2 ) {
! 780: *nr = 0; return;
! 781: }
! 782: d1 = DEG(n1)+1; d2 = DEG(n2)+1;
! 783: if ( (d1 < up_kara_mag) && (d2 < up_kara_mag) )
! 784: mulup(n1,n2,nr);
! 785: else
! 786: kmulupmain(n1,n2,nr);
! 787: }
! 788:
! 789: void ksquareup(n1,nr)
! 790: UP n1,*nr;
! 791: {
! 792: int d1;
! 793: extern Q TWO;
! 794:
! 795: if ( !n1 ) {
! 796: *nr = 0; return;
! 797: }
! 798: d1 = DEG(n1)+1;
! 799: if ( (d1 < up_kara_mag) )
! 800: squareup(n1,nr);
! 801: else
! 802: ksquareupmain(n1,nr);
! 803: }
! 804:
! 805: void copyup(n1,n2)
! 806: UP n1,n2;
! 807: {
! 808: n2->d = n1->d;
! 809: bcopy((char *)n1->c,(char *)n2->c,(n1->d+1)*sizeof(Q));
! 810: }
! 811:
! 812: void c_copyup(n,len,p)
! 813: UP n;
! 814: int len;
! 815: pointer *p;
! 816: {
! 817: if ( n )
! 818: bcopy((char *)COEF(n),(char *)p,MIN((DEG(n)+1),len)*sizeof(pointer));
! 819: }
! 820:
! 821: void kmulupmain(n1,n2,nr)
! 822: UP n1,n2,*nr;
! 823: {
! 824: int d1,d2,h,len;
! 825: UP n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
! 826:
! 827: d1 = DEG(n1)+1; d2 = DEG(n2)+1; h = (MAX(d1,d2)+1)/2;
! 828: decompup(n1,h,&n1lo,&n1hi);
! 829: decompup(n2,h,&n2lo,&n2hi);
! 830: kmulup(n1lo,n2lo,&lo);
! 831: kmulup(n1hi,n2hi,&hi);
! 832: shiftup(hi,2*h,&t2);
! 833: addup(lo,t2,&t1);
! 834: addup(hi,lo,&mid1);
! 835: subup(n1hi,n1lo,&s1); subup(n2lo,n2hi,&s2); kmulup(s1,s2,&mid2);
! 836: addup(mid1,mid2,&mid);
! 837: shiftup(mid,h,&t2);
! 838: addup(t1,t2,nr);
! 839: }
! 840:
! 841: void ksquareupmain(n1,nr)
! 842: UP n1,*nr;
! 843: {
! 844: int d1,h,len;
! 845: UP n1lo,n1hi,hi,lo,mid1,mid2,mid,s1,t1,t2;
! 846:
! 847: d1 = DEG(n1)+1; h = (d1+1)/2;
! 848: decompup(n1,h,&n1lo,&n1hi);
! 849: ksquareup(n1hi,&hi); ksquareup(n1lo,&lo);
! 850: shiftup(hi,2*h,&t2);
! 851: addup(lo,t2,&t1);
! 852: addup(hi,lo,&mid1);
! 853: subup(n1hi,n1lo,&s1); ksquareup(s1,&mid2);
! 854: subup(mid1,mid2,&mid);
! 855: shiftup(mid,h,&t2);
! 856: addup(t1,t2,nr);
! 857: }
! 858:
! 859: void rembymulup(n1,n2,nr)
! 860: UP n1,n2;
! 861: UP *nr;
! 862: {
! 863: int d1,d2,d;
! 864: UP r1,r2,inv2,t,s,q;
! 865:
! 866: if ( !n2 )
! 867: error("rembymulup : division by 0");
! 868: else if ( !n1 || !n2->d )
! 869: *nr = 0;
! 870: else if ( (d1 = n1->d) < (d2 = n2->d) )
! 871: *nr = n1;
! 872: else {
! 873: d = d1-d2;
! 874: reverseup(n1,d1,&t); truncup(t,d+1,&r1);
! 875: reverseup(n2,d2,&r2);
! 876: invmodup(r2,d,&inv2);
! 877: kmulup(r1,inv2,&t);
! 878: truncup(t,d+1,&s);
! 879: reverseup(s,d,&q);
! 880: kmulup(q,n2,&t); subup(n1,t,nr);
! 881: }
! 882: }
! 883:
! 884: /*
! 885: deg n2 = d
! 886: deg n1 <= 2*d-1
! 887: inv2 = inverse of reversep(n2) mod x^d
! 888: */
! 889:
! 890: void hybrid_rembymulup_special(ff,n1,n2,inv2,nr)
! 891: int ff;
! 892: UP n1,n2,inv2;
! 893: UP *nr;
! 894: {
! 895: int d1,d2,d;
! 896: UP r1,t,s,q,u;
! 897:
! 898: if ( !n2 )
! 899: error("hybrid_rembymulup : division by 0");
! 900: else if ( !n1 || !n2->d )
! 901: *nr = 0;
! 902: else if ( (d1 = n1->d) < (d2 = n2->d) )
! 903: *nr = n1;
! 904: else {
! 905: d = d1-d2;
! 906: reverseup(n1,d1,&t); truncup(t,d+1,&r1);
! 907: hybrid_tmulup(ff,r1,inv2,d+1,&t);
! 908: truncup(t,d+1,&s);
! 909: reverseup(s,d,&q);
! 910:
! 911: hybrid_tmulup(ff,q,n2,d2,&t);
! 912: truncup(n1,d2,&s);
! 913: subup(s,t,nr);
! 914: }
! 915: }
! 916:
! 917: void rembymulup_special(n1,n2,inv2,nr)
! 918: UP n1,n2,inv2;
! 919: UP *nr;
! 920: {
! 921: int d1,d2,d;
! 922: UP r1,t,s,q,u;
! 923:
! 924: if ( !n2 )
! 925: error("rembymulup : division by 0");
! 926: else if ( !n1 || !n2->d )
! 927: *nr = 0;
! 928: else if ( (d1 = n1->d) < (d2 = n2->d) )
! 929: *nr = n1;
! 930: else {
! 931: d = d1-d2;
! 932: reverseup(n1,d1,&t); truncup(t,d+1,&r1);
! 933: tkmulup(r1,inv2,d+1,&t);
! 934: truncup(t,d+1,&s);
! 935: reverseup(s,d,&q);
! 936:
! 937: tkmulup(q,n2,d2,&t);
! 938: truncup(n1,d2,&s);
! 939: subup(s,t,nr);
! 940: }
! 941: }
! 942:
! 943: /* *nr = n1*n2 mod x^d */
! 944:
! 945: void tkmulup(n1,n2,d,nr)
! 946: UP n1,n2;
! 947: int d;
! 948: UP *nr;
! 949: {
! 950: int m;
! 951: UP n1l,n1h,n2l,n2h,l,h,t,s,u,afo;
! 952:
! 953: if ( d < 0 )
! 954: error("tkmulup : invalid argument");
! 955: else if ( d == 0 )
! 956: *nr = 0;
! 957: else {
! 958: truncup(n1,d,&t); n1 = t;
! 959: truncup(n2,d,&t); n2 = t;
! 960: if ( !n1 || !n2 )
! 961: *nr = 0;
! 962: else if ( n1->d < up_tkara_mag || n2->d < up_tkara_mag )
! 963: tmulup(n1,n2,d,nr);
! 964: else {
! 965: m = (d+1)/2;
! 966: decompup(n1,m,&n1l,&n1h);
! 967: decompup(n2,m,&n2l,&n2h);
! 968: kmulup(n1l,n2l,&l);
! 969: tkmulup(n1l,n2h,d-m,&t);
! 970: tkmulup(n2l,n1h,d-m,&s);
! 971: addup(t,s,&u);
! 972: shiftup(u,m,&h);
! 973: addup(l,h,&t);
! 974: truncup(t,d,nr);
! 975: }
! 976: }
! 977: }
! 978:
! 979: /* n->n*x^d */
! 980:
! 981: void shiftup(n,d,nr)
! 982: UP n;
! 983: int d;
! 984: UP *nr;
! 985: {
! 986: int dr;
! 987: UP r;
! 988:
! 989: if ( !n )
! 990: *nr = 0;
! 991: else {
! 992: dr = n->d+d;
! 993: *nr = r = UPALLOC(dr); r->d = dr;
! 994: bzero(r->c,(dr+1)*sizeof(Num));
! 995: bcopy(n->c,r->c+d,(n->d+1)*sizeof(Num));
! 996: }
! 997: }
! 998:
! 999: void fft_rembymulup_special(n1,n2,inv2,nr)
! 1000: UP n1,n2,inv2;
! 1001: UP *nr;
! 1002: {
! 1003: int d1,d2,d;
! 1004: UP r1,t,s,q,u;
! 1005:
! 1006: if ( !n2 )
! 1007: error("rembymulup : division by 0");
! 1008: else if ( !n1 || !n2->d )
! 1009: *nr = 0;
! 1010: else if ( (d1 = n1->d) < (d2 = n2->d) )
! 1011: *nr = n1;
! 1012: else {
! 1013: d = d1-d2;
! 1014: reverseup(n1,d1,&t); truncup(t,d+1,&r1);
! 1015: trunc_fft_mulup(r1,inv2,d+1,&t);
! 1016: truncup(t,d+1,&s);
! 1017: reverseup(s,d,&q);
! 1018: trunc_fft_mulup(q,n2,d2,&t); truncup(t,d2,&u);
! 1019: truncup(n1,d2,&s);
! 1020: subup(s,u,nr);
! 1021: }
! 1022: }
! 1023:
! 1024: void set_degreeup(n,d)
! 1025: UP n;
! 1026: int d;
! 1027: {
! 1028: int i;
! 1029:
! 1030: for ( i = d; i >= 0 && !n->c[i]; i-- );
! 1031: n->d = i;
! 1032: }
! 1033:
! 1034: /* n -> n0 + x^d n1 */
! 1035:
! 1036: void decompup(n,d,n0,n1)
! 1037: UP n;
! 1038: int d;
! 1039: UP *n0,*n1;
! 1040: {
! 1041: int dn;
! 1042: UP r0,r1;
! 1043:
! 1044: if ( !n || d > n->d ) {
! 1045: *n0 = n; *n1 = 0;
! 1046: } else if ( d < 0 )
! 1047: error("decompup : invalid argument");
! 1048: else if ( d == 0 ) {
! 1049: *n0 = 0; *n1 = n;
! 1050: } else {
! 1051: dn = n->d;
! 1052: *n0 = r0 = UPALLOC(d-1);
! 1053: *n1 = r1 = UPALLOC(dn-d);
! 1054: bcopy(n->c,r0->c,d*sizeof(Num));
! 1055: bcopy(n->c+d,r1->c,(dn-d+1)*sizeof(Num));
! 1056: set_degreeup(r0,d-1);
! 1057: if ( r0->d < 0 )
! 1058: *n0 = 0;
! 1059: set_degreeup(r1,dn-d);
! 1060: if ( r1->d < 0 )
! 1061: *n1 = 0;
! 1062: }
! 1063: }
! 1064:
! 1065: /* n -> n mod x^d */
! 1066:
! 1067: void truncup(n1,d,nr)
! 1068: UP n1;
! 1069: int d;
! 1070: UP *nr;
! 1071: {
! 1072: int i;
! 1073: UP r;
! 1074:
! 1075: if ( !n1 || d > n1->d )
! 1076: *nr = n1;
! 1077: else if ( d < 0 )
! 1078: error("truncup : invalid argument");
! 1079: else if ( d == 0 )
! 1080: *nr = 0;
! 1081: else {
! 1082: *nr = r = UPALLOC(d-1);
! 1083: bcopy(n1->c,r->c,d*sizeof(Num));
! 1084: for ( i = d-1; i >= 0 && !r->c[i]; i-- );
! 1085: if ( i < 0 )
! 1086: *nr = 0;
! 1087: else
! 1088: r->d = i;
! 1089: }
! 1090: }
! 1091:
! 1092: int int_bits(t)
! 1093: int t;
! 1094: {
! 1095: int k;
! 1096:
! 1097: for ( k = 0; t; t>>=1, k++);
! 1098: return k;
! 1099: }
! 1100:
! 1101: /* n is assumed to be LM or integer coefficient */
! 1102:
! 1103: int maxblenup(n)
! 1104: UP n;
! 1105: {
! 1106: int m,r,i,d;
! 1107: Num *c;
! 1108:
! 1109: if ( !n )
! 1110: return 0;
! 1111: d = n->d; c = (Num *)n->c;
! 1112: for ( r = 0, i = 0; i <= d; i++ )
! 1113: if ( c[i] ) {
! 1114: switch ( NID(c[i]) ) {
! 1115: case N_LM:
! 1116: m = n_bits(((LM)c[i])->body);
! 1117: break;
! 1118: case N_Q:
! 1119: m = n_bits(((Q)c[i])->nm);
! 1120: break;
! 1121: default:
! 1122: error("maxblenup : invalid coefficient");
! 1123: }
! 1124: r = MAX(m,r);
! 1125: }
! 1126: return r;
! 1127: }
! 1128:
! 1129: void uptofmarray(mod,n,f)
! 1130: int mod;
! 1131: UP n;
! 1132: ModNum *f;
! 1133: {
! 1134: int d,i;
! 1135: unsigned int r;
! 1136: Num *c;
! 1137:
! 1138: if ( !n )
! 1139: return;
! 1140: else {
! 1141: d = n->d; c = (Num *)n->c;
! 1142: for ( i = 0; i <= d; i++ ) {
! 1143: if ( c[i] ) {
! 1144: switch ( NID(c[i]) ) {
! 1145: case N_LM:
! 1146: f[i] = (ModNum)rem(((LM)c[i])->body,mod);
! 1147: break;
! 1148: case N_Q:
! 1149: r = rem(NM((Q)c[i]),mod);
! 1150: if ( r && (SGN((Q)c[i])<0) )
! 1151: r = mod-r;
! 1152: f[i] = (ModNum)r;
! 1153: break;
! 1154: default:
! 1155: error("uptofmarray : invalid coefficient");
! 1156: }
! 1157: } else
! 1158: f[i] = 0;
! 1159: }
! 1160: }
! 1161: }
! 1162:
! 1163: void fmarraytoup(f,d,nr)
! 1164: ModNum *f;
! 1165: int d;
! 1166: UP *nr;
! 1167: {
! 1168: int i;
! 1169: Q *c;
! 1170: UP r;
! 1171:
! 1172: if ( d < 0 ) {
! 1173: *nr = 0;
! 1174: } else {
! 1175: *nr = r = UPALLOC(d); c = (Q *)r->c;
! 1176: for ( i = 0; i <= d; i++ ) {
! 1177: UTOQ((unsigned int)f[i],c[i]);
! 1178: }
! 1179: for ( i = d; i >= 0 && !c[i]; i-- );
! 1180: if ( i < 0 )
! 1181: *nr = 0;
! 1182: else
! 1183: r->d = i;
! 1184: }
! 1185: }
! 1186:
! 1187: /* f[i]: an array of length n */
! 1188:
! 1189: void uiarraytoup(f,n,d,nr)
! 1190: unsigned int **f;
! 1191: int n,d;
! 1192: UP *nr;
! 1193: {
! 1194: int i,j;
! 1195: unsigned int *fi;
! 1196: N ci;
! 1197: Q *c;
! 1198: UP r;
! 1199:
! 1200: if ( d < 0 ) {
! 1201: *nr = 0;
! 1202: } else {
! 1203: *nr = r = UPALLOC(d); c = (Q *)r->c;
! 1204: for ( i = 0; i <= d; i++ ) {
! 1205: fi = f[i];
! 1206: for ( j = n-1; j >= 0 && !fi[j]; j-- );
! 1207: j++;
! 1208: if ( j ) {
! 1209: ci = NALLOC(j);
! 1210: PL(ci) = j;
! 1211: bcopy(fi,BD(ci),j*sizeof(unsigned int));
! 1212: NTOQ(ci,1,c[i]);
! 1213: } else
! 1214: c[i] = 0;
! 1215: }
! 1216: for ( i = d; i >= 0 && !c[i]; i-- );
! 1217: if ( i < 0 )
! 1218: *nr = 0;
! 1219: else
! 1220: r->d = i;
! 1221: }
! 1222: }
! 1223:
! 1224: void adj_coefup(n,m,m2,nr)
! 1225: UP n;
! 1226: N m,m2;
! 1227: UP *nr;
! 1228: {
! 1229: int d;
! 1230: Q *c,*cr;
! 1231: Q mq;
! 1232: int i;
! 1233: UP r;
! 1234:
! 1235: if ( !n )
! 1236: *nr = 0;
! 1237: else {
! 1238: d = n->d; c = (Q *)n->c;
! 1239: *nr = r = UPALLOC(d); cr = (Q *)r->c;
! 1240: NTOQ(m,1,mq);
! 1241: for ( i = 0; i <= d; i++ ) {
! 1242: if ( !c[i] )
! 1243: continue;
! 1244: if ( cmpn(NM(c[i]),m2) > 0 )
! 1245: subq(c[i],mq,&cr[i]);
! 1246: else
! 1247: cr[i] = c[i];
! 1248: }
! 1249: for ( i = d; i >= 0 && !cr[i]; i-- );
! 1250: if ( i < 0 )
! 1251: *nr = 0;
! 1252: else
! 1253: r->d = i;
! 1254: }
! 1255: }
! 1256:
! 1257: /* n is assumed to have positive integer coefficients. */
! 1258:
! 1259: void remcup(n,mod,nr)
! 1260: UP n;
! 1261: N mod;
! 1262: UP *nr;
! 1263: {
! 1264: int i,d;
! 1265: Q *c,*cr;
! 1266: UP r;
! 1267: N t;
! 1268:
! 1269: if ( !n )
! 1270: *nr = 0;
! 1271: else {
! 1272: d = n->d; c = (Q *)n->c;
! 1273: *nr = r = UPALLOC(d); cr = (Q *)r->c;
! 1274: for ( i = 0; i <= d; i++ )
! 1275: if ( c[i] ) {
! 1276: remn(NM(c[i]),mod,&t);
! 1277: if ( t )
! 1278: NTOQ(t,1,cr[i]);
! 1279: else
! 1280: cr[i] = 0;
! 1281: } else
! 1282: cr[i] = 0;
! 1283: for ( i = d; i >= 0 && !cr[i]; i-- );
! 1284: if ( i < 0 )
! 1285: *nr = 0;
! 1286: else
! 1287: r->d = i;
! 1288: }
! 1289: }
! 1290:
! 1291: void fft_mulup_main(UP,UP,int,UP *);
! 1292:
! 1293: void fft_mulup(n1,n2,nr)
! 1294: UP n1,n2;
! 1295: UP *nr;
! 1296: {
! 1297: int d1,d2,d,b1,b2,h;
! 1298: UP n1lo,n1hi,n2lo,n2hi,lo,hi,t1,t2,mid1,mid2,mid,s1,s2;
! 1299:
! 1300: if ( !n1 || !n2 )
! 1301: *nr = 0;
! 1302: else {
! 1303: d1 = n1->d; d2 = n2->d;
! 1304: if ( MAX(d1,d2) < up_fft_mag )
! 1305: kmulup(n1,n2,nr);
! 1306: else {
! 1307: b1 = maxblenup(n1); b2 = maxblenup(n2);
! 1308: if ( fft_available(d1,b1,d2,b2) )
! 1309: fft_mulup_main(n1,n2,0,nr);
! 1310: else {
! 1311: d = MAX(d1,d2)+1; h = (d+1)/2;
! 1312: decompup(n1,h,&n1lo,&n1hi);
! 1313: decompup(n2,h,&n2lo,&n2hi);
! 1314: fft_mulup(n1lo,n2lo,&lo);
! 1315: fft_mulup(n1hi,n2hi,&hi);
! 1316: shiftup(hi,2*h,&t2);
! 1317: addup(lo,t2,&t1);
! 1318: addup(hi,lo,&mid1);
! 1319: subup(n1hi,n1lo,&s1); subup(n2lo,n2hi,&s2);
! 1320: fft_mulup(s1,s2,&mid2);
! 1321: addup(mid1,mid2,&mid);
! 1322: shiftup(mid,h,&t2);
! 1323: addup(t1,t2,nr);
! 1324: }
! 1325: }
! 1326: }
! 1327: }
! 1328:
! 1329: void trunc_fft_mulup(n1,n2,dbd,nr)
! 1330: UP n1,n2;
! 1331: int dbd;
! 1332: UP *nr;
! 1333: {
! 1334: int d1,d2,b1,b2,m;
! 1335: UP n1l,n1h,n2l,n2h,l,h,t,s,u;
! 1336:
! 1337: if ( !n1 || !n2 )
! 1338: *nr = 0;
! 1339: else if ( dbd < 0 )
! 1340: error("trunc_fft_mulup : invalid argument");
! 1341: else if ( dbd == 0 )
! 1342: *nr = 0;
! 1343: else {
! 1344: truncup(n1,dbd,&t); n1 = t;
! 1345: truncup(n2,dbd,&t); n2 = t;
! 1346: d1 = n1->d; d2 = n2->d;
! 1347: if ( MAX(d1,d2) < up_fft_mag )
! 1348: tkmulup(n1,n2,dbd,nr);
! 1349: else {
! 1350: b1 = maxblenup(n1); b2 = maxblenup(n2);
! 1351: if ( fft_available(d1,b1,d2,b2) )
! 1352: fft_mulup_main(n1,n2,dbd,nr);
! 1353: else {
! 1354: m = (dbd+1)/2;
! 1355: decompup(n1,m,&n1l,&n1h);
! 1356: decompup(n2,m,&n2l,&n2h);
! 1357: fft_mulup(n1l,n2l,&l);
! 1358: trunc_fft_mulup(n1l,n2h,dbd-m,&t);
! 1359: trunc_fft_mulup(n2l,n1h,dbd-m,&s);
! 1360: addup(t,s,&u);
! 1361: shiftup(u,m,&h);
! 1362: addup(l,h,&t);
! 1363: truncup(t,dbd,nr);
! 1364: }
! 1365: }
! 1366: }
! 1367: }
! 1368:
! 1369: void fft_squareup(n1,nr)
! 1370: UP n1;
! 1371: UP *nr;
! 1372: {
! 1373: int d1,d,h,len,b1;
! 1374: UP n1lo,n1hi,hi,lo,mid1,mid2,mid,s1,t1,t2;
! 1375:
! 1376: if ( !n1 )
! 1377: *nr = 0;
! 1378: else {
! 1379: d1 = n1->d;
! 1380: if ( d1 < up_fft_mag )
! 1381: ksquareup(n1,nr);
! 1382: else {
! 1383: b1 = maxblenup(n1);
! 1384: if ( fft_available(d1,b1,d1,b1) )
! 1385: fft_mulup_main(n1,n1,0,nr);
! 1386: else {
! 1387: d = d1+1; h = (d1+1)/2;
! 1388: decompup(n1,h,&n1lo,&n1hi);
! 1389: fft_squareup(n1hi,&hi);
! 1390: fft_squareup(n1lo,&lo);
! 1391: shiftup(hi,2*h,&t2);
! 1392: addup(lo,t2,&t1);
! 1393: addup(hi,lo,&mid1);
! 1394: subup(n1hi,n1lo,&s1);
! 1395: fft_squareup(s1,&mid2);
! 1396: subup(mid1,mid2,&mid);
! 1397: shiftup(mid,h,&t2);
! 1398: addup(t1,t2,nr);
! 1399: }
! 1400: }
! 1401: }
! 1402: }
! 1403:
! 1404: /*
! 1405: * dbd == 0 => n1 * n2
! 1406: * dbd > 0 => n1 * n2 mod x^dbd
! 1407: * n1 == n2 => squaring
! 1408: */
! 1409:
! 1410: void fft_mulup_main(n1,n2,dbd,nr)
! 1411: UP n1,n2;
! 1412: UP *nr;
! 1413: {
! 1414: ModNum *f1,*f2,*w,*fr;
! 1415: ModNum **frarray,**fa;
! 1416: unsigned int *modarray,*ma;
! 1417: int modarray_len;
! 1418: int frarray_index = 0;
! 1419: N m,m1,m2;
! 1420: int d1,d2,dmin,i,mod,root,d,cond,bound;
! 1421: UP r;
! 1422:
! 1423: if ( !n1 || !n2 ) {
! 1424: *nr = 0; return;
! 1425: }
! 1426: d1 = n1->d; d2 = n2->d; dmin = MIN(d1,d2);
! 1427: if ( !d1 || !d2 ) {
! 1428: mulup(n1,n2,nr); return;
! 1429: }
! 1430: m = ONEN;
! 1431: bound = maxblenup(n1)+maxblenup(n2)+int_bits(dmin)+1;
! 1432: f1 = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
! 1433: if ( n1 == n2 )
! 1434: f2 = 0;
! 1435: else
! 1436: f2 = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
! 1437: w = (ModNum *)MALLOC_ATOMIC(6*(1<<int_bits(d1+d2+1))*sizeof(ModNum));
! 1438: modarray_len = 1024;
! 1439: modarray = (unsigned int *)MALLOC_ATOMIC(modarray_len*sizeof(unsigned int));
! 1440: frarray = (ModNum **)MALLOC(modarray_len*sizeof(ModNum *));
! 1441: for ( i = 0; i < NPrimes; i++ ) {
! 1442: FFT_primes(i,&mod,&root,&d);
! 1443: if ( (1<<d) < d1+d2+1 )
! 1444: continue;
! 1445: if ( frarray_index == modarray_len ) {
! 1446: ma = (unsigned int *)MALLOC_ATOMIC(2*modarray_len*sizeof(unsigned int));
! 1447: bcopy(modarray,ma,modarray_len*sizeof(unsigned int));
! 1448: modarray = ma;
! 1449: fa = (ModNum **)MALLOC(2*modarray_len*sizeof(ModNum *));
! 1450: bcopy(frarray,fa,modarray_len*sizeof(ModNum *));
! 1451: frarray = fa;
! 1452: modarray_len *= 2;
! 1453: }
! 1454: modarray[frarray_index] = mod;
! 1455: frarray[frarray_index++] = fr
! 1456: = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
! 1457: uptofmarray(mod,n1,f1);
! 1458: if ( !f2 )
! 1459: cond = FFT_pol_square(d1,f1,fr,i,w);
! 1460: else {
! 1461: uptofmarray(mod,n2,f2);
! 1462: cond = FFT_pol_product(d1,f1,d2,f2,fr,i,w);
! 1463: }
! 1464: if ( cond )
! 1465: error("fft_mulup : error in FFT_pol_product");
! 1466: STON(mod,m1); muln(m,m1,&m2); m = m2;
! 1467: if ( n_bits(m) > bound ) {
! 1468: if ( !dbd )
! 1469: dbd = d1+d2+1;
! 1470: crup(frarray,MIN(d1+d2,dbd-1),modarray,frarray_index,m,&r);
! 1471: divin(m,2,&m2);
! 1472: adj_coefup(r,m,m2,nr);
! 1473: return;
! 1474: }
! 1475: }
! 1476: error("fft_mulup : FFT_primes exhausted");
! 1477: }
! 1478: #if 0
! 1479: /* inefficient version */
! 1480:
! 1481: void crup(f,d,mod,index,m,r)
! 1482: ModNum **f;
! 1483: int d;
! 1484: int *mod;
! 1485: int index;
! 1486: N m;
! 1487: UP *r;
! 1488: {
! 1489: N *cof,*c;
! 1490: int *inv;
! 1491: struct oUP w;
! 1492: int i;
! 1493: UP s,s1,s2;
! 1494: N t;
! 1495: UP *g;
! 1496: Q q;
! 1497: struct oEGT eg0,eg1;
! 1498:
! 1499: get_eg(&eg0);
! 1500: w.d = 0;
! 1501: inv = (int *)ALLOCA(index*sizeof(int));
! 1502: cof = (N *)ALLOCA(index*sizeof(N));
! 1503: c = (N *)ALLOCA(index*sizeof(N));
! 1504: g = (UP *)ALLOCA(index*sizeof(UP));
! 1505: up_lazy = 1;
! 1506: for ( i = 0, s = 0; i < index; i++ ) {
! 1507: divin(m,mod[i],&cof[i]);
! 1508: inv[i] = invm(rem(cof[i],mod[i]),mod[i]);
! 1509: STON(inv[i],t);
! 1510: muln(cof[i],t,&c[i]);
! 1511: NTOQ(c[i],1,q); w.c[0] = (Num)q;
! 1512: fmarraytoup(f[i],d,&g[i]);
! 1513: mulup(g[i],&w,&s1);
! 1514: addup(s,s1,&s2);
! 1515: s = s2;
! 1516: }
! 1517: up_lazy = 0;
! 1518: remcup(s,m,r);
! 1519: get_eg(&eg1);
! 1520: add_eg(&eg_chrem,&eg0,&eg1);
! 1521: }
! 1522:
! 1523: #else
! 1524: /* improved version */
! 1525:
! 1526: void crup(f,d,mod,index,m,r)
! 1527: ModNum **f;
! 1528: int d;
! 1529: int *mod;
! 1530: int index;
! 1531: N m;
! 1532: UP *r;
! 1533: {
! 1534: N cof,c,t,w,w1;
! 1535: struct oN fc;
! 1536: N *s;
! 1537: UP u;
! 1538: Q q;
! 1539: int inv,i,j,rlen;
! 1540:
! 1541: rlen = PL(m)+10; /* XXX */
! 1542: PL(&fc) = 1;
! 1543: c = NALLOC(rlen);
! 1544: w = NALLOC(rlen);
! 1545: w1 = NALLOC(rlen);
! 1546: s = (N *)MALLOC((d+1)*sizeof(N));
! 1547: for ( i = 0; i <= d; i++ ) {
! 1548: s[i] = NALLOC(rlen);
! 1549: PL(s[i]) = 0;
! 1550: bzero(BD(s[i]),rlen*sizeof(unsigned int));
! 1551: }
! 1552: for ( i = 0; i < index; i++ ) {
! 1553: divin(m,mod[i],&cof);
! 1554: inv = invm(rem(cof,mod[i]),mod[i]); STON(inv,t);
! 1555: _muln(cof,t,c);
! 1556: /* s += c*f[i] */
! 1557: for ( j = 0; j <= d; j++ )
! 1558: if ( f[i][j] ) {
! 1559: BD(&fc)[0] = f[i][j];
! 1560: _muln(c,&fc,w);
! 1561: _addn(s[j],w,w1);
! 1562: dupn(w1,s[j]);
! 1563: }
! 1564: }
! 1565: for ( i = d; i >= 0; i-- )
! 1566: if ( s[i] )
! 1567: break;
! 1568: if ( i < 0 )
! 1569: *r = 0;
! 1570: else {
! 1571: u = UPALLOC(i);
! 1572: DEG(u) = i;
! 1573: for ( j = 0; j <= i; j++ ) {
! 1574: if ( PL(s[j]) )
! 1575: NTOQ(s[j],1,q);
! 1576: else
! 1577: q = 0;
! 1578: COEF(u)[j] = (Num)q;
! 1579: }
! 1580: remcup(u,m,r);
! 1581: }
! 1582: }
! 1583: #endif
! 1584:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>