Annotation of OpenXM_contrib2/asir2000/builtin/poly.c, Revision 1.1.1.1
1.1 noro 1: /* $OpenXM: OpenXM/src/asir99/builtin/poly.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
2: #include "ca.h"
3: #include "parse.h"
4: #include "base.h"
5:
6: void Pranp();
7:
8: void Pumul(),Pumul_ff(),Pusquare(),Pusquare_ff(),Putmul(),Putmul_ff();
9: void Pkmul(),Pksquare(),Pktmul();
10: void Pord(), Pcoef0(), Pcoef(), Pdeg(), Pmindeg(), Psetmod();
11: void Pcoef_gf2n();
12: void getcoef(), getdeglist(), mergedeglist(), change_mvar(), restore_mvar();
13:
14: void Pp_mag();
15: void Pmergelist(), Pch_mv(), Pre_mv(), Pdeglist();
16: void Pptomp(),Pmptop();
17: void Pptolmp(),Plmptop();
18: void Pptogf2n(),Pgf2ntop(),Pgf2ntovect();
19: void Pptogfpn(),Pgfpntop();
20: void Pfind_root_gf2n();
21:
22: void Pureverse(),Putrunc(),Pudecomp(),Purembymul(),Purembymul_precomp();
23: void Puinvmod(),Purevinvmod();
24: void Ppwrmod_ff(),Ppwrtab_ff(),Pgeneric_pwrmod_ff();
25: void Pkpwrmod_lm(),Pkpwrtab_lm(),Pkgeneric_pwrmod_lm();
26:
27: void Pkmulum();
28: void Pksquareum();
29:
30: void Pfmultest();
31: void Phfmul_lm();
32: void Plazy_lm();
33:
34: void Psetmod_ff();
35: void Psimp_ff();
36: void Pextdeg_ff();
37: void Pcharacteristic_ff();
38: void Pfield_type_ff();
39: void Pfield_order_ff();
40: void Prandom_ff();
41:
42: void Ptracemod_gf2n();
43: void Psparsemod_gf2n();
44: void Pmultest_gf2n();
45: void Psquaretest_gf2n();
46: void Pinvtest_gf2n();
47: void Pbininv_gf2n();
48: void Prinvtest_gf2n();
49: void Pis_irred_gf2();
50: void Pis_irred_ddd_gf2();
51:
52: void simp_ff(Obj,Obj *);
53: void ranp(int,UP *);
54: void field_order_ff(N *);
55:
56: extern int current_mod;
57: extern GEN_UP2 current_mod_gf2n;
58: extern int lm_lazy;
59:
60: int current_ff;
61:
62: struct ftab poly_tab[] = {
63: {"ranp",Pranp,2},
64: {"p_mag",Pp_mag,1},
65: {"ord",Pord,-1},
66: {"coef0",Pcoef0,-3},
67: {"coef",Pcoef,-3},
68: {"coef_gf2n",Pcoef_gf2n,2},
69: {"deg",Pdeg,2},
70: {"mindeg",Pmindeg,2},
71: {"setmod",Psetmod,-1},
72:
73: {"sparsemod_gf2n",Psparsemod_gf2n,-1},
74:
75: {"setmod_ff",Psetmod_ff,-2},
76: {"simp_ff",Psimp_ff,1},
77: {"extdeg_ff",Pextdeg_ff,0},
78: {"characteristic_ff",Pcharacteristic_ff,0},
79: {"field_type_ff",Pfield_type_ff,0},
80: {"field_order_ff",Pfield_order_ff,0},
81: {"random_ff",Prandom_ff,0},
82:
83: {"deglist",Pdeglist,2},
84: {"mergelist",Pmergelist,2},
85: {"ch_mv",Pch_mv,2},
86: {"re_mv",Pre_mv,2},
87:
88: {"ptomp",Pptomp,2},
89: {"mptop",Pmptop,1},
90:
91: {"ptolmp",Pptolmp,1},
92: {"lmptop",Plmptop,1},
93:
94: {"ptogf2n",Pptogf2n,1},
95: {"gf2ntop",Pgf2ntop,-2},
96: {"gf2ntovect",Pgf2ntovect,1},
97:
98: {"ptogfpn",Pptogfpn,1},
99: {"gfpntop",Pgfpntop,-2},
100:
101: {"kmul",Pkmul,2},
102: {"ksquare",Pksquare,1},
103: {"ktmul",Pktmul,3},
104:
105: {"umul",Pumul,2},
106: {"usquare",Pusquare,1},
107: {"ureverse_inv_as_power_series",Purevinvmod,2},
108: {"uinv_as_power_series",Puinvmod,2},
109:
110: {"utmul",Putmul,3},
111: {"umul_ff",Pumul_ff,2},
112: {"usquare_ff",Pusquare_ff,1},
113: {"utmul_ff",Putmul_ff,3},
114:
115: /* for historical reason */
116: {"trunc",Putrunc,2},
117: {"decomp",Pudecomp,2},
118:
119: {"utrunc",Putrunc,2},
120: {"udecomp",Pudecomp,2},
121: {"ureverse",Pureverse,1},
122: {"urembymul",Purembymul,2},
123: {"urembymul_precomp",Purembymul_precomp,3},
124:
125: {"lazy_lm",Plazy_lm,1},
126: {"lazy_ff",Plazy_lm,1},
127:
128: {"pwrmod_ff",Ppwrmod_ff,1},
129: {"generic_pwrmod_ff",Pgeneric_pwrmod_ff,3},
130: {"pwrtab_ff",Ppwrtab_ff,2},
131:
132: {"tracemod_gf2n",Ptracemod_gf2n,3},
133: {"b_find_root_gf2n",Pfind_root_gf2n,1},
134:
135: {"is_irred_gf2",Pis_irred_gf2,1},
136: {"is_irred_ddd_gf2",Pis_irred_ddd_gf2,1},
137:
138: {"kpwrmod_lm",Pkpwrmod_lm,1},
139: {"kgeneric_pwrmod_lm",Pkgeneric_pwrmod_lm,3},
140: {"kpwrtab_lm",Pkpwrtab_lm,2},
141:
142: {"kmulum",Pkmulum,3},
143: {"ksquareum",Pksquareum,2},
144:
145: {"fmultest",Pfmultest,3},
146: {"hfmul_lm",Phfmul_lm,2},
147:
148: {"multest_gf2n",Pmultest_gf2n,2},
149: {"squaretest_gf2n",Psquaretest_gf2n,1},
150: {"bininv_gf2n",Pbininv_gf2n,2},
151: {"invtest_gf2n",Pinvtest_gf2n,1},
152: {"rinvtest_gf2n",Prinvtest_gf2n,0},
153: {0,0,0},
154: };
155:
156: extern V up_var;
157:
158: void Pranp(arg,rp)
159: NODE arg;
160: P *rp;
161: {
162: int n;
163: UP c;
164:
165: n = QTOS((Q)ARG0(arg));
166: ranp(n,&c);
167: if ( c ) {
168: up_var = VR((P)ARG1(arg));
169: uptop(c,rp);
170: } else
171: *rp = 0;
172: }
173:
174: void ranp(n,nr)
175: int n;
176: UP *nr;
177: {
178: int i;
179: unsigned int r;
180: Q q;
181: UP c;
182:
183: *nr = c = UPALLOC(n);
184: for ( i = 0; i <= n; i++ ) {
185: r = random();
186: UTOQ(r,q);
187: c->c[i] = (Num)q;
188: }
189: for ( i = n; i >= 0 && !c->c[i]; i-- );
190: if ( i >= 0 )
191: c->d = i;
192: else
193: *nr = 0;
194: }
195:
196: void Pp_mag(arg,rp)
197: NODE arg;
198: Q *rp;
199: {
200: int l;
201: l = p_mag(ARG0(arg));
202: STOQ(l,*rp);
203: }
204:
205: void Pord(arg,listp)
206: NODE arg;
207: LIST *listp;
208: {
209: NODE n,tn;
210: LIST l;
211: VL vl,tvl,svl;
212: P t;
213: int i,j;
214: V *va;
215: V v;
216:
217: if ( argc(arg) ) {
218: asir_assert(ARG0(arg),O_LIST,"ord");
219: for ( vl = 0, i = 0, n = BDY((LIST)ARG0(arg));
220: n; n = NEXT(n), i++ ) {
221: if ( !vl ) {
222: NEWVL(vl); tvl = vl;
223: } else {
224: NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
225: }
226: if ( !(t = (P)BDY(n)) || (OID(t) != O_P) )
227: error("ord : invalid argument");
228: VR(tvl) = VR(t);
229: }
230: va = (V *)ALLOCA(i*sizeof(V));
231: for ( j = 0, svl = vl; j < i; j++, svl = NEXT(svl) )
232: va[j] = VR(svl);
233: for ( svl = CO; svl; svl = NEXT(svl) ) {
234: v = VR(svl);
235: for ( j = 0; j < i; j++ )
236: if ( v == va[j] )
237: break;
238: if ( j == i ) {
239: if ( !vl ) {
240: NEWVL(vl); tvl = vl;
241: } else {
242: NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
243: }
244: VR(tvl) = v;
245: }
246: }
247: if ( vl )
248: NEXT(tvl) = 0;
249: CO = vl;
250: }
251: for ( n = 0, vl = CO; vl; vl = NEXT(vl) ) {
252: NEXTNODE(n,tn); MKV(VR(vl),t); BDY(tn) = (pointer)t;
253: }
254: NEXT(tn) = 0; MKLIST(l,n); *listp = l;
255: }
256:
257: void Pcoef0(arg,rp)
258: NODE arg;
259: Obj *rp;
260: {
261: Obj t,n;
262: P s;
263: DCP dc;
264: int id;
265: V v;
266: VL vl;
267:
268: if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
269: *rp = 0;
270: else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
271: *rp = 0;
272: else if ( id == O_N )
273: if ( !n )
274: *rp = t;
275: else
276: *rp = 0;
277: else {
278: if ( argc(arg) == 3 ) {
279: if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
280: reordvar(CO,v,&vl); reorderp(vl,CO,(P)t,&s);
281: } else
282: s = (P)t;
283: if ( VR(s) != v ) {
284: if ( n )
285: *rp = 0;
286: else
287: *rp = t;
288: return;
289: }
290: } else
291: s = (P)t;
292: for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
293: if ( dc )
294: *rp = (Obj)COEF(dc);
295: else
296: *rp = 0;
297: }
298: }
299:
300: void Pcoef(arg,rp)
301: NODE arg;
302: Obj *rp;
303: {
304: Obj t,n;
305: P s;
306: DCP dc;
307: int id;
308: V v;
309:
310: if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
311: *rp = 0;
312: else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
313: *rp = 0;
314: else if ( id == O_N ) {
315: if ( !n )
316: *rp = t;
317: else
318: *rp = 0;
319: } else {
320: if ( argc(arg) == 3 ) {
321: if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
322: getcoef(CO,(P)t,v,(Q)n,(P *)rp); return;
323: } else
324: s = (P)t;
325: if ( VR(s) != v ) {
326: if ( n )
327: *rp = 0;
328: else
329: *rp = t;
330: return;
331: }
332: } else
333: s = (P)t;
334: for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
335: if ( dc )
336: *rp = (Obj)COEF(dc);
337: else
338: *rp = 0;
339: }
340: }
341:
342: void Pcoef_gf2n(arg,rp)
343: NODE arg;
344: Obj *rp;
345: {
346: Obj t,n;
347: int id,d;
348: UP2 up2;
349:
350: if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
351: *rp = 0;
352: else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
353: *rp = 0;
354: else if ( id == O_N && NID((Num)t) == N_GF2N ) {
355: d = QTOS((Q)n);
356: up2 = ((GF2N)t)->body;
357: if ( d > degup2(up2) )
358: *rp = 0;
359: else
360: *rp = (Obj)(up2->b[d/BSH]&(((unsigned long)1)<<(d%BSH))?ONE:0);
361: } else
362: *rp = 0;
363: }
364:
365: void Pdeg(arg,rp)
366: NODE arg;
367: Q *rp;
368: {
369: Obj t,v;
370: int d;
371:
372: #if 0
373: if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
374: *rp = 0;
375: else if ( !(v = (Obj)ARG1(arg)) || (VR((P)v) != VR((P)t)) )
376: *rp = 0;
377: else
378: *rp = (Obj)DEG(DC((P)t));
379: #endif
380: if ( !(t = (Obj)ARG0(arg)) )
381: STOQ(-1,*rp);
382: else if ( OID(t) != O_P ) {
383: if ( OID(t) == O_N && NID(t) == N_GF2N
384: && (v=(Obj)ARG1(arg)) && OID(v)== O_N && NID(v) == N_GF2N ) {
385: d = degup2(((GF2N)t)->body);
386: STOQ(d,*rp);
387: } else
388: *rp = 0;
389: } else
390: degp(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
391: }
392:
393: void Pmindeg(arg,rp)
394: NODE arg;
395: Q *rp;
396: {
397: Obj t;
398:
399: if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
400: *rp = 0;
401: else
402: getmindeg(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
403: }
404:
405: void Psetmod(arg,rp)
406: NODE arg;
407: Q *rp;
408: {
409: if ( arg ) {
410: asir_assert(ARG0(arg),O_N,"setmod");
411: current_mod = QTOS((Q)ARG0(arg));
412: }
413: STOQ(current_mod,*rp);
414: }
415:
416: void Psparsemod_gf2n(arg,rp)
417: NODE arg;
418: Q *rp;
419: {
420: int id;
421:
422: if ( arg && current_mod_gf2n )
423: current_mod_gf2n->id = ARG0(arg)?1:0;
424: if ( !current_mod_gf2n )
425: id = -1;
426: else
427: id = current_mod_gf2n->id;
428: STOQ(id,*rp);
429: }
430:
431: void Pmultest_gf2n(arg,rp)
432: NODE arg;
433: GF2N *rp;
434: {
435: GF2N a,b,c;
436: int i;
437:
438: a = (GF2N)ARG0(arg); b = (GF2N)ARG0(arg);
439: for ( i = 0; i < 10000; i++ )
440: mulgf2n(a,b,&c);
441: *rp = c;
442: }
443:
444: void Psquaretest_gf2n(arg,rp)
445: NODE arg;
446: GF2N *rp;
447: {
448: GF2N a,c;
449: int i;
450:
451: a = (GF2N)ARG0(arg);
452: for ( i = 0; i < 10000; i++ )
453: squaregf2n(a,&c);
454: *rp = c;
455: }
456:
457: void Pinvtest_gf2n(arg,rp)
458: NODE arg;
459: GF2N *rp;
460: {
461: GF2N a,c;
462: int i;
463:
464: a = (GF2N)ARG0(arg);
465: for ( i = 0; i < 10000; i++ )
466: invgf2n(a,&c);
467: *rp = c;
468: }
469:
470: void Pbininv_gf2n(arg,rp)
471: NODE arg;
472: GF2N *rp;
473: {
474: UP2 a,inv;
475: int n;
476:
477: a = ((GF2N)ARG0(arg))->body;
478: n = QTOS((Q)ARG1(arg));
479: type1_bin_invup2(a,n,&inv);
480: MKGF2N(inv,*rp);
481: }
482:
483: void Prinvtest_gf2n(rp)
484: Real *rp;
485: {
486: GF2N *a;
487: GF2N c;
488: double t0,t1,r;
489: int i;
490: double get_clock();
491:
492: a = (GF2N *)ALLOCA(1000*sizeof(GF2N));
493: for ( i = 0; i < 1000; i++ ) {
494: randomgf2n(&a[i]);
495: }
496: t0 = get_clock();
497: for ( i = 0; i < 1000; i++ )
498: invgf2n(a[i],&c);
499: t1 = get_clock();
500: r = (t1-t0)/1000;
501: MKReal(r,*rp);
502: }
503:
504: void Pfind_root_gf2n(arg,rp)
505: NODE arg;
506: GF2N *rp;
507: {
508:
509: #if 0
510: UP p;
511:
512: ptoup((P)ARG0(arg),&p);
513: find_root_gf2n(p,rp);
514: #else
515: UP2 p;
516:
517: ptoup2((P)ARG0(arg),&p);
518: find_root_up2(p,rp);
519: #endif
520: }
521:
522: void Pis_irred_gf2(arg,rp)
523: NODE arg;
524: Q *rp;
525: {
526: UP2 t;
527:
528: ptoup2(ARG0(arg),&t);
529: *rp = irredcheckup2(t) ? ONE : 0;
530: }
531:
532: void Pis_irred_ddd_gf2(arg,rp)
533: NODE arg;
534: Q *rp;
535: {
536: UP2 t;
537: int ret;
538:
539: ptoup2(ARG0(arg),&t);
540: ret = irredcheck_dddup2(t);
541: STOQ(ret,*rp);
542: }
543:
544: void Psetmod_ff(arg,rp)
545: NODE arg;
546: Obj *rp;
547: {
548: int ac;
549: Obj mod,defpoly;
550: N n;
551: UP up;
552: UP2 up2;
553: Q q;
554: P p;
555: NODE n0,n1;
556: LIST list;
557:
558: ac = argc(arg);
559: if ( ac == 1 ) {
560: mod = (Obj)ARG0(arg);
561: if ( !mod )
562: error("setmod_ff : invalid argument");
563: switch ( OID(mod) ) {
564: case O_N:
565: current_ff = FF_GFP;
566: setmod_lm(NM((Q)mod)); break;
567: case O_P:
568: current_ff = FF_GF2N;
569: setmod_gf2n((P)mod); break;
570: default:
571: error("setmod_ff : invalid argument");
572: }
573: } else if ( ac == 2 ) {
574: current_ff = FF_GFPN;
575: defpoly = (Obj)ARG0(arg);
576: mod = (Obj)ARG1(arg);
577: if ( !mod || !defpoly )
578: error("setmod_ff : invalid argument");
579: setmod_lm(NM((Q)mod));
580: setmod_gfpn((P)defpoly);
581: }
582: switch ( current_ff ) {
583: case FF_GFP:
584: getmod_lm(&n); NTOQ(n,1,q); *rp = (Obj)q; break;
585: case FF_GF2N:
586: getmod_gf2n(&up2); up2top(up2,&p); *rp = (Obj)p; break;
587: case FF_GFPN:
588: getmod_lm(&n); NTOQ(n,1,q);
589: getmod_gfpn(&up); uptop(up,&p);
590: MKNODE(n1,q,0); MKNODE(n0,p,n1);
591: MKLIST(list,n0);
592: *rp = (Obj)list; break;
593: default:
594: *rp = 0; break;
595: }
596: }
597:
598: void Pextdeg_ff(rp)
599: Q *rp;
600: {
601: int d;
602: UP2 up2;
603: UP up;
604:
605: switch ( current_ff ) {
606: case FF_GFP:
607: *rp = ONE; break;
608: case FF_GF2N:
609: getmod_gf2n(&up2); d = degup2(up2); STOQ(d,*rp); break;
610: case FF_GFPN:
611: getmod_gfpn(&up); STOQ(up->d,*rp); break;
612: default:
613: error("extdeg_ff : current_ff is not set");
614: }
615: }
616:
617: void Pcharacteristic_ff(rp)
618: Q *rp;
619: {
620: N lm;
621:
622: switch ( current_ff ) {
623: case FF_GFP:
624: case FF_GFPN:
625: getmod_lm(&lm); NTOQ(lm,1,*rp); break;
626: case FF_GF2N:
627: STOQ(2,*rp); break;
628: default:
629: error("characteristic_ff : current_ff is not set");
630: }
631: }
632:
633: void Pfield_type_ff(rp)
634: Q *rp;
635: {
636: STOQ(current_ff,*rp);
637: }
638:
639: void Pfield_order_ff(rp)
640: Q *rp;
641: {
642: N n;
643:
644: field_order_ff(&n);
645: NTOQ(n,1,*rp);
646: }
647:
648: void field_order_ff(order)
649: N *order;
650: {
651: UP2 up2;
652: UP up;
653: N m;
654: int d,w;
655:
656: switch ( current_ff ) {
657: case FF_GFP:
658: getmod_lm(order); break;
659: case FF_GF2N:
660: getmod_gf2n(&up2); d = degup2(up2);
661: w = (d>>5)+1;
662: *order = m = NALLOC(w);
663: PL(m)=w;
664: bzero((char *)BD(m),w*sizeof(unsigned int));
665: BD(m)[d>>5] |= 1<<(d&31);
666: break;
667: case FF_GFPN:
668: getmod_lm(&m);
669: getmod_gfpn(&up); pwrn(m,up->d,order); break;
670: default:
671: error("field_order_ff : current_ff is not set");
672: }
673: }
674:
675: void Prandom_ff(rp)
676: Obj *rp;
677: {
678: LM l;
679: GF2N g;
680: GFPN p;
681:
682: switch ( current_ff ) {
683: case FF_GFP:
684: random_lm(&l); *rp = (Obj)l; break;
685: case FF_GF2N:
686: randomgf2n(&g); *rp = (Obj)g; break;
687: case FF_GFPN:
688: randomgfpn(&p); *rp = (Obj)p; break;
689: default:
690: error("random_ff : current_ff is not set");
691: }
692: }
693:
694: void Psimp_ff(arg,rp)
695: NODE arg;
696: Obj *rp;
697: {
698: LM r;
699: GF2N rg;
700: extern lm_lazy;
701:
702: simp_ff((Obj)ARG0(arg),rp);
703: }
704:
705: void simp_ff(p,rp)
706: Obj p;
707: Obj *rp;
708: {
709: Num n;
710: LM r,s;
711: DCP dc,dcr0,dcr;
712: GF2N rg,sg;
713: GFPN rpn,spn;
714: P t;
715: Obj obj;
716:
717: lm_lazy = 0;
718: if ( !p )
719: *rp = 0;
720: else if ( OID(p) == O_N ) {
721: switch ( current_ff ) {
722: case FF_GFP:
723: ptolmp((P)p,&t); simplm((LM)t,&s); *rp = (Obj)s;
724: break;
725: case FF_GF2N:
726: ptogf2n((Obj)p,&rg); simpgf2n((GF2N)rg,&sg); *rp = (Obj)sg;
727: break;
728: case FF_GFPN:
729: ntogfpn((Obj)p,&rpn); simpgfpn((GFPN)rpn,&spn); *rp = (Obj)spn;
730: break;
731: default:
732: *rp = (Obj)p;
733: break;
734: }
735: } else if ( OID(p) == O_P ) {
736: for ( dc = DC((P)p), dcr0 = 0; dc; dc = NEXT(dc) ) {
737: simp_ff((Obj)COEF(dc),&obj);
738: if ( obj ) {
739: NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc); COEF(dcr) = (P)obj;
740: }
741: }
742: if ( !dcr0 )
743: *rp = 0;
744: else {
745: NEXT(dcr) = 0; MKP(VR((P)p),dcr0,t); *rp = (Obj)t;
746: }
747: } else
748: error("simp_ff : not implemented yet");
749: }
750:
751: void getcoef(vl,p,v,d,r)
752: VL vl;
753: P p;
754: V v;
755: Q d;
756: P *r;
757: {
758: P s,t,u,a,b,x;
759: DCP dc;
760: V w;
761:
762: if ( !p )
763: *r = 0;
764: else if ( NUM(p) )
765: *r = d ? 0 : p;
766: else if ( (w=VR(p)) == v ) {
767: for ( dc = DC(p); dc && cmpq(DEG(dc),d); dc = NEXT(dc) );
768: *r = dc ? COEF(dc) : 0;
769: } else {
770: MKV(w,x);
771: for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
772: getcoef(vl,COEF(dc),v,d,&t);
773: if ( t ) {
774: pwrp(vl,x,DEG(dc),&u); mulp(vl,t,u,&a);
775: addp(vl,s,a,&b); s = b;
776: }
777: }
778: *r = s;
779: }
780: }
781:
782: void Pdeglist(arg,rp)
783: NODE arg;
784: LIST *rp;
785: {
786: NODE d;
787:
788: getdeglist((P)ARG0(arg),VR((P)ARG1(arg)),&d);
789: MKLIST(*rp,d);
790: }
791:
792: void Pch_mv(arg,rp)
793: NODE arg;
794: P *rp;
795: {
796: change_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
797: }
798:
799: void Pre_mv(arg,rp)
800: NODE arg;
801: P *rp;
802: {
803: restore_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
804: }
805:
806: void change_mvar(vl,p,v,r)
807: VL vl;
808: P p;
809: V v;
810: P *r;
811: {
812: Q d;
813: DCP dc,dc0;
814: NODE dl;
815:
816: if ( !p || NUM(p) || (VR(p) == v) )
817: *r = p;
818: else {
819: getdeglist(p,v,&dl);
820: for ( dc0 = 0; dl; dl = NEXT(dl) ) {
821: NEXTDC(dc0,dc); DEG(dc) = d = (Q)BDY(dl);
822: getcoef(vl,p,v,d,&COEF(dc));
823: }
824: NEXT(dc) = 0; MKP(v,dc0,*r);
825: }
826: }
827:
828: void restore_mvar(vl,p,v,r)
829: VL vl;
830: P p;
831: V v;
832: P *r;
833: {
834: P s,u,a,b,x;
835: DCP dc;
836:
837: if ( !p || NUM(p) || (VR(p) != v) )
838: *r = p;
839: else {
840: MKV(v,x);
841: for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
842: pwrp(vl,x,DEG(dc),&u); mulp(vl,COEF(dc),u,&a);
843: addp(vl,s,a,&b); s = b;
844: }
845: *r = s;
846: }
847: }
848:
849: void getdeglist(p,v,d)
850: P p;
851: V v;
852: NODE *d;
853: {
854: NODE n,n0,d0,d1,d2;
855: DCP dc;
856:
857: if ( !p || NUM(p) ) {
858: MKNODE(n,0,0); *d = n;
859: } else if ( VR(p) == v ) {
860: for ( n0 = 0, dc = DC(p); dc; dc = NEXT(dc) ) {
861: NEXTNODE(n0,n); BDY(n) = (pointer)DEG(dc);
862: }
863: NEXT(n) = 0; *d = n0;
864: } else {
865: for ( dc = DC(p), d0 = 0; dc; dc = NEXT(dc) ) {
866: getdeglist(COEF(dc),v,&d1); mergedeglist(d0,d1,&d2); d0 = d2;
867: }
868: *d = d0;
869: }
870: }
871: void Pmergelist(arg,rp)
872: NODE arg;
873: LIST *rp;
874: {
875: NODE n;
876:
877: asir_assert(ARG0(arg),O_LIST,"mergelist");
878: asir_assert(ARG1(arg),O_LIST,"mergelist");
879: mergedeglist(BDY((LIST)ARG0(arg)),BDY((LIST)ARG1(arg)),&n);
880: MKLIST(*rp,n);
881: }
882:
883: void mergedeglist(d0,d1,dr)
884: NODE d0,d1,*dr;
885: {
886: NODE t0,t,dt;
887: Q d;
888: int c;
889:
890: if ( !d0 )
891: *dr = d1;
892: else {
893: while ( d1 ) {
894: dt = d1; d1 = NEXT(d1); d = (Q)BDY(dt);
895: for ( t0 = 0, t = d0; t; t0 = t, t = NEXT(t) ) {
896: c = cmpq(d,(Q)BDY(t));
897: if ( !c )
898: break;
899: else if ( c > 0 ) {
900: if ( !t0 ) {
901: NEXT(dt) = d0; d0 = dt;
902: } else {
903: NEXT(t0) = dt; NEXT(dt) = t;
904: }
905: break;
906: }
907: }
908: if ( !t ) {
909: NEXT(t0) = dt; *dr = d0; return;
910: }
911: }
912: *dr = d0;
913: }
914: }
915:
916: void Pptomp(arg,rp)
917: NODE arg;
918: P *rp;
919: {
920: ptomp(QTOS((Q)ARG1(arg)),(P)ARG0(arg),rp);
921: }
922:
923: void Pmptop(arg,rp)
924: NODE arg;
925: P *rp;
926: {
927: mptop((P)ARG0(arg),rp);
928: }
929:
930: void Pptolmp(arg,rp)
931: NODE arg;
932: P *rp;
933: {
934: ptolmp((P)ARG0(arg),rp);
935: }
936:
937: void Plmptop(arg,rp)
938: NODE arg;
939: P *rp;
940: {
941: lmptop((P)ARG0(arg),rp);
942: }
943:
944: void Pptogf2n(arg,rp)
945: NODE arg;
946: GF2N *rp;
947: {
948: ptogf2n((Obj)ARG0(arg),rp);
949: }
950:
951: void Pgf2ntop(arg,rp)
952: NODE arg;
953: P *rp;
954: {
955: extern V up2_var;
956:
957: if ( argc(arg) == 2 )
958: up2_var = VR((P)ARG1(arg));
959: gf2ntop((GF2N)ARG0(arg),rp);
960: }
961:
962: void Pgf2ntovect(arg,rp)
963: NODE arg;
964: VECT *rp;
965: {
966: gf2ntovect((GF2N)ARG0(arg),rp);
967: }
968:
969: void Pptogfpn(arg,rp)
970: NODE arg;
971: GF2N *rp;
972: {
973: ptogfpn((Obj)ARG0(arg),rp);
974: }
975:
976: void Pgfpntop(arg,rp)
977: NODE arg;
978: P *rp;
979: {
980: extern V up_var;
981:
982: if ( argc(arg) == 2 )
983: up_var = VR((P)ARG1(arg));
984: gfpntop((GFPN)ARG0(arg),rp);
985: }
986:
987: void Pureverse(arg,rp)
988: NODE arg;
989: P *rp;
990: {
991: UP p,r;
992:
993: ptoup((P)ARG0(arg),&p);
994: reverseup(p,p->d,&r);
995: uptop(r,rp);
996: }
997:
998: void Putrunc(arg,rp)
999: NODE arg;
1000: P *rp;
1001: {
1002: UP p,r;
1003:
1004: ptoup((P)ARG0(arg),&p);
1005: truncup(p,QTOS((Q)ARG1(arg))+1,&r);
1006: uptop(r,rp);
1007: }
1008:
1009: void Pudecomp(arg,rp)
1010: NODE arg;
1011: LIST *rp;
1012: {
1013: P u,l;
1014: UP p,up,low;
1015: NODE n0,n1;
1016:
1017: ptoup((P)ARG0(arg),&p);
1018: decompup(p,QTOS((Q)ARG1(arg))+1,&low,&up);
1019: uptop(low,&l);
1020: uptop(up,&u);
1021: MKNODE(n1,u,0); MKNODE(n0,l,n1);
1022: MKLIST(*rp,n0);
1023: }
1024:
1025: void Purembymul(arg,rp)
1026: NODE arg;
1027: P *rp;
1028: {
1029: UP p1,p2,r;
1030:
1031: if ( !ARG0(arg) || !ARG1(arg) )
1032: *rp = 0;
1033: else {
1034: ptoup((P)ARG0(arg),&p1);
1035: ptoup((P)ARG1(arg),&p2);
1036: rembymulup(p1,p2,&r);
1037: uptop(r,rp);
1038: }
1039: }
1040:
1041: /*
1042: * d1 = deg(p1), d2 = deg(p2)
1043: * d1 <= 2*d2-1
1044: * p2*inv = 1 mod x^d2
1045: */
1046:
1047: void Purembymul_precomp(arg,rp)
1048: NODE arg;
1049: P *rp;
1050: {
1051: UP p1,p2,inv,r;
1052:
1053: if ( !ARG0(arg) || !ARG1(arg) )
1054: *rp = 0;
1055: else {
1056: ptoup((P)ARG0(arg),&p1);
1057: ptoup((P)ARG1(arg),&p2);
1058: ptoup((P)ARG2(arg),&inv);
1059: if ( p1->d >= 2*p2->d ) {
1060: error("urembymul_precomp : degree of 1st arg is too large");
1061: /* fprintf(stderr,"urembymul_precomp : degree of 1st arg is too large"); */
1062: remup(p1,p2,&r);
1063: } else
1064: hybrid_rembymulup_special(current_ff,p1,p2,inv,&r);
1065: uptop(r,rp);
1066: }
1067: }
1068:
1069: void Puinvmod(arg,rp)
1070: NODE arg;
1071: P *rp;
1072: {
1073: UP p,r;
1074:
1075: ptoup((P)ARG0(arg),&p);
1076: invmodup(p,QTOS((Q)ARG1(arg)),&r);
1077: uptop(r,rp);
1078: }
1079:
1080: void Purevinvmod(arg,rp)
1081: NODE arg;
1082: P *rp;
1083: {
1084: UP p,pr,r;
1085:
1086: ptoup((P)ARG0(arg),&p);
1087: reverseup(p,p->d,&pr);
1088: invmodup(pr,QTOS((Q)ARG1(arg)),&r);
1089: uptop(r,rp);
1090: }
1091:
1092: void Ppwrmod_ff(arg,rp)
1093: NODE arg;
1094: P *rp;
1095: {
1096: UP p1,p2;
1097:
1098: ptoup((P)ARG0(arg),&p1);
1099: switch ( current_ff ) {
1100: case FF_GFP:
1101: hybrid_powermodup(p1,&p2); break;
1102: case FF_GF2N:
1103: powermodup_gf2n(p1,&p2); break;
1104: case FF_GFPN:
1105: powermodup(p1,&p2); break;
1106: default:
1107: error("pwrmod_ff : current_ff is not set");
1108: }
1109: uptop(p2,rp);
1110: }
1111:
1112: void Pgeneric_pwrmod_ff(arg,rp)
1113: NODE arg;
1114: P *rp;
1115: {
1116: UP g,f,r;
1117:
1118: ptoup((P)ARG0(arg),&g);
1119: ptoup((P)ARG1(arg),&f);
1120: switch ( current_ff ) {
1121: case FF_GFP:
1122: hybrid_generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
1123: case FF_GF2N:
1124: generic_powermodup_gf2n(g,f,(Q)ARG2(arg),&r); break;
1125: case FF_GFPN:
1126: generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
1127: default:
1128: error("generic_pwrmod_ff : current_ff is not set");
1129: }
1130: uptop(r,rp);
1131: }
1132:
1133: void Ppwrtab_ff(arg,rp)
1134: NODE arg;
1135: VECT *rp;
1136: {
1137: UP f,xp;
1138: UP *tab;
1139: VECT r;
1140: int i,d;
1141:
1142: ptoup((P)ARG0(arg),&f);
1143: ptoup((P)ARG1(arg),&xp);
1144: d = f->d;
1145:
1146: tab = (UP *)ALLOCA(d*sizeof(UP));
1147: switch ( current_ff ) {
1148: case FF_GFP:
1149: hybrid_powertabup(f,xp,tab); break;
1150: case FF_GF2N:
1151: powertabup_gf2n(f,xp,tab); break;
1152: case FF_GFPN:
1153: powertabup(f,xp,tab); break;
1154: default:
1155: error("pwrtab_ff : current_ff is not set");
1156: }
1157: MKVECT(r,d); *rp = r;
1158: for ( i = 0; i < d; i++ )
1159: uptop(tab[i],(P *)&BDY(r)[i]);
1160: }
1161:
1162: void Pkpwrmod_lm(arg,rp)
1163: NODE arg;
1164: P *rp;
1165: {
1166: UP p1,p2;
1167:
1168: ptoup((P)ARG0(arg),&p1);
1169: powermodup(p1,&p2);
1170: uptop(p2,rp);
1171: }
1172:
1173: void Pkgeneric_pwrmod_lm(arg,rp)
1174: NODE arg;
1175: P *rp;
1176: {
1177: UP g,f,r;
1178:
1179: ptoup((P)ARG0(arg),&g);
1180: ptoup((P)ARG1(arg),&f);
1181: generic_powermodup(g,f,(Q)ARG2(arg),&r);
1182: uptop(r,rp);
1183: }
1184:
1185: void Pkpwrtab_lm(arg,rp)
1186: NODE arg;
1187: VECT *rp;
1188: {
1189: UP f,xp;
1190: UP *tab;
1191: VECT r;
1192: int i,d;
1193:
1194: ptoup((P)ARG0(arg),&f);
1195: ptoup((P)ARG1(arg),&xp);
1196: d = f->d;
1197:
1198: tab = (UP *)ALLOCA(d*sizeof(UP));
1199: powertabup(f,xp,tab);
1200: MKVECT(r,d); *rp = r;
1201: for ( i = 0; i < d; i++ )
1202: uptop(tab[i],(P *)&BDY(r)[i]);
1203: }
1204:
1205: void Plazy_lm(arg,rp)
1206: NODE arg;
1207: Q *rp;
1208: {
1209: lm_lazy = QTOS((Q)ARG0(arg));
1210: *rp = 0;
1211: }
1212:
1213: void Pkmul(arg,rp)
1214: NODE arg;
1215: P *rp;
1216: {
1217: P n1,n2;
1218:
1219: n1 = (P)ARG0(arg); n2 = (P)ARG1(arg);
1220: asir_assert(n1,O_P,"kmul");
1221: asir_assert(n2,O_P,"kmul");
1222: kmulp(CO,n1,n2,rp);
1223: }
1224:
1225: void Pksquare(arg,rp)
1226: NODE arg;
1227: P *rp;
1228: {
1229: P n1;
1230:
1231: n1 = (P)ARG0(arg);
1232: asir_assert(n1,O_P,"ksquare");
1233: ksquarep(CO,n1,rp);
1234: }
1235:
1236: void Pktmul(arg,rp)
1237: NODE arg;
1238: P *rp;
1239: {
1240: UP p1,p2,r;
1241:
1242: ptoup((P)ARG0(arg),&p1);
1243: ptoup((P)ARG1(arg),&p2);
1244: tkmulup(p1,p2,QTOS((Q)ARG2(arg))+1,&r);
1245: uptop(r,rp);
1246: }
1247:
1248: void Pumul(arg,rp)
1249: NODE arg;
1250: P *rp;
1251: {
1252: P a1,a2;
1253: UP p1,p2,r;
1254:
1255: a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
1256: if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
1257: mulp(CO,a1,a2,rp);
1258: else {
1259: if ( !uzpcheck(a1) || !uzpcheck(a2) || VR(a1) != VR(a2) )
1260: error("umul : invalid argument");
1261: ptoup(a1,&p1);
1262: ptoup(a2,&p2);
1263: hybrid_mulup(0,p1,p2,&r);
1264: uptop(r,rp);
1265: }
1266: }
1267:
1268: void Pusquare(arg,rp)
1269: NODE arg;
1270: P *rp;
1271: {
1272: UP p1,p2,r;
1273:
1274: ptoup((P)ARG0(arg),&p1);
1275: hybrid_squareup(0,p1,&r);
1276: uptop(r,rp);
1277: }
1278:
1279: void Putmul(arg,rp)
1280: NODE arg;
1281: P *rp;
1282: {
1283: UP p1,p2,r;
1284:
1285: ptoup((P)ARG0(arg),&p1);
1286: ptoup((P)ARG1(arg),&p2);
1287: hybrid_tmulup(0,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
1288: uptop(r,rp);
1289: }
1290:
1291: void Pumul_ff(arg,rp)
1292: NODE arg;
1293: Obj *rp;
1294: {
1295: P a1,a2;
1296: UP p1,p2,r;
1297: P p;
1298:
1299: a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
1300: ptoup(a1,&p1);
1301: ptoup(a2,&p2);
1302: hybrid_mulup(current_ff,p1,p2,&r);
1303: uptop(r,&p);
1304: simp_ff((Obj)p,rp);
1305: }
1306:
1307: void Pusquare_ff(arg,rp)
1308: NODE arg;
1309: Obj *rp;
1310: {
1311: UP p1,p2,r;
1312: P p;
1313:
1314: ptoup((P)ARG0(arg),&p1);
1315: hybrid_squareup(current_ff,p1,&r);
1316: uptop(r,&p);
1317: simp_ff((Obj)p,rp);
1318: }
1319:
1320: void Putmul_ff(arg,rp)
1321: NODE arg;
1322: Obj *rp;
1323: {
1324: UP p1,p2,r;
1325: P p;
1326:
1327: ptoup((P)ARG0(arg),&p1);
1328: ptoup((P)ARG1(arg),&p2);
1329: hybrid_tmulup(current_ff,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
1330: uptop(r,&p);
1331: simp_ff((Obj)p,rp);
1332: }
1333:
1334: void Phfmul_lm(arg,rp)
1335: NODE arg;
1336: P *rp;
1337: {
1338: UP p1,p2,r;
1339: UP hi,lo,mid,t,s,p10,p11,p20,p21;
1340: unsigned int m,d;
1341: int i;
1342:
1343: ptoup((P)ARG0(arg),&p1);
1344: ptoup((P)ARG1(arg),&p2);
1345: d = MAX(p1->d,p2->d);
1346: for ( m = 1; m < d; m <<= 1 );
1347: if ( m > d )
1348: m >>= 1;
1349: if ( d-m < 10000 ) {
1350: decompup(p1,m,&p10,&p11); /* p1 = p11*x^m+p10 */
1351: decompup(p2,m,&p20,&p21); /* p2 = p21*x^m+p20 */
1352: fft_mulup_lm(p10,p20,&lo);
1353: kmulup(p11,p21,&hi);
1354: kmulup(p11,p20,&t); kmulup(p10,p21,&s); addup(t,s,&mid);
1355: r = UPALLOC(2*d);
1356: bzero((char *)COEF(r),(2*d+1)*sizeof(Num));
1357: if ( lo )
1358: bcopy((char *)COEF(lo),(char *)COEF(r),(DEG(lo)+1)*sizeof(Num));
1359: if ( hi )
1360: bcopy((char *)COEF(hi),(char *)(COEF(r)+2*m),(DEG(hi)+1)*sizeof(Num));
1361: for ( i = 2*d; i >= 0 && !COEF(r)[i]; i-- );
1362: if ( i < 0 )
1363: r = 0;
1364: else {
1365: DEG(r) = i;
1366: t = UPALLOC(DEG(mid)+m); DEG(t) = DEG(mid)+m;
1367: bzero((char *)COEF(t),(DEG(mid)+m+1)*sizeof(Num));
1368: bcopy((char *)COEF(mid),(char *)(COEF(t)+m),(DEG(mid)+1)*sizeof(Num));
1369: addup(t,r,&s);
1370: r = s;
1371: }
1372: } else
1373: fft_mulup_lm(p1,p2,&r);
1374: uptop(r,rp);
1375: }
1376:
1377: void Pfmultest(arg,rp)
1378: NODE arg;
1379: LIST *rp;
1380: {
1381: P p1,p2,r;
1382: int d1,d2;
1383: UM w1,w2,wr;
1384: unsigned int *f1,*f2,*fr,*w;
1385: int index,mod,root,d,maxint,i;
1386: int cond;
1387: Q prime;
1388: NODE n0,n1;
1389:
1390: p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); index = QTOS((Q)ARG2(arg));
1391: FFT_primes(index,&mod,&root,&d);
1392: maxint = 1<<d;
1393: d1 = UDEG(p1); d2 = UDEG(p2);
1394: if ( maxint < d1+d2+1 )
1395: *rp = 0;
1396: else {
1397: w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
1398: wr = W_UMALLOC(d1+d2);
1399: ptoum(mod,p1,w1); ptoum(mod,p2,w2);
1400: f1 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
1401: f2 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
1402: fr = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
1403: w = (unsigned int *)ALLOCA(12*maxint*sizeof(unsigned int));
1404:
1405: for ( i = 0; i <= d1; i++ )
1406: f1[i] = (unsigned int)w1->c[i];
1407: for ( i = 0; i <= d2; i++ )
1408: f2[i] = (unsigned int)w2->c[i];
1409:
1410: cond = FFT_pol_product(d1,f1,d2,f2,fr,index,w);
1411: if ( cond )
1412: error("fmultest : ???");
1413: wr->d = d1+d2;
1414: for ( i = 0; i <= d1+d2; i++ )
1415: wr->c[i] = (unsigned int)fr[i];
1416: umtop(VR(p1),wr,&r);
1417: STOQ(mod,prime);
1418: MKNODE(n1,prime,0);
1419: MKNODE(n0,r,n1);
1420: MKLIST(*rp,n0);
1421: }
1422: }
1423:
1424: void Pkmulum(arg,rp)
1425: NODE arg;
1426: P *rp;
1427: {
1428: P p1,p2;
1429: int d1,d2,mod;
1430: UM w1,w2,wr;
1431:
1432: p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); mod = QTOS((Q)ARG2(arg));
1433: d1 = UDEG(p1); d2 = UDEG(p2);
1434: w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
1435: wr = W_UMALLOC(d1+d2);
1436: ptoum(mod,p1,w1); ptoum(mod,p2,w2);
1437: kmulum(mod,w1,w2,wr);
1438: umtop(VR(p1),wr,rp);
1439: }
1440:
1441: void Pksquareum(arg,rp)
1442: NODE arg;
1443: P *rp;
1444: {
1445: P p1;
1446: int d1,mod;
1447: UM w1,wr;
1448:
1449: p1 = (P)ARG0(arg); mod = QTOS((Q)ARG1(arg));
1450: d1 = UDEG(p1);
1451: w1 = W_UMALLOC(d1);
1452: wr = W_UMALLOC(2*d1);
1453: ptoum(mod,p1,w1);
1454: kmulum(mod,w1,w1,wr);
1455: umtop(VR(p1),wr,rp);
1456: }
1457:
1458: void Ptracemod_gf2n(arg,rp)
1459: NODE arg;
1460: P *rp;
1461: {
1462: UP g,f,r;
1463:
1464: ptoup((P)ARG0(arg),&g);
1465: ptoup((P)ARG1(arg),&f);
1466: tracemodup_gf2n(g,f,(Q)ARG2(arg),&r);
1467: uptop(r,rp);
1468: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>