Annotation of OpenXM_contrib2/asir2000/builtin/gf.c, Revision 1.1.1.1
1.1 noro 1: /* $OpenXM: OpenXM/src/asir99/builtin/gf.c,v 1.1.1.1 1999/11/10 08:12:25 noro Exp $ */
2: #include "ca.h"
3: #include "parse.h"
4:
5: struct resf_dlist {
6: int ib,id;
7: };
8:
9: int resf_degtest(int,int *,int,struct resf_dlist *);
10: void uhensel(P,NODE,int,int,NODE *);
11: void resf_hensel(int,P,int,P *,ML *);
12: void resf_dtest(P,ML,int,int *,int *,DCP *);
13: void resf_dtest_special(P,ML,int,int *,int *,DCP *);
14: void dtest_special(P,ML,P *);
15: void hensel_special(int,int,P,P *,ML *);
16:
17: void nullspace(UM **,UM,int,int,int *);
18: void nullspace_lm(LM **,int,int *);
19: void nullspace_gf2n(GF2N **,int,int *);
20: void nullspace_gfpn(GFPN **,int,int *);
21: void null_to_sol(int **,int *,int,int,UM *);
22:
23: void showgfmat(UM **,int);
24: void pwr_mod(P,P,V,P,int,N,P *);
25: void rem_mod(P,P,V,P,int,P *);
26:
27: void Pnullspace(),Pgcda_mod(),Pftest(),Presfmain(),Ppwr_mod(),Puhensel();
28:
29: void Pnullspace_ff();
30:
31: void Psolve_linear_equation_gf2n();
32: void Plinear_form_to_vect(),Pvect_to_linear_form();
33:
34: void solve_linear_equation_gf2n(GF2N **,int,int,int *);
35: void linear_form_to_array(P,VL,int,Num *);
36: void array_to_linear_form(Num *,VL,int,P *);
37:
38: extern int current_ff;
39:
40: struct ftab gf_tab[] = {
41: {"solve_linear_equation_gf2n",Psolve_linear_equation_gf2n,1},
42: {"nullspace",Pnullspace,3},
43: {"nullspace_ff",Pnullspace_ff,1},
44: /* {"gcda_mod",Pgcda_mod,5}, */
45: {"ftest",Pftest,2},
46: {"resfmain",Presfmain,4},
47: {"pwr_mod",Ppwr_mod,6},
48: {"uhensel",Puhensel,4},
49: {0,0,0},
50: };
51:
52: int resf_degtest(k,in,nb,dlist)
53: int k;
54: int *in;
55: int nb;
56: struct resf_dlist *dlist;
57: {
58: int i,d0,d;
59: int dl_i;
60: struct resf_dlist *t;
61:
62: if ( k < nb )
63: return 0;
64: if ( nb == 1 )
65: return 1;
66: d0 = 0; d = 0; dl_i = 0;
67: for ( i = 0; i < k; i++ ) {
68: t = &dlist[in[i]];
69: if ( t->ib > dl_i + 1 )
70: return 0;
71: else if ( t->ib == dl_i )
72: d += t->id;
73: else if ( !d || (dl_i && d0 != d) )
74: return 0;
75: else {
76: d0 = d; dl_i++; d = t->id;
77: }
78: }
79: if ( dl_i != nb - 1 || d0 != d )
80: return 0;
81: else
82: return 1;
83: }
84:
85: void Puhensel(arg,rp)
86: NODE arg;
87: LIST *rp;
88: {
89: P f;
90: NODE mfl,r;
91: int mod,bound;
92:
93: f = (P)ARG0(arg);
94: mfl = BDY((LIST)ARG1(arg));
95: mod = QTOS((Q)ARG2(arg));
96: bound = QTOS((Q)ARG3(arg));
97: uhensel(f,mfl,mod,bound,&r);
98: MKLIST(*rp,r);
99: }
100:
101: void uhensel(f,mfl,mod,bound,rp)
102: P f;
103: NODE mfl;
104: int mod,bound;
105: NODE *rp;
106: {
107: ML blist,clist,rlist;
108: LUM fl;
109: int nf,i;
110: P s;
111: V v;
112: NODE t,top;
113:
114: nf = length(mfl);
115: blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
116: for ( i = 0, t = mfl; i < nf; i++, t = NEXT(t) ) {
117: blist->c[i] = (pointer)UMALLOC(UDEG((P)BDY(t)));
118: ptoum(mod,(P)BDY(t),blist->c[i]);
119: }
120: gcdgen(f,blist,&clist);
121: blist->bound = clist->bound = bound;
122: W_LUMALLOC((int)UDEG(f),bound,fl);
123: ptolum(mod,bound,f,fl);
124: henmain(fl,blist,clist,&rlist);
125: v = VR(f);
126: for ( i = nf-1, top = 0; i >= 0; i-- ) {
127: lumtop(v,mod,bound,rlist->c[i],&s);
128: MKNODE(t,s,top); top = t;
129: }
130: *rp = top;
131: }
132:
133: void Presfmain(arg,rp)
134: NODE arg;
135: LIST *rp;
136: {
137: P f;
138: int mod,n,nb,i,j,k;
139: int *nf,*md;
140: P *mf;
141: NODE mfl,mdl,t,s,u;
142: ML list;
143: DCP dc;
144: int sflag;
145:
146: f = (P)ARG0(arg);
147: mod = QTOS((Q)ARG1(arg));
148: mfl = BDY((LIST)ARG2(arg));
149: mdl = BDY((LIST)ARG3(arg));
150: for ( n = nb = 0, t = mfl; t; nb++, t = NEXT(t) )
151: for ( s = BDY((LIST)BDY(t)); s; n++, s = NEXT(s) );
152: if ( n == nb ) {
153: /* f must be irreducible! */
154: NEWDC(dc);
155: dc->c = f; dc->d = ONE;
156: } else {
157: nf = W_ALLOC(nb); md = W_ALLOC(nb); mf = (P *)ALLOCA(n*sizeof(P));
158: for ( k = i = 0, t = mfl, u = mdl, sflag = 1; t;
159: i++, t = NEXT(t), u = NEXT(u) ) {
160: if ( sflag && length(BDY((LIST)BDY(t))) != 2 )
161: sflag = 0;
162: for ( j = 0, s = BDY((LIST)BDY(t)); s; j++, s = NEXT(s) )
163: mf[k++] = (P)BDY(s);
164: nf[i] = j; md[i] = QTOS((Q)BDY(u));
165: }
166: resf_hensel(mod,f,n,mf,&list);
167: if ( sflag )
168: resf_dtest_special(f,list,nb,nf,md,&dc);
169: else
170: resf_dtest(f,list,nb,nf,md,&dc);
171: }
172: dcptolist(dc,rp);
173: }
174:
175: void resf_hensel(mod,f,nf,mfl,listp)
176: int mod;
177: P f;
178: int nf;
179: P *mfl;
180: ML *listp;
181: {
182: register int i,j;
183: int q,n,bound;
184: int *p;
185: int **pp;
186: ML blist,clist,bqlist,cqlist,rlist;
187: UM *b;
188: LUM fl,tl;
189: LUM *l;
190:
191: blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
192: for ( i = 0; i < nf; i++ ) {
193: blist->c[i] = (pointer)UMALLOC(UDEG(mfl[i]));
194: ptoum(mod,mfl[i],blist->c[i]);
195: }
196: gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
197: n = bqlist->n; q = bqlist->mod;
198: bqlist->bound = cqlist->bound = bound = mignotte(q,f);
199: if ( bound == 1 ) {
200: *listp = rlist = MLALLOC(n);
201: rlist->n = n; rlist->mod = q; rlist->bound = bound;
202: for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
203: tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
204: for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
205: pp[j][0] = p[j];
206: }
207: } else {
208: W_LUMALLOC((int)UDEG(f),bound,fl);
209: ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
210: }
211: }
212:
213: void resf_dtest(f,list,nb,nfl,mdl,dcp)
214: P f;
215: ML list;
216: int nb;
217: int *nfl,*mdl;
218: DCP *dcp;
219: {
220: int n,np,bound,q;
221: int i,j,k;
222: int *win;
223: P g,factor,cofactor;
224: Q csum,csumt;
225: DCP dcf,dcf0;
226: LUM *c;
227: ML wlist;
228: struct resf_dlist *dlist;
229: int z;
230:
231: n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
232: win = W_ALLOC(np+1);
233: ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
234: wlist = W_MLALLOC(np); wlist->n = list->n;
235: wlist->mod = list->mod; wlist->bound = list->bound;
236: c = (LUM *)COEF(wlist);
237: bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
238: dlist = (struct resf_dlist *)ALLOCA(np*sizeof(struct resf_dlist));
239: for ( i = 0, j = 0; j < nb; j++ )
240: for ( k = 0; k < nfl[j]; k++, i++ ) {
241: dlist[i].ib = j; dlist[i].id = DEG(c[i])/mdl[j];
242: }
243: k = nb;
244: for ( i = 0; i < nb; i++ )
245: win[i] = i+1;
246: for ( g = f, dcf = dcf0 = 0, --np, z = 0; ; ) {
247: #if 0
248: if ( !(z++ % 10000) )
249: fputc('.',stderr);
250: #endif
251: if ( resf_degtest(k,win,nb,dlist) &&
252: dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
253: NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
254: g = cofactor;
255: ucsump(g,&csum); mulq(csum,(Q)COEF(DC(g)),&csumt); csum = csumt;
256: for ( i = 0; i < k - 1; i++ )
257: for ( j = win[i] + 1; j < win[i + 1]; j++ ) {
258: c[j-i-1] = c[j];
259: dlist[j-i-1] = dlist[j];
260: }
261: for ( j = win[k-1] + 1; j <= np; j++ ) {
262: c[j-k] = c[j];
263: dlist[j-k] = dlist[j];
264: }
265: if ( ( np -= k ) < k )
266: break;
267: if ( np - win[0] + 1 < k )
268: if ( ++k > np )
269: break;
270: else
271: for ( i = 0; i < k; i++ )
272: win[i] = i + 1;
273: else
274: for ( i = 1; i < k; i++ )
275: win[i] = win[0] + i;
276: } else if ( !ncombi(1,np,k,win) )
277: if ( k == np )
278: break;
279: else
280: for ( i = 0, ++k; i < k; i++ )
281: win[i] = i + 1;
282: }
283: NEXTDC(dcf0,dcf); COEF(dcf) = g;
284: DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
285: }
286:
287: void resf_dtest_special(f,list,nb,nfl,mdl,dcp)
288: P f;
289: ML list;
290: int nb;
291: int *nfl,*mdl;
292: DCP *dcp;
293: {
294: int n,np,bound,q;
295: int i,j;
296: int *win;
297: P g,factor,cofactor;
298: Q csum,csumt;
299: DCP dcf,dcf0;
300: LUM *c;
301: ML wlist;
302: int max;
303:
304: n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
305: win = W_ALLOC(np+1);
306: ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
307: wlist = W_MLALLOC(np); wlist->n = list->n;
308: wlist->mod = list->mod; wlist->bound = list->bound;
309: c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
310: max = 1<<nb;
311: for ( g = f, dcf = dcf0 = 0, i = 0; i < max; i++ ) {
312: #if 0
313: if ( !(i % 1000) )
314: fprintf(stderr,"i=%d\n",i);
315: #endif
316: for ( j = 0; j < nb; j++ )
317: win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
318: if ( dtestmain(g,csum,wlist,nb,win,&factor,&cofactor) ) {
319: #if 0
320: fprintf(stderr,"success : i=%d\n",i);
321: #endif
322: NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
323: NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = cofactor;
324: NEXT(dcf) = 0;*dcp = dcf0;
325: return;
326: }
327: }
328: NEXTDC(dcf0,dcf); COEF(dcf) = g;
329: DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
330: }
331:
332: #if 0
333: void Pftest(arg,rp)
334: NODE arg;
335: P *rp;
336: {
337: ML list;
338: DCP dc;
339: P p;
340: P *mfl;
341:
342: p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
343: hensel_special(4,1,p,mfl,&list);
344: dtest_special(p,list,rp);
345: }
346:
347: void dtest_special(f,list,pr)
348: P f;
349: ML list;
350: P *pr;
351: {
352: int n,np,bound,q;
353: int i,j,k;
354: int *win;
355: P g,factor,cofactor;
356: Q csum,csumt;
357: DCP dc,dcf,dcf0;
358: LUM *c;
359: ML wlist;
360:
361: n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
362: win = W_ALLOC(np+1);
363: ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
364: wlist = W_MLALLOC(np); wlist->n = list->n;
365: wlist->mod = list->mod; wlist->bound = list->bound;
366: c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
367: for ( g = f, i = 130000; i < (1<<20); i++ ) {
368: #if 0
369: if ( !(i % 1000) )
370: fprintf(stderr,"i=%d\n",i);
371: #endif
372: for ( j = 0; j < 20; j++ )
373: win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
374: if ( dtestmain(g,csum,wlist,20,win,&factor,&cofactor) ) {
375: #if 0
376: fprintf(stderr,"success : i=%d\n",i);
377: #endif
378: *pr = factor; return;
379: }
380: }
381: }
382:
383: void hensel_special(index,count,f,mfl,listp)
384: int index,count;
385: P f;
386: P *mfl;
387: ML *listp;
388: {
389: register int i,j;
390: int q,n,t,d,r,u,br,tmp,bound;
391: int *c,*p,*m,*w;
392: int **pp;
393: DCP dc;
394: ML blist,clist,bqlist,cqlist,rlist;
395: UM *b;
396: LUM fl,tl;
397: LUM *l;
398:
399: blist = MLALLOC(40); blist->n = 40; blist->mod = 11;
400: for ( i = 0; i < 40; i++ ) {
401: blist->c[i] = (pointer)UMALLOC(6);
402: ptoum(11,mfl[i],blist->c[i]);
403: }
404: gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
405: n = bqlist->n; q = bqlist->mod;
406: bqlist->bound = cqlist->bound = bound = mignotte(q,f);
407: if ( bound == 1 ) {
408: *listp = rlist = MLALLOC(n);
409: rlist->n = n; rlist->mod = q; rlist->bound = bound;
410: for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
411: tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
412: for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
413: pp[j][0] = p[j];
414: }
415: } else {
416: W_LUMALLOC(UDEG(f),bound,fl);
417: ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
418: }
419: }
420: #endif
421:
422: #if 0
423: void Pftest(arg,rp)
424: NODE arg;
425: P *rp;
426: {
427: ML list;
428: DCP dc;
429: P p;
430: P *mfl;
431:
432: p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
433: hensel_special(2,1,p,mfl,&list);
434: dtest_special(p,list,rp);
435: }
436:
437: void dtest_special(f,list,pr)
438: P f;
439: ML list;
440: P *pr;
441: {
442: int n,np,bound,q;
443: int i,j,k,t,b0;
444: int *win;
445: P g,factor,cofactor;
446: Q csum,csumt;
447: DCP dc,dcf,dcf0;
448: LUM *c;
449: ML wlist;
450: static int nbits[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
451:
452: n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
453: win = W_ALLOC(np+1);
454: ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
455: wlist = W_MLALLOC(np); wlist->n = list->n;
456: wlist->mod = list->mod; wlist->bound = list->bound;
457: c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
458: for ( g = f, i = 0; i < (1<<23); i++ ) {
459: #if 0
460: if ( !(i % 1000) )
461: fprintf(stderr,"i=%d\n",i);
462: #endif
463: t = i>>20; b0 = nbits[t];
464: if ( !b0 )
465: continue;
466: for ( j = 1; j < 6; j++ ) {
467: t = (i>>(20-4*j))&0xf;
468: if ( nbits[t] != b0 )
469: break;
470: }
471: if ( j != 6 )
472: continue;
473: for ( j = k = 0; j < 24; j++ )
474: if ( i & (1<<(23-j)) )
475: win[k++] = j;
476: if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
477: #if 0
478: fprintf(stderr,"success : i=%d\n",i);
479: #endif
480: *pr = factor; return;
481: }
482: }
483: *pr = f;
484: }
485:
486: void hensel_special(index,count,f,mfl,listp)
487: int index,count;
488: P f;
489: P *mfl;
490: ML *listp;
491: {
492: register int i,j;
493: int q,n,t,d,r,u,br,tmp,bound;
494: int *c,*p,*m,*w;
495: int **pp;
496: DCP dc;
497: ML blist,clist,bqlist,cqlist,rlist;
498: UM *b;
499: LUM fl,tl;
500: LUM *l;
501:
502: blist = MLALLOC(24); blist->n = 24; blist->mod = 5;
503: for ( i = 0; i < 24; i++ ) {
504: blist->c[i] = (pointer)UMALLOC(7);
505: ptoum(5,mfl[i],blist->c[i]);
506: }
507: gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
508: n = bqlist->n; q = bqlist->mod;
509: bqlist->bound = cqlist->bound = bound = mignotte(q,f);
510: if ( bound == 1 ) {
511: *listp = rlist = MLALLOC(n);
512: rlist->n = n; rlist->mod = q; rlist->bound = bound;
513: for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
514: tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
515: for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
516: pp[j][0] = p[j];
517: }
518: } else {
519: W_LUMALLOC(UDEG(f),bound,fl);
520: ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
521: }
522: }
523: #endif
524:
525: void Pftest(arg,rp)
526: NODE arg;
527: P *rp;
528: {
529: ML list;
530: P p;
531: P *mfl;
532:
533: p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
534: hensel_special(5,1,p,mfl,&list);
535: dtest_special(p,list,rp);
536: }
537:
538: int nbits(a)
539: int a;
540: {
541: int i,s;
542:
543: for ( i = 0, s = 0; a && (i < 20); i++, a >>= 1 )
544: if ( a & 1 ) s++;
545: return s;
546: }
547:
548: void dtest_special(f,list,pr)
549: P f;
550: ML list;
551: P *pr;
552: {
553: int n,np,bound,q;
554: int i,j,k,b0;
555: int *win;
556: P g,factor,cofactor;
557: Q csum,csumt;
558: LUM *c;
559: ML wlist;
560:
561: n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
562: win = W_ALLOC(np+1);
563: ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
564: wlist = W_MLALLOC(np); wlist->n = list->n;
565: wlist->mod = list->mod; wlist->bound = list->bound;
566: c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
567: for ( g = f, i = 0; i < (1<<19); i++ ) {
568: #if 0
569: if ( !(i % 10000) )
570: fprintf(stderr,"i=%d\n",i);
571: #endif
572: b0 = nbits(i>>10);
573: if ( !b0 || (nbits(i&0x3ff) != b0) )
574: continue;
575: for ( j = k = 0; j < 20; j++ )
576: if ( i & (1<<(19-j)) )
577: win[k++] = j;
578: if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
579: #if 0
580: fprintf(stderr,"success : i=%d\n",i);
581: #endif
582: *pr = factor; return;
583: }
584: }
585: *pr = f;
586: }
587:
588: void hensel_special(index,count,f,mfl,listp)
589: int index,count;
590: P f;
591: P *mfl;
592: ML *listp;
593: {
594: register int i,j;
595: int q,n,bound;
596: int *p;
597: int **pp;
598: ML blist,clist,bqlist,cqlist,rlist;
599: UM *b;
600: LUM fl,tl;
601: LUM *l;
602:
603: blist = MLALLOC(20); blist->n = 20; blist->mod = 11;
604: for ( i = 0; i < 20; i++ ) {
605: blist->c[i] = (pointer)UMALLOC(10);
606: ptoum(11,mfl[i],blist->c[i]);
607: }
608: gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
609: n = bqlist->n; q = bqlist->mod;
610: bqlist->bound = cqlist->bound = bound = mignotte(q,f);
611: if ( bound == 1 ) {
612: *listp = rlist = MLALLOC(n);
613: rlist->n = n; rlist->mod = q; rlist->bound = bound;
614: for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
615: tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
616: for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
617: pp[j][0] = p[j];
618: }
619: } else {
620: W_LUMALLOC((int)UDEG(f),bound,fl);
621: ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
622: }
623: }
624:
625: void Pnullspace(arg,rp)
626: NODE arg;
627: LIST *rp;
628: {
629: int i,j,n,mod;
630: MAT mat,r;
631: VECT u;
632: V v;
633: P p,z;
634: Q q;
635: UM **w;
636: UM mp;
637: P *t;
638: UM *s;
639: int *ind;
640: NODE n0,n1;
641:
642: mat = (MAT)ARG0(arg);
643: p = (P)ARG1(arg);
644: v = VR(p);
645: mod = QTOS((Q)ARG2(arg));
646: n = mat->row;
647: w = (UM **)almat_pointer(n,n);
648: for ( i = 0; i < n; i++ )
649: for ( j = 0, t = (P *)mat->body[i], s = w[i]; j < n; j++ ) {
650: ptomp(mod,t[j],&z);
651: s[j] = W_UMALLOC((z&&!NUM(z))?UDEG(z):0);
652: mptoum(z,s[j]);
653: }
654: mp = W_UMALLOC(UDEG(p)); ptoum(mod,p,mp);
655: ind = (int *)ALLOCA(n*sizeof(int));
656: nullspace(w,mp,mod,n,ind);
657: MKMAT(r,n,n);
658: for ( i = 0; i < n; i++ )
659: for ( j = 0, t = (P *)r->body[i], s = w[i]; j < n; j++ )
660: umtop(v,s[j],&t[j]);
661: MKVECT(u,n);
662: for ( i = 0; i < n; i++ ) {
663: STOQ(ind[i],q); u->body[i] = (pointer)q;
664: }
665: MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
666: }
667:
668: void nullspace(mat,p,mod,n,ind)
669: UM **mat;
670: UM p;
671: int mod,n;
672: int *ind;
673: {
674: int i,j,l,s,d;
675: UM q,w,w1,h,inv;
676: UM *t,*u;
677:
678: d = DEG(p); inv = W_UMALLOC(d); q = W_UMALLOC(2*d);
679: w = W_UMALLOC(2*d); w1 = W_UMALLOC(2*d); h = W_UMALLOC(d);
680: bzero(ind,n*sizeof(int));
681: ind[0] = 0;
682: for ( i = j = 0; j < n; i++, j++ ) {
683: for ( ; j < n; j++ ) {
684: for ( l = i; l < n; l++ )
685: if ( DEG(mat[l][j])>=0 )
686: break;
687: if ( l < n ) {
688: t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
689: } else
690: ind[j] = 1;
691: }
692: if ( j == n )
693: break;
694: invum(mod,p,mat[i][j],inv);
695: for ( s = j, t = mat[i]; s < n; s++ ) {
696: mulum(mod,t[s],inv,w);
697: DEG(w) = divum(mod,w,p,q);
698: cpyum(w,t[s]);
699: }
700: for ( l = 0; l < n; l++ ) {
701: if ( l == i )
702: continue;
703: u = mat[l]; DEG(w) = -1; subum(mod,w,u[j],h);
704: for ( s = j; s < n; s++ ) {
705: mulum(mod,h,t[s],w); addum(mod,w,u[s],w1);
706: DEG(w1) = divum(mod,w1,p,q); cpyum(w1,u[s]);
707: }
708: }
709: }
710: }
711:
712: void Pnullspace_ff(arg,rp)
713: NODE arg;
714: LIST *rp;
715: {
716: int i,j,n;
717: Q mod;
718: MAT mat,r;
719: VECT u;
720: Q q;
721: Obj **w;
722: Obj *t;
723: Obj *s;
724: int *ind;
725: NODE n0,n1;
726:
727: mat = (MAT)ARG0(arg);
728: n = mat->row;
729: w = (Obj **)almat_pointer(n,n);
730: for ( i = 0; i < n; i++ )
731: for ( j = 0, t = (Obj *)mat->body[i], s = w[i]; j < n; j++ )
732: s[j] = t[j];
733: ind = (int *)ALLOCA(n*sizeof(int));
734: switch ( current_ff ) {
735: case FF_GFP:
736: nullspace_lm((LM **)w,n,ind); break;
737: case FF_GF2N:
738: nullspace_gf2n((GF2N **)w,n,ind); break;
739: case FF_GFPN:
740: nullspace_gfpn((GFPN **)w,n,ind); break;
741: default:
742: error("nullspace_ff : current_ff is not set");
743: }
744: MKMAT(r,n,n);
745: for ( i = 0; i < n; i++ )
746: for ( j = 0, t = (Obj *)r->body[i], s = w[i]; j < n; j++ )
747: t[j] = s[j];
748: MKVECT(u,n);
749: for ( i = 0; i < n; i++ ) {
750: STOQ(ind[i],q); u->body[i] = (pointer)q;
751: }
752: MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
753: }
754:
755: void nullspace_lm(mat,n,ind)
756: LM **mat;
757: int n;
758: int *ind;
759: {
760: int i,j,l,s;
761: Q q,mod;
762: N lm;
763: LM w,w1,h,inv;
764: LM *t,*u;
765:
766: getmod_lm(&lm); NTOQ(lm,1,mod);
767:
768: bzero(ind,n*sizeof(int));
769: ind[0] = 0;
770: for ( i = j = 0; j < n; i++, j++ ) {
771: for ( ; j < n; j++ ) {
772: for ( l = i; l < n; l++ ) {
773: simplm(mat[l][j],&w); mat[l][j] = w;
774: if ( mat[l][j] )
775: break;
776: }
777: if ( l < n ) {
778: t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
779: } else
780: ind[j] = 1;
781: }
782: if ( j == n )
783: break;
784: NTOQ(mat[i][j]->body,1,q); invl(q,mod,(Q *)&inv);
785: for ( s = j, t = mat[i]; s < n; s++ ) {
786: mullm(t[s],inv,&w); t[s] = w;
787: }
788: for ( l = 0; l < n; l++ ) {
789: if ( l == i )
790: continue;
791: u = mat[l]; chsgnlm(u[j],&h);
792: for ( s = j; s < n; s++ ) {
793: mullm(h,t[s],&w); addlm(w,u[s],&w1); u[s] = w1;
794: }
795: }
796: }
797: }
798:
799: void nullspace_gf2n(mat,n,ind)
800: GF2N **mat;
801: int n;
802: int *ind;
803: {
804: int i,j,l,s;
805: GF2N w,w1,h,inv;
806: GF2N *t,*u;
807: extern gf2n_lazy;
808:
809: bzero(ind,n*sizeof(int));
810: ind[0] = 0;
811: for ( i = j = 0; j < n; i++, j++ ) {
812: for ( ; j < n; j++ ) {
813: for ( l = i; l < n; l++ ) {
814: simpgf2n(mat[l][j],&w); mat[l][j] = w;
815: if ( mat[l][j] )
816: break;
817: }
818: if ( l < n ) {
819: t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
820: } else
821: ind[j] = 1;
822: }
823: if ( j == n )
824: break;
825: invgf2n(mat[i][j],&inv);
826: for ( s = j, t = mat[i]; s < n; s++ ) {
827: mulgf2n(t[s],inv,&w); t[s] = w;
828: }
829: for ( l = 0; l < n; l++ ) {
830: if ( l == i )
831: continue;
832: u = mat[l]; h = u[j];
833: for ( s = j; s < n; s++ ) {
834: mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
835: }
836: }
837: }
838: }
839:
840: void nullspace_gfpn(mat,n,ind)
841: GFPN **mat;
842: int n;
843: int *ind;
844: {
845: int i,j,l,s;
846: GFPN w,w1,h,inv;
847: GFPN *t,*u;
848:
849: bzero(ind,n*sizeof(int));
850: ind[0] = 0;
851: for ( i = j = 0; j < n; i++, j++ ) {
852: for ( ; j < n; j++ ) {
853: for ( l = i; l < n; l++ ) {
854: simpgfpn(mat[l][j],&w); mat[l][j] = w;
855: if ( mat[l][j] )
856: break;
857: }
858: if ( l < n ) {
859: t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
860: } else
861: ind[j] = 1;
862: }
863: if ( j == n )
864: break;
865: divgfpn((GFPN)ONE,(GFPN)mat[i][j],&inv);
866: for ( s = j, t = mat[i]; s < n; s++ ) {
867: mulgfpn(t[s],inv,&w); t[s] = w;
868: }
869: for ( l = 0; l < n; l++ ) {
870: if ( l == i )
871: continue;
872: u = mat[l]; chsgngfpn(u[j],&h);
873: for ( s = j; s < n; s++ ) {
874: mulgfpn(h,t[s],&w); addgfpn(w,u[s],&w1); u[s] = w1;
875: }
876: }
877: }
878: }
879: /* p = a(0)vl[0]+a(1)vl[1]+...+a(m-1)vl[m-1]+a(m) -> array = [a(0) a(1) ... a(m)] */
880:
881: void linear_form_to_array(p,vl,m,array)
882: P p;
883: VL vl;
884: int m;
885: Num *array;
886: {
887: int i;
888: DCP dc;
889:
890: bzero((char *)array,(m+1)*sizeof(Num *));
891: for ( i = 0; p && vl; vl = NEXT(vl), i++ ) {
892: if ( ID(p) == O_N )
893: break;
894: else if ( VR(p) == vl->v ) {
895: dc = DC(p);
896: array[i] = (Num)COEF(dc);
897: dc = NEXT(dc);
898: p = dc ? COEF(dc) : 0;
899: }
900: }
901: array[m] = (Num)p;
902: }
903:
904: void array_to_linear_form(array,vl,m,r)
905: Num *array;
906: VL vl;
907: int m;
908: P *r;
909: {
910: P t;
911: DCP dc0,dc1;
912:
913: if ( !m )
914: *r = (P)array[0];
915: else {
916: array_to_linear_form(array+1,NEXT(vl),m-1,&t);
917: if ( !array[0] )
918: *r = t;
919: else {
920: NEWDC(dc0); DEG(dc0) = ONE; COEF(dc0) = (P)array[0];
921: if ( !t )
922: NEXT(dc0) = 0;
923: else {
924: NEWDC(dc1); DEG(dc1) = 0; COEF(dc1) = t;
925: NEXT(dc1) = 0;
926: NEXT(dc0) = dc1;
927: }
928: MKP(vl->v,dc0,*r);
929: }
930: }
931: }
932:
933: void Psolve_linear_equation_gf2n(arg,rp)
934: NODE arg;
935: LIST *rp;
936: {
937: NODE eqs,tn;
938: VL vars,tvl;
939: int i,j,n,m,dim,codim;
940: GF2N **w;
941: int *ind;
942: NODE n0,n1;
943:
944: get_vars(ARG0(arg),&vars);
945: eqs = BDY((LIST)ARG0(arg));
946: for ( n = 0, tn = eqs; tn; tn = NEXT(tn), n++);
947: for ( m = 0, tvl = vars; tvl; tvl = NEXT(tvl), m++);
948: w = (GF2N **)almat_pointer(n,m+1);
949: for ( i = 0, tn = eqs; i < n; i++, tn = NEXT(tn) )
950: linear_form_to_array(BDY(tn),vars,m,(Num *)w[i]);
951: ind = (int *)ALLOCA(m*sizeof(int));
952: solve_linear_equation_gf2n(w,n,m,ind);
953: for ( j = 0, dim = 0; j < m; j++ )
954: if ( ind[j] )
955: dim++;
956: codim = m-dim;
957: for ( i = codim; i < n; i++ )
958: if ( w[i][m] ) {
959: MKLIST(*rp,0); return;
960: }
961: for ( i = 0, n0 = 0; i < codim; i++ ) {
962: NEXTNODE(n0,n1);
963: array_to_linear_form((Num *)w[i],vars,m,(P *)&BDY(n1));
964: }
965: if ( n0 )
966: NEXT(n1) = 0;
967: MKLIST(*rp,n0);
968: }
969:
970: void solve_linear_equation_gf2n(mat,n,m,ind)
971: GF2N **mat;
972: int n;
973: int *ind;
974: {
975: int i,j,l,s;
976: GF2N w,w1,h,inv;
977: GF2N *t,*u;
978: extern gf2n_lazy;
979:
980: bzero(ind,m*sizeof(int));
981: ind[0] = 0;
982: for ( i = j = 0; j < m; i++, j++ ) {
983: for ( ; j < m; j++ ) {
984: for ( l = i; l < n; l++ ) {
985: simpgf2n(mat[l][j],&w); mat[l][j] = w;
986: if ( mat[l][j] )
987: break;
988: }
989: if ( l < n ) {
990: t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
991: } else
992: ind[j] = 1;
993: }
994: if ( j == m )
995: break;
996: invgf2n(mat[i][j],&inv);
997: for ( s = j, t = mat[i]; s <= m; s++ ) {
998: mulgf2n(t[s],inv,&w); t[s] = w;
999: }
1000: for ( l = 0; l < n; l++ ) {
1001: if ( l == i )
1002: continue;
1003: u = mat[l]; h = u[j];
1004: for ( s = j; s <= m; s++ ) {
1005: mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
1006: }
1007: }
1008: }
1009: }
1010:
1011: /*
1012: void null_to_sol(mat,ind,mod,n,r)
1013: int **mat;
1014: int *ind;
1015: int mod,n;
1016: UM *r;
1017: {
1018: int i,j,k,l;
1019: int *c;
1020: UM w;
1021:
1022: for ( i = 0, l = 0; i < n; i++ ) {
1023: if ( !ind[i] )
1024: continue;
1025: w = UMALLOC(n);
1026: for ( j = k = 0, c = COEF(w); j < n; j++ )
1027: if ( ind[j] )
1028: c[j] = 0;
1029: else
1030: c[j] = mat[k++][i];
1031: c[i] = mod-1;
1032: for ( j = n; j >= 0; j-- )
1033: if ( c[j] )
1034: break;
1035: DEG(w) = j;
1036: r[l++] = w;
1037: }
1038: }
1039: */
1040:
1041: void showgfmat(mat,n)
1042: UM **mat;
1043: int n;
1044: {
1045: int i,j,k;
1046: int *c;
1047: UM p;
1048:
1049: for ( i = 0; i < n; i++ ) {
1050: for ( j = 0; j < n; j++ ) {
1051: p = mat[i][j];
1052: if ( DEG(p) < 0 )
1053: fprintf(asir_out,"0");
1054: else
1055: for ( p = mat[i][j], k = DEG(p), c = COEF(p); k >= 0; k-- ) {
1056: if ( c[k] )
1057: fprintf(asir_out,"+%d",c[k]);
1058: if ( k > 1 )
1059: fprintf(asir_out,"a^%d",k);
1060: else if ( k == 1 )
1061: fprintf(asir_out,"a",k);
1062: }
1063: fprintf(asir_out," ");
1064: }
1065: fprintf(asir_out,"\n");
1066: }
1067: }
1068:
1069: #if 0
1070: void Pgcda_mod(arg,rp)
1071: NODE arg;
1072: P *rp;
1073: {
1074: p1 = (P)ARG0(arg);
1075: p2 = (P)ARG1(arg);
1076: v = VR((P)ARG2(arg));
1077: d = (P)ARG3(arg);
1078: m = QTOS((Q)ARG4(arg));
1079: reordvar(CO,v,&vl);
1080: reorderp(vl,CO,p1,&t); ptomp(m,t,&m1);
1081: reorderp(vl,CO,p2,&t); ptomp(m,t,&m2);
1082: if ( NUM(m1) || NUM(m2) || VR(m1) != v || VR(m2) != v ) {
1083: *rp = ONE; return;
1084: }
1085: if ( deg(v,m1) >= deg(v,m2) ) {
1086: t = m1; m1 = m2; m2 = t;
1087: }
1088: while ( 1 ) {
1089: inva_mod(COEF(DC(m2)),d,m,&inv);
1090: NEWDC(dc); NEXT(dc) = 0; MKP(v,dc,h);
1091: d0 = deg(v,m1)-deg(v,m2); STOQ(d0,DEG(dc));
1092: mulgq(m,d,inv,COEF(DC(m1)),&COEF(dc));
1093: mulgp(vl,m,d,m2,h,&t); subgp(vl,m,d,m1,t,&s);
1094: }
1095: }
1096: #endif
1097:
1098: void Ppwr_mod(arg,rp)
1099: NODE arg;
1100: P *rp;
1101: {
1102: P p,a,d,r;
1103: int m;
1104: Q q;
1105: N n;
1106:
1107: m = QTOS((Q)ARG4(arg)); q = (Q)ARG5(arg); n = q ? NM(q) : 0;
1108: ptomp(m,(P)ARG0(arg),&p); ptomp(m,(P)ARG1(arg),&a);
1109: ptomp(m,(P)ARG3(arg),&d);
1110: pwr_mod(p,a,VR((P)ARG2(arg)),d,m,n,&r);
1111: mptop(r,rp);
1112: }
1113:
1114: void pwr_mod(p,a,v,d,m,n,rp)
1115: P p,a,d;
1116: V v;
1117: int m;
1118: N n;
1119: P *rp;
1120: {
1121: int b;
1122: P t,s,r;
1123: N n1;
1124:
1125: if ( !n )
1126: *rp = (P)ONEM;
1127: else if ( UNIN(n) )
1128: *rp = p;
1129: else {
1130: b = divin(n,2,&n1);
1131: pwr_mod(p,a,v,d,m,n1,&t);
1132: mulmp(CO,m,t,t,&s); rem_mod(s,a,v,d,m,&r);
1133: if ( b ) {
1134: mulmp(CO,m,r,p,&t); rem_mod(t,a,v,d,m,rp);
1135: } else
1136: *rp = r;
1137: }
1138: }
1139:
1140: void rem_mod(p,a,v,d,m,rp)
1141: P p,a,d;
1142: V v;
1143: int m;
1144: P *rp;
1145: {
1146: P tmp,r1,r2;
1147:
1148: divsrmp(CO,m,p,d,&tmp,&r1);
1149: divsrmp(CO,m,r1,a,&tmp,&r2);
1150: divsrmp(CO,m,r2,d,&tmp,rp);
1151: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>