Annotation of OpenXM_contrib2/asir2000/engine/distm.c, Revision 1.12
1.5 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.6 noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.5 noro 27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
47: *
1.12 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/engine/distm.c,v 1.11 2003/07/18 10:13:13 noro Exp $
1.5 noro 49: */
1.1 noro 50: #include "ca.h"
51: #include "inline.h"
52:
53: extern int (*cmpdl)();
1.2 noro 54: extern int do_weyl;
55:
1.9 noro 56: void ptomd(VL vl,int mod,VL dvl,P p,DP *pr)
1.1 noro 57: {
58: P t;
59:
60: ptomp(mod,p,&t);
61: mptomd(vl,mod,dvl,t,pr);
62: }
63:
1.9 noro 64: void mptomd(VL vl,int mod,VL dvl,P p,DP *pr)
1.1 noro 65: {
66: int n,i;
67: VL tvl;
68: V v;
69: DL d;
70: MP m;
71: DCP dc;
72: DP r,s,t,u;
73: P x,c;
74:
75: if ( !p )
76: *pr = 0;
77: else {
78: for ( n = 0, tvl = dvl; tvl; tvl = NEXT(tvl), n++ );
79: if ( NUM(p) ) {
80: NEWDL(d,n);
81: NEWMP(m); m->dl = d; C(m) = p; NEXT(m) = 0; MKDP(n,m,*pr);
82: } else {
83: for ( i = 0, tvl = dvl, v = VR(p);
84: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
85: if ( !tvl ) {
86: for ( dc = DC(p), s = 0, MKV(v,x); dc; dc = NEXT(dc) ) {
87: mptomd(vl,mod,dvl,COEF(dc),&t); pwrmp(vl,mod,x,DEG(dc),&c);
88: mulmdc(vl,mod,t,c,&r); addmd(vl,mod,r,s,&t); s = t;
89: }
90: *pr = s;
91: } else {
92: for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
93: mptomd(vl,mod,dvl,COEF(dc),&t);
1.10 noro 94: NEWDL(d,n); d->d[i] = QTOS(DEG(dc));
95: d->td = MUL_WEIGHT(d->d[i],i);
1.1 noro 96: NEWMP(m); m->dl = d; C(m) = (P)ONEM; NEXT(m) = 0; MKDP(n,m,u);
1.2 noro 97: comm_mulmd(vl,mod,t,u,&r); addmd(vl,mod,r,s,&t); s = t;
1.1 noro 98: }
99: *pr = s;
100: }
101: }
102: }
103: }
104:
1.9 noro 105: void mdtop(VL vl,int mod,VL dvl,DP p,P *pr)
1.1 noro 106: {
107: int n,i;
108: DL d;
109: MP m;
110: P r,s,t,u,w;
111: Q q;
112: VL tvl;
113:
114: if ( !p )
115: *pr = 0;
116: else {
117: for ( n = p->nv, m = BDY(p), s = 0; m; m = NEXT(m) ) {
118: for ( i = 0, t = C(m), d = m->dl, tvl = dvl;
119: i < n; tvl = NEXT(tvl), i++ ) {
120: MKMV(tvl->v,r); STOQ(d->d[i],q); pwrmp(vl,mod,r,q,&u);
121: mulmp(vl,mod,t,u,&w); t = w;
122: }
123: addmp(vl,mod,s,t,&u); s = u;
124: }
125: mptop(s,pr);
126: }
127: }
128:
1.9 noro 129: void addmd(VL vl,int mod,DP p1,DP p2,DP *pr)
1.1 noro 130: {
131: int n;
132: MP m1,m2,mr,mr0;
133: P t;
134: int tmp;
135: MQ q;
136:
137: if ( !p1 )
138: *pr = p2;
139: else if ( !p2 )
140: *pr = p1;
141: else {
142: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; )
143: switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {
144: case 0:
145: if ( NUM(C(m1)) && NUM(C(m2)) ) {
146: tmp = (CONT((MQ)C(m1))+CONT((MQ)C(m2))) - mod;
147: if ( tmp < 0 )
148: tmp += mod;
149: if ( tmp ) {
150: STOMQ(tmp,q); t = (P)q;
151: } else
152: t = 0;
153: } else
154: addmp(vl,mod,C(m1),C(m2),&t);
155: if ( t ) {
156: NEXTMP(mr0,mr); mr->dl = m1->dl; C(mr) = t;
157: }
158: m1 = NEXT(m1); m2 = NEXT(m2); break;
159: case 1:
160: NEXTMP(mr0,mr); mr->dl = m1->dl; C(mr) = C(m1);
161: m1 = NEXT(m1); break;
162: case -1:
163: NEXTMP(mr0,mr); mr->dl = m2->dl; C(mr) = C(m2);
164: m2 = NEXT(m2); break;
165: }
166: if ( !mr0 )
167: if ( m1 )
168: mr0 = m1;
169: else if ( m2 )
170: mr0 = m2;
171: else {
172: *pr = 0;
173: return;
174: }
175: else if ( m1 )
176: NEXT(mr) = m1;
177: else if ( m2 )
178: NEXT(mr) = m2;
179: else
180: NEXT(mr) = 0;
181: MKDP(NV(p1),mr0,*pr);
182: if ( *pr )
183: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
184: }
185: }
186:
1.9 noro 187: void submd(VL vl,int mod,DP p1,DP p2,DP *pr)
1.1 noro 188: {
189: DP t;
190:
191: if ( !p2 )
192: *pr = p1;
193: else {
194: chsgnmd(mod,p2,&t); addmd(vl,mod,p1,t,pr);
195: }
196: }
197:
1.9 noro 198: void chsgnmd(int mod,DP p,DP *pr)
1.1 noro 199: {
200: MP m,mr,mr0;
201:
202: if ( !p )
203: *pr = 0;
204: else {
205: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
206: NEXTMP(mr0,mr); chsgnmp(mod,C(m),&C(mr)); mr->dl = m->dl;
207: }
208: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
209: if ( *pr )
210: (*pr)->sugar = p->sugar;
211: }
212: }
213:
1.9 noro 214: void mulmd(VL vl,int mod,DP p1,DP p2,DP *pr)
1.1 noro 215: {
1.2 noro 216: if ( !do_weyl )
217: comm_mulmd(vl,mod,p1,p2,pr);
218: else
219: weyl_mulmd(vl,mod,p1,p2,pr);
220: }
221:
1.9 noro 222: void comm_mulmd(VL vl,int mod,DP p1,DP p2,DP *pr)
1.2 noro 223: {
224: MP m;
225: DP s,t,u;
226: int i,l,l1;
227: static MP *w;
228: static int wlen;
229:
230: if ( !p1 || !p2 )
231: *pr = 0;
232: else if ( OID(p1) <= O_P )
233: mulmdc(vl,mod,p2,(P)p1,pr);
234: else if ( OID(p2) <= O_P )
235: mulmdc(vl,mod,p1,(P)p2,pr);
236: else {
237: for ( m = BDY(p1), l1 = 0; m; m = NEXT(m), l1++ );
238: for ( m = BDY(p2), l = 0; m; m = NEXT(m), l++ );
239: if ( l1 < l ) {
240: t = p1; p1 = p2; p2 = t;
241: l = l1;
242: }
243: if ( l > wlen ) {
244: if ( w ) GC_free(w);
245: w = (MP *)MALLOC(l*sizeof(MP));
246: wlen = l;
247: }
248: for ( m = BDY(p2), i = 0; i < l; m = NEXT(m), i++ )
249: w[i] = m;
250: for ( s = 0, i = l-1; i >= 0; i-- ) {
251: mulmdm(vl,mod,p1,w[i],&t); addmd(vl,mod,s,t,&u); s = u;
252: }
253: bzero(w,l*sizeof(MP));
254: *pr = s;
255: }
256: }
257:
1.9 noro 258: void weyl_mulmd(VL vl,int mod,DP p1,DP p2,DP *pr)
1.2 noro 259: {
1.1 noro 260: MP m;
261: DP s,t,u;
1.9 noro 262: int i,l;
1.2 noro 263: static MP *w;
264: static int wlen;
1.1 noro 265:
266: if ( !p1 || !p2 )
267: *pr = 0;
268: else if ( OID(p1) <= O_P )
269: mulmdc(vl,mod,p2,(P)p1,pr);
270: else if ( OID(p2) <= O_P )
271: mulmdc(vl,mod,p1,(P)p2,pr);
272: else {
1.2 noro 273: for ( m = BDY(p2), l = 0; m; m = NEXT(m), l++ );
274: if ( l > wlen ) {
275: if ( w ) GC_free(w);
276: w = (MP *)MALLOC(l*sizeof(MP));
277: wlen = l;
278: }
279: for ( m = BDY(p2), i = 0; i < l; m = NEXT(m), i++ )
280: w[i] = m;
281: for ( s = 0, i = l-1; i >= 0; i-- ) {
282: weyl_mulmdm(vl,mod,p1,w[i],&t); addmd(vl,mod,s,t,&u); s = u;
1.1 noro 283: }
1.2 noro 284: bzero(w,l*sizeof(MP));
1.1 noro 285: *pr = s;
286: }
287: }
288:
1.9 noro 289: void mulmdm(VL vl,int mod,DP p,MP m0,DP *pr)
1.1 noro 290: {
291: MP m,mr,mr0;
292: P c;
293: DL d;
294: int n,t;
295: MQ q;
296:
297: if ( !p )
298: *pr = 0;
299: else {
300: for ( mr0 = 0, m = BDY(p), c = C(m0), d = m0->dl, n = NV(p);
301: m; m = NEXT(m) ) {
302: NEXTMP(mr0,mr);
303: if ( NUM(C(m)) && NUM(c) ) {
304: t = dmar(((MQ)(C(m)))->cont,((MQ)c)->cont,0,mod);
305: STOMQ(t,q); C(mr) = (P)q;
306: } else
307: mulmp(vl,mod,C(m),c,&C(mr));
308: adddl(n,m->dl,d,&mr->dl);
309: }
310: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
311: if ( *pr )
312: (*pr)->sugar = p->sugar + m0->dl->td;
313: }
314: }
315:
1.9 noro 316: void weyl_mulmdm(VL vl,int mod,DP p,MP m0,DP *pr)
1.2 noro 317: {
318: DP r,t,t1;
319: MP m;
320: int n,l,i;
321: static MP *w;
322: static int wlen;
323:
324: if ( !p )
325: *pr = 0;
326: else {
327: for ( m = BDY(p), l = 0; m; m = NEXT(m), l++ );
328: if ( l > wlen ) {
329: if ( w ) GC_free(w);
330: w = (MP *)MALLOC(l*sizeof(MP));
331: wlen = l;
332: }
333: for ( m = BDY(p), i = 0; i < l; m = NEXT(m), i++ )
334: w[i] = m;
335: for ( r = 0, i = l-1, n = NV(p); i >= 0; i-- ) {
336: weyl_mulmmm(vl,mod,w[i],m0,n,&t);
337: addmd(vl,mod,r,t,&t1); r = t1;
338: }
339: bzero(w,l*sizeof(MP));
340: if ( r )
341: r->sugar = p->sugar + m0->dl->td;
342: *pr = r;
343: }
344: }
345:
346: /* m0 = x0^d0*x1^d1*... * dx0^d(n/2)*dx1^d(n/2+1)*... */
347:
1.9 noro 348: void weyl_mulmmm(VL vl,int mod,MP m0,MP m1,int n,DP *pr)
1.2 noro 349: {
1.9 noro 350: MP mr,mr0;
1.2 noro 351: MQ mq;
352: DP r,t,t1;
1.9 noro 353: P c,c0,c1;
1.2 noro 354: DL d,d0,d1;
1.3 noro 355: int i,j,a,b,k,l,n2,s,min;
1.2 noro 356: static int *tab;
357: static int tablen;
358:
359: if ( !m0 || !m1 )
360: *pr = 0;
361: else {
362: c0 = C(m0); c1 = C(m1);
363: mulmp(vl,mod,c0,c1,&c);
364: d0 = m0->dl; d1 = m1->dl;
365: n2 = n>>1;
366: if ( n & 1 ) {
367: /* homogenized computation; dx-xd=h^2 */
368: /* offset of h-degree */
1.3 noro 369: NEWDL(d,n);
370: d->td = d->d[n-1] = d0->d[n-1]+d1->d[n-1];
1.4 noro 371: NEWMP(mr); mr->c = (P)ONEM; mr->dl = d; NEXT(mr) = 0;
1.3 noro 372: MKDP(n,mr,r); r->sugar = d->td;
373: } else
374: r = (DP)ONEM;
375: for ( i = 0; i < n2; i++ ) {
376: a = d0->d[i]; b = d1->d[n2+i];
377: k = d0->d[n2+i]; l = d1->d[i];
1.10 noro 378:
1.3 noro 379: /* degree of xi^a*(Di^k*xi^l)*Di^b */
1.10 noro 380: a += l;
381: b += k;
382: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
383:
1.3 noro 384: /* compute xi^a*(Di^k*xi^l)*Di^b */
385: min = MIN(k,l);
386:
387: if ( min+1 > tablen ) {
388: if ( tab ) GC_free(tab);
389: tab = (int *)MALLOC((min+1)*sizeof(int));
390: tablen = min+1;
391: }
392: mkwcm(k,l,mod,tab);
393: if ( n & 1 )
1.2 noro 394: for ( mr0 = 0, j = 0; j <= min; j++ ) {
1.3 noro 395: NEXTMP(mr0,mr); NEWDL(d,n);
1.10 noro 396: d->d[i] = a-j; d->d[n2+i] = b-j;
1.3 noro 397: d->td = s;
1.10 noro 398: d->d[n-1] = s-(MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i));
1.3 noro 399: STOMQ(tab[j],mq); mr->c = (P)mq; mr->dl = d;
1.2 noro 400: }
1.3 noro 401: else
1.2 noro 402: for ( mr0 = 0, s = 0, j = 0; j <= min; j++ ) {
1.3 noro 403: NEXTMP(mr0,mr); NEWDL(d,n);
1.10 noro 404: d->d[i] = a-j; d->d[n2+i] = b-j;
405: d->td = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i); /* XXX */
1.2 noro 406: s = MAX(s,d->td); /* XXX */
1.3 noro 407: STOMQ(tab[j],mq); mr->c = (P)mq; mr->dl = d;
1.2 noro 408: }
1.3 noro 409: bzero(tab,(min+1)*sizeof(int));
410: if ( mr0 )
411: NEXT(mr) = 0;
412: MKDP(n,mr0,t);
413: if ( t )
414: t->sugar = s;
415: comm_mulmd(vl,mod,r,t,&t1); r = t1;
416: }
1.2 noro 417: mulmdc(vl,mod,r,c,pr);
418: }
419: }
420:
1.9 noro 421: void mulmdc(VL vl,int mod,DP p,P c,DP *pr)
1.1 noro 422: {
423: MP m,mr,mr0;
424: int t;
425: MQ q;
426:
427: if ( !p || !c )
428: *pr = 0;
429: else {
430: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
431: NEXTMP(mr0,mr);
432: if ( NUM(C(m)) && NUM(c) ) {
433: t = dmar(((MQ)(C(m)))->cont,((MQ)c)->cont,0,mod);
434: STOMQ(t,q); C(mr) = (P)q;
435: } else
436: mulmp(vl,mod,C(m),c,&C(mr));
437: mr->dl = m->dl;
438: }
439: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
440: if ( *pr )
441: (*pr)->sugar = p->sugar;
442: }
443: }
444:
1.9 noro 445: void divsmdc(VL vl,int mod,DP p,P c,DP *pr)
1.1 noro 446: {
447: MP m,mr,mr0;
448:
449: if ( !c )
450: error("disvsdc : division by 0");
451: else if ( !p )
452: *pr = 0;
453: else {
454: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
455: NEXTMP(mr0,mr); divsmp(vl,mod,C(m),c,&C(mr)); mr->dl = m->dl;
456: }
457: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
458: if ( *pr )
459: (*pr)->sugar = p->sugar;
460: }
461: }
462:
1.9 noro 463: void _dtop_mod(VL vl,VL dvl,DP p,P *pr)
1.1 noro 464: {
465: int n,i;
466: DL d;
467: MP m;
468: P r,s,t,u,w;
469: Q q;
470: VL tvl;
471:
472: if ( !p )
473: *pr = 0;
474: else {
475: for ( n = p->nv, m = BDY(p), s = 0; m; m = NEXT(m) ) {
476: i = ITOS(m->c); STOQ(i,q); t = (P)q;
477: for ( i = 0, d = m->dl, tvl = dvl;
478: i < n; tvl = NEXT(tvl), i++ ) {
479: MKV(tvl->v,r); STOQ(d->d[i],q); pwrp(vl,r,q,&u);
480: mulp(vl,t,u,&w); t = w;
481: }
482: addp(vl,s,t,&u); s = u;
483: }
484: *pr = s;
485: }
486: }
487:
1.9 noro 488: void _dp_mod(DP p,int mod,NODE subst,DP *rp)
1.1 noro 489: {
490: MP m,mr,mr0;
491: P t,s;
492: NODE tn;
493:
494: if ( !p )
495: *rp = 0;
496: else {
497: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
498: for ( tn = subst, s = m->c; tn; tn = NEXT(NEXT(tn)) ) {
499: substp(CO,s,BDY(tn),BDY(NEXT(tn)),&t);
500: s = t;
501: }
502: ptomp(mod,s,&t);
503: if ( t ) {
504: NEXTMP(mr0,mr); mr->c = STOI(CONT((MQ)t)); mr->dl = m->dl;
505: }
506: }
507: if ( mr0 ) {
508: NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
509: } else
510: *rp = 0;
511: }
512: }
513:
1.9 noro 514: void _dp_monic(DP p,int mod,DP *rp)
1.2 noro 515: {
516: MP m,mr,mr0;
517: int c,c1;
518:
519: if ( !p )
520: *rp = 0;
521: else {
522: c = invm(ITOS(BDY(p)->c),mod);
523: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
524: c1 = dmar(ITOS(m->c),c,0,mod);
525: NEXTMP(mr0,mr); mr->c = STOI(c1); mr->dl = m->dl;
526: }
527: NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
528: }
1.1 noro 529: }
530:
1.9 noro 531: void _printdp(DP d)
1.1 noro 532: {
533: int n,i;
534: MP m;
535: DL dl;
536:
537: if ( !d ) {
538: printf("0"); return;
539: }
540: for ( n = d->nv, m = BDY(d); m; m = NEXT(m) ) {
541: printf("%d*<<",ITOS(m->c));
542: for ( i = 0, dl = m->dl; i < n-1; i++ )
543: printf("%d,",dl->d[i]);
544: printf("%d",dl->d[i]);
545: printf(">>");
546: if ( NEXT(m) )
547: printf("+");
548: }
1.8 noro 549: }
550:
551: /* merge p1 and p2 into pr */
552:
1.9 noro 553: void addmd_destructive(int mod,DP p1,DP p2,DP *pr)
1.8 noro 554: {
555: int n;
556: MP m1,m2,mr,mr0,s;
557: int t;
558:
559: if ( !p1 )
560: *pr = p2;
561: else if ( !p2 )
562: *pr = p1;
563: else {
564: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; )
565: switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {
566: case 0:
567: t = (ITOS(C(m1))+ITOS(C(m2))) - mod;
568: if ( t < 0 )
569: t += mod;
570: s = m1; m1 = NEXT(m1);
571: if ( t ) {
572: NEXTMP2(mr0,mr,s); C(mr) = STOI(t);
573: }
574: s = m2; m2 = NEXT(m2);
575: break;
576: case 1:
577: s = m1; m1 = NEXT(m1); NEXTMP2(mr0,mr,s);
578: break;
579: case -1:
580: s = m2; m2 = NEXT(m2); NEXTMP2(mr0,mr,s);
581: break;
582: }
583: if ( !mr0 )
584: if ( m1 )
585: mr0 = m1;
586: else if ( m2 )
587: mr0 = m2;
588: else {
589: *pr = 0;
590: return;
591: }
592: else if ( m1 )
593: NEXT(mr) = m1;
594: else if ( m2 )
595: NEXT(mr) = m2;
596: else
597: NEXT(mr) = 0;
598: MKDP(NV(p1),mr0,*pr);
599: if ( *pr )
600: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
601: }
602: }
603:
1.9 noro 604: void mulmd_dup(int mod,DP p1,DP p2,DP *pr)
1.8 noro 605: {
606: if ( !do_weyl )
607: comm_mulmd_dup(mod,p1,p2,pr);
608: else
609: weyl_mulmd_dup(mod,p1,p2,pr);
610: }
611:
1.9 noro 612: void comm_mulmd_dup(int mod,DP p1,DP p2,DP *pr)
1.8 noro 613: {
614: MP m;
615: DP s,t,u;
616: int i,l,l1;
617: static MP *w;
618: static int wlen;
619:
620: if ( !p1 || !p2 )
621: *pr = 0;
622: else {
623: for ( m = BDY(p1), l1 = 0; m; m = NEXT(m), l1++ );
624: for ( m = BDY(p2), l = 0; m; m = NEXT(m), l++ );
625: if ( l1 < l ) {
626: t = p1; p1 = p2; p2 = t;
627: l = l1;
628: }
629: if ( l > wlen ) {
630: if ( w ) GC_free(w);
631: w = (MP *)MALLOC(l*sizeof(MP));
632: wlen = l;
633: }
634: for ( m = BDY(p2), i = 0; i < l; m = NEXT(m), i++ )
635: w[i] = m;
636: for ( s = 0, i = l-1; i >= 0; i-- ) {
637: mulmdm_dup(mod,p1,w[i],&t); addmd_destructive(mod,s,t,&u); s = u;
638: }
639: bzero(w,l*sizeof(MP));
640: *pr = s;
641: }
642: }
643:
1.9 noro 644: void weyl_mulmd_dup(int mod,DP p1,DP p2,DP *pr)
1.8 noro 645: {
646: MP m;
647: DP s,t,u;
1.9 noro 648: int i,l;
1.8 noro 649: static MP *w;
650: static int wlen;
651:
652: if ( !p1 || !p2 )
653: *pr = 0;
654: else {
655: for ( m = BDY(p1), l = 0; m; m = NEXT(m), l++ );
656: if ( l > wlen ) {
657: if ( w ) GC_free(w);
658: w = (MP *)MALLOC(l*sizeof(MP));
659: wlen = l;
660: }
661: for ( m = BDY(p1), i = 0; i < l; m = NEXT(m), i++ )
662: w[i] = m;
663: for ( s = 0, i = l-1; i >= 0; i-- ) {
664: weyl_mulmdm_dup(mod,w[i],p2,&t); addmd_destructive(mod,s,t,&u); s = u;
665: }
666: bzero(w,l*sizeof(MP));
667: *pr = s;
668: }
669: }
670:
1.9 noro 671: void mulmdm_dup(int mod,DP p,MP m0,DP *pr)
1.8 noro 672: {
673: MP m,mr,mr0;
674: DL d,dt,dm;
1.9 noro 675: int c,n,i;
1.8 noro 676: int *pt,*p1,*p2;
677:
678: if ( !p )
679: *pr = 0;
680: else {
681: for ( mr0 = 0, m = BDY(p), c = ITOS(C(m0)), d = m0->dl, n = NV(p);
682: m; m = NEXT(m) ) {
683: NEXTMP(mr0,mr);
684: C(mr) = STOI(dmar(ITOS(C(m)),c,0,mod));
685: NEWDL_NOINIT(dt,n); mr->dl = dt;
686: dm = m->dl;
687: dt->td = d->td + dm->td;
688: for ( i = 0, pt = dt->d, p1=d->d, p2 = dm->d; i < n; i++ )
689: *pt++ = *p1++ + *p2++;
690: }
691: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
692: if ( *pr )
693: (*pr)->sugar = p->sugar + m0->dl->td;
694: }
695: }
696:
1.9 noro 697: void weyl_mulmdm_dup(int mod,MP m0,DP p,DP *pr)
1.8 noro 698: {
699: DP r,t,t1;
700: MP m;
701: DL d0;
702: int n,n2,l,i,j,tlen;
703: static MP *w,*psum;
704: static struct cdlm *tab;
705: static int wlen;
706: static int rtlen;
707:
708: if ( !p )
709: *pr = 0;
710: else {
711: for ( m = BDY(p), l = 0; m; m = NEXT(m), l++ );
712: if ( l > wlen ) {
713: if ( w ) GC_free(w);
714: w = (MP *)MALLOC(l*sizeof(MP));
715: wlen = l;
716: }
717: for ( m = BDY(p), i = 0; i < l; m = NEXT(m), i++ )
718: w[i] = m;
719: n = NV(p); n2 = n>>1;
720: d0 = m0->dl;
721:
722: for ( i = 0, tlen = 1; i < n2; i++ )
723: tlen *= d0->d[n2+i]+1;
724: if ( tlen > rtlen ) {
725: if ( tab ) GC_free(tab);
726: if ( psum ) GC_free(psum);
727: rtlen = tlen;
728: tab = (struct cdlm *)MALLOC(rtlen*sizeof(struct cdlm));
729: psum = (MP *)MALLOC(rtlen*sizeof(MP));
730: }
731: bzero(psum,tlen*sizeof(MP));
732: for ( i = l-1; i >= 0; i-- ) {
733: bzero(tab,tlen*sizeof(struct cdlm));
734: weyl_mulmmm_dup(mod,m0,w[i],n,tab,tlen);
735: for ( j = 0; j < tlen; j++ ) {
736: if ( tab[j].c ) {
737: NEWMP(m); m->dl = tab[j].d;
738: C(m) = STOI(tab[j].c); NEXT(m) = psum[j];
739: psum[j] = m;
740: }
741: }
742: }
743: for ( j = tlen-1, r = 0; j >= 0; j-- )
744: if ( psum[j] ) {
745: MKDP(n,psum[j],t); addmd_destructive(mod,r,t,&t1); r = t1;
746: }
747: if ( r )
748: r->sugar = p->sugar + m0->dl->td;
749: *pr = r;
750: }
751: }
752:
753: /* m0 = x0^d0*x1^d1*... * dx0^d(n/2)*dx1^d(n/2+1)*... */
754:
1.9 noro 755: void weyl_mulmmm_dup(int mod,MP m0,MP m1,int n,struct cdlm *rtab,int rtablen)
1.8 noro 756: {
1.9 noro 757: int c,c0,c1;
1.8 noro 758: DL d,d0,d1,dt;
1.9 noro 759: int i,j,a,b,k,l,n2,s,min,curlen;
1.8 noro 760: struct cdlm *p;
761: static int *ctab;
762: static struct cdlm *tab;
763: static int tablen;
764: static struct cdlm *tmptab;
765: static int tmptablen;
766:
767: if ( !m0 || !m1 ) {
768: rtab[0].c = 0;
769: rtab[0].d = 0;
770: return;
771: }
772: c0 = ITOS(C(m0)); c1 = ITOS(C(m1));
773: c = dmar(c0,c1,0,mod);
774: d0 = m0->dl; d1 = m1->dl;
775: n2 = n>>1;
776: curlen = 1;
777:
778: NEWDL(d,n);
779: if ( n & 1 )
780: /* offset of h-degree */
781: d->td = d->d[n-1] = d0->d[n-1]+d1->d[n-1];
782: else
783: d->td = 0;
784: rtab[0].c = c;
785: rtab[0].d = d;
786:
787: if ( rtablen > tmptablen ) {
788: if ( tmptab ) GC_free(tmptab);
789: tmptab = (struct cdlm *)MALLOC(rtablen*sizeof(struct cdlm));
790: tmptablen = rtablen;
791: }
792:
793: for ( i = 0; i < n2; i++ ) {
794: a = d0->d[i]; b = d1->d[n2+i];
795: k = d0->d[n2+i]; l = d1->d[i];
1.10 noro 796:
797: /* degree of xi^a*(Di^k*xi^l)*Di^b */
798: a += l;
799: b += k;
800: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
801:
1.8 noro 802: if ( !k || !l ) {
803: for ( j = 0, p = rtab; j < curlen; j++, p++ ) {
804: if ( p->c ) {
805: dt = p->d;
806: dt->d[i] = a;
807: dt->d[n2+i] = b;
808: dt->td += s;
809: }
810: }
811: curlen *= k+1;
812: continue;
813: }
814: if ( k+1 > tablen ) {
815: if ( tab ) GC_free(tab);
816: if ( ctab ) GC_free(ctab);
817: tablen = k+1;
818: tab = (struct cdlm *)MALLOC(tablen*sizeof(struct cdlm));
819: ctab = (int *)MALLOC(tablen*sizeof(int));
820: }
821: /* compute xi^a*(Di^k*xi^l)*Di^b */
822: min = MIN(k,l);
823: mkwcm(k,l,mod,ctab);
824: bzero(tab,(k+1)*sizeof(struct cdlm));
825: /* n&1 != 0 => homogenized computation; dx-xd=h^2 */
826: if ( n & 1 )
827: for ( j = 0; j <= min; j++ ) {
828: NEWDL(d,n);
1.10 noro 829: d->d[i] = a-j; d->d[n2+i] = b-j;
1.8 noro 830: d->td = s;
1.10 noro 831: d->d[n-1] = s-(MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i));
1.8 noro 832: tab[j].d = d;
833: tab[j].c = ctab[j];
834: }
835: else
836: for ( j = 0; j <= min; j++ ) {
837: NEWDL(d,n);
1.10 noro 838: d->d[i] = a-j; d->d[n2+i] = b-j;
839: d->td = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i); /* XXX */
1.8 noro 840: tab[j].d = d;
841: tab[j].c = ctab[j];
842: }
843: comm_mulmd_tab_destructive(mod,n,rtab,curlen,tab,k+1);
844: curlen *= k+1;
845: }
846: }
847:
1.9 noro 848: void comm_mulmd_tab_destructive(int mod,int nv,struct cdlm *t,int n,struct cdlm *t1,int n1)
1.8 noro 849: {
850: int i,j;
851: struct cdlm *p;
852: int c;
853: DL d;
854:
855: for ( j = 1, p = t+n; j < n1; j++ ) {
856: c = t1[j].c;
857: d = t1[j].d;
858: if ( !c )
859: break;
860: for ( i = 0; i < n; i++, p++ ) {
861: if ( t[i].c ) {
862: p->c = dmar(t[i].c,c,0,mod);
863: adddl_dup(nv,t[i].d,d,&p->d);
864: }
865: }
866: }
867: c = t1[0].c;
868: d = t1[0].d;
869: for ( i = 0, p = t; i < n; i++, p++ )
870: if ( t[i].c ) {
871: p->c = dmar(t[i].c,c,0,mod);
872: /* t[i].d += d */
873: adddl_destructive(nv,t[i].d,d);
874: }
875: }
876:
1.9 noro 877: void adddl_dup(int n,DL d1,DL d2,DL *dr)
1.8 noro 878: {
879: DL dt;
880: int i;
881:
882: NEWDL(dt,n);
883: *dr = dt;
884: dt->td = d1->td + d2->td;
885: for ( i = 0; i < n; i++ )
886: dt->d[i] = d1->d[i]+d2->d[i];
1.11 noro 887: }
888:
889: /* ------------------------------------------------------ */
890:
891: #if defined(__GNUC__)
892: #define INLINE inline
893: #elif defined(VISUAL)
894: #define INLINE __inline
895: #else
896: #define INLINE
897: #endif
898:
899: typedef struct oPGeoBucket {
900: int m;
901: struct oND *body[32];
902: } *PGeoBucket;
903:
904: typedef struct oND {
905: struct oNM *body;
906: int nv;
907: int sugar;
908: } *ND;
909:
910: typedef struct oNM {
911: struct oNM *next;
912: int td;
913: int c;
914: unsigned int dl[1];
915: } *NM;
916:
917: typedef struct oND_pairs {
918: struct oND_pairs *next;
919: int i1,i2;
920: int td,sugar;
921: unsigned int lcm[1];
922: } *ND_pairs;
923:
924: static ND *nps;
925: int nd_mod,nd_nvar;
926: int is_rlex;
927: int nd_epw,nd_bpe,nd_wpd;
1.12 ! noro 928: unsigned int nd_mask[32];
! 929: unsigned int nd_mask0;
1.11 noro 930: NM _nm_free_list;
931: ND _nd_free_list;
932: ND_pairs _ndp_free_list;
933:
934: extern int Top,Reverse;
935: int nd_psn,nd_pslen;
936:
937: void GC_gcollect();
938: NODE append_one(NODE,int);
939:
940: #define HTD(d) ((d)->body->td)
941: #define HDL(d) ((d)->body->dl)
942: #define HC(d) ((d)->body->c)
943:
944: #define NEWND_pairs(m) if(!_ndp_free_list)_NDP_alloc(); (m)=_ndp_free_list; _ndp_free_list = NEXT(_ndp_free_list)
945: #define NEWNM(m) if(!_nm_free_list)_NM_alloc(); (m)=_nm_free_list; _nm_free_list = NEXT(_nm_free_list)
946: #define MKND(n,m,d) if(!_nd_free_list)_ND_alloc(); (d)=_nd_free_list; _nd_free_list = (ND)BDY(_nd_free_list); (d)->nv=(n); BDY(d)=(m)
947:
948: #define NEXTNM(r,c) \
949: if(!(r)){NEWNM(r);(c)=(r);}else{NEWNM(NEXT(c));(c)=NEXT(c);}
950: #define NEXTNM2(r,c,s) \
951: if(!(r)){(c)=(r)=(s);}else{NEXT(c)=(s);(c)=(s);}
952: #define FREENM(m) NEXT(m)=_nm_free_list; _nm_free_list=(m)
953: #define FREEND(m) BDY(m)=(NM)_nd_free_list; _nd_free_list=(m)
954:
955: #define NEXTND_pairs(r,c) \
956: if(!(r)){NEWND_pairs(r);(c)=(r);}else{NEWND_pairs(NEXT(c));(c)=NEXT(c);}
957:
958: ND_pairs crit_B( ND_pairs d, int s );
959: void nd_gr(LIST f,LIST v,int m,struct order_spec *ord,LIST *rp);
960: NODE nd_setup(NODE f);
961: int nd_newps(ND a);
962: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest );
963: NODE update_base(NODE nd,int ndp);
964: static ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest );
965: int crit_2( int dp1, int dp2 );
966: ND_pairs crit_F( ND_pairs d1 );
967: ND_pairs crit_M( ND_pairs d1 );
968: ND_pairs nd_newpairs( NODE g, int t );
969: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t);
970: NODE nd_gb(NODE f);
971: void nd_free_private_storage();
972: void _NM_alloc();
973: void _ND_alloc();
974: int ndl_td(unsigned int *d);
975: ND nd_add(ND p1,ND p2);
976: ND nd_mul_nm(ND p,NM m0);
977: ND nd_sp(ND_pairs p);
978: ND nd_reducer(ND p1,ND p2);
1.12 ! noro 979: ND nd_find_reducer(ND g);
! 980: ND nd_nf(ND g,int full);
1.11 noro 981: void ndl_print(unsigned int *dl);
982: void nd_print(ND p);
983: void ndp_print(ND_pairs d);
984: int nd_length(ND p);
985: void nd_monic(ND p);
986:
987: void nd_free_private_storage()
988: {
989: _nd_free_list = 0;
990: _nm_free_list = 0;
991: GC_gcollect();
992: }
993:
994: void _NM_alloc()
995: {
996: NM p;
997: int i;
998:
1.12 ! noro 999: for ( i = 0; i < 10240; i++ ) {
1.11 noro 1000: p = (NM)GC_malloc(sizeof(struct oNM)+(nd_wpd-1)*sizeof(unsigned int));
1001: p->next = _nm_free_list; _nm_free_list = p;
1002: }
1003: }
1004:
1005: void _ND_alloc()
1006: {
1007: ND p;
1008: int i;
1009:
1.12 ! noro 1010: for ( i = 0; i < 10240; i++ ) {
1.11 noro 1011: p = (ND)GC_malloc(sizeof(struct oND));
1012: p->body = (NM)_nd_free_list; _nd_free_list = p;
1013: }
1014: }
1015:
1016: void _NDP_alloc()
1017: {
1018: ND_pairs p;
1019: int i;
1020:
1.12 ! noro 1021: for ( i = 0; i < 10240; i++ ) {
1.11 noro 1022: p = (ND_pairs)GC_malloc(sizeof(struct oND_pairs)
1023: +(nd_wpd-1)*sizeof(unsigned int));
1024: p->next = _ndp_free_list; _ndp_free_list = p;
1025: }
1026: }
1027:
1028: INLINE nd_length(ND p)
1029: {
1030: NM m;
1031: int i;
1032:
1033: if ( !p )
1034: return 0;
1035: else {
1036: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
1037: return i;
1038: }
1039: }
1040:
1041: INLINE int ndl_reducible(unsigned int *d1,unsigned int *d2)
1042: {
1043: unsigned int u1,u2;
1.12 ! noro 1044: int i,j;
1.11 noro 1045:
1046: switch ( nd_bpe ) {
1047: case 4:
1048: for ( i = 0; i < nd_wpd; i++ ) {
1049: u1 = d1[i]; u2 = d2[i];
1050: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
1051: if ( (u1&0xf000000) < (u2&0xf000000) ) return 0;
1052: if ( (u1&0xf00000) < (u2&0xf00000) ) return 0;
1053: if ( (u1&0xf0000) < (u2&0xf0000) ) return 0;
1054: if ( (u1&0xf000) < (u2&0xf000) ) return 0;
1055: if ( (u1&0xf00) < (u2&0xf00) ) return 0;
1056: if ( (u1&0xf0) < (u2&0xf0) ) return 0;
1057: if ( (u1&0xf) < (u2&0xf) ) return 0;
1058: }
1059: return 1;
1060: break;
1061: case 8:
1062: for ( i = 0; i < nd_wpd; i++ ) {
1063: u1 = d1[i]; u2 = d2[i];
1064: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
1065: if ( (u1&0xff0000) < (u2&0xff0000) ) return 0;
1066: if ( (u1&0xff00) < (u2&0xff00) ) return 0;
1067: if ( (u1&0xff) < (u2&0xff) ) return 0;
1068: }
1069: return 1;
1070: break;
1071: case 16:
1072: for ( i = 0; i < nd_wpd; i++ ) {
1073: u1 = d1[i]; u2 = d2[i];
1074: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
1075: if ( (u1&0xffff) < (u2&0xffff) ) return 0;
1076: }
1077: return 1;
1078: break;
1079: case 32:
1080: for ( i = 0; i < nd_wpd; i++ )
1081: if ( d1[i] < d2[i] ) return 0;
1082: return 1;
1083: break;
1084: default:
1.12 ! noro 1085: for ( i = 0; i < nd_wpd; i++ ) {
! 1086: u1 = d1[i]; u2 = d2[i];
! 1087: for ( j = 0; j < nd_epw; j++ )
! 1088: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
! 1089: }
! 1090: return 1;
1.11 noro 1091: }
1092: }
1093:
1.12 ! noro 1094: void ndl_lcm(unsigned int *d1,unsigned *d2,unsigned int *d)
1.11 noro 1095: {
1096: unsigned int t1,t2,u,u1,u2;
1.12 ! noro 1097: int i,j;
1.11 noro 1098:
1099: switch ( nd_bpe ) {
1100: case 4:
1101: for ( i = 0; i < nd_wpd; i++ ) {
1102: u1 = d1[i]; u2 = d2[i];
1103: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
1104: t1 = (u1&0xf000000); t2 = (u2&0xf000000); u |= t1>t2?t1:t2;
1105: t1 = (u1&0xf00000); t2 = (u2&0xf00000); u |= t1>t2?t1:t2;
1106: t1 = (u1&0xf0000); t2 = (u2&0xf0000); u |= t1>t2?t1:t2;
1107: t1 = (u1&0xf000); t2 = (u2&0xf000); u |= t1>t2?t1:t2;
1108: t1 = (u1&0xf00); t2 = (u2&0xf00); u |= t1>t2?t1:t2;
1109: t1 = (u1&0xf0); t2 = (u2&0xf0); u |= t1>t2?t1:t2;
1110: t1 = (u1&0xf); t2 = (u2&0xf); u |= t1>t2?t1:t2;
1111: d[i] = u;
1112: }
1113: break;
1114: case 8:
1115: for ( i = 0; i < nd_wpd; i++ ) {
1116: u1 = d1[i]; u2 = d2[i];
1117: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
1118: t1 = (u1&0xff0000); t2 = (u2&0xff0000); u |= t1>t2?t1:t2;
1119: t1 = (u1&0xff00); t2 = (u2&0xff00); u |= t1>t2?t1:t2;
1120: t1 = (u1&0xff); t2 = (u2&0xff); u |= t1>t2?t1:t2;
1121: d[i] = u;
1122: }
1123: break;
1124: case 16:
1125: for ( i = 0; i < nd_wpd; i++ ) {
1126: u1 = d1[i]; u2 = d2[i];
1127: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
1128: t1 = (u1&0xffff); t2 = (u2&0xffff); u |= t1>t2?t1:t2;
1129: d[i] = u;
1130: }
1131: break;
1132: case 32:
1133: for ( i = 0; i < nd_wpd; i++ ) {
1134: u1 = d1[i]; u2 = d2[i];
1135: d[i] = u1>u2?u1:u2;
1136: }
1137: break;
1138: default:
1.12 ! noro 1139: for ( i = 0; i < nd_wpd; i++ ) {
! 1140: u1 = d1[i]; u2 = d2[i];
! 1141: for ( j = 0, u = 0; j < nd_epw; j++ ) {
! 1142: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
! 1143: }
! 1144: d[i] = u;
! 1145: }
! 1146: break;
1.11 noro 1147: }
1148: }
1149:
1.12 ! noro 1150: int ndl_td(unsigned int *d)
1.11 noro 1151: {
1152: unsigned int t,u;
1.12 ! noro 1153: int i,j;
1.11 noro 1154:
1.12 ! noro 1155: for ( t = 0, i = 0; i < nd_wpd; i++ ) {
! 1156: u = d[i];
! 1157: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
! 1158: t += (u&nd_mask0);
1.11 noro 1159: }
1160: return t;
1161: }
1162:
1163: INLINE int ndl_compare(unsigned int *d1,unsigned int *d2)
1164: {
1165: int i;
1166:
1.12 ! noro 1167: for ( i = 0; i < nd_wpd; i++, d1++, d2++ )
! 1168: if ( *d1 > *d2 )
1.11 noro 1169: return is_rlex ? -1 : 1;
1.12 ! noro 1170: else if ( *d1 < *d2 )
1.11 noro 1171: return is_rlex ? 1 : -1;
1172: return 0;
1173: }
1174:
1175: INLINE int ndl_equal(unsigned int *d1,unsigned int *d2)
1176: {
1177: int i;
1178:
1179: for ( i = 0; i < nd_wpd; i++ )
1180: if ( d1[i] != d2[i] )
1181: return 0;
1182: return 1;
1183: }
1184:
1185: INLINE void ndl_add(unsigned int *d1,unsigned int *d2,unsigned int *d)
1186: {
1187: int i;
1188:
1189: for ( i = 0; i < nd_wpd; i++ )
1190: d[i] = d1[i]+d2[i];
1191: }
1192:
1.12 ! noro 1193: void ndl_sub(unsigned int *d1,unsigned int *d2,unsigned int *d)
1.11 noro 1194: {
1195: int i;
1196:
1197: for ( i = 0; i < nd_wpd; i++ )
1198: d[i] = d1[i]-d2[i];
1199: }
1200:
1.12 ! noro 1201: int ndl_disjoint(unsigned int *d1,unsigned int *d2)
1.11 noro 1202: {
1203: unsigned int t1,t2,u,u1,u2;
1.12 ! noro 1204: int i,j;
1.11 noro 1205:
1206: switch ( nd_bpe ) {
1207: case 4:
1208: for ( i = 0; i < nd_wpd; i++ ) {
1209: u1 = d1[i]; u2 = d2[i];
1210: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
1211: t1 = u1&0xf000000; t2 = u2&0xf000000; if ( t1&&t2 ) return 0;
1212: t1 = u1&0xf00000; t2 = u2&0xf00000; if ( t1&&t2 ) return 0;
1213: t1 = u1&0xf0000; t2 = u2&0xf0000; if ( t1&&t2 ) return 0;
1214: t1 = u1&0xf000; t2 = u2&0xf000; if ( t1&&t2 ) return 0;
1215: t1 = u1&0xf00; t2 = u2&0xf00; if ( t1&&t2 ) return 0;
1216: t1 = u1&0xf0; t2 = u2&0xf0; if ( t1&&t2 ) return 0;
1217: t1 = u1&0xf; t2 = u2&0xf; if ( t1&&t2 ) return 0;
1218: }
1219: return 1;
1220: break;
1221: case 8:
1222: for ( i = 0; i < nd_wpd; i++ ) {
1223: u1 = d1[i]; u2 = d2[i];
1224: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1225: t1 = u1&0xff0000; t2 = u2&0xff0000; if ( t1&&t2 ) return 0;
1226: t1 = u1&0xff00; t2 = u2&0xff00; if ( t1&&t2 ) return 0;
1227: t1 = u1&0xff; t2 = u2&0xff; if ( t1&&t2 ) return 0;
1228: }
1229: return 1;
1230: break;
1231: case 16:
1232: for ( i = 0; i < nd_wpd; i++ ) {
1233: u1 = d1[i]; u2 = d2[i];
1234: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1235: t1 = u1&0xffff; t2 = u2&0xffff; if ( t1&&t2 ) return 0;
1236: }
1237: return 1;
1238: break;
1239: case 32:
1240: for ( i = 0; i < nd_wpd; i++ )
1241: if ( d1[i] && d2[i] ) return 0;
1242: return 1;
1243: break;
1244: default:
1.12 ! noro 1245: for ( i = 0; i < nd_wpd; i++ ) {
! 1246: u1 = d1[i]; u2 = d2[i];
! 1247: for ( j = 0; j < nd_epw; j++ ) {
! 1248: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
! 1249: u1 >>= nd_bpe; u2 >>= nd_bpe;
! 1250: }
1.11 noro 1251: }
1.12 ! noro 1252: return 1;
! 1253: break;
1.11 noro 1254: }
1255: }
1256:
1257: ND nd_reduce(ND p1,ND p2)
1258: {
1259: int c,t,td,td2,mul;
1260: NM m2,prev,head,cur,new;
1261: unsigned int *d;
1262:
1263: if ( !p1 )
1264: return 0;
1265: else {
1266: mul = ((nd_mod-HC(p1))*invm(HC(p2),nd_mod))%nd_mod;
1267: td = HTD(p1)-HTD(p2);
1268: d = (unsigned int *)ALLOCA(nd_wpd*sizeof(unsigned int));
1269: ndl_sub(HDL(p1),HDL(p2),d);
1270: prev = 0; head = cur = BDY(p1);
1271: NEWNM(new);
1272: for ( m2 = BDY(p2); m2; ) {
1273: td2 = new->td = m2->td+td;
1274: ndl_add(m2->dl,d,new->dl);
1275: if ( !cur ) {
1276: C(new) = (C(m2)*mul)%nd_mod;
1277: if ( !prev ) {
1278: prev = new;
1279: NEXT(prev) = 0;
1280: head = prev;
1281: } else {
1282: NEXT(prev) = new;
1283: NEXT(new) = 0;
1284: prev = new;
1285: }
1286: m2 = NEXT(m2);
1287: NEWNM(new);
1288: continue;
1289: }
1290: if ( cur->td > td2 )
1291: c = 1;
1292: else if ( cur->td < td2 )
1293: c = -1;
1294: else
1295: c = ndl_compare(cur->dl,new->dl);
1296: switch ( c ) {
1297: case 0:
1298: t = (C(cur)+C(m2)*mul)%nd_mod;
1299: if ( t )
1300: C(cur) = t;
1301: else if ( !prev ) {
1302: head = NEXT(cur);
1303: FREENM(cur);
1304: cur = head;
1305: } else {
1306: NEXT(prev) = NEXT(cur);
1307: FREENM(cur);
1308: cur = NEXT(prev);
1309: }
1310: m2 = NEXT(m2);
1311: break;
1312: case 1:
1313: prev = cur;
1314: cur = NEXT(cur);
1315: break;
1316: case -1:
1317: if ( !prev ) {
1318: /* cur = head */
1319: prev = new;
1320: C(prev) = (C(m2)*mul)%nd_mod;
1321: NEXT(prev) = head;
1322: head = prev;
1323: } else {
1324: C(new) = (C(m2)*mul)%nd_mod;
1325: NEXT(prev) = new;
1326: NEXT(new) = cur;
1327: prev = new;
1328: }
1329: NEWNM(new);
1330: m2 = NEXT(m2);
1331: break;
1332: }
1333: }
1334: FREENM(new);
1335: if ( head ) {
1336: BDY(p1) = head;
1337: p1->sugar = MAX(p1->sugar,p2->sugar+td);
1338: return p1;
1339: } else {
1340: FREEND(p1);
1341: return 0;
1342: }
1343:
1344: }
1345: }
1346:
1347: ND nd_sp(ND_pairs p)
1348: {
1349: NM m;
1350: ND p1,p2,t1,t2;
1351: unsigned int *lcm;
1352: int td;
1353:
1354: p1 = nps[p->i1];
1355: p2 = nps[p->i2];
1356: lcm = p->lcm;
1357: td = p->td;
1358: NEWNM(m);
1359: C(m) = HC(p2); m->td = td-HTD(p1); ndl_sub(lcm,HDL(p1),m->dl); NEXT(m) = 0;
1360: t1 = nd_mul_nm(p1,m);
1361: C(m) = nd_mod-HC(p1); m->td = td-HTD(p2); ndl_sub(lcm,HDL(p2),m->dl);
1362: t2 = nd_mul_nm(p2,m);
1363: FREENM(m);
1364: return nd_add(t1,t2);
1365: }
1366:
1367: ND nd_reducer(ND p1,ND p2)
1368: {
1369: NM m;
1370: ND r;
1371:
1.12 ! noro 1372:
1.11 noro 1373: NEWNM(m);
1374: C(m) = ((nd_mod-HC(p1))*invm(HC(p2),nd_mod))%nd_mod;
1375: m->td = HTD(p1)-HTD(p2);
1376: ndl_sub(HDL(p1),HDL(p2),m->dl);
1377: NEXT(m) = 0;
1378: r = nd_mul_nm(p2,m);
1379: FREENM(m);
1380: return r;
1381: }
1382:
1.12 ! noro 1383: ND nd_find_reducer(ND g)
! 1384: {
! 1385: NM m;
! 1386: ND r,p;
! 1387: int i;
! 1388:
! 1389: for ( i = 0; i < nd_psn; i++ ) {
! 1390: p = nps[i];
! 1391: if ( HTD(g) >= HTD(p) && ndl_reducible(HDL(g),HDL(p)) ) {
1.11 noro 1392: #if 1
1.12 ! noro 1393: NEWNM(m);
! 1394: C(m) = ((nd_mod-HC(g))*invm(HC(p),nd_mod))%nd_mod;
! 1395: m->td = HTD(g)-HTD(p);
! 1396: ndl_sub(HDL(g),HDL(p),m->dl);
! 1397: NEXT(m) = 0;
! 1398: r = nd_mul_nm(p,m);
! 1399: FREENM(m);
! 1400: r->sugar = m->td + p->sugar;
! 1401: return r;
! 1402: #else
! 1403: return p;
! 1404: #endif
! 1405: }
! 1406: }
! 1407: return 0;
! 1408: }
! 1409:
! 1410: ND nd_add(ND p1,ND p2)
1.11 noro 1411: {
1.12 ! noro 1412: int n,c;
! 1413: int t;
! 1414: ND r;
! 1415: NM m1,m2,mr0,mr,s;
! 1416:
! 1417: if ( !p1 )
! 1418: return p2;
! 1419: else if ( !p2 )
! 1420: return p1;
! 1421: else {
! 1422: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
! 1423: if ( m1->td > m2->td )
! 1424: c = 1;
! 1425: else if ( m1->td < m2->td )
! 1426: c = -1;
! 1427: else
! 1428: c = ndl_compare(m1->dl,m2->dl);
! 1429: switch ( c ) {
! 1430: case 0:
! 1431: t = ((C(m1))+(C(m2))) - nd_mod;
! 1432: if ( t < 0 )
! 1433: t += nd_mod;
! 1434: s = m1; m1 = NEXT(m1);
! 1435: if ( t ) {
! 1436: NEXTNM2(mr0,mr,s); C(mr) = (t);
! 1437: } else {
! 1438: FREENM(s);
! 1439: }
! 1440: s = m2; m2 = NEXT(m2); FREENM(s);
! 1441: break;
! 1442: case 1:
! 1443: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
! 1444: break;
! 1445: case -1:
! 1446: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
! 1447: break;
! 1448: }
! 1449: }
! 1450: if ( !mr0 )
! 1451: if ( m1 )
! 1452: mr0 = m1;
! 1453: else if ( m2 )
! 1454: mr0 = m2;
! 1455: else
! 1456: return 0;
! 1457: else if ( m1 )
! 1458: NEXT(mr) = m1;
! 1459: else if ( m2 )
! 1460: NEXT(mr) = m2;
! 1461: else
! 1462: NEXT(mr) = 0;
! 1463: BDY(p1) = mr0;
! 1464: p1->sugar = MAX(p1->sugar,p2->sugar);
! 1465: FREEND(p2);
! 1466: return p1;
! 1467: }
! 1468: }
! 1469:
! 1470: ND nd_mul_nm(ND p,NM m0)
! 1471: {
! 1472: NM m,mr,mr0;
! 1473: unsigned int *d,*dt,*dm;
! 1474: int c,n,td;
! 1475: int *pt,*p1,*p2;
! 1476: ND r;
1.11 noro 1477:
1.12 ! noro 1478: if ( !p )
1.11 noro 1479: return 0;
1.12 ! noro 1480: else {
! 1481: n = NV(p); m = BDY(p);
! 1482: d = m0->dl; td = m0->td; c = C(m0);
! 1483: mr0 = 0;
! 1484: for ( ; m; m = NEXT(m) ) {
! 1485: NEXTNM(mr0,mr);
! 1486: C(mr) = (C(m)*c)%nd_mod;
! 1487: mr->td = m->td+td;
! 1488: ndl_add(m->dl,d,mr->dl);
! 1489: }
! 1490: NEXT(mr) = 0;
! 1491: MKND(NV(p),mr0,r);
! 1492: r->sugar = p->sugar + td;
! 1493: return r;
1.11 noro 1494: }
1.12 ! noro 1495: }
! 1496:
! 1497: #if 1
! 1498: ND nd_nf(ND g,int full)
! 1499: {
! 1500: ND p,d,red;
! 1501: NM m,mrd,tail;
! 1502: int n,sugar,psugar;
! 1503:
! 1504: if ( !g )
! 1505: return 0;
1.11 noro 1506: sugar = g->sugar;
1.12 ! noro 1507: n = NV(g);
1.11 noro 1508: for ( d = 0; g; ) {
1.12 ! noro 1509: red = nd_find_reducer(g);
! 1510: if ( red ) {
! 1511: #if 1
! 1512: g = nd_add(g,red);
! 1513: sugar = MAX(sugar,red->sugar);
1.11 noro 1514: #else
1.12 ! noro 1515: psugar = (HTD(g)-HTD(red))+red->sugar;
! 1516: g = nd_reduce(g,red);
! 1517: sugar = MAX(sugar,psugar);
1.11 noro 1518: #endif
1.12 ! noro 1519: } else if ( !full )
! 1520: return g;
! 1521: else {
! 1522: m = BDY(g);
! 1523: if ( NEXT(m) ) {
! 1524: BDY(g) = NEXT(m); NEXT(m) = 0;
! 1525: } else {
! 1526: FREEND(g); g = 0;
1.11 noro 1527: }
1.12 ! noro 1528: if ( d ) {
! 1529: NEXT(tail)=m;
! 1530: tail=m;
1.11 noro 1531: } else {
1.12 ! noro 1532: MKND(n,m,d);
! 1533: tail = BDY(d);
1.11 noro 1534: }
1535: }
1536: }
1537: if ( d )
1538: d->sugar = sugar;
1539: return d;
1540: }
1541: #else
1542:
1543: ND nd_remove_head(ND p)
1544: {
1545: NM m;
1546:
1547: m = BDY(p);
1548: if ( !NEXT(m) ) {
1549: FREEND(p);
1550: p = 0;
1551: } else
1552: BDY(p) = NEXT(m);
1553: FREENM(m);
1554: return p;
1555: }
1556:
1557: PGeoBucket create_pbucket()
1558: {
1559: PGeoBucket g;
1560:
1561: g = CALLOC(1,sizeof(struct oPGeoBucket));
1562: g->m = -1;
1563: return g;
1564: }
1565:
1566: void add_pbucket(PGeoBucket g,ND d)
1567: {
1568: int l,k,m;
1569:
1570: l = nd_length(d);
1571: for ( k = 0, m = 1; l > m; k++, m <<= 2 );
1572: /* 4^(k-1) < l <= 4^k */
1573: d = nd_add(g->body[k],d);
1574: for ( ; d && nd_length(d) > 1<<(2*k); k++ ) {
1575: g->body[k] = 0;
1576: d = nd_add(g->body[k+1],d);
1577: }
1578: g->body[k] = d;
1579: g->m = MAX(g->m,k);
1580: }
1581:
1582: int head_pbucket(PGeoBucket g)
1583: {
1584: int j,i,c,k,nv,sum;
1585: unsigned int *di,*dj;
1586: ND gi,gj;
1587:
1588: k = g->m;
1589: while ( 1 ) {
1590: j = -1;
1591: for ( i = 0; i <= k; i++ ) {
1592: if ( !(gi = g->body[i]) )
1593: continue;
1594: if ( j < 0 ) {
1595: j = i;
1596: gj = g->body[j];
1597: dj = HDL(gj);
1598: sum = HC(gj);
1599: } else {
1600: di = HDL(gi);
1601: nv = NV(gi);
1602: if ( HTD(gi) > HTD(gj) )
1603: c = 1;
1604: else if ( HTD(gi) < HTD(gj) )
1605: c = -1;
1606: else
1607: c = ndl_compare(di,dj);
1608: if ( c > 0 ) {
1609: if ( sum )
1610: HC(gj) = sum;
1611: else
1612: g->body[j] = nd_remove_head(gj);
1613: j = i;
1614: gj = g->body[j];
1615: dj = HDL(gj);
1616: sum = HC(gj);
1617: } else if ( c == 0 ) {
1618: sum = sum+HC(gi)-nd_mod;
1619: if ( sum < 0 )
1620: sum += nd_mod;
1621: g->body[i] = nd_remove_head(gi);
1622: }
1623: }
1624: }
1625: if ( j < 0 )
1626: return -1;
1627: else if ( sum ) {
1628: HC(gj) = sum;
1629: return j;
1630: } else
1631: g->body[j] = nd_remove_head(gj);
1632: }
1633: }
1634:
1635: ND normalize_pbucket(PGeoBucket g)
1636: {
1637: int i;
1638: ND r,t;
1639:
1640: r = 0;
1641: for ( i = 0; i <= g->m; i++ )
1642: r = nd_add(r,g->body[i]);
1643: return r;
1644: }
1645:
1.12 ! noro 1646: ND nd_nf(ND g,int full)
1.11 noro 1647: {
1648: ND u,p,d,red;
1649: NODE l;
1650: NM m,mrd;
1651: int sugar,psugar,n,h_reducible,h;
1652: PGeoBucket bucket;
1653:
1654: if ( !g ) {
1655: return 0;
1656: }
1657: sugar = g->sugar;
1658: n = g->nv;
1659: bucket = create_pbucket();
1660: add_pbucket(bucket,g);
1661: d = 0;
1662: while ( 1 ) {
1663: h = head_pbucket(bucket);
1664: if ( h < 0 ) {
1665: if ( d )
1666: d->sugar = sugar;
1667: return d;
1668: }
1669: g = bucket->body[h];
1.12 ! noro 1670: red = nd_find_reducer(g);
! 1671: if ( red ) {
! 1672: bucket->body[h] = nd_remove_head(g);
! 1673: red = nd_remove_head(red);
! 1674: add_pbucket(bucket,red);
! 1675: sugar = MAX(sugar,red->sugar);
! 1676: } else if ( !full ) {
! 1677: g = normalize_pbucket(bucket);
! 1678: if ( g )
! 1679: g->sugar = sugar;
! 1680: return g;
! 1681: } else {
! 1682: m = BDY(g);
! 1683: if ( NEXT(m) ) {
! 1684: BDY(g) = NEXT(m); NEXT(m) = 0;
! 1685: } else {
! 1686: FREEND(g); g = 0;
1.11 noro 1687: }
1.12 ! noro 1688: bucket->body[h] = g;
! 1689: NEXT(m) = 0;
! 1690: if ( d ) {
! 1691: for ( mrd = BDY(d); NEXT(mrd); mrd = NEXT(mrd) );
! 1692: NEXT(mrd) = m;
1.11 noro 1693: } else {
1.12 ! noro 1694: MKND(n,m,d);
1.11 noro 1695: }
1696: }
1697: }
1698: }
1699: #endif
1700:
1701: NODE nd_gb(NODE f)
1702: {
1703: int i,nh;
1704: NODE r,g,gall;
1705: ND_pairs d;
1706: ND_pairs l;
1707: ND h,nf;
1708:
1709: for ( gall = g = 0, d = 0, r = f; r; r = NEXT(r) ) {
1710: i = (int)BDY(r);
1711: d = update_pairs(d,g,i);
1712: g = update_base(g,i);
1713: gall = append_one(gall,i);
1714: }
1715: while ( d ) {
1716: #if 0
1717: ndp_print(d);
1718: #endif
1719: l = nd_minp(d,&d);
1720: h = nd_sp(l);
1.12 ! noro 1721: nf = nd_nf(h,!Top);
1.11 noro 1722: if ( nf ) {
1723: printf("+"); fflush(stdout);
1724: #if 0
1725: ndl_print(HDL(nf)); fflush(stdout);
1726: #endif
1727: nh = nd_newps(nf);
1728: d = update_pairs(d,g,nh);
1729: g = update_base(g,nh);
1730: gall = append_one(gall,nh);
1731: } else {
1732: printf("."); fflush(stdout);
1733: }
1734: }
1735: return g;
1736: }
1737:
1738: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t)
1739: {
1740: ND_pairs d1,nd,cur,head,prev;
1741:
1742: if ( !g ) return d;
1743: d = crit_B(d,t);
1744: d1 = nd_newpairs(g,t);
1745: d1 = crit_M(d1);
1746: d1 = crit_F(d1);
1747: prev = 0; cur = head = d1;
1748: while ( cur ) {
1749: if ( crit_2( cur->i1,cur->i2 ) ) {
1750: if ( !prev ) {
1751: head = cur = NEXT(cur);
1752: } else {
1753: cur = NEXT(prev) = NEXT(cur);
1754: }
1755: } else {
1756: prev = cur;
1757: cur = NEXT(cur);
1758: }
1759: }
1760: if ( !d )
1761: return head;
1762: else {
1763: nd = d;
1764: while ( NEXT(nd) )
1765: nd = NEXT(nd);
1766: NEXT(nd) = head;
1767: return d;
1768: }
1769: }
1770:
1771: ND_pairs nd_newpairs( NODE g, int t )
1772: {
1773: NODE h;
1774: unsigned int *dl;
1775: int td,ts,s;
1776: ND_pairs r,r0;
1777:
1778: dl = HDL(nps[t]);
1779: td = HTD(nps[t]);
1780: ts = nps[t]->sugar - td;
1781: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
1782: NEXTND_pairs(r0,r);
1783: r->i1 = (int)BDY(h);
1784: r->i2 = t;
1785: ndl_lcm(HDL(nps[r->i1]),dl,r->lcm);
1786: r->td = ndl_td(r->lcm);
1787: s = nps[r->i1]->sugar-HTD(nps[r->i1]);
1788: r->sugar = MAX(s,ts) + r->td;
1789: }
1790: NEXT(r) = 0;
1791: return r0;
1792: }
1793:
1794: ND_pairs crit_B( ND_pairs d, int s )
1795: {
1796: ND_pairs cur,head,prev;
1797: unsigned int *t,*tl,*lcm;
1798: int td,tdl;
1799:
1800: if ( !d ) return 0;
1801: t = HDL(nps[s]);
1802: prev = 0;
1803: head = cur = d;
1804: lcm = (unsigned int *)ALLOCA(nd_wpd*sizeof(unsigned int));
1805: while ( cur ) {
1806: tl = cur->lcm;
1807: if ( ndl_reducible(tl,t)
1808: && (ndl_lcm(HDL(nps[cur->i1]),t,lcm),!ndl_equal(lcm,tl))
1809: && (ndl_lcm(HDL(nps[cur->i2]),t,lcm),!ndl_equal(lcm,tl)) ) {
1810: if ( !prev ) {
1811: head = cur = NEXT(cur);
1812: } else {
1813: cur = NEXT(prev) = NEXT(cur);
1814: }
1815: } else {
1816: prev = cur;
1817: cur = NEXT(cur);
1818: }
1819: }
1820: return head;
1821: }
1822:
1823: ND_pairs crit_M( ND_pairs d1 )
1824: {
1825: ND_pairs e,d2,d3,dd,p;
1826: unsigned int *id,*jd;
1827: int itd,jtd;
1828:
1829: for ( dd = 0, e = d1; e; e = d3 ) {
1830: if ( !(d2 = NEXT(e)) ) {
1831: NEXT(e) = dd;
1832: return e;
1833: }
1834: id = e->lcm;
1835: itd = e->td;
1836: for ( d3 = 0; d2; d2 = p ) {
1837: p = NEXT(d2),
1838: jd = d2->lcm;
1839: jtd = d2->td;
1840: if ( jtd == itd )
1841: if ( id == jd );
1842: else if ( ndl_reducible(jd,id) ) continue;
1843: else if ( ndl_reducible(id,jd) ) goto delit;
1844: else ;
1845: else if ( jtd > itd )
1846: if ( ndl_reducible(jd,id) ) continue;
1847: else ;
1848: else if ( ndl_reducible(id,jd ) ) goto delit;
1849: NEXT(d2) = d3;
1850: d3 = d2;
1851: }
1852: NEXT(e) = dd;
1853: dd = e;
1854: continue;
1855: /**/
1856: delit: NEXT(d2) = d3;
1857: d3 = d2;
1858: for ( ; p; p = d2 ) {
1859: d2 = NEXT(p);
1860: NEXT(p) = d3;
1861: d3 = p;
1862: }
1863: }
1864: return dd;
1865: }
1866:
1867: ND_pairs crit_F( ND_pairs d1 )
1868: {
1869: ND_pairs rest, head;
1870: ND_pairs last, p, r, w;
1871: int s;
1872:
1873: for ( head = last = 0, p = d1; NEXT(p); ) {
1874: r = w = equivalent_pairs(p,&rest);
1875: s = r->sugar;
1876: while ( w = NEXT(w) )
1877: if ( crit_2(w->i1,w->i2) ) {
1878: r = w;
1879: break;
1880: } else if ( w->sugar < s ) {
1881: r = w;
1882: s = r->sugar;
1883: }
1884: if ( last ) NEXT(last) = r;
1885: else head = r;
1886: NEXT(last = r) = 0;
1887: p = rest;
1888: if ( !p ) return head;
1889: }
1890: if ( !last ) return p;
1891: NEXT(last) = p;
1892: return head;
1893: }
1894:
1895: int crit_2( int dp1, int dp2 )
1896: {
1897: return ndl_disjoint(HDL(nps[dp1]),HDL(nps[dp2]));
1898: }
1899:
1900: static ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
1901: {
1902: ND_pairs w,p,r,s;
1903: unsigned int *d;
1904: int td;
1905:
1906: w = d1;
1907: d = w->lcm;
1908: td = w->td;
1909: s = NEXT(w);
1910: NEXT(w) = 0;
1911: for ( r = 0; s; s = p ) {
1912: p = NEXT(s);
1913: if ( td == s->td && ndl_equal(d,s->lcm) ) {
1914: NEXT(s) = w;
1915: w = s;
1916: } else {
1917: NEXT(s) = r;
1918: r = s;
1919: }
1920: }
1921: *prest = r;
1922: return w;
1923: }
1924:
1925: NODE update_base(NODE nd,int ndp)
1926: {
1927: unsigned int *dl, *dln;
1928: NODE last, p, head;
1929: int td,tdn;
1930:
1931: dl = HDL(nps[ndp]);
1932: td = HTD(nps[ndp]);
1933: for ( head = last = 0, p = nd; p; ) {
1934: dln = HDL(nps[(int)BDY(p)]);
1935: tdn = HTD(nps[(int)BDY(p)]);
1936: if ( tdn >= td && ndl_reducible( dln, dl ) ) {
1937: p = NEXT(p);
1938: if ( last ) NEXT(last) = p;
1939: } else {
1940: if ( !last ) head = p;
1941: p = NEXT(last = p);
1942: }
1943: }
1944: head = append_one(head,ndp);
1945: return head;
1946: }
1947:
1948: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
1949: {
1950: ND_pairs m,ml,p,l;
1951: unsigned int *lcm;
1952: int s,td,len,tlen,c;
1953:
1954: if ( !(p = NEXT(m = d)) ) {
1955: *prest = p;
1956: NEXT(m) = 0;
1957: return m;
1958: }
1959: lcm = m->lcm;
1960: s = m->sugar;
1961: td = m->td;
1962: len = nd_length(nps[m->i1])+nd_length(nps[m->i2]);
1963: for ( ml = 0, l = m; p; p = NEXT(l = p) ) {
1964: if (p->sugar < s)
1965: goto find;
1966: else if ( p->sugar == s ) {
1967: if ( p->td < td )
1968: goto find;
1969: else if ( p->td == td ) {
1970: c = ndl_compare(p->lcm,lcm);
1971: if ( c < 0 )
1972: goto find;
1973: else if ( c == 0 ) {
1974: tlen = nd_length(nps[p->i1])+nd_length(nps[p->i2]);
1975: if ( tlen < len )
1976: goto find;
1977: }
1978: }
1979: }
1980: continue;
1981: find:
1982: ml = l;
1983: m = p;
1984: lcm = m->lcm;
1985: s = m->sugar;
1986: td = m->td;
1987: len = tlen;
1988: }
1989: if ( !ml ) *prest = NEXT(m);
1990: else {
1991: NEXT(ml) = NEXT(m);
1992: *prest = d;
1993: }
1994: NEXT(m) = 0;
1995: return m;
1996: }
1997:
1998: int nd_newps(ND a)
1999: {
2000: if ( nd_psn == nd_pslen ) {
2001: nd_pslen *= 2;
2002: nps = (ND *)REALLOC((char *)nps,nd_pslen*sizeof(ND));
2003: }
2004: nd_monic(a);
2005: nps[nd_psn] = a;
2006: return nd_psn++;
2007: }
2008:
2009: NODE NODE_sortb(NODE f,int);
2010: ND dptond(DP);
2011: DP ndtodp(ND);
2012:
2013: NODE nd_setup(NODE f)
2014: {
2015: int i;
2016: NODE s,s0,f0;
2017:
2018: #if 0
2019: f0 = f = NODE_sortb(f,1);
2020: #endif
2021: nd_psn = length(f); nd_pslen = 2*nd_psn;
2022: nps = (ND *)MALLOC(nd_pslen*sizeof(ND));
2023: nd_bpe = 4;
2024: nd_epw = (sizeof(unsigned int)*8)/nd_bpe;
2025: nd_wpd = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
1.12 ! noro 2026: nd_mask0 = (1<<nd_bpe)-1;
! 2027: bzero(nd_mask,sizeof(nd_mask));
! 2028: for ( i = 0; i < nd_epw; i++ )
! 2029: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
1.11 noro 2030: nd_free_private_storage();
2031: for ( i = 0; i < nd_psn; i++, f = NEXT(f) ) {
2032: nps[i] = dptond((DP)BDY(f));
2033: nd_monic(nps[i]);
2034: }
2035: for ( s0 = 0, i = 0; i < nd_psn; i++ ) {
2036: NEXTNODE(s0,s); BDY(s) = (pointer)i;
2037: }
2038: if ( s0 ) NEXT(s) = 0;
2039: return s0;
2040: }
2041:
2042: void nd_gr(LIST f,LIST v,int m,struct order_spec *ord,LIST *rp)
2043: {
2044: struct order_spec ord1;
2045: VL fv,vv,vc;
2046: NODE fd,fd0,r,r0,t,x,s,xx;
2047: DP a,b,c;
2048:
2049: get_vars((Obj)f,&fv); pltovl(v,&vv);
2050: nd_nvar = length(vv);
2051: if ( ord->id )
2052: error("nd_gr : unsupported order");
2053: switch ( ord->ord.simple ) {
2054: case 0:
2055: is_rlex = 1;
2056: break;
2057: case 1:
2058: is_rlex = 0;
2059: break;
2060: default:
2061: error("nd_gr : unsupported order");
2062: }
2063: initd(ord);
2064: nd_mod = m;
2065: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
2066: ptod(CO,vv,(P)BDY(t),&b);
2067: _dp_mod(b,m,0,&c);
2068: if ( c ) {
2069: NEXTNODE(fd0,fd); BDY(fd) = (pointer)c;
2070: }
2071: }
2072: if ( fd0 ) NEXT(fd) = 0;
2073: s = nd_setup(fd0);
2074: x = nd_gb(s);
2075: #if 0
2076: x = nd_reduceall(x,m);
2077: #endif
2078: for ( r0 = 0; x; x = NEXT(x) ) {
2079: NEXTNODE(r0,r);
2080: a = ndtodp(nps[(int)BDY(x)]);
2081: _dtop_mod(CO,vv,a,(P *)&BDY(r));
2082: }
2083: if ( r0 ) NEXT(r) = 0;
2084: MKLIST(*rp,r0);
2085: }
2086:
2087: void dltondl(int n,DL dl,unsigned int *r)
2088: {
2089: unsigned int *d;
2090: int i;
2091:
2092: d = dl->d;
1.12 ! noro 2093: bzero(r,nd_wpd*sizeof(unsigned int));
1.11 noro 2094: if ( is_rlex )
2095: for ( i = 0; i < n; i++ )
2096: r[(n-1-i)/nd_epw] |= (d[i]<<((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe));
2097: else
2098: for ( i = 0; i < n; i++ )
2099: r[i/nd_epw] |= d[i]<<((nd_epw-(i%nd_epw)-1)*nd_bpe);
2100: }
2101:
2102: DL ndltodl(int n,int td,unsigned int *ndl)
2103: {
2104: DL dl;
2105: int *d;
2106: int i;
2107:
2108: NEWDL(dl,n);
2109: dl->td = td;
2110: d = dl->d;
2111: if ( is_rlex )
2112: for ( i = 0; i < n; i++ )
2113: d[i] = (ndl[(n-1-i)/nd_epw]>>((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe))
2114: &((1<<nd_bpe)-1);
2115: else
2116: for ( i = 0; i < n; i++ )
2117: d[i] = (ndl[i/nd_epw]>>((nd_epw-(i%nd_epw)-1)*nd_bpe))
2118: &((1<<nd_bpe)-1);
2119: return dl;
2120: }
2121:
2122: ND dptond(DP p)
2123: {
2124: ND d;
2125: NM m0,m;
2126: MP t;
2127: int n;
2128:
2129: if ( !p )
2130: return 0;
2131: n = NV(p);
2132: m0 = 0;
2133: for ( t = BDY(p); t; t = NEXT(t) ) {
2134: NEXTNM(m0,m);
2135: m->c = ITOS(t->c);
2136: m->td = t->dl->td;
2137: dltondl(n,t->dl,m->dl);
2138: }
2139: NEXT(m) = 0;
2140: MKND(n,m0,d);
2141: d->nv = n;
2142: d->sugar = p->sugar;
2143: return d;
2144: }
2145:
2146: DP ndtodp(ND p)
2147: {
2148: DP d;
2149: MP m0,m;
2150: NM t;
2151: int n;
2152:
2153: if ( !p )
2154: return 0;
2155: n = NV(p);
2156: m0 = 0;
2157: for ( t = BDY(p); t; t = NEXT(t) ) {
2158: NEXTMP(m0,m);
2159: m->c = STOI(t->c);
2160: m->dl = ndltodl(n,t->td,t->dl);
2161: }
2162: NEXT(m) = 0;
2163: MKDP(n,m0,d);
2164: d->sugar = p->sugar;
2165: return d;
2166: }
2167:
2168: void ndl_print(unsigned int *dl)
2169: {
2170: int n;
2171: int i;
2172:
2173: n = nd_nvar;
2174: printf("<<");
2175: if ( is_rlex )
2176: for ( i = 0; i < n; i++ )
2177: printf(i==n-1?"%d":"%d,",
2178: (dl[(n-1-i)/nd_epw]>>((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe))
2179: &((1<<nd_bpe)-1));
2180: else
2181: for ( i = 0; i < n; i++ )
2182: printf(i==n-1?"%d":"%d,",
2183: (dl[i/nd_epw]>>((nd_epw-(i%nd_epw)-1)*nd_bpe))
2184: &((1<<nd_bpe)-1));
2185: printf(">>");
2186: }
2187:
2188: void nd_print(ND p)
2189: {
2190: NM m;
2191:
2192: if ( !p )
2193: printf("0\n");
2194: else {
2195: for ( m = BDY(p); m; m = NEXT(m) ) {
2196: printf("+%d*",m->c);
2197: ndl_print(m->dl);
2198: }
2199: printf("\n");
2200: }
2201: }
2202:
2203: void ndp_print(ND_pairs d)
2204: {
2205: ND_pairs t;
2206:
2207: for ( t = d; t; t = NEXT(t) ) {
2208: printf("%d,%d ",t->i1,t->i2);
2209: }
2210: printf("\n");
2211: }
2212:
2213: void nd_monic(ND p)
2214: {
2215: int mul;
2216: NM m;
2217:
2218: if ( !p )
2219: return;
2220: mul = invm(HC(p),nd_mod);
2221: for ( m = BDY(p); m; m = NEXT(m) )
2222: C(m) = (C(m)*mul)%nd_mod;
1.1 noro 2223: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>