Annotation of OpenXM_contrib2/asir2000/engine/up.c, Revision 1.1.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>