Annotation of OpenXM_contrib2/asir2000/engine/distm.c, Revision 1.14
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.14 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/engine/distm.c,v 1.13 2003/07/21 01:57:51 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:
1.14 ! noro 899: #define REDTAB_LEN 32003
! 900:
1.11 noro 901: typedef struct oPGeoBucket {
902: int m;
903: struct oND *body[32];
904: } *PGeoBucket;
905:
906: typedef struct oND {
907: struct oNM *body;
908: int nv;
909: int sugar;
910: } *ND;
911:
912: typedef struct oNM {
913: struct oNM *next;
914: int td;
915: int c;
916: unsigned int dl[1];
917: } *NM;
918:
919: typedef struct oND_pairs {
920: struct oND_pairs *next;
921: int i1,i2;
922: int td,sugar;
923: unsigned int lcm[1];
924: } *ND_pairs;
925:
926: static ND *nps;
927: int nd_mod,nd_nvar;
928: int is_rlex;
929: int nd_epw,nd_bpe,nd_wpd;
1.12 noro 930: unsigned int nd_mask[32];
931: unsigned int nd_mask0;
1.11 noro 932: NM _nm_free_list;
933: ND _nd_free_list;
934: ND_pairs _ndp_free_list;
1.14 ! noro 935: NM *nd_red;
! 936: int nd_red_len;
1.11 noro 937:
938: extern int Top,Reverse;
939: int nd_psn,nd_pslen;
1.14 ! noro 940: int nd_found,nd_create,nd_notfirst;
1.11 noro 941:
942: void GC_gcollect();
943: NODE append_one(NODE,int);
944:
945: #define HTD(d) ((d)->body->td)
946: #define HDL(d) ((d)->body->dl)
947: #define HC(d) ((d)->body->c)
948:
949: #define NEWND_pairs(m) if(!_ndp_free_list)_NDP_alloc(); (m)=_ndp_free_list; _ndp_free_list = NEXT(_ndp_free_list)
950: #define NEWNM(m) if(!_nm_free_list)_NM_alloc(); (m)=_nm_free_list; _nm_free_list = NEXT(_nm_free_list)
951: #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)
952:
953: #define NEXTNM(r,c) \
954: if(!(r)){NEWNM(r);(c)=(r);}else{NEWNM(NEXT(c));(c)=NEXT(c);}
955: #define NEXTNM2(r,c,s) \
956: if(!(r)){(c)=(r)=(s);}else{NEXT(c)=(s);(c)=(s);}
957: #define FREENM(m) NEXT(m)=_nm_free_list; _nm_free_list=(m)
958: #define FREEND(m) BDY(m)=(NM)_nd_free_list; _nd_free_list=(m)
959:
960: #define NEXTND_pairs(r,c) \
961: if(!(r)){NEWND_pairs(r);(c)=(r);}else{NEWND_pairs(NEXT(c));(c)=NEXT(c);}
962:
963: ND_pairs crit_B( ND_pairs d, int s );
964: void nd_gr(LIST f,LIST v,int m,struct order_spec *ord,LIST *rp);
965: NODE nd_setup(NODE f);
966: int nd_newps(ND a);
967: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest );
968: NODE update_base(NODE nd,int ndp);
969: static ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest );
970: int crit_2( int dp1, int dp2 );
971: ND_pairs crit_F( ND_pairs d1 );
972: ND_pairs crit_M( ND_pairs d1 );
973: ND_pairs nd_newpairs( NODE g, int t );
974: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t);
975: NODE nd_gb(NODE f);
976: void nd_free_private_storage();
977: void _NM_alloc();
978: void _ND_alloc();
979: int ndl_td(unsigned int *d);
980: ND nd_add(ND p1,ND p2);
981: ND nd_mul_nm(ND p,NM m0);
1.13 noro 982: ND nd_mul_term(ND p,int td,unsigned int *d);
1.11 noro 983: ND nd_sp(ND_pairs p);
1.12 noro 984: ND nd_find_reducer(ND g);
985: ND nd_nf(ND g,int full);
1.14 ! noro 986: ND nd_reduce(ND p1,ND p2);
! 987: ND nd_reduce_special(ND p1,ND p2);
! 988: void nd_free(ND p);
1.11 noro 989: void ndl_print(unsigned int *dl);
990: void nd_print(ND p);
991: void ndp_print(ND_pairs d);
992: int nd_length(ND p);
993: void nd_monic(ND p);
1.13 noro 994: void nd_mul_c(ND p,int mul);
1.14 ! noro 995: void nd_free_redlist();
! 996: void nd_append_red(unsigned int *d,int td,int i);
1.11 noro 997:
998: void nd_free_private_storage()
999: {
1000: _nd_free_list = 0;
1001: _nm_free_list = 0;
1.14 ! noro 1002: nd_red = 0;
1.11 noro 1003: GC_gcollect();
1004: }
1005:
1006: void _NM_alloc()
1007: {
1008: NM p;
1009: int i;
1010:
1.14 ! noro 1011: for ( i = 0; i < 16; i++ ) {
1.11 noro 1012: p = (NM)GC_malloc(sizeof(struct oNM)+(nd_wpd-1)*sizeof(unsigned int));
1013: p->next = _nm_free_list; _nm_free_list = p;
1014: }
1015: }
1016:
1017: void _ND_alloc()
1018: {
1019: ND p;
1020: int i;
1021:
1.13 noro 1022: for ( i = 0; i < 1024; i++ ) {
1.11 noro 1023: p = (ND)GC_malloc(sizeof(struct oND));
1024: p->body = (NM)_nd_free_list; _nd_free_list = p;
1025: }
1026: }
1027:
1028: void _NDP_alloc()
1029: {
1030: ND_pairs p;
1031: int i;
1032:
1.12 noro 1033: for ( i = 0; i < 10240; i++ ) {
1.11 noro 1034: p = (ND_pairs)GC_malloc(sizeof(struct oND_pairs)
1035: +(nd_wpd-1)*sizeof(unsigned int));
1036: p->next = _ndp_free_list; _ndp_free_list = p;
1037: }
1038: }
1039:
1040: INLINE nd_length(ND p)
1041: {
1042: NM m;
1043: int i;
1044:
1045: if ( !p )
1046: return 0;
1047: else {
1048: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
1049: return i;
1050: }
1051: }
1052:
1053: INLINE int ndl_reducible(unsigned int *d1,unsigned int *d2)
1054: {
1055: unsigned int u1,u2;
1.12 noro 1056: int i,j;
1.11 noro 1057:
1058: switch ( nd_bpe ) {
1059: case 4:
1060: for ( i = 0; i < nd_wpd; i++ ) {
1061: u1 = d1[i]; u2 = d2[i];
1062: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
1063: if ( (u1&0xf000000) < (u2&0xf000000) ) return 0;
1064: if ( (u1&0xf00000) < (u2&0xf00000) ) return 0;
1065: if ( (u1&0xf0000) < (u2&0xf0000) ) return 0;
1066: if ( (u1&0xf000) < (u2&0xf000) ) return 0;
1067: if ( (u1&0xf00) < (u2&0xf00) ) return 0;
1068: if ( (u1&0xf0) < (u2&0xf0) ) return 0;
1069: if ( (u1&0xf) < (u2&0xf) ) return 0;
1070: }
1071: return 1;
1072: break;
1.13 noro 1073: case 6:
1074: for ( i = 0; i < nd_wpd; i++ ) {
1075: u1 = d1[i]; u2 = d2[i];
1076: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
1077: if ( (u1&0xfc0000) < (u2&0xfc0000) ) return 0;
1078: if ( (u1&0x3f000) < (u2&0x3f000) ) return 0;
1079: if ( (u1&0xfc0) < (u2&0xfc0) ) return 0;
1080: if ( (u1&0x3f) < (u2&0x3f) ) return 0;
1081: }
1082: return 1;
1083: break;
1.11 noro 1084: case 8:
1085: for ( i = 0; i < nd_wpd; i++ ) {
1086: u1 = d1[i]; u2 = d2[i];
1087: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
1088: if ( (u1&0xff0000) < (u2&0xff0000) ) return 0;
1089: if ( (u1&0xff00) < (u2&0xff00) ) return 0;
1090: if ( (u1&0xff) < (u2&0xff) ) return 0;
1091: }
1092: return 1;
1093: break;
1094: case 16:
1095: for ( i = 0; i < nd_wpd; i++ ) {
1096: u1 = d1[i]; u2 = d2[i];
1097: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
1098: if ( (u1&0xffff) < (u2&0xffff) ) return 0;
1099: }
1100: return 1;
1101: break;
1102: case 32:
1103: for ( i = 0; i < nd_wpd; i++ )
1104: if ( d1[i] < d2[i] ) return 0;
1105: return 1;
1106: break;
1107: default:
1.12 noro 1108: for ( i = 0; i < nd_wpd; i++ ) {
1109: u1 = d1[i]; u2 = d2[i];
1110: for ( j = 0; j < nd_epw; j++ )
1111: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
1112: }
1113: return 1;
1.11 noro 1114: }
1115: }
1116:
1.12 noro 1117: void ndl_lcm(unsigned int *d1,unsigned *d2,unsigned int *d)
1.11 noro 1118: {
1119: unsigned int t1,t2,u,u1,u2;
1.12 noro 1120: int i,j;
1.11 noro 1121:
1122: switch ( nd_bpe ) {
1123: case 4:
1124: for ( i = 0; i < nd_wpd; i++ ) {
1125: u1 = d1[i]; u2 = d2[i];
1126: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
1127: t1 = (u1&0xf000000); t2 = (u2&0xf000000); u |= t1>t2?t1:t2;
1128: t1 = (u1&0xf00000); t2 = (u2&0xf00000); u |= t1>t2?t1:t2;
1129: t1 = (u1&0xf0000); t2 = (u2&0xf0000); u |= t1>t2?t1:t2;
1130: t1 = (u1&0xf000); t2 = (u2&0xf000); u |= t1>t2?t1:t2;
1131: t1 = (u1&0xf00); t2 = (u2&0xf00); u |= t1>t2?t1:t2;
1132: t1 = (u1&0xf0); t2 = (u2&0xf0); u |= t1>t2?t1:t2;
1133: t1 = (u1&0xf); t2 = (u2&0xf); u |= t1>t2?t1:t2;
1134: d[i] = u;
1135: }
1136: break;
1.13 noro 1137: case 6:
1138: for ( i = 0; i < nd_wpd; i++ ) {
1139: u1 = d1[i]; u2 = d2[i];
1140: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
1141: t1 = (u1&0xfc0000); t2 = (u2&0xfc0000); u |= t1>t2?t1:t2;
1142: t1 = (u1&0x3f000); t2 = (u2&0x3f000); u |= t1>t2?t1:t2;
1143: t1 = (u1&0xfc0); t2 = (u2&0xfc0); u |= t1>t2?t1:t2;
1144: t1 = (u1&0x3f); t2 = (u2&0x3f); u |= t1>t2?t1:t2;
1145: d[i] = u;
1146: }
1147: break;
1.11 noro 1148: case 8:
1149: for ( i = 0; i < nd_wpd; i++ ) {
1150: u1 = d1[i]; u2 = d2[i];
1151: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
1152: t1 = (u1&0xff0000); t2 = (u2&0xff0000); u |= t1>t2?t1:t2;
1153: t1 = (u1&0xff00); t2 = (u2&0xff00); u |= t1>t2?t1:t2;
1154: t1 = (u1&0xff); t2 = (u2&0xff); u |= t1>t2?t1:t2;
1155: d[i] = u;
1156: }
1157: break;
1158: case 16:
1159: for ( i = 0; i < nd_wpd; i++ ) {
1160: u1 = d1[i]; u2 = d2[i];
1161: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
1162: t1 = (u1&0xffff); t2 = (u2&0xffff); u |= t1>t2?t1:t2;
1163: d[i] = u;
1164: }
1165: break;
1166: case 32:
1167: for ( i = 0; i < nd_wpd; i++ ) {
1168: u1 = d1[i]; u2 = d2[i];
1169: d[i] = u1>u2?u1:u2;
1170: }
1171: break;
1172: default:
1.12 noro 1173: for ( i = 0; i < nd_wpd; i++ ) {
1174: u1 = d1[i]; u2 = d2[i];
1175: for ( j = 0, u = 0; j < nd_epw; j++ ) {
1176: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
1177: }
1178: d[i] = u;
1179: }
1180: break;
1.11 noro 1181: }
1182: }
1183:
1.12 noro 1184: int ndl_td(unsigned int *d)
1.11 noro 1185: {
1186: unsigned int t,u;
1.12 noro 1187: int i,j;
1.11 noro 1188:
1.12 noro 1189: for ( t = 0, i = 0; i < nd_wpd; i++ ) {
1190: u = d[i];
1191: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
1192: t += (u&nd_mask0);
1.11 noro 1193: }
1194: return t;
1195: }
1196:
1197: INLINE int ndl_compare(unsigned int *d1,unsigned int *d2)
1198: {
1199: int i;
1200:
1.12 noro 1201: for ( i = 0; i < nd_wpd; i++, d1++, d2++ )
1202: if ( *d1 > *d2 )
1.11 noro 1203: return is_rlex ? -1 : 1;
1.12 noro 1204: else if ( *d1 < *d2 )
1.11 noro 1205: return is_rlex ? 1 : -1;
1206: return 0;
1207: }
1208:
1209: INLINE int ndl_equal(unsigned int *d1,unsigned int *d2)
1210: {
1211: int i;
1212:
1213: for ( i = 0; i < nd_wpd; i++ )
1214: if ( d1[i] != d2[i] )
1215: return 0;
1216: return 1;
1217: }
1218:
1219: INLINE void ndl_add(unsigned int *d1,unsigned int *d2,unsigned int *d)
1220: {
1221: int i;
1222:
1223: for ( i = 0; i < nd_wpd; i++ )
1224: d[i] = d1[i]+d2[i];
1225: }
1226:
1.12 noro 1227: void ndl_sub(unsigned int *d1,unsigned int *d2,unsigned int *d)
1.11 noro 1228: {
1229: int i;
1230:
1231: for ( i = 0; i < nd_wpd; i++ )
1232: d[i] = d1[i]-d2[i];
1233: }
1234:
1.12 noro 1235: int ndl_disjoint(unsigned int *d1,unsigned int *d2)
1.11 noro 1236: {
1237: unsigned int t1,t2,u,u1,u2;
1.12 noro 1238: int i,j;
1.11 noro 1239:
1240: switch ( nd_bpe ) {
1241: case 4:
1242: for ( i = 0; i < nd_wpd; i++ ) {
1243: u1 = d1[i]; u2 = d2[i];
1244: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
1245: t1 = u1&0xf000000; t2 = u2&0xf000000; if ( t1&&t2 ) return 0;
1246: t1 = u1&0xf00000; t2 = u2&0xf00000; if ( t1&&t2 ) return 0;
1247: t1 = u1&0xf0000; t2 = u2&0xf0000; if ( t1&&t2 ) return 0;
1248: t1 = u1&0xf000; t2 = u2&0xf000; if ( t1&&t2 ) return 0;
1249: t1 = u1&0xf00; t2 = u2&0xf00; if ( t1&&t2 ) return 0;
1250: t1 = u1&0xf0; t2 = u2&0xf0; if ( t1&&t2 ) return 0;
1251: t1 = u1&0xf; t2 = u2&0xf; if ( t1&&t2 ) return 0;
1252: }
1253: return 1;
1254: break;
1.13 noro 1255: case 6:
1256: for ( i = 0; i < nd_wpd; i++ ) {
1257: u1 = d1[i]; u2 = d2[i];
1258: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1259: t1 = u1&0xfc0000; t2 = u2&0xfc0000; if ( t1&&t2 ) return 0;
1260: t1 = u1&0x3f000; t2 = u2&0x3f000; if ( t1&&t2 ) return 0;
1261: t1 = u1&0xfc0; t2 = u2&0xfc0; if ( t1&&t2 ) return 0;
1262: t1 = u1&0x3f; t2 = u2&0x3f; if ( t1&&t2 ) return 0;
1263: }
1264: return 1;
1265: break;
1.11 noro 1266: case 8:
1267: for ( i = 0; i < nd_wpd; i++ ) {
1268: u1 = d1[i]; u2 = d2[i];
1269: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1270: t1 = u1&0xff0000; t2 = u2&0xff0000; if ( t1&&t2 ) return 0;
1271: t1 = u1&0xff00; t2 = u2&0xff00; if ( t1&&t2 ) return 0;
1272: t1 = u1&0xff; t2 = u2&0xff; if ( t1&&t2 ) return 0;
1273: }
1274: return 1;
1275: break;
1276: case 16:
1277: for ( i = 0; i < nd_wpd; i++ ) {
1278: u1 = d1[i]; u2 = d2[i];
1279: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1280: t1 = u1&0xffff; t2 = u2&0xffff; if ( t1&&t2 ) return 0;
1281: }
1282: return 1;
1283: break;
1284: case 32:
1285: for ( i = 0; i < nd_wpd; i++ )
1286: if ( d1[i] && d2[i] ) return 0;
1287: return 1;
1288: break;
1289: default:
1.12 noro 1290: for ( i = 0; i < nd_wpd; i++ ) {
1291: u1 = d1[i]; u2 = d2[i];
1292: for ( j = 0; j < nd_epw; j++ ) {
1293: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1294: u1 >>= nd_bpe; u2 >>= nd_bpe;
1295: }
1.11 noro 1296: }
1.12 noro 1297: return 1;
1298: break;
1.11 noro 1299: }
1300: }
1301:
1302: ND nd_reduce(ND p1,ND p2)
1303: {
1.13 noro 1304: int c,c1,c2,t,td,td2,mul;
1.11 noro 1305: NM m2,prev,head,cur,new;
1306: unsigned int *d;
1307:
1308: if ( !p1 )
1309: return 0;
1310: else {
1.13 noro 1311: c2 = invm(HC(p2),nd_mod);
1312: c1 = nd_mod-HC(p1);
1313: DMAR(c1,c2,0,nd_mod,mul);
1.11 noro 1314: td = HTD(p1)-HTD(p2);
1315: d = (unsigned int *)ALLOCA(nd_wpd*sizeof(unsigned int));
1316: ndl_sub(HDL(p1),HDL(p2),d);
1317: prev = 0; head = cur = BDY(p1);
1318: NEWNM(new);
1319: for ( m2 = BDY(p2); m2; ) {
1320: td2 = new->td = m2->td+td;
1321: ndl_add(m2->dl,d,new->dl);
1322: if ( !cur ) {
1.13 noro 1323: c1 = C(m2);
1324: DMAR(c1,mul,0,nd_mod,c2);
1325: C(new) = c2;
1.11 noro 1326: if ( !prev ) {
1327: prev = new;
1328: NEXT(prev) = 0;
1329: head = prev;
1330: } else {
1331: NEXT(prev) = new;
1332: NEXT(new) = 0;
1333: prev = new;
1334: }
1335: m2 = NEXT(m2);
1336: NEWNM(new);
1337: continue;
1338: }
1339: if ( cur->td > td2 )
1340: c = 1;
1341: else if ( cur->td < td2 )
1342: c = -1;
1343: else
1344: c = ndl_compare(cur->dl,new->dl);
1345: switch ( c ) {
1346: case 0:
1.13 noro 1347: c2 = C(m2);
1348: c1 = C(cur);
1349: DMAR(c2,mul,c1,nd_mod,t);
1.11 noro 1350: if ( t )
1351: C(cur) = t;
1352: else if ( !prev ) {
1353: head = NEXT(cur);
1354: FREENM(cur);
1355: cur = head;
1356: } else {
1357: NEXT(prev) = NEXT(cur);
1358: FREENM(cur);
1359: cur = NEXT(prev);
1360: }
1361: m2 = NEXT(m2);
1362: break;
1363: case 1:
1364: prev = cur;
1365: cur = NEXT(cur);
1366: break;
1367: case -1:
1368: if ( !prev ) {
1369: /* cur = head */
1370: prev = new;
1.13 noro 1371: c2 = C(m2);
1372: DMAR(c2,mul,0,nd_mod,c1);
1373: C(prev) = c1;
1.11 noro 1374: NEXT(prev) = head;
1375: head = prev;
1376: } else {
1.13 noro 1377: c2 = C(m2);
1378: DMAR(c2,mul,0,nd_mod,c1);
1379: C(new) = c1;
1.11 noro 1380: NEXT(prev) = new;
1381: NEXT(new) = cur;
1382: prev = new;
1383: }
1384: NEWNM(new);
1385: m2 = NEXT(m2);
1386: break;
1387: }
1388: }
1389: FREENM(new);
1390: if ( head ) {
1391: BDY(p1) = head;
1392: p1->sugar = MAX(p1->sugar,p2->sugar+td);
1393: return p1;
1394: } else {
1395: FREEND(p1);
1396: return 0;
1397: }
1398:
1399: }
1400: }
1401:
1.14 ! noro 1402: /* HDL(p1) = HDL(p2) */
! 1403:
! 1404: ND nd_reduce_special(ND p1,ND p2)
! 1405: {
! 1406: int c,c1,c2,t,td,td2,mul;
! 1407: NM m2,prev,head,cur,new;
! 1408:
! 1409: if ( !p1 )
! 1410: return 0;
! 1411: else {
! 1412: c2 = invm(HC(p2),nd_mod);
! 1413: c1 = nd_mod-HC(p1);
! 1414: DMAR(c1,c2,0,nd_mod,mul);
! 1415: prev = 0; head = cur = BDY(p1);
! 1416: NEWNM(new);
! 1417: for ( m2 = BDY(p2); m2; ) {
! 1418: td2 = new->td = m2->td;
! 1419: if ( !cur ) {
! 1420: c1 = C(m2);
! 1421: DMAR(c1,mul,0,nd_mod,c2);
! 1422: C(new) = c2;
! 1423: bcopy(m2->dl,new->dl,nd_wpd*sizeof(unsigned int));
! 1424: if ( !prev ) {
! 1425: prev = new;
! 1426: NEXT(prev) = 0;
! 1427: head = prev;
! 1428: } else {
! 1429: NEXT(prev) = new;
! 1430: NEXT(new) = 0;
! 1431: prev = new;
! 1432: }
! 1433: m2 = NEXT(m2);
! 1434: NEWNM(new);
! 1435: continue;
! 1436: }
! 1437: if ( cur->td > td2 )
! 1438: c = 1;
! 1439: else if ( cur->td < td2 )
! 1440: c = -1;
! 1441: else
! 1442: c = ndl_compare(cur->dl,m2->dl);
! 1443: switch ( c ) {
! 1444: case 0:
! 1445: c2 = C(m2);
! 1446: c1 = C(cur);
! 1447: DMAR(c2,mul,c1,nd_mod,t);
! 1448: if ( t )
! 1449: C(cur) = t;
! 1450: else if ( !prev ) {
! 1451: head = NEXT(cur);
! 1452: FREENM(cur);
! 1453: cur = head;
! 1454: } else {
! 1455: NEXT(prev) = NEXT(cur);
! 1456: FREENM(cur);
! 1457: cur = NEXT(prev);
! 1458: }
! 1459: m2 = NEXT(m2);
! 1460: break;
! 1461: case 1:
! 1462: prev = cur;
! 1463: cur = NEXT(cur);
! 1464: break;
! 1465: case -1:
! 1466: bcopy(m2->dl,new->dl,nd_wpd*sizeof(unsigned int));
! 1467: if ( !prev ) {
! 1468: /* cur = head */
! 1469: prev = new;
! 1470: c2 = C(m2);
! 1471: DMAR(c2,mul,0,nd_mod,c1);
! 1472: C(prev) = c1;
! 1473: NEXT(prev) = head;
! 1474: head = prev;
! 1475: } else {
! 1476: c2 = C(m2);
! 1477: DMAR(c2,mul,0,nd_mod,c1);
! 1478: C(new) = c1;
! 1479: NEXT(prev) = new;
! 1480: NEXT(new) = cur;
! 1481: prev = new;
! 1482: }
! 1483: NEWNM(new);
! 1484: m2 = NEXT(m2);
! 1485: break;
! 1486: }
! 1487: }
! 1488: FREENM(new);
! 1489: if ( head ) {
! 1490: BDY(p1) = head;
! 1491: p1->sugar = MAX(p1->sugar,p2->sugar+td);
! 1492: return p1;
! 1493: } else {
! 1494: FREEND(p1);
! 1495: return 0;
! 1496: }
! 1497:
! 1498: }
! 1499: }
! 1500:
1.11 noro 1501: ND nd_sp(ND_pairs p)
1502: {
1503: NM m;
1504: ND p1,p2,t1,t2;
1505: unsigned int *lcm;
1506: int td;
1507:
1508: p1 = nps[p->i1];
1509: p2 = nps[p->i2];
1510: lcm = p->lcm;
1511: td = p->td;
1512: NEWNM(m);
1513: C(m) = HC(p2); m->td = td-HTD(p1); ndl_sub(lcm,HDL(p1),m->dl); NEXT(m) = 0;
1514: t1 = nd_mul_nm(p1,m);
1515: C(m) = nd_mod-HC(p1); m->td = td-HTD(p2); ndl_sub(lcm,HDL(p2),m->dl);
1516: t2 = nd_mul_nm(p2,m);
1517: FREENM(m);
1518: return nd_add(t1,t2);
1519: }
1520:
1.14 ! noro 1521: int ndl_hash_value(int td,unsigned int *d)
! 1522: {
! 1523: int i;
! 1524: int r;
! 1525:
! 1526: r = td;
! 1527: for ( i = 0; i < nd_wpd; i++ )
! 1528: r = ((r<<16)+d[i])%REDTAB_LEN;
! 1529: return r;
! 1530: }
! 1531:
1.12 noro 1532: ND nd_find_reducer(ND g)
1533: {
1534: NM m;
1535: ND r,p;
1.13 noro 1536: int i,c1,c2,c;
1.14 ! noro 1537: int d,k;
! 1538: NM t;
! 1539:
! 1540: #if 1
! 1541: d = ndl_hash_value(HTD(g),HDL(g));
! 1542: for ( m = nd_red[d], k = 0; m; m = NEXT(m), k++ ) {
! 1543: if ( HTD(g) == m->td && ndl_equal(HDL(g),m->dl) ) {
! 1544: #if 1
! 1545: if ( k > 0 ) nd_notfirst++;
! 1546: #endif
! 1547: nd_found++;
! 1548: p = nps[m->c];
! 1549: #if 1
! 1550: c1 = invm(HC(p),nd_mod);
! 1551: c2 = nd_mod-HC(g);
! 1552: DMAR(c1,c2,0,nd_mod,c);
! 1553: NEWNM(m);
! 1554: C(m) = c;
! 1555: m->td = HTD(g)-HTD(p);
! 1556: ndl_sub(HDL(g),HDL(p),m->dl);
! 1557: NEXT(m) = 0;
! 1558: r = nd_mul_nm(p,m);
! 1559: FREENM(m);
! 1560: return r;
! 1561: #else
! 1562: return p;
! 1563: #endif
! 1564: }
! 1565: }
! 1566: #endif
1.12 noro 1567:
1568: for ( i = 0; i < nd_psn; i++ ) {
1569: p = nps[i];
1570: if ( HTD(g) >= HTD(p) && ndl_reducible(HDL(g),HDL(p)) ) {
1.14 ! noro 1571: nd_create++;
1.11 noro 1572: #if 1
1.12 noro 1573: NEWNM(m);
1.13 noro 1574: c1 = invm(HC(p),nd_mod);
1575: c2 = nd_mod-HC(g);
1576: DMAR(c1,c2,0,nd_mod,c);
1577: C(m) = c;
1.12 noro 1578: m->td = HTD(g)-HTD(p);
1579: ndl_sub(HDL(g),HDL(p),m->dl);
1580: NEXT(m) = 0;
1581: r = nd_mul_nm(p,m);
1582: FREENM(m);
1583: r->sugar = m->td + p->sugar;
1.14 ! noro 1584: nd_append_red(HDL(g),HTD(g),i);
1.12 noro 1585: return r;
1586: #else
1.14 ! noro 1587: nd_append_red(HDL(g),HTD(g),i);
1.12 noro 1588: return p;
1589: #endif
1590: }
1591: }
1592: return 0;
1593: }
1594:
1.13 noro 1595: ND nd_find_monic_reducer(ND g)
1596: {
1597: int *d;
1598: ND p,r;
1599: int i;
1600:
1601: for ( i = 0; i < nd_psn; i++ ) {
1602: p = nps[i];
1603: if ( HTD(g) >= HTD(p) && ndl_reducible(HDL(g),HDL(p)) ) {
1604: d = (int *)ALLOCA(nd_wpd*sizeof(int));
1605: ndl_sub(HDL(g),HDL(p),d);
1606: r = nd_mul_term(p,HTD(g)-HTD(p),d);
1607: return r;
1608: }
1609: }
1610: return 0;
1611: }
1612:
1.12 noro 1613: ND nd_add(ND p1,ND p2)
1.11 noro 1614: {
1.12 noro 1615: int n,c;
1616: int t;
1617: ND r;
1618: NM m1,m2,mr0,mr,s;
1619:
1620: if ( !p1 )
1621: return p2;
1622: else if ( !p2 )
1623: return p1;
1624: else {
1625: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1626: if ( m1->td > m2->td )
1627: c = 1;
1628: else if ( m1->td < m2->td )
1629: c = -1;
1630: else
1631: c = ndl_compare(m1->dl,m2->dl);
1632: switch ( c ) {
1633: case 0:
1634: t = ((C(m1))+(C(m2))) - nd_mod;
1635: if ( t < 0 )
1636: t += nd_mod;
1637: s = m1; m1 = NEXT(m1);
1638: if ( t ) {
1639: NEXTNM2(mr0,mr,s); C(mr) = (t);
1640: } else {
1641: FREENM(s);
1642: }
1643: s = m2; m2 = NEXT(m2); FREENM(s);
1644: break;
1645: case 1:
1646: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1647: break;
1648: case -1:
1649: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1650: break;
1651: }
1652: }
1653: if ( !mr0 )
1654: if ( m1 )
1655: mr0 = m1;
1656: else if ( m2 )
1657: mr0 = m2;
1658: else
1659: return 0;
1660: else if ( m1 )
1661: NEXT(mr) = m1;
1662: else if ( m2 )
1663: NEXT(mr) = m2;
1664: else
1665: NEXT(mr) = 0;
1666: BDY(p1) = mr0;
1667: p1->sugar = MAX(p1->sugar,p2->sugar);
1668: FREEND(p2);
1669: return p1;
1670: }
1671: }
1672:
1673: ND nd_mul_nm(ND p,NM m0)
1674: {
1675: NM m,mr,mr0;
1676: unsigned int *d,*dt,*dm;
1.13 noro 1677: int c,n,td,i,c1,c2;
1.12 noro 1678: int *pt,*p1,*p2;
1679: ND r;
1.11 noro 1680:
1.12 noro 1681: if ( !p )
1.11 noro 1682: return 0;
1.12 noro 1683: else {
1684: n = NV(p); m = BDY(p);
1685: d = m0->dl; td = m0->td; c = C(m0);
1686: mr0 = 0;
1687: for ( ; m; m = NEXT(m) ) {
1688: NEXTNM(mr0,mr);
1.13 noro 1689: c1 = C(m);
1690: DMAR(c1,c,0,nd_mod,c2);
1691: C(mr) = c2;
1692: mr->td = m->td+td;
1693: ndl_add(m->dl,d,mr->dl);
1694: }
1695: NEXT(mr) = 0;
1696: MKND(NV(p),mr0,r);
1697: r->sugar = p->sugar + td;
1698: return r;
1699: }
1700: }
1701:
1702: ND nd_mul_term(ND p,int td,unsigned int *d)
1703: {
1704: NM m,mr,mr0;
1705: int c,n;
1706: ND r;
1707:
1708: if ( !p )
1709: return 0;
1710: else {
1711: n = NV(p); m = BDY(p);
1712: mr0 = 0;
1.14 ! noro 1713: NEWNM(mr0);
! 1714: C(mr0) = C(m);
! 1715: mr0->td = m->td+td;
! 1716: ndl_add(m->dl,d,mr0->dl);
! 1717: mr = mr0;
! 1718: m = NEXT(m);
1.13 noro 1719: for ( ; m; m = NEXT(m) ) {
1.14 ! noro 1720: NEWNM(NEXT(mr));
! 1721: mr = NEXT(mr);
1.13 noro 1722: C(mr) = C(m);
1.12 noro 1723: mr->td = m->td+td;
1724: ndl_add(m->dl,d,mr->dl);
1725: }
1726: NEXT(mr) = 0;
1727: MKND(NV(p),mr0,r);
1728: r->sugar = p->sugar + td;
1729: return r;
1.11 noro 1730: }
1.12 noro 1731: }
1732:
1733: #if 1
1734: ND nd_nf(ND g,int full)
1735: {
1736: ND p,d,red;
1737: NM m,mrd,tail;
1738: int n,sugar,psugar;
1739:
1740: if ( !g )
1741: return 0;
1.11 noro 1742: sugar = g->sugar;
1.12 noro 1743: n = NV(g);
1.11 noro 1744: for ( d = 0; g; ) {
1.12 noro 1745: red = nd_find_reducer(g);
1746: if ( red ) {
1747: #if 1
1748: g = nd_add(g,red);
1749: sugar = MAX(sugar,red->sugar);
1.11 noro 1750: #else
1.12 noro 1751: psugar = (HTD(g)-HTD(red))+red->sugar;
1752: g = nd_reduce(g,red);
1753: sugar = MAX(sugar,psugar);
1.11 noro 1754: #endif
1.12 noro 1755: } else if ( !full )
1756: return g;
1757: else {
1758: m = BDY(g);
1759: if ( NEXT(m) ) {
1760: BDY(g) = NEXT(m); NEXT(m) = 0;
1761: } else {
1762: FREEND(g); g = 0;
1.11 noro 1763: }
1.12 noro 1764: if ( d ) {
1765: NEXT(tail)=m;
1766: tail=m;
1.11 noro 1767: } else {
1.12 noro 1768: MKND(n,m,d);
1769: tail = BDY(d);
1.11 noro 1770: }
1771: }
1772: }
1773: if ( d )
1774: d->sugar = sugar;
1775: return d;
1776: }
1777: #else
1778:
1779: ND nd_remove_head(ND p)
1780: {
1781: NM m;
1782:
1783: m = BDY(p);
1784: if ( !NEXT(m) ) {
1785: FREEND(p);
1786: p = 0;
1787: } else
1788: BDY(p) = NEXT(m);
1789: FREENM(m);
1790: return p;
1791: }
1792:
1793: PGeoBucket create_pbucket()
1794: {
1795: PGeoBucket g;
1796:
1797: g = CALLOC(1,sizeof(struct oPGeoBucket));
1798: g->m = -1;
1799: return g;
1800: }
1801:
1802: void add_pbucket(PGeoBucket g,ND d)
1803: {
1804: int l,k,m;
1805:
1806: l = nd_length(d);
1807: for ( k = 0, m = 1; l > m; k++, m <<= 2 );
1808: /* 4^(k-1) < l <= 4^k */
1809: d = nd_add(g->body[k],d);
1810: for ( ; d && nd_length(d) > 1<<(2*k); k++ ) {
1811: g->body[k] = 0;
1812: d = nd_add(g->body[k+1],d);
1813: }
1814: g->body[k] = d;
1815: g->m = MAX(g->m,k);
1816: }
1817:
1818: int head_pbucket(PGeoBucket g)
1819: {
1820: int j,i,c,k,nv,sum;
1821: unsigned int *di,*dj;
1822: ND gi,gj;
1823:
1824: k = g->m;
1825: while ( 1 ) {
1826: j = -1;
1827: for ( i = 0; i <= k; i++ ) {
1828: if ( !(gi = g->body[i]) )
1829: continue;
1830: if ( j < 0 ) {
1831: j = i;
1832: gj = g->body[j];
1833: dj = HDL(gj);
1834: sum = HC(gj);
1835: } else {
1836: di = HDL(gi);
1837: nv = NV(gi);
1838: if ( HTD(gi) > HTD(gj) )
1839: c = 1;
1840: else if ( HTD(gi) < HTD(gj) )
1841: c = -1;
1842: else
1843: c = ndl_compare(di,dj);
1844: if ( c > 0 ) {
1845: if ( sum )
1846: HC(gj) = sum;
1847: else
1848: g->body[j] = nd_remove_head(gj);
1849: j = i;
1850: gj = g->body[j];
1851: dj = HDL(gj);
1852: sum = HC(gj);
1853: } else if ( c == 0 ) {
1854: sum = sum+HC(gi)-nd_mod;
1855: if ( sum < 0 )
1856: sum += nd_mod;
1857: g->body[i] = nd_remove_head(gi);
1858: }
1859: }
1860: }
1861: if ( j < 0 )
1862: return -1;
1863: else if ( sum ) {
1864: HC(gj) = sum;
1865: return j;
1866: } else
1867: g->body[j] = nd_remove_head(gj);
1868: }
1869: }
1870:
1871: ND normalize_pbucket(PGeoBucket g)
1872: {
1873: int i;
1874: ND r,t;
1875:
1876: r = 0;
1877: for ( i = 0; i <= g->m; i++ )
1878: r = nd_add(r,g->body[i]);
1879: return r;
1880: }
1881:
1.12 noro 1882: ND nd_nf(ND g,int full)
1.11 noro 1883: {
1884: ND u,p,d,red;
1885: NODE l;
1886: NM m,mrd;
1887: int sugar,psugar,n,h_reducible,h;
1888: PGeoBucket bucket;
1889:
1890: if ( !g ) {
1891: return 0;
1892: }
1893: sugar = g->sugar;
1894: n = g->nv;
1895: bucket = create_pbucket();
1896: add_pbucket(bucket,g);
1897: d = 0;
1898: while ( 1 ) {
1899: h = head_pbucket(bucket);
1900: if ( h < 0 ) {
1901: if ( d )
1902: d->sugar = sugar;
1903: return d;
1904: }
1905: g = bucket->body[h];
1.12 noro 1906: red = nd_find_reducer(g);
1907: if ( red ) {
1908: bucket->body[h] = nd_remove_head(g);
1909: red = nd_remove_head(red);
1910: add_pbucket(bucket,red);
1911: sugar = MAX(sugar,red->sugar);
1912: } else if ( !full ) {
1913: g = normalize_pbucket(bucket);
1914: if ( g )
1915: g->sugar = sugar;
1916: return g;
1917: } else {
1918: m = BDY(g);
1919: if ( NEXT(m) ) {
1920: BDY(g) = NEXT(m); NEXT(m) = 0;
1921: } else {
1922: FREEND(g); g = 0;
1.11 noro 1923: }
1.12 noro 1924: bucket->body[h] = g;
1925: NEXT(m) = 0;
1926: if ( d ) {
1927: for ( mrd = BDY(d); NEXT(mrd); mrd = NEXT(mrd) );
1928: NEXT(mrd) = m;
1.11 noro 1929: } else {
1.12 noro 1930: MKND(n,m,d);
1.11 noro 1931: }
1932: }
1933: }
1934: }
1935: #endif
1936:
1937: NODE nd_gb(NODE f)
1938: {
1.14 ! noro 1939: int i,nh,sugar;
1.11 noro 1940: NODE r,g,gall;
1941: ND_pairs d;
1942: ND_pairs l;
1943: ND h,nf;
1944:
1945: for ( gall = g = 0, d = 0, r = f; r; r = NEXT(r) ) {
1946: i = (int)BDY(r);
1947: d = update_pairs(d,g,i);
1948: g = update_base(g,i);
1949: gall = append_one(gall,i);
1950: }
1.14 ! noro 1951: sugar = 0;
1.11 noro 1952: while ( d ) {
1953: #if 0
1954: ndp_print(d);
1955: #endif
1956: l = nd_minp(d,&d);
1.14 ! noro 1957: if ( l->sugar != sugar ) {
! 1958: sugar = l->sugar;
! 1959: fprintf(asir_out,"%d",sugar);
! 1960: }
1.11 noro 1961: h = nd_sp(l);
1.12 noro 1962: nf = nd_nf(h,!Top);
1.11 noro 1963: if ( nf ) {
1964: printf("+"); fflush(stdout);
1965: #if 0
1966: ndl_print(HDL(nf)); fflush(stdout);
1967: #endif
1968: nh = nd_newps(nf);
1969: d = update_pairs(d,g,nh);
1970: g = update_base(g,nh);
1971: gall = append_one(gall,nh);
1972: } else {
1973: printf("."); fflush(stdout);
1974: }
1975: }
1976: return g;
1977: }
1978:
1979: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t)
1980: {
1981: ND_pairs d1,nd,cur,head,prev;
1982:
1983: if ( !g ) return d;
1984: d = crit_B(d,t);
1985: d1 = nd_newpairs(g,t);
1986: d1 = crit_M(d1);
1987: d1 = crit_F(d1);
1988: prev = 0; cur = head = d1;
1989: while ( cur ) {
1990: if ( crit_2( cur->i1,cur->i2 ) ) {
1991: if ( !prev ) {
1992: head = cur = NEXT(cur);
1993: } else {
1994: cur = NEXT(prev) = NEXT(cur);
1995: }
1996: } else {
1997: prev = cur;
1998: cur = NEXT(cur);
1999: }
2000: }
2001: if ( !d )
2002: return head;
2003: else {
2004: nd = d;
2005: while ( NEXT(nd) )
2006: nd = NEXT(nd);
2007: NEXT(nd) = head;
2008: return d;
2009: }
2010: }
2011:
2012: ND_pairs nd_newpairs( NODE g, int t )
2013: {
2014: NODE h;
2015: unsigned int *dl;
2016: int td,ts,s;
2017: ND_pairs r,r0;
2018:
2019: dl = HDL(nps[t]);
2020: td = HTD(nps[t]);
2021: ts = nps[t]->sugar - td;
2022: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
2023: NEXTND_pairs(r0,r);
2024: r->i1 = (int)BDY(h);
2025: r->i2 = t;
2026: ndl_lcm(HDL(nps[r->i1]),dl,r->lcm);
2027: r->td = ndl_td(r->lcm);
2028: s = nps[r->i1]->sugar-HTD(nps[r->i1]);
2029: r->sugar = MAX(s,ts) + r->td;
2030: }
2031: NEXT(r) = 0;
2032: return r0;
2033: }
2034:
2035: ND_pairs crit_B( ND_pairs d, int s )
2036: {
2037: ND_pairs cur,head,prev;
2038: unsigned int *t,*tl,*lcm;
2039: int td,tdl;
2040:
2041: if ( !d ) return 0;
2042: t = HDL(nps[s]);
2043: prev = 0;
2044: head = cur = d;
2045: lcm = (unsigned int *)ALLOCA(nd_wpd*sizeof(unsigned int));
2046: while ( cur ) {
2047: tl = cur->lcm;
2048: if ( ndl_reducible(tl,t)
2049: && (ndl_lcm(HDL(nps[cur->i1]),t,lcm),!ndl_equal(lcm,tl))
2050: && (ndl_lcm(HDL(nps[cur->i2]),t,lcm),!ndl_equal(lcm,tl)) ) {
2051: if ( !prev ) {
2052: head = cur = NEXT(cur);
2053: } else {
2054: cur = NEXT(prev) = NEXT(cur);
2055: }
2056: } else {
2057: prev = cur;
2058: cur = NEXT(cur);
2059: }
2060: }
2061: return head;
2062: }
2063:
2064: ND_pairs crit_M( ND_pairs d1 )
2065: {
2066: ND_pairs e,d2,d3,dd,p;
2067: unsigned int *id,*jd;
2068: int itd,jtd;
2069:
2070: for ( dd = 0, e = d1; e; e = d3 ) {
2071: if ( !(d2 = NEXT(e)) ) {
2072: NEXT(e) = dd;
2073: return e;
2074: }
2075: id = e->lcm;
2076: itd = e->td;
2077: for ( d3 = 0; d2; d2 = p ) {
2078: p = NEXT(d2),
2079: jd = d2->lcm;
2080: jtd = d2->td;
2081: if ( jtd == itd )
2082: if ( id == jd );
2083: else if ( ndl_reducible(jd,id) ) continue;
2084: else if ( ndl_reducible(id,jd) ) goto delit;
2085: else ;
2086: else if ( jtd > itd )
2087: if ( ndl_reducible(jd,id) ) continue;
2088: else ;
2089: else if ( ndl_reducible(id,jd ) ) goto delit;
2090: NEXT(d2) = d3;
2091: d3 = d2;
2092: }
2093: NEXT(e) = dd;
2094: dd = e;
2095: continue;
2096: /**/
2097: delit: NEXT(d2) = d3;
2098: d3 = d2;
2099: for ( ; p; p = d2 ) {
2100: d2 = NEXT(p);
2101: NEXT(p) = d3;
2102: d3 = p;
2103: }
2104: }
2105: return dd;
2106: }
2107:
2108: ND_pairs crit_F( ND_pairs d1 )
2109: {
2110: ND_pairs rest, head;
2111: ND_pairs last, p, r, w;
2112: int s;
2113:
2114: for ( head = last = 0, p = d1; NEXT(p); ) {
2115: r = w = equivalent_pairs(p,&rest);
2116: s = r->sugar;
2117: while ( w = NEXT(w) )
2118: if ( crit_2(w->i1,w->i2) ) {
2119: r = w;
2120: break;
2121: } else if ( w->sugar < s ) {
2122: r = w;
2123: s = r->sugar;
2124: }
2125: if ( last ) NEXT(last) = r;
2126: else head = r;
2127: NEXT(last = r) = 0;
2128: p = rest;
2129: if ( !p ) return head;
2130: }
2131: if ( !last ) return p;
2132: NEXT(last) = p;
2133: return head;
2134: }
2135:
2136: int crit_2( int dp1, int dp2 )
2137: {
2138: return ndl_disjoint(HDL(nps[dp1]),HDL(nps[dp2]));
2139: }
2140:
2141: static ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
2142: {
2143: ND_pairs w,p,r,s;
2144: unsigned int *d;
2145: int td;
2146:
2147: w = d1;
2148: d = w->lcm;
2149: td = w->td;
2150: s = NEXT(w);
2151: NEXT(w) = 0;
2152: for ( r = 0; s; s = p ) {
2153: p = NEXT(s);
2154: if ( td == s->td && ndl_equal(d,s->lcm) ) {
2155: NEXT(s) = w;
2156: w = s;
2157: } else {
2158: NEXT(s) = r;
2159: r = s;
2160: }
2161: }
2162: *prest = r;
2163: return w;
2164: }
2165:
2166: NODE update_base(NODE nd,int ndp)
2167: {
2168: unsigned int *dl, *dln;
2169: NODE last, p, head;
2170: int td,tdn;
2171:
2172: dl = HDL(nps[ndp]);
2173: td = HTD(nps[ndp]);
2174: for ( head = last = 0, p = nd; p; ) {
2175: dln = HDL(nps[(int)BDY(p)]);
2176: tdn = HTD(nps[(int)BDY(p)]);
2177: if ( tdn >= td && ndl_reducible( dln, dl ) ) {
2178: p = NEXT(p);
2179: if ( last ) NEXT(last) = p;
2180: } else {
2181: if ( !last ) head = p;
2182: p = NEXT(last = p);
2183: }
2184: }
2185: head = append_one(head,ndp);
2186: return head;
2187: }
2188:
2189: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
2190: {
2191: ND_pairs m,ml,p,l;
2192: unsigned int *lcm;
2193: int s,td,len,tlen,c;
2194:
2195: if ( !(p = NEXT(m = d)) ) {
2196: *prest = p;
2197: NEXT(m) = 0;
2198: return m;
2199: }
2200: lcm = m->lcm;
2201: s = m->sugar;
2202: td = m->td;
2203: len = nd_length(nps[m->i1])+nd_length(nps[m->i2]);
2204: for ( ml = 0, l = m; p; p = NEXT(l = p) ) {
2205: if (p->sugar < s)
2206: goto find;
2207: else if ( p->sugar == s ) {
2208: if ( p->td < td )
2209: goto find;
2210: else if ( p->td == td ) {
2211: c = ndl_compare(p->lcm,lcm);
2212: if ( c < 0 )
2213: goto find;
2214: else if ( c == 0 ) {
2215: tlen = nd_length(nps[p->i1])+nd_length(nps[p->i2]);
2216: if ( tlen < len )
2217: goto find;
2218: }
2219: }
2220: }
2221: continue;
2222: find:
2223: ml = l;
2224: m = p;
2225: lcm = m->lcm;
2226: s = m->sugar;
2227: td = m->td;
2228: len = tlen;
2229: }
2230: if ( !ml ) *prest = NEXT(m);
2231: else {
2232: NEXT(ml) = NEXT(m);
2233: *prest = d;
2234: }
2235: NEXT(m) = 0;
2236: return m;
2237: }
2238:
2239: int nd_newps(ND a)
2240: {
2241: if ( nd_psn == nd_pslen ) {
2242: nd_pslen *= 2;
2243: nps = (ND *)REALLOC((char *)nps,nd_pslen*sizeof(ND));
2244: }
2245: nd_monic(a);
2246: nps[nd_psn] = a;
2247: return nd_psn++;
2248: }
2249:
2250: NODE NODE_sortb(NODE f,int);
2251: ND dptond(DP);
2252: DP ndtodp(ND);
2253:
2254: NODE nd_setup(NODE f)
2255: {
1.14 ! noro 2256: int i,td;
1.11 noro 2257: NODE s,s0,f0;
2258:
1.14 ! noro 2259: nd_found = 0;
! 2260: nd_notfirst = 0;
! 2261: nd_create = 0;
1.11 noro 2262: #if 0
2263: f0 = f = NODE_sortb(f,1);
2264: #endif
2265: nd_psn = length(f); nd_pslen = 2*nd_psn;
2266: nps = (ND *)MALLOC(nd_pslen*sizeof(ND));
1.14 ! noro 2267: nd_bpe = 6;
1.11 noro 2268: nd_epw = (sizeof(unsigned int)*8)/nd_bpe;
2269: nd_wpd = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
1.13 noro 2270: if ( nd_bpe < 32 ) {
2271: nd_mask0 = (1<<nd_bpe)-1;
2272: } else {
2273: nd_mask0 = 0xffffffff;
2274: }
1.12 noro 2275: bzero(nd_mask,sizeof(nd_mask));
2276: for ( i = 0; i < nd_epw; i++ )
2277: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
1.11 noro 2278: nd_free_private_storage();
1.14 ! noro 2279: td = 0;
1.11 noro 2280: for ( i = 0; i < nd_psn; i++, f = NEXT(f) ) {
2281: nps[i] = dptond((DP)BDY(f));
1.14 ! noro 2282: td = MAX(td,HTD(nps[i]));
1.11 noro 2283: nd_monic(nps[i]);
2284: }
1.14 ! noro 2285: nd_red = (NM *)MALLOC(REDTAB_LEN*sizeof(NM));
1.11 noro 2286: for ( s0 = 0, i = 0; i < nd_psn; i++ ) {
2287: NEXTNODE(s0,s); BDY(s) = (pointer)i;
2288: }
2289: if ( s0 ) NEXT(s) = 0;
2290: return s0;
2291: }
2292:
2293: void nd_gr(LIST f,LIST v,int m,struct order_spec *ord,LIST *rp)
2294: {
2295: struct order_spec ord1;
2296: VL fv,vv,vc;
2297: NODE fd,fd0,r,r0,t,x,s,xx;
2298: DP a,b,c;
2299:
2300: get_vars((Obj)f,&fv); pltovl(v,&vv);
2301: nd_nvar = length(vv);
2302: if ( ord->id )
2303: error("nd_gr : unsupported order");
2304: switch ( ord->ord.simple ) {
2305: case 0:
2306: is_rlex = 1;
2307: break;
2308: case 1:
2309: is_rlex = 0;
2310: break;
2311: default:
2312: error("nd_gr : unsupported order");
2313: }
2314: initd(ord);
2315: nd_mod = m;
2316: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
2317: ptod(CO,vv,(P)BDY(t),&b);
2318: _dp_mod(b,m,0,&c);
2319: if ( c ) {
2320: NEXTNODE(fd0,fd); BDY(fd) = (pointer)c;
2321: }
2322: }
2323: if ( fd0 ) NEXT(fd) = 0;
2324: s = nd_setup(fd0);
2325: x = nd_gb(s);
2326: #if 0
2327: x = nd_reduceall(x,m);
2328: #endif
2329: for ( r0 = 0; x; x = NEXT(x) ) {
2330: NEXTNODE(r0,r);
2331: a = ndtodp(nps[(int)BDY(x)]);
2332: _dtop_mod(CO,vv,a,(P *)&BDY(r));
2333: }
2334: if ( r0 ) NEXT(r) = 0;
2335: MKLIST(*rp,r0);
1.14 ! noro 2336: fprintf(asir_out,"found=%d,notfirst=%d,create=%d\n",
! 2337: nd_found,nd_notfirst,nd_create);
1.11 noro 2338: }
2339:
2340: void dltondl(int n,DL dl,unsigned int *r)
2341: {
2342: unsigned int *d;
2343: int i;
2344:
2345: d = dl->d;
1.12 noro 2346: bzero(r,nd_wpd*sizeof(unsigned int));
1.11 noro 2347: if ( is_rlex )
2348: for ( i = 0; i < n; i++ )
2349: r[(n-1-i)/nd_epw] |= (d[i]<<((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe));
2350: else
2351: for ( i = 0; i < n; i++ )
2352: r[i/nd_epw] |= d[i]<<((nd_epw-(i%nd_epw)-1)*nd_bpe);
2353: }
2354:
2355: DL ndltodl(int n,int td,unsigned int *ndl)
2356: {
2357: DL dl;
2358: int *d;
2359: int i;
2360:
2361: NEWDL(dl,n);
2362: dl->td = td;
2363: d = dl->d;
2364: if ( is_rlex )
2365: for ( i = 0; i < n; i++ )
2366: d[i] = (ndl[(n-1-i)/nd_epw]>>((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe))
2367: &((1<<nd_bpe)-1);
2368: else
2369: for ( i = 0; i < n; i++ )
2370: d[i] = (ndl[i/nd_epw]>>((nd_epw-(i%nd_epw)-1)*nd_bpe))
2371: &((1<<nd_bpe)-1);
2372: return dl;
2373: }
2374:
2375: ND dptond(DP p)
2376: {
2377: ND d;
2378: NM m0,m;
2379: MP t;
2380: int n;
2381:
2382: if ( !p )
2383: return 0;
2384: n = NV(p);
2385: m0 = 0;
2386: for ( t = BDY(p); t; t = NEXT(t) ) {
2387: NEXTNM(m0,m);
2388: m->c = ITOS(t->c);
2389: m->td = t->dl->td;
2390: dltondl(n,t->dl,m->dl);
2391: }
2392: NEXT(m) = 0;
2393: MKND(n,m0,d);
2394: d->nv = n;
2395: d->sugar = p->sugar;
2396: return d;
2397: }
2398:
2399: DP ndtodp(ND p)
2400: {
2401: DP d;
2402: MP m0,m;
2403: NM t;
2404: int n;
2405:
2406: if ( !p )
2407: return 0;
2408: n = NV(p);
2409: m0 = 0;
2410: for ( t = BDY(p); t; t = NEXT(t) ) {
2411: NEXTMP(m0,m);
2412: m->c = STOI(t->c);
2413: m->dl = ndltodl(n,t->td,t->dl);
2414: }
2415: NEXT(m) = 0;
2416: MKDP(n,m0,d);
2417: d->sugar = p->sugar;
2418: return d;
2419: }
2420:
2421: void ndl_print(unsigned int *dl)
2422: {
2423: int n;
2424: int i;
2425:
2426: n = nd_nvar;
2427: printf("<<");
2428: if ( is_rlex )
2429: for ( i = 0; i < n; i++ )
2430: printf(i==n-1?"%d":"%d,",
2431: (dl[(n-1-i)/nd_epw]>>((nd_epw-((n-1-i)%nd_epw)-1)*nd_bpe))
2432: &((1<<nd_bpe)-1));
2433: else
2434: for ( i = 0; i < n; i++ )
2435: printf(i==n-1?"%d":"%d,",
2436: (dl[i/nd_epw]>>((nd_epw-(i%nd_epw)-1)*nd_bpe))
2437: &((1<<nd_bpe)-1));
2438: printf(">>");
2439: }
2440:
2441: void nd_print(ND p)
2442: {
2443: NM m;
2444:
2445: if ( !p )
2446: printf("0\n");
2447: else {
2448: for ( m = BDY(p); m; m = NEXT(m) ) {
2449: printf("+%d*",m->c);
2450: ndl_print(m->dl);
2451: }
2452: printf("\n");
2453: }
2454: }
2455:
2456: void ndp_print(ND_pairs d)
2457: {
2458: ND_pairs t;
2459:
2460: for ( t = d; t; t = NEXT(t) ) {
2461: printf("%d,%d ",t->i1,t->i2);
2462: }
2463: printf("\n");
2464: }
2465:
2466: void nd_monic(ND p)
2467: {
1.13 noro 2468: if ( !p )
2469: return;
2470: else
2471: nd_mul_c(p,invm(HC(p),nd_mod));
2472: }
2473:
2474: void nd_mul_c(ND p,int mul)
2475: {
1.11 noro 2476: NM m;
1.13 noro 2477: int c,c1;
1.11 noro 2478:
2479: if ( !p )
2480: return;
1.13 noro 2481: for ( m = BDY(p); m; m = NEXT(m) ) {
2482: c1 = C(m);
2483: DMAR(c1,mul,0,nd_mod,c);
2484: C(m) = c;
2485: }
1.14 ! noro 2486: }
! 2487:
! 2488: void nd_free(ND p)
! 2489: {
! 2490: NM t,s;
! 2491:
! 2492: if ( !p )
! 2493: return;
! 2494: t = BDY(p);
! 2495: while ( t ) {
! 2496: s = NEXT(t);
! 2497: FREENM(t);
! 2498: t = s;
! 2499: }
! 2500: FREEND(p);
! 2501: }
! 2502:
! 2503: void nd_append_red(unsigned int *d,int td,int i)
! 2504: {
! 2505: NM m,m0;
! 2506: int h;
! 2507:
! 2508: NEWNM(m);
! 2509: h = ndl_hash_value(td,d);
! 2510: m->c = i;
! 2511: m->td = td;
! 2512: bcopy(d,m->dl,nd_wpd*sizeof(unsigned int));
! 2513: NEXT(m) = nd_red[h];
! 2514: nd_red[h] = m;
1.1 noro 2515: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>