Annotation of OpenXM_contrib2/asir2018/engine/dist.c, Revision 1.24
1.1 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
26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
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.24 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2018/engine/dist.c,v 1.23 2020/06/19 10:18:13 noro Exp $
1.1 noro 49: */
50: #include "ca.h"
51:
52: #define ORD_REVGRADLEX 0
53: #define ORD_GRADLEX 1
54: #define ORD_LEX 2
55: #define ORD_BREVGRADLEX 3
56: #define ORD_BGRADLEX 4
57: #define ORD_BLEX 5
58: #define ORD_BREVREV 6
59: #define ORD_BGRADREV 7
60: #define ORD_BLEXREV 8
61: #define ORD_ELIM 9
62: #define ORD_WEYL_ELIM 10
63: #define ORD_HOMO_WW_DRL 11
64: #define ORD_DRL_ZIGZAG 12
65: #define ORD_HOMO_WW_DRL_ZIGZAG 13
66:
67: int cmpdl_drl_zigzag(), cmpdl_homo_ww_drl_zigzag();
68: int cmpdl_top_weight();
69:
70: int (*cmpdl)()=cmpdl_revgradlex;
71: int (*cmpdl_tie_breaker)();
72: int (*primitive_cmpdl[3])() = {cmpdl_revgradlex,cmpdl_gradlex,cmpdl_lex};
73:
74: Obj current_top_weight;
75: int current_top_weight_len;
76:
77: int do_weyl;
78:
79: int dp_nelim,dp_fcoeffs;
80: struct order_spec *dp_current_spec;
81: struct modorder_spec *dp_current_modspec;
82: int *dp_dl_work;
83:
84: void comm_muld_trunc(VL vl,DP p1,DP p2,DL dl,DP *pr);
85: void comm_quod(VL vl,DP p1,DP p2,DP *pr);
86: void muldm_trunc(VL vl,DP p,MP m0,DL dl,DP *pr);
87: void muldc_trunc(VL vl,DP p,Obj c,DL dl,DP *pr);
88: int create_order_spec(VL vl,Obj obj,struct order_spec **specp);
89: void create_modorder_spec(int id,LIST shift,struct modorder_spec **s);
90:
91: void order_init()
92: {
93: struct order_spec *spec;
94:
95: create_order_spec(0,0,&spec);
96: initd(spec);
97: create_modorder_spec(0,0,&dp_current_modspec);
98: }
99:
100: int has_sfcoef_p(Obj f);
101:
102: int has_sfcoef(DP f)
103: {
104: MP t;
105:
106: if ( !f )
107: return 0;
108: for ( t = BDY(f); t; t = NEXT(t) )
109: if ( has_sfcoef_p(t->c) )
110: break;
111: return t ? 1 : 0;
112: }
113:
114: int has_sfcoef_p(Obj f)
115: {
116: DCP dc;
117:
118: if ( !f )
119: return 0;
120: else if ( NUM(f) )
121: return (NID((Num)f) == N_GFS) ? 1 : 0;
122: else if ( POLY(f) ) {
123: for ( dc = DC((P)f); dc; dc = NEXT(dc) )
124: if ( has_sfcoef_p((Obj)COEF(dc)) )
125: return 1;
126: return 0;
127: } else
128: return 0;
129: }
130:
131: extern Obj nd_top_weight;
132:
133: void reset_top_weight()
134: {
135: cmpdl = cmpdl_tie_breaker;
136: cmpdl_tie_breaker = 0;
137: nd_top_weight = 0;
138: current_top_weight = 0;
139: current_top_weight_len = 0;
140: }
141:
142: void initd(struct order_spec *spec)
143: {
144: int len,i,k,row;
145: Q **mat;
146:
147: switch ( spec->id ) {
148: case 3:
149: cmpdl = cmpdl_composite;
150: dp_dl_work = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));
151: break;
152: case 2:
153: cmpdl = cmpdl_matrix;
154: dp_dl_work = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));
155: break;
156: case 1:
157: cmpdl = cmpdl_order_pair;
158: break;
159: default:
160: switch ( spec->ord.simple ) {
161: case ORD_REVGRADLEX:
162: cmpdl = cmpdl_revgradlex; break;
163: case ORD_GRADLEX:
164: cmpdl = cmpdl_gradlex; break;
165: case ORD_BREVGRADLEX:
166: cmpdl = cmpdl_brevgradlex; break;
167: case ORD_BGRADLEX:
168: cmpdl = cmpdl_bgradlex; break;
169: case ORD_BLEX:
170: cmpdl = cmpdl_blex; break;
171: case ORD_BREVREV:
172: cmpdl = cmpdl_brevrev; break;
173: case ORD_BGRADREV:
174: cmpdl = cmpdl_bgradrev; break;
175: case ORD_BLEXREV:
176: cmpdl = cmpdl_blexrev; break;
177: case ORD_ELIM:
178: cmpdl = cmpdl_elim; break;
179: case ORD_WEYL_ELIM:
180: cmpdl = cmpdl_weyl_elim; break;
181: case ORD_HOMO_WW_DRL:
182: cmpdl = cmpdl_homo_ww_drl; break;
183: case ORD_DRL_ZIGZAG:
184: cmpdl = cmpdl_drl_zigzag; break;
185: case ORD_HOMO_WW_DRL_ZIGZAG:
186: cmpdl = cmpdl_homo_ww_drl_zigzag; break;
187: case ORD_LEX: default:
188: cmpdl = cmpdl_lex; break;
189: }
190: break;
191: }
192: if ( current_top_weight ) {
193: cmpdl_tie_breaker = cmpdl;
194: cmpdl = cmpdl_top_weight;
195: if ( OID(current_top_weight) == O_VECT ) {
196: mat = (Q **)&BDY((VECT)current_top_weight);
197: row = 1;
198: } else {
199: mat = (Q **)BDY((MAT)current_top_weight);
200: row = ((MAT)current_top_weight)->row;
201: }
202: for ( k = 0, len = 0; k < row; k++ )
203: for ( i = 0; i < spec->nv; i++ )
204: if ( mat[k][i] )
205: len = MAX(mpz_size(BDY((Z)mat[k][i])),len);
206: current_top_weight_len = len;
207: }
208: dp_current_spec = spec;
209: }
210:
1.3 noro 211: int dpm_ordtype;
1.1 noro 212:
213: void ptod(VL vl,VL dvl,P p,DP *pr)
214: {
215: int n,i,j,k;
216: VL tvl;
217: V v;
218: DL d;
219: MP m;
220: DCP dc;
221: DCP *w;
222: DP r,s,t,u;
223: P x,c;
224:
225: if ( !p )
226: *pr = 0;
227: else if ( OID(p) > O_P )
228: error("ptod : only polynomials can be converted.");
229: else {
230: for ( n = 0, tvl = dvl; tvl; tvl = NEXT(tvl), n++ );
231: if ( NUM(p) ) {
232: NEWDL(d,n);
233: NEWMP(m); m->dl = d; C(m) = (Obj)p; NEXT(m) = 0; MKDP(n,m,*pr); (*pr)->sugar = 0;
234: } else {
235: for ( i = 0, tvl = dvl, v = VR(p);
236: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
237: if ( !tvl ) {
238: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
239: w = (DCP *)ALLOCA(k*sizeof(DCP));
240: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ )
241: w[j] = dc;
242:
243: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
244: ptod(vl,dvl,COEF(w[j]),&t); pwrp(vl,x,DEG(w[j]),&c);
245: muldc(vl,t,(Obj)c,&r); addd(vl,r,s,&t); s = t;
246: }
247: *pr = s;
248: } else {
249: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
250: w = (DCP *)ALLOCA(k*sizeof(DCP));
251: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ )
252: w[j] = dc;
253:
254: for ( j = k-1, s = 0; j >= 0; j-- ) {
255: ptod(vl,dvl,COEF(w[j]),&t);
1.2 noro 256: NEWDL(d,n); d->d[i] = ZTOS(DEG(w[j]));
1.1 noro 257: d->td = MUL_WEIGHT(d->d[i],i);
258: NEWMP(m); m->dl = d; C(m) = (Obj)ONE; NEXT(m) = 0; MKDP(n,m,u); u->sugar = d->td;
259: comm_muld(vl,t,u,&r); addd(vl,r,s,&t); s = t;
260: }
261: *pr = s;
262: }
263: }
264: }
265: #if 0
266: if ( !dp_fcoeffs && has_sfcoef(*pr) )
267: dp_fcoeffs = N_GFS;
268: #endif
269: }
270:
271: void dtop(VL vl,VL dvl,DP p,Obj *pr)
272: {
273: int n,i,j,k;
274: DL d;
275: MP m;
276: MP *a;
277: P r;
278: Obj t,w,s,u;
279: Z q;
280: VL tvl;
281:
282: if ( !p )
283: *pr = 0;
284: else {
285: for ( k = 0, m = BDY(p); m; m = NEXT(m), k++ );
286: a = (MP *)ALLOCA(k*sizeof(MP));
287: for ( j = 0, m = BDY(p); j < k; m = NEXT(m), j++ )
288: a[j] = m;
289:
290: for ( n = p->nv, j = k-1, s = 0; j >= 0; j-- ) {
291: m = a[j];
292: t = C(m);
293: if ( NUM(t) && NID((Num)t) == N_M ) {
294: mptop((P)t,(P *)&u); t = u;
295: }
296: for ( i = 0, d = m->dl, tvl = dvl;
297: i < n; tvl = NEXT(tvl), i++ ) {
1.2 noro 298: MKV(tvl->v,r); STOZ(d->d[i],q); pwrp(vl,r,q,(P *)&u);
1.1 noro 299: arf_mul(vl,t,(Obj)u,&w); t = w;
300: }
301: arf_add(vl,s,t,&u); s = u;
302: }
303: *pr = s;
304: }
305: }
306:
307: void nodetod(NODE node,DP *dp)
308: {
309: NODE t;
310: int len,i,td;
311: Q e;
312: DL d;
313: MP m;
314: DP u;
315:
316: for ( t = node, len = 0; t; t = NEXT(t), len++ );
317: NEWDL(d,len);
318: for ( t = node, i = 0, td = 0; i < len; t = NEXT(t), i++ ) {
319: e = (Q)BDY(t);
320: if ( !e )
321: d->d[i] = 0;
322: else if ( !NUM(e) || !RATN(e) || !INT(e) )
323: error("nodetod : invalid input");
324: else {
1.2 noro 325: d->d[i] = ZTOS((Q)e); td += MUL_WEIGHT(d->d[i],i);
1.1 noro 326: }
327: }
328: d->td = td;
329: NEWMP(m); m->dl = d; C(m) = (Obj)ONE; NEXT(m) = 0;
330: MKDP(len,m,u); u->sugar = td; *dp = u;
331: }
332:
333: void nodetodpm(NODE node,Obj pos,DPM *dp)
334: {
335: NODE t;
1.9 noro 336: int len,i,td,p;
1.1 noro 337: Q e;
338: DL d;
339: DMM m;
340: DPM u;
341:
342: for ( t = node, len = 0; t; t = NEXT(t), len++ );
343: NEWDL(d,len);
344: for ( t = node, i = 0, td = 0; i < len; t = NEXT(t), i++ ) {
345: e = (Q)BDY(t);
346: if ( !e )
347: d->d[i] = 0;
348: else if ( !NUM(e) || !RATN(e) || !INT(e) )
349: error("nodetodpm : invalid input");
350: else {
1.2 noro 351: d->d[i] = ZTOS((Q)e); td += MUL_WEIGHT(d->d[i],i);
1.1 noro 352: }
353: }
354: d->td = td;
1.9 noro 355: p = ZTOS((Q)pos);
1.19 noro 356: if ( dp_current_spec->module_top_weight ) {
1.9 noro 357: if ( p > dp_current_spec->module_rank )
358: error("nodetodpm : inconsistent order spec");
359: d->td += dp_current_spec->module_top_weight[p-1];
360: }
361: NEWDMM(m); m->dl = d; m->pos = p; C(m) = (Obj)ONE; NEXT(m) = 0;
1.1 noro 362: MKDPM(len,m,u); u->sugar = td; *dp = u;
363: }
364:
365: void dtodpm(DP d,int pos,DPM *dp)
366: {
367: DMM mr0,mr;
368: MP m;
1.9 noro 369: int shift;
1.1 noro 370:
371: if ( !d ) *dp = 0;
372: else {
1.9 noro 373: shift = 0;
1.19 noro 374: if ( dp_current_spec->module_top_weight ) {
1.9 noro 375: if ( pos > dp_current_spec->module_rank )
376: error("nodetodpm : inconsistent order spec");
377: shift = dp_current_spec->module_top_weight[pos-1];
378: }
1.1 noro 379: for ( m = BDY(d), mr0 = 0; m; m = NEXT(m) ) {
380: NEXTDMM(mr0,mr);
381: mr->dl = m->dl;
1.9 noro 382: mr->dl->td += shift;
1.1 noro 383: mr->pos = pos;
384: C(mr) = C(m);
385: }
386: MKDPM(d->nv,mr0,*dp); (*dp)->sugar = d->sugar;
387: }
388: }
389:
390: int sugard(MP m)
391: {
392: int s;
393:
394: for ( s = 0; m; m = NEXT(m) )
395: s = MAX(s,m->dl->td);
396: return s;
397: }
398:
399: void addd(VL vl,DP p1,DP p2,DP *pr)
400: {
401: int n;
402: MP m1,m2,mr=0,mr0;
403: Obj t;
404: DL d;
405:
406: if ( !p1 )
407: *pr = p2;
408: else if ( !p2 )
409: *pr = p1;
410: else {
411: if ( OID(p1) <= O_R ) {
412: n = NV(p2); NEWDL(d,n);
413: NEWMP(m1); m1->dl = d; C(m1) = (Obj)p1; NEXT(m1) = 0;
414: MKDP(n,m1,p1); (p1)->sugar = 0;
415: }
416: if ( OID(p2) <= O_R ) {
417: n = NV(p1); NEWDL(d,n);
418: NEWMP(m2); m2->dl = d; C(m2) = (Obj)p2; NEXT(m2) = 0;
419: MKDP(n,m2,p2); (p2)->sugar = 0;
420: }
421: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; )
422: switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {
423: case 0:
424: arf_add(vl,C(m1),C(m2),&t);
425: if ( t ) {
426: NEXTMP(mr0,mr); mr->dl = m1->dl; C(mr) = t;
427: }
428: m1 = NEXT(m1); m2 = NEXT(m2); break;
429: case 1:
430: NEXTMP(mr0,mr); mr->dl = m1->dl; C(mr) = C(m1);
431: m1 = NEXT(m1); break;
432: case -1:
433: NEXTMP(mr0,mr); mr->dl = m2->dl; C(mr) = C(m2);
434: m2 = NEXT(m2); break;
435: }
436: if ( !mr0 )
437: if ( m1 )
438: mr0 = m1;
439: else if ( m2 )
440: mr0 = m2;
441: else {
442: *pr = 0;
443: return;
444: }
445: else if ( m1 )
446: NEXT(mr) = m1;
447: else if ( m2 )
448: NEXT(mr) = m2;
449: else
450: NEXT(mr) = 0;
451: MKDP(NV(p1),mr0,*pr);
452: if ( *pr )
453: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
454: }
455: }
456:
457: /* for F4 symbolic reduction */
458:
459: void symb_addd(DP p1,DP p2,DP *pr)
460: {
461: int n;
462: MP m1,m2,mr=0,mr0;
463:
464: if ( !p1 )
465: *pr = p2;
466: else if ( !p2 )
467: *pr = p1;
468: else {
469: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
470: NEXTMP(mr0,mr); C(mr) = (Obj)ONE;
471: switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {
472: case 0:
473: mr->dl = m1->dl;
474: m1 = NEXT(m1); m2 = NEXT(m2); break;
475: case 1:
476: mr->dl = m1->dl;
477: m1 = NEXT(m1); break;
478: case -1:
479: mr->dl = m2->dl;
480: m2 = NEXT(m2); break;
481: }
482: }
483: if ( !mr0 )
484: if ( m1 )
485: mr0 = m1;
486: else if ( m2 )
487: mr0 = m2;
488: else {
489: *pr = 0;
490: return;
491: }
492: else if ( m1 )
493: NEXT(mr) = m1;
494: else if ( m2 )
495: NEXT(mr) = m2;
496: else
497: NEXT(mr) = 0;
498: MKDP(NV(p1),mr0,*pr);
499: if ( *pr )
500: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
501: }
502: }
503:
504: /*
505: * destructive merge of two list
506: *
507: * p1, p2 : list of DL
508: * return : a merged list
509: */
510:
511: NODE symb_merge(NODE m1,NODE m2,int n)
512: {
513: NODE top=0,prev,cur,m=0,t;
514: DL d1,d2;
515:
516: if ( !m1 )
517: return m2;
518: else if ( !m2 )
519: return m1;
520: else {
521: switch ( (*cmpdl)(n,(DL)BDY(m1),(DL)BDY(m2)) ) {
522: case 0:
523: top = m1; m = NEXT(m2);
524: break;
525: case 1:
526: top = m1; m = m2;
527: break;
528: case -1:
529: top = m2; m = m1;
530: break;
531: }
532: prev = top; cur = NEXT(top);
533: /* BDY(prev) > BDY(m) always holds */
534: while ( cur && m ) {
535: d1 = (DL)BDY(cur);
536: d2 = (DL)BDY(m);
537: #if 1
538: switch ( (*cmpdl)(n,(DL)BDY(cur),(DL)BDY(m)) ) {
539: #else
540: /* XXX only valid for DRL */
541: if ( d1->td > d2->td )
542: c = 1;
543: else if ( d1->td < d2->td )
544: c = -1;
545: else {
546: for ( i = n-1; i >= 0 && d1->d[i] == d2->d[i]; i-- );
547: if ( i < 0 )
548: c = 0;
549: else if ( d1->d[i] < d2->d[i] )
550: c = 1;
551: else
552: c = -1;
553: }
554: switch ( c ) {
555: #endif
556: case 0:
557: m = NEXT(m);
558: prev = cur; cur = NEXT(cur);
559: break;
560: case 1:
561: t = NEXT(cur); NEXT(cur) = m; m = t;
562: prev = cur; cur = NEXT(cur);
563: break;
564: case -1:
565: NEXT(prev) = m; m = cur;
566: prev = NEXT(prev); cur = NEXT(prev);
567: break;
568: }
569: }
570: if ( !cur )
571: NEXT(prev) = m;
572: return top;
573: }
574: }
575:
576: void _adddl(int n,DL d1,DL d2,DL d3)
577: {
578: int i;
579:
580: d3->td = d1->td+d2->td;
581: for ( i = 0; i < n; i++ )
582: d3->d[i] = d1->d[i]+d2->d[i];
583: }
584:
1.3 noro 585: void _addtodl(int n,DL d1,DL d2)
586: {
587: int i;
588:
589: d2->td += d1->td;
590: for ( i = 0; i < n; i++ )
591: d2->d[i] += d1->d[i];
592: }
593:
1.23 noro 594: void _subfromdl(int n,DL d1,DL d2)
595: {
596: int i;
597:
598: d2->td -= d1->td;
599: for ( i = 0; i < n; i++ )
600: d2->d[i] -= d1->d[i];
601: }
602:
1.3 noro 603: void _copydl(int n,DL d1,DL d2)
604: {
605: int i;
606:
607: d2->td = d1->td;
608: for ( i = 0; i < n; i++ )
609: d2->d[i] = d1->d[i];
610: }
611:
612: int _eqdl(int n,DL d1,DL d2)
613: {
614: int i;
615:
616: if ( d2->td != d1->td ) return 0;
617: for ( i = 0; i < n; i++ )
618: if ( d2->d[i] != d1->d[i] ) return 0;
619: return 1;
620: }
621:
1.1 noro 622: /* m1 <- m1 U dl*f, destructive */
623:
624: NODE mul_dllist(DL dl,DP f);
625:
626: NODE symb_mul_merge(NODE m1,DL dl,DP f,int n)
627: {
628: NODE top,prev,cur,n1;
629: DP g;
630: DL t,s;
631: MP m;
632:
633: if ( !m1 )
634: return mul_dllist(dl,f);
635: else if ( !f )
636: return m1;
637: else {
638: m = BDY(f);
639: NEWDL_NOINIT(t,n);
640: _adddl(n,m->dl,dl,t);
641: top = m1; prev = 0; cur = m1;
642: while ( m ) {
643: switch ( (*cmpdl)(n,(DL)BDY(cur),t) ) {
644: case 0:
645: prev = cur; cur = NEXT(cur);
646: if ( !cur ) {
647: MKDP(n,m,g);
648: NEXT(prev) = mul_dllist(dl,g);
649: return top;
650: }
651: m = NEXT(m);
652: if ( m ) _adddl(n,m->dl,dl,t);
653: break;
654: case 1:
655: prev = cur; cur = NEXT(cur);
656: if ( !cur ) {
657: MKDP(n,m,g);
658: NEXT(prev) = mul_dllist(dl,g);
659: return top;
660: }
661: break;
662: case -1:
663: NEWDL_NOINIT(s,n);
664: s->td = t->td;
665: bcopy(t->d,s->d,n*sizeof(int));
666: NEWNODE(n1);
667: n1->body = (pointer)s;
668: NEXT(n1) = cur;
669: if ( !prev ) {
670: top = n1; cur = n1;
671: } else {
672: NEXT(prev) = n1; prev = n1;
673: }
674: m = NEXT(m);
675: if ( m ) _adddl(n,m->dl,dl,t);
676: break;
677: }
678: }
679: return top;
680: }
681: }
682:
683: DLBUCKET symb_merge_bucket(DLBUCKET m1,DLBUCKET m2,int n)
684: {
685: DLBUCKET top,prev,cur,m,t;
686:
687: if ( !m1 )
688: return m2;
689: else if ( !m2 )
690: return m1;
691: else {
692: if ( m1->td == m2->td ) {
693: top = m1;
694: BDY(top) = symb_merge(BDY(top),BDY(m2),n);
695: m = NEXT(m2);
696: } else if ( m1->td > m2->td ) {
697: top = m1; m = m2;
698: } else {
699: top = m2; m = m1;
700: }
701: prev = top; cur = NEXT(top);
702: /* prev->td > m->td always holds */
703: while ( cur && m ) {
704: if ( cur->td == m->td ) {
705: BDY(cur) = symb_merge(BDY(cur),BDY(m),n);
706: m = NEXT(m);
707: prev = cur; cur = NEXT(cur);
708: } else if ( cur->td > m->td ) {
709: t = NEXT(cur); NEXT(cur) = m; m = t;
710: prev = cur; cur = NEXT(cur);
711: } else {
712: NEXT(prev) = m; m = cur;
713: prev = NEXT(prev); cur = NEXT(prev);
714: }
715: }
716: if ( !cur )
717: NEXT(prev) = m;
718: return top;
719: }
720: }
721:
722: void subd(VL vl,DP p1,DP p2,DP *pr)
723: {
724: DP t;
725:
726: if ( !p2 )
727: *pr = p1;
728: else {
729: chsgnd(p2,&t); addd(vl,p1,t,pr);
730: }
731: }
732:
733: void chsgnd(DP p,DP *pr)
734: {
735: MP m,mr=0,mr0;
736: Obj r;
737:
738: if ( !p )
739: *pr = 0;
740: else if ( OID(p) <= O_R ) {
741: arf_chsgn((Obj)p,&r); *pr = (DP)r;
742: } else {
743: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
744: NEXTMP(mr0,mr); arf_chsgn(C(m),&C(mr)); mr->dl = m->dl;
745: }
746: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
747: if ( *pr )
748: (*pr)->sugar = p->sugar;
749: }
750: }
751:
752: void muld(VL vl,DP p1,DP p2,DP *pr)
753: {
754: if ( ! do_weyl )
755: comm_muld(vl,p1,p2,pr);
756: else
757: weyl_muld(vl,p1,p2,pr);
758: }
759:
760: void comm_muld(VL vl,DP p1,DP p2,DP *pr)
761: {
762: MP m;
763: DP s,t,u;
764: int i,l,l1;
765: static MP *w;
766: static int wlen;
767:
768: if ( !p1 || !p2 )
769: *pr = 0;
770: else if ( OID(p1) != O_DP )
771: muldc(vl,p2,(Obj)p1,pr);
772: else if ( OID(p2) != O_DP )
773: muldc(vl,p1,(Obj)p2,pr);
774: else {
775: for ( m = BDY(p1), l1 = 0; m; m = NEXT(m), l1++ );
776: for ( m = BDY(p2), l = 0; m; m = NEXT(m), l++ );
777: if ( l1 < l ) {
778: t = p1; p1 = p2; p2 = t;
779: l = l1;
780: }
781: if ( l > wlen ) {
782: if ( w ) GCFREE(w);
783: w = (MP *)MALLOC(l*sizeof(MP));
784: wlen = l;
785: }
786: for ( m = BDY(p2), i = 0; i < l; m = NEXT(m), i++ )
787: w[i] = m;
788: for ( s = 0, i = l-1; i >= 0; i-- ) {
789: muldm(vl,p1,w[i],&t); addd(vl,s,t,&u); s = u;
790: }
791: bzero(w,l*sizeof(MP));
792: *pr = s;
793: }
794: }
795:
796: /* discard terms which is not a multiple of dl */
797:
798: void comm_muld_trunc(VL vl,DP p1,DP p2,DL dl,DP *pr)
799: {
800: MP m;
801: DP s,t,u;
802: int i,l,l1;
803: static MP *w;
804: static int wlen;
805:
806: if ( !p1 || !p2 )
807: *pr = 0;
808: else if ( OID(p1) != O_DP )
809: muldc_trunc(vl,p2,(Obj)p1,dl,pr);
810: else if ( OID(p2) != O_DP )
811: muldc_trunc(vl,p1,(Obj)p2,dl,pr);
812: else {
813: for ( m = BDY(p1), l1 = 0; m; m = NEXT(m), l1++ );
814: for ( m = BDY(p2), l = 0; m; m = NEXT(m), l++ );
815: if ( l1 < l ) {
816: t = p1; p1 = p2; p2 = t;
817: l = l1;
818: }
819: if ( l > wlen ) {
820: if ( w ) GCFREE(w);
821: w = (MP *)MALLOC(l*sizeof(MP));
822: wlen = l;
823: }
824: for ( m = BDY(p2), i = 0; i < l; m = NEXT(m), i++ )
825: w[i] = m;
826: for ( s = 0, i = l-1; i >= 0; i-- ) {
827: muldm_trunc(vl,p1,w[i],dl,&t); addd(vl,s,t,&u); s = u;
828: }
829: bzero(w,l*sizeof(MP));
830: *pr = s;
831: }
832: }
833:
834: void comm_quod(VL vl,DP p1,DP p2,DP *pr)
835: {
836: MP m=0,m0;
837: DP s,t;
838: int i,n,sugar;
839: DL d1,d2,d;
840: Q a,b;
841:
842: if ( !p2 )
843: error("comm_quod : invalid input");
844: if ( !p1 )
845: *pr = 0;
846: else {
847: n = NV(p1);
848: d2 = BDY(p2)->dl;
849: m0 = 0;
850: sugar = p1->sugar;
851: while ( p1 ) {
852: d1 = BDY(p1)->dl;
853: NEWDL(d,n);
854: d->td = d1->td - d2->td;
855: for ( i = 0; i < n; i++ )
856: d->d[i] = d1->d[i]-d2->d[i];
857: NEXTMP(m0,m);
858: m->dl = d;
859: divq((Q)BDY(p1)->c,(Q)BDY(p2)->c,&a); chsgnq(a,&b);
860: C(m) = (Obj)b;
861: muldm_trunc(vl,p2,m,d2,&t);
862: addd(vl,p1,t,&s); p1 = s;
863: C(m) = (Obj)a;
864: }
865: if ( m0 ) {
866: NEXT(m) = 0; MKDP(n,m0,*pr);
867: } else
868: *pr = 0;
869: /* XXX */
870: if ( *pr )
871: (*pr)->sugar = sugar - d2->td;
872: }
873: }
874:
875: void muldm(VL vl,DP p,MP m0,DP *pr)
876: {
877: MP m,mr=0,mr0;
878: Obj c;
879: DL d;
880: int n;
881:
882: if ( !p )
883: *pr = 0;
884: else {
885: for ( mr0 = 0, m = BDY(p), c = C(m0), d = m0->dl, n = NV(p);
886: m; m = NEXT(m) ) {
887: NEXTMP(mr0,mr);
888: if ( NUM(C(m)) && RATN(C(m)) && NUM(c) && RATN(c) )
889: mulq((Q)C(m),(Q)c,(Q *)&C(mr));
890: else
891: arf_mul(vl,C(m),c,&C(mr));
892: adddl(n,m->dl,d,&mr->dl);
893: }
894: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
895: if ( *pr )
896: (*pr)->sugar = p->sugar + m0->dl->td;
897: }
898: }
899:
900: void muldm_trunc(VL vl,DP p,MP m0,DL dl,DP *pr)
901: {
902: MP m,mr=0,mr0;
903: Obj c;
904: DL d,tdl;
905: int n,i;
906:
907: if ( !p )
908: *pr = 0;
909: else {
910: n = NV(p);
911: NEWDL(tdl,n);
912: for ( mr0 = 0, m = BDY(p), c = C(m0), d = m0->dl;
913: m; m = NEXT(m) ) {
914: _adddl(n,m->dl,d,tdl);
915: for ( i = 0; i < n; i++ )
916: if ( tdl->d[i] < dl->d[i] )
917: break;
918: if ( i < n )
919: continue;
920: NEXTMP(mr0,mr);
921: mr->dl = tdl;
922: NEWDL(tdl,n);
923: if ( NUM(C(m)) && RATN(C(m)) && NUM(c) && RATN(c) )
924: mulq((Q)C(m),(Q)c,(Q *)&C(mr));
925: else
926: arf_mul(vl,C(m),(Obj)c,&C(mr));
927: }
928: if ( mr0 ) {
929: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
930: } else
931: *pr = 0;
932: if ( *pr )
933: (*pr)->sugar = p->sugar + m0->dl->td;
934: }
935: }
936:
937: void weyl_muld(VL vl,DP p1,DP p2,DP *pr)
938: {
939: MP m;
940: DP s,t,u;
941: int i,l;
942: static MP *w;
943: static int wlen;
944:
945: if ( !p1 || !p2 )
946: *pr = 0;
947: else if ( OID(p1) != O_DP )
948: muldc(vl,p2,(Obj)p1,pr);
949: else if ( OID(p2) != O_DP )
950: muldc(vl,p1,(Obj)p2,pr);
951: else {
952: for ( m = BDY(p1), l = 0; m; m = NEXT(m), l++ );
953: if ( l > wlen ) {
954: if ( w ) GCFREE(w);
955: w = (MP *)MALLOC(l*sizeof(MP));
956: wlen = l;
957: }
958: for ( m = BDY(p1), i = 0; i < l; m = NEXT(m), i++ )
959: w[i] = m;
960: for ( s = 0, i = l-1; i >= 0; i-- ) {
961: weyl_muldm(vl,w[i],p2,&t); addd(vl,s,t,&u); s = u;
962: }
963: bzero(w,l*sizeof(MP));
964: *pr = s;
965: }
966: }
967:
968: void actm(VL vl,int nv,MP m1,MP m2,DP *pr)
969: {
970: DL d1,d2,d;
971: int n2,i,j,k;
972: Z jq,c,c1;
973: MP m;
974: Obj t;
975:
976: d1 = m1->dl;
977: d2 = m2->dl;
978: for ( i = 0; i < nv; i++ )
979: if ( d1->d[i] > d2->d[i] ) {
980: *pr = 0; return;
981: }
982: NEWDL(d,nv);
983: c = ONE;
984: for ( i = 0; i < nv; i++ ) {
985: for ( j = d2->d[i], k = d1->d[i]; k > 0; k--, j-- ) {
1.2 noro 986: STOZ(j,jq); mulz(c,jq,&c1); c = c1;
1.1 noro 987: }
988: d->d[i] = d2->d[i]-d1->d[i];
989: }
990: arf_mul(vl,C(m1),C(m2),&t);
991: NEWMP(m);
992: arf_mul(vl,(Obj)c,t,&C(m));
993: m->dl = d;
994: MKDP(nv,m,*pr);
995: }
996:
997: void weyl_actd(VL vl,DP p1,DP p2,DP *pr)
998: {
999: int n;
1000: MP m1,m2;
1001: DP d,r,s;
1002:
1003: if ( !p1 || !p2 ) *pr = 0;
1004: else {
1005: n = NV(p1);
1006: r = 0;
1007: for ( m1 = BDY(p1); m1; m1 = NEXT(m1) )
1008: for ( m2 = BDY(p2); m2; m2 = NEXT(m2) ) {
1009: actm(vl,n,m1,m2,&d);
1010: addd(vl,r,d,&s); r = s;
1011: }
1012: *pr = r;
1013: }
1014: }
1015:
1016: /* monomial * polynomial */
1017:
1018: void weyl_muldm(VL vl,MP m0,DP p,DP *pr)
1019: {
1020: DP r,t,t1;
1021: MP m;
1022: DL d0;
1023: int n,n2,l,i,j,tlen;
1024: static MP *w,*psum;
1025: static struct cdl *tab;
1026: static int wlen;
1027: static int rtlen;
1028:
1029: if ( !p )
1030: *pr = 0;
1031: else {
1032: for ( m = BDY(p), l = 0; m; m = NEXT(m), l++ );
1033: if ( l > wlen ) {
1034: if ( w ) GCFREE(w);
1035: w = (MP *)MALLOC(l*sizeof(MP));
1036: wlen = l;
1037: }
1038: for ( m = BDY(p), i = 0; i < l; m = NEXT(m), i++ )
1039: w[i] = m;
1040:
1041: n = NV(p); n2 = n>>1;
1042: d0 = m0->dl;
1043: for ( i = 0, tlen = 1; i < n2; i++ )
1044: tlen *= d0->d[n2+i]+1;
1045: if ( tlen > rtlen ) {
1046: if ( tab ) GCFREE(tab);
1047: if ( psum ) GCFREE(psum);
1048: rtlen = tlen;
1049: tab = (struct cdl *)MALLOC(rtlen*sizeof(struct cdl));
1050: psum = (MP *)MALLOC(rtlen*sizeof(MP));
1051: }
1052: bzero(psum,tlen*sizeof(MP));
1053: for ( i = l-1; i >= 0; i-- ) {
1054: bzero(tab,tlen*sizeof(struct cdl));
1055: weyl_mulmm(vl,m0,w[i],n,tab,tlen);
1056: for ( j = 0; j < tlen; j++ ) {
1057: if ( tab[j].c ) {
1058: NEWMP(m); m->dl = tab[j].d; C(m) = (Obj)tab[j].c; NEXT(m) = psum[j];
1059: psum[j] = m;
1060: }
1061: }
1062: }
1063: for ( j = tlen-1, r = 0; j >= 0; j-- )
1064: if ( psum[j] ) {
1065: MKDP(n,psum[j],t); addd(vl,r,t,&t1); r = t1;
1066: }
1067: if ( r )
1068: r->sugar = p->sugar + m0->dl->td;
1069: *pr = r;
1070: }
1071: }
1072:
1073: /* m0 = x0^d0*x1^d1*... * dx0^e0*dx1^e1*... */
1074: /* rtab : array of length (e0+1)*(e1+1)*... */
1075:
1076: void weyl_mulmm(VL vl,MP m0,MP m1,int n,struct cdl *rtab,int rtablen)
1077: {
1078: Obj c,c0,c1;
1079: DL d,d0,d1,dt;
1080: int i,j,a,b,k,l,n2,s,min,curlen;
1081: struct cdl *p;
1082: static Z *ctab;
1083: static struct cdl *tab;
1084: static int tablen;
1085: static struct cdl *tmptab;
1086: static int tmptablen;
1087:
1088:
1089: if ( !m0 || !m1 ) {
1090: rtab[0].c = 0;
1091: rtab[0].d = 0;
1092: return;
1093: }
1094: c0 = C(m0); c1 = C(m1);
1095: arf_mul(vl,c0,c1,&c);
1096: d0 = m0->dl; d1 = m1->dl;
1097: n2 = n>>1;
1098: curlen = 1;
1099: NEWDL(d,n);
1100: if ( n & 1 )
1101: /* offset of h-degree */
1102: d->td = d->d[n-1] = d0->d[n-1]+d1->d[n-1];
1103: else
1104: d->td = 0;
1105: rtab[0].c = c;
1106: rtab[0].d = d;
1107:
1108: if ( rtablen > tmptablen ) {
1109: if ( tmptab ) GCFREE(tmptab);
1110: tmptab = (struct cdl *)MALLOC(rtablen*sizeof(struct cdl));
1111: tmptablen = rtablen;
1112: }
1113: for ( i = 0; i < n2; i++ ) {
1114: a = d0->d[i]; b = d1->d[n2+i];
1115: k = d0->d[n2+i]; l = d1->d[i];
1116:
1117: /* degree of xi^a*(Di^k*xi^l)*Di^b */
1118: a += l;
1119: b += k;
1120: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
1121:
1122: if ( !k || !l ) {
1123: for ( j = 0, p = rtab; j < curlen; j++, p++ ) {
1124: if ( p->c ) {
1125: dt = p->d;
1126: dt->d[i] = a;
1127: dt->d[n2+i] = b;
1128: dt->td += s;
1129: }
1130: }
1131: curlen *= k+1;
1132: continue;
1133: }
1134: if ( k+1 > tablen ) {
1135: if ( tab ) GCFREE(tab);
1136: if ( ctab ) GCFREE(ctab);
1137: tablen = k+1;
1138: tab = (struct cdl *)MALLOC(tablen*sizeof(struct cdl));
1139: ctab = (Z *)MALLOC(tablen*sizeof(Q));
1140: }
1141: /* compute xi^a*(Di^k*xi^l)*Di^b */
1142: min = MIN(k,l);
1143: mkwc(k,l,ctab);
1144: bzero(tab,(k+1)*sizeof(struct cdl));
1145: if ( n & 1 )
1146: for ( j = 0; j <= min; j++ ) {
1147: NEWDL(d,n);
1148: d->d[i] = a-j; d->d[n2+i] = b-j;
1149: d->td = s;
1150: d->d[n-1] = s-(MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i));
1151: tab[j].d = d;
1152: tab[j].c = (Obj)ctab[j];
1153: }
1154: else
1155: for ( j = 0; j <= min; j++ ) {
1156: NEWDL(d,n);
1157: d->d[i] = a-j; d->d[n2+i] = b-j;
1158: d->td = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i); /* XXX */
1159: tab[j].d = d;
1160: tab[j].c = (Obj)ctab[j];
1161: }
1162: bzero(ctab,(min+1)*sizeof(Q));
1163: comm_muld_tab(vl,n,rtab,curlen,tab,k+1,tmptab);
1164: curlen *= k+1;
1165: bcopy(tmptab,rtab,curlen*sizeof(struct cdl));
1166: }
1167: }
1168:
1169: /* direct product of two cdl tables
1170: rt[] = [
1171: t[0]*t1[0],...,t[n-1]*t1[0],
1172: t[0]*t1[1],...,t[n-1]*t1[1],
1173: ...
1174: t[0]*t1[n1-1],...,t[n-1]*t1[n1-1]
1175: ]
1176: */
1177:
1178: void comm_muld_tab(VL vl,int nv,struct cdl *t,int n,struct cdl *t1,int n1,struct cdl *rt)
1179: {
1180: int i,j;
1181: struct cdl *p;
1182: Obj c;
1183: DL d;
1184:
1185: bzero(rt,n*n1*sizeof(struct cdl));
1186: for ( j = 0, p = rt; j < n1; j++ ) {
1187: c = (Obj)t1[j].c;
1188: d = t1[j].d;
1189: if ( !c )
1190: break;
1191: for ( i = 0; i < n; i++, p++ ) {
1192: if ( t[i].c ) {
1193: arf_mul(vl,(Obj)t[i].c,c,(Obj *)&p->c);
1194: adddl(nv,t[i].d,d,&p->d);
1195: }
1196: }
1197: }
1198: }
1199:
1200: void muldc(VL vl,DP p,Obj c,DP *pr)
1201: {
1202: MP m,mr=0,mr0;
1203:
1204: if ( !p || !c )
1205: *pr = 0;
1206: else if ( NUM(c) && UNIQ((Q)c) )
1207: *pr = p;
1208: else if ( NUM(c) && MUNIQ((Q)c) )
1209: chsgnd(p,pr);
1210: else {
1211: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
1212: NEXTMP(mr0,mr);
1213: if ( NUM(C(m)) && RATN(C(m)) && NUM(c) && RATN(c) )
1214: mulq((Q)C(m),(Q)c,(Q *)&C(mr));
1215: else
1216: arf_mul(vl,C(m),c,&C(mr));
1217: mr->dl = m->dl;
1218: }
1219: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
1220: if ( *pr )
1221: (*pr)->sugar = p->sugar;
1222: }
1223: }
1224:
1225: void divdc(VL vl,DP p,Obj c,DP *pr)
1226: {
1227: Obj inv;
1228:
1229: arf_div(vl,(Obj)ONE,c,&inv);
1230: muld(vl,p,(DP)inv,pr);
1231: }
1232:
1233: void muldc_trunc(VL vl,DP p,Obj c,DL dl,DP *pr)
1234: {
1235: MP m,mr=0,mr0;
1236: DL mdl;
1237: int i,n;
1238:
1239: if ( !p || !c ) {
1240: *pr = 0; return;
1241: }
1242: n = NV(p);
1243: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
1244: mdl = m->dl;
1245: for ( i = 0; i < n; i++ )
1246: if ( mdl->d[i] < dl->d[i] )
1247: break;
1248: if ( i < n )
1249: break;
1250: NEXTMP(mr0,mr);
1251: if ( NUM(C(m)) && RATN(C(m)) && NUM(c) && RATN(c) )
1252: mulq((Q)C(m),(Q)c,(Q *)&C(mr));
1253: else
1254: arf_mul(vl,C(m),c,&C(mr));
1255: mr->dl = m->dl;
1256: }
1257: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
1258: if ( *pr )
1259: (*pr)->sugar = p->sugar;
1260: }
1261:
1262: void divsdc(VL vl,DP p,P c,DP *pr)
1263: {
1264: MP m,mr=0,mr0;
1265:
1266: if ( !c )
1267: error("disvsdc : division by 0");
1268: else if ( !p )
1269: *pr = 0;
1270: else if ( OID(c) > O_P )
1271: error("divsdc : invalid argument");
1272: else {
1273: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
1274: NEXTMP(mr0,mr); divsp(vl,(P)C(m),c,(P *)&C(mr)); mr->dl = m->dl;
1275: }
1276: NEXT(mr) = 0; MKDP(NV(p),mr0,*pr);
1277: if ( *pr )
1278: (*pr)->sugar = p->sugar;
1279: }
1280: }
1281:
1282: void adddl(int n,DL d1,DL d2,DL *dr)
1283: {
1284: DL dt;
1285: int i;
1286:
1287: *dr = dt = (DL)MALLOC_ATOMIC((n+1)*sizeof(int));
1288: dt->td = d1->td + d2->td;
1289: for ( i = 0; i < n; i++ )
1290: dt->d[i] = d1->d[i]+d2->d[i];
1291: }
1292:
1293: /* d1 += d2 */
1294:
1295: void adddl_destructive(int n,DL d1,DL d2)
1296: {
1297: int i;
1298:
1299: d1->td += d2->td;
1300: for ( i = 0; i < n; i++ )
1301: d1->d[i] += d2->d[i];
1302: }
1303:
1304: int compd(VL vl,DP p1,DP p2)
1305: {
1306: int n,t;
1307: MP m1,m2;
1308:
1309: if ( !p1 )
1310: return p2 ? -1 : 0;
1311: else if ( !p2 )
1312: return 1;
1313: else if ( NV(p1) != NV(p2) ) {
1314: error("compd : size mismatch");
1315: return 0; /* XXX */
1316: } else {
1317: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2);
1318: m1 && m2; m1 = NEXT(m1), m2 = NEXT(m2) )
1319: if ( (t = (*cmpdl)(n,m1->dl,m2->dl)) ||
1320: (t = arf_comp(vl,C(m1),C(m2)) ) )
1321: return t;
1322: if ( m1 )
1323: return 1;
1324: else if ( m2 )
1325: return -1;
1326: else
1327: return 0;
1328: }
1329: }
1330:
1331: int cmpdl_lex(int n,DL d1,DL d2)
1332: {
1333: int i;
1334:
1335: for ( i = 0; i < n && d1->d[i] == d2->d[i]; i++ );
1336: return i == n ? 0 : (d1->d[i] > d2->d[i] ? 1 : -1);
1337: }
1338:
1339: int cmpdl_revlex(int n,DL d1,DL d2)
1340: {
1341: int i;
1342:
1343: for ( i = n - 1; i >= 0 && d1->d[i] == d2->d[i]; i-- );
1344: return i < 0 ? 0 : (d1->d[i] < d2->d[i] ? 1 : -1);
1345: }
1346:
1347: int cmpdl_gradlex(int n,DL d1,DL d2)
1348: {
1349: if ( d1->td > d2->td )
1350: return 1;
1351: else if ( d1->td < d2->td )
1352: return -1;
1353: else
1354: return cmpdl_lex(n,d1,d2);
1355: }
1356:
1357: int cmpdl_revgradlex(int n,DL d1,DL d2)
1358: {
1359: register int i,c;
1360: register int *p1,*p2;
1361:
1362: if ( d1->td > d2->td )
1363: return 1;
1364: else if ( d1->td < d2->td )
1365: return -1;
1366: else {
1367: i = n-1;
1368: p1 = d1->d+n-1;
1369: p2 = d2->d+n-1;
1370: while ( i >= 7 ) {
1371: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1372: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1373: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1374: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1375: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1376: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1377: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1378: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1379: i -= 8;
1380: }
1381: switch ( i ) {
1382: case 6:
1383: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1384: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1385: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1386: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1387: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1388: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1389: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1390: return 0;
1391: case 5:
1392: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1393: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1394: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1395: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1396: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1397: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1398: return 0;
1399: case 4:
1400: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1401: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1402: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1403: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1404: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1405: return 0;
1406: case 3:
1407: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1408: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1409: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1410: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1411: return 0;
1412: case 2:
1413: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1414: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1415: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1416: return 0;
1417: case 1:
1418: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1419: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1420: return 0;
1421: case 0:
1422: c = (*p1--) - (*p2--); if ( c ) goto LAST;
1423: return 0;
1424: default:
1425: return 0;
1426: }
1427: LAST:
1428: if ( c > 0 ) return -1;
1429: else return 1;
1430: }
1431: }
1432:
1433: int cmpdl_blex(int n,DL d1,DL d2)
1434: {
1435: int c;
1436:
1437: if ( (c = cmpdl_lex(n-1,d1,d2)) )
1438: return c;
1439: else {
1440: c = d1->d[n-1] - d2->d[n-1];
1441: return c > 0 ? 1 : c < 0 ? -1 : 0;
1442: }
1443: }
1444:
1445: int cmpdl_bgradlex(int n,DL d1,DL d2)
1446: {
1447: int e1,e2,c;
1448:
1449: e1 = d1->td - d1->d[n-1]; e2 = d2->td - d2->d[n-1];
1450: if ( e1 > e2 )
1451: return 1;
1452: else if ( e1 < e2 )
1453: return -1;
1454: else {
1455: c = cmpdl_lex(n-1,d1,d2);
1456: if ( c )
1457: return c;
1458: else
1459: return d1->td > d2->td ? 1 : d1->td < d2->td ? -1 : 0;
1460: }
1461: }
1462:
1463: int cmpdl_brevgradlex(int n,DL d1,DL d2)
1464: {
1465: int e1,e2,c;
1466:
1467: e1 = d1->td - d1->d[n-1]; e2 = d2->td - d2->d[n-1];
1468: if ( e1 > e2 )
1469: return 1;
1470: else if ( e1 < e2 )
1471: return -1;
1472: else {
1473: c = cmpdl_revlex(n-1,d1,d2);
1474: if ( c )
1475: return c;
1476: else
1477: return d1->td > d2->td ? 1 : d1->td < d2->td ? -1 : 0;
1478: }
1479: }
1480:
1481: int cmpdl_brevrev(int n,DL d1,DL d2)
1482: {
1483: int e1,e2,f1,f2,c,i;
1484:
1485: for ( i = 0, e1 = 0, e2 = 0; i < dp_nelim; i++ ) {
1486: e1 += d1->d[i]; e2 += d2->d[i];
1487: }
1488: f1 = d1->td - e1; f2 = d2->td - e2;
1489: if ( e1 > e2 )
1490: return 1;
1491: else if ( e1 < e2 )
1492: return -1;
1493: else {
1494: c = cmpdl_revlex(dp_nelim,d1,d2);
1495: if ( c )
1496: return c;
1497: else if ( f1 > f2 )
1498: return 1;
1499: else if ( f1 < f2 )
1500: return -1;
1501: else {
1502: for ( i = n - 1; i >= dp_nelim && d1->d[i] == d2->d[i]; i-- );
1503: return i < dp_nelim ? 0 : (d1->d[i] < d2->d[i] ? 1 : -1);
1504: }
1505: }
1506: }
1507:
1508: int cmpdl_bgradrev(int n,DL d1,DL d2)
1509: {
1510: int e1,e2,f1,f2,c,i;
1511:
1512: for ( i = 0, e1 = 0, e2 = 0; i < dp_nelim; i++ ) {
1513: e1 += d1->d[i]; e2 += d2->d[i];
1514: }
1515: f1 = d1->td - e1; f2 = d2->td - e2;
1516: if ( e1 > e2 )
1517: return 1;
1518: else if ( e1 < e2 )
1519: return -1;
1520: else {
1521: c = cmpdl_lex(dp_nelim,d1,d2);
1522: if ( c )
1523: return c;
1524: else if ( f1 > f2 )
1525: return 1;
1526: else if ( f1 < f2 )
1527: return -1;
1528: else {
1529: for ( i = n - 1; i >= dp_nelim && d1->d[i] == d2->d[i]; i-- );
1530: return i < dp_nelim ? 0 : (d1->d[i] < d2->d[i] ? 1 : -1);
1531: }
1532: }
1533: }
1534:
1535: int cmpdl_blexrev(int n,DL d1,DL d2)
1536: {
1537: int e1,e2,f1,f2,c,i;
1538:
1539: for ( i = 0, e1 = 0, e2 = 0; i < dp_nelim; i++ ) {
1540: e1 += d1->d[i]; e2 += d2->d[i];
1541: }
1542: f1 = d1->td - e1; f2 = d2->td - e2;
1543: c = cmpdl_lex(dp_nelim,d1,d2);
1544: if ( c )
1545: return c;
1546: else if ( f1 > f2 )
1547: return 1;
1548: else if ( f1 < f2 )
1549: return -1;
1550: else {
1551: for ( i = n - 1; i >= dp_nelim && d1->d[i] == d2->d[i]; i-- );
1552: return i < dp_nelim ? 0 : (d1->d[i] < d2->d[i] ? 1 : -1);
1553: }
1554: }
1555:
1556: int cmpdl_elim(int n,DL d1,DL d2)
1557: {
1558: int e1,e2,i;
1559:
1560: for ( i = 0, e1 = 0, e2 = 0; i < dp_nelim; i++ ) {
1561: e1 += d1->d[i]; e2 += d2->d[i];
1562: }
1563: if ( e1 > e2 )
1564: return 1;
1565: else if ( e1 < e2 )
1566: return -1;
1567: else
1568: return cmpdl_revgradlex(n,d1,d2);
1569: }
1570:
1571: int cmpdl_weyl_elim(int n,DL d1,DL d2)
1572: {
1573: int e1,e2,i;
1574:
1575: for ( i = 1, e1 = 0, e2 = 0; i <= dp_nelim; i++ ) {
1576: e1 += d1->d[n-i]; e2 += d2->d[n-i];
1577: }
1578: if ( e1 > e2 )
1579: return 1;
1580: else if ( e1 < e2 )
1581: return -1;
1582: else if ( d1->td > d2->td )
1583: return 1;
1584: else if ( d1->td < d2->td )
1585: return -1;
1586: else return -cmpdl_revlex(n,d1,d2);
1587: }
1588:
1589: /*
1590: a special ordering
1591: 1. total order
1592: 2. (-w,w) for the first 2*m variables
1593: 3. DRL for the first 2*m variables
1594: */
1595:
1596: extern int *current_weyl_weight_vector;
1597:
1598: int cmpdl_homo_ww_drl(int n,DL d1,DL d2)
1599: {
1600: int e1,e2,m,i;
1601: int *p1,*p2;
1602:
1603: if ( d1->td > d2->td )
1604: return 1;
1605: else if ( d1->td < d2->td )
1606: return -1;
1607:
1608: m = n>>1;
1609: for ( i = 0, e1 = e2 = 0, p1 = d1->d, p2 = d2->d; i < m; i++ ) {
1610: e1 += current_weyl_weight_vector[i]*(p1[m+i] - p1[i]);
1611: e2 += current_weyl_weight_vector[i]*(p2[m+i] - p2[i]);
1612: }
1613: if ( e1 > e2 )
1614: return 1;
1615: else if ( e1 < e2 )
1616: return -1;
1617:
1618: e1 = d1->td - d1->d[n-1];
1619: e2 = d2->td - d2->d[n-1];
1620: if ( e1 > e2 )
1621: return 1;
1622: else if ( e1 < e2 )
1623: return -1;
1624:
1625: for ( i= n - 1, p1 = d1->d+n-1, p2 = d2->d+n-1;
1626: i >= 0 && *p1 == *p2; i--, p1--, p2-- );
1627: return i < 0 ? 0 : (*p1 < *p2 ? 1 : -1);
1628: }
1629:
1630: int cmpdl_drl_zigzag(int n,DL d1,DL d2)
1631: {
1632: int i,t,m;
1633: int *p1,*p2;
1634:
1635: if ( d1->td > d2->td )
1636: return 1;
1637: else if ( d1->td < d2->td )
1638: return -1;
1639: else {
1640: m = n>>1;
1641: for ( i= m - 1, p1 = d1->d, p2 = d2->d; i >= 0; i-- ) {
1642: if ( (t = p1[m+i] - p2[m+i]) ) return t > 0 ? -1 : 1;
1643: if ( (t = p1[i] - p2[i]) ) return t > 0 ? -1 : 1;
1644: }
1645: return 0;
1646: }
1647: }
1648:
1649: int cmpdl_homo_ww_drl_zigzag(int n,DL d1,DL d2)
1650: {
1651: int e1,e2,m,i,t;
1652: int *p1,*p2;
1653:
1654: if ( d1->td > d2->td )
1655: return 1;
1656: else if ( d1->td < d2->td )
1657: return -1;
1658:
1659: m = n>>1;
1660: for ( i = 0, e1 = e2 = 0, p1 = d1->d, p2 = d2->d; i < m; i++ ) {
1661: e1 += current_weyl_weight_vector[i]*(p1[m+i] - p1[i]);
1662: e2 += current_weyl_weight_vector[i]*(p2[m+i] - p2[i]);
1663: }
1664: if ( e1 > e2 )
1665: return 1;
1666: else if ( e1 < e2 )
1667: return -1;
1668:
1669: e1 = d1->td - d1->d[n-1];
1670: e2 = d2->td - d2->d[n-1];
1671: if ( e1 > e2 )
1672: return 1;
1673: else if ( e1 < e2 )
1674: return -1;
1675:
1676: for ( i= m - 1, p1 = d1->d, p2 = d2->d; i >= 0; i-- ) {
1677: if ( (t = p1[m+i] - p2[m+i]) ) return t > 0 ? -1 : 1;
1678: if ( (t = p1[i] - p2[i]) ) return t > 0 ? -1 : 1;
1679: }
1680: return 0;
1681: }
1682:
1683: int cmpdl_order_pair(int n,DL d1,DL d2)
1684: {
1685: int e1,e2,i,j,l;
1686: int *t1,*t2;
1687: int len,head;
1688: struct order_pair *pair;
1689:
1690: len = dp_current_spec->ord.block.length;
1691: if ( n != dp_current_spec->nv )
1692: error("cmpdl_order_pair : incompatible order specification");
1693: pair = dp_current_spec->ord.block.order_pair;
1694:
1695: head = 0;
1696: for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {
1697: l = pair[i].length;
1698: switch ( pair[i].order ) {
1699: case 0:
1700: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
1701: e1 += MUL_WEIGHT(t1[j],head+j);
1702: e2 += MUL_WEIGHT(t2[j],head+j);
1703: }
1704: if ( e1 > e2 )
1705: return 1;
1706: else if ( e1 < e2 )
1707: return -1;
1708: else {
1709: for ( j = l - 1; j >= 0 && t1[j] == t2[j]; j-- );
1710: if ( j >= 0 )
1711: return t1[j] < t2[j] ? 1 : -1;
1712: }
1713: break;
1714: case 1:
1715: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
1716: e1 += MUL_WEIGHT(t1[j],head+j);
1717: e2 += MUL_WEIGHT(t2[j],head+j);
1718: }
1719: if ( e1 > e2 )
1720: return 1;
1721: else if ( e1 < e2 )
1722: return -1;
1723: else {
1724: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
1725: if ( j < l )
1726: return t1[j] > t2[j] ? 1 : -1;
1727: }
1728: break;
1729: case 2:
1730: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
1731: if ( j < l )
1732: return t1[j] > t2[j] ? 1 : -1;
1733: break;
1734: default:
1735: error("cmpdl_order_pair : invalid order"); break;
1736: }
1737: t1 += l; t2 += l; head += l;
1738: }
1739: return 0;
1740: }
1741:
1742: int cmpdl_composite(int nv,DL d1,DL d2)
1743: {
1744: int n,i,j,k,start,s,len;
1745: int *dw;
1746: struct sparse_weight *sw;
1747: struct weight_or_block *worb;
1748: int *w,*t1,*t2;
1749:
1750: n = dp_current_spec->ord.composite.length;
1751: worb = dp_current_spec->ord.composite.w_or_b;
1752: w = dp_dl_work;
1753: for ( i = 0, t1 = d1->d, t2 = d2->d; i < nv; i++ )
1754: w[i] = t1[i]-t2[i];
1755: for ( i = 0; i < n; i++, worb++ ) {
1756: len = worb->length;
1757: switch ( worb->type ) {
1758: case IS_DENSE_WEIGHT:
1759: dw = worb->body.dense_weight;
1760: for ( j = 0, s = 0; j < len; j++ )
1761: s += dw[j]*w[j];
1762: if ( s > 0 ) return 1;
1763: else if ( s < 0 ) return -1;
1764: break;
1765: case IS_SPARSE_WEIGHT:
1766: sw = worb->body.sparse_weight;
1767: for ( j = 0, s = 0; j < len; j++ )
1768: s += sw[j].value*w[sw[j].pos];
1769: if ( s > 0 ) return 1;
1770: else if ( s < 0 ) return -1;
1771: break;
1772: case IS_BLOCK:
1773: start = worb->body.block.start;
1774: switch ( worb->body.block.order ) {
1775: case 0:
1776: for ( j = 0, k = start, s = 0; j < len; j++, k++ ) {
1777: s += MUL_WEIGHT(w[k],k);
1778: }
1779: if ( s > 0 ) return 1;
1780: else if ( s < 0 ) return -1;
1781: else {
1782: for ( j = k-1; j >= start && w[j] == 0; j-- );
1783: if ( j >= start )
1784: return w[j] < 0 ? 1 : -1;
1785: }
1786: break;
1787: case 1:
1788: for ( j = 0, k = start, s = 0; j < len; j++, k++ ) {
1789: s += MUL_WEIGHT(w[k],k);
1790: }
1791: if ( s > 0 ) return 1;
1792: else if ( s < 0 ) return -1;
1793: else {
1794: for ( j = 0, k = start; j < len && w[j] == 0; j++, k++ );
1795: if ( j < len )
1796: return w[j] > 0 ? 1 : -1;
1797: }
1798: break;
1799: case 2:
1800: for ( j = 0, k = start; j < len && w[j] == 0; j++, k++ );
1801: if ( j < len )
1802: return w[j] > 0 ? 1 : -1;
1803: break;
1804: }
1805: break;
1806: }
1807: }
1808: return 0;
1809: }
1810:
1811: int cmpdl_matrix(int n,DL d1,DL d2)
1812: {
1813: int *v,*w,*t1,*t2;
1814: int s,i,j,len;
1815: int **matrix;
1816:
1817: for ( i = 0, t1 = d1->d, t2 = d2->d, w = dp_dl_work; i < n; i++ )
1818: w[i] = t1[i]-t2[i];
1819: len = dp_current_spec->ord.matrix.row;
1820: matrix = dp_current_spec->ord.matrix.matrix;
1821: for ( j = 0; j < len; j++ ) {
1822: v = matrix[j];
1823: for ( i = 0, s = 0; i < n; i++ )
1824: s += v[i]*w[i];
1825: if ( s > 0 )
1826: return 1;
1827: else if ( s < 0 )
1828: return -1;
1829: }
1830: return 0;
1831: }
1832:
1833: int cmpdl_top_weight(int n,DL d1,DL d2)
1834: {
1835: int *w;
1836: Z **mat;
1837: Z *a;
1838: mpz_t sum;
1839: int len,i,sgn,tsgn,row,k;
1840: int *t1,*t2;
1841:
1842: w = (int *)ALLOCA(n*sizeof(int));
1843: len = current_top_weight_len+3;
1844: t1 = d1->d; t2 = d2->d;
1845: for ( i = 0; i < n; i++ ) w[i] = t1[i]-t2[i];
1846: mpz_init_set_ui(sum,0);
1847: if ( OID(current_top_weight) == O_VECT ) {
1848: mat = (Z **)&BDY((VECT)current_top_weight);
1849: row = 1;
1850: } else {
1851: mat = (Z **)BDY((MAT)current_top_weight);
1852: row = ((MAT)current_top_weight)->row;
1853: }
1854: for ( k = 0; k < row; k++ ) {
1855: a = mat[k];
1856: for ( i = 0; i < n; i++ ) {
1857: if ( !a[i] || !w[i] ) continue;
1858: if ( w[i] > 0 )
1859: mpz_addmul_ui(sum,BDY(a[i]),(unsigned int)w[i]);
1860: else
1861: mpz_submul_ui(sum,BDY(a[i]),(unsigned int)(-w[i]));
1862: }
1863: sgn = mpz_sgn(sum);
1864: if ( sgn > 0 ) return 1;
1865: else if ( sgn < 0 ) return -1;
1866: }
1867: return (*cmpdl_tie_breaker)(n,d1,d2);
1868: }
1869:
1870: GeoBucket create_bucket()
1871: {
1872: GeoBucket g;
1873:
1874: g = CALLOC(1,sizeof(struct oGeoBucket));
1875: g->m = 32;
1876: return g;
1877: }
1878:
1879: int length(NODE d);
1880:
1881: void add_bucket(GeoBucket g,NODE d,int nv)
1882: {
1883: int l,k,m;
1884:
1885: l = length(d);
1886: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
1887: /* 2^(k-1) < l <= 2^k */
1888: d = symb_merge(g->body[k],d,nv);
1889: for ( ; length(d) > (1<<(k)); k++ ) {
1890: g->body[k] = 0;
1891: d = symb_merge(g->body[k+1],d,nv);
1892: }
1893: g->body[k] = d;
1894: g->m = MAX(g->m,k);
1895: }
1896:
1897: DL remove_head_bucket(GeoBucket g,int nv)
1898: {
1899: int j,i,c,m;
1900: DL d;
1901:
1902: j = -1;
1903: m = g->m;
1904: for ( i = 0; i <= m; i++ ) {
1905: if ( !g->body[i] )
1906: continue;
1907: if ( j < 0 ) j = i;
1908: else {
1909: c = (*cmpdl)(nv,g->body[i]->body,g->body[j]->body);
1910: if ( c > 0 )
1911: j = i;
1912: else if ( c == 0 )
1913: g->body[i] = NEXT(g->body[i]);
1914: }
1915: }
1916: if ( j < 0 )
1917: return 0;
1918: else {
1919: d = g->body[j]->body;
1920: g->body[j] = NEXT(g->body[j]);
1921: return d;
1922: }
1923: }
1924:
1925: /* DPV functions */
1926:
1927: void adddv(VL vl,DPV p1,DPV p2,DPV *pr)
1928: {
1929: int i,len;
1930: DP *e;
1931:
1932: if ( !p1 || !p2 )
1933: error("adddv : invalid argument");
1934: else if ( p1->len != p2->len )
1935: error("adddv : size mismatch");
1936: else {
1937: len = p1->len;
1938: e = (DP *)MALLOC(p1->len*sizeof(DP));
1939: for ( i = 0; i < len; i++ )
1940: addd(vl,p1->body[i],p2->body[i],&e[i]);
1941: MKDPV(len,e,*pr);
1942: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
1943: }
1944: }
1945:
1946: void subdv(VL vl,DPV p1,DPV p2,DPV *pr)
1947: {
1948: int i,len;
1949: DP *e;
1950:
1951: if ( !p1 || !p2 )
1952: error("subdv : invalid argument");
1953: else if ( p1->len != p2->len )
1954: error("subdv : size mismatch");
1955: else {
1956: len = p1->len;
1957: e = (DP *)MALLOC(p1->len*sizeof(DP));
1958: for ( i = 0; i < len; i++ )
1959: subd(vl,p1->body[i],p2->body[i],&e[i]);
1960: MKDPV(len,e,*pr);
1961: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
1962: }
1963: }
1964:
1965: void chsgndv(DPV p1,DPV *pr)
1966: {
1967: int i,len;
1968: DP *e;
1969:
1970: if ( !p1 )
1971: error("subdv : invalid argument");
1972: else {
1973: len = p1->len;
1974: e = (DP *)MALLOC(p1->len*sizeof(DP));
1975: for ( i = 0; i < len; i++ )
1976: chsgnd(p1->body[i],&e[i]);
1977: MKDPV(len,e,*pr);
1978: (*pr)->sugar = p1->sugar;
1979: }
1980: }
1981:
1982: void muldv(VL vl,DP p1,DPV p2,DPV *pr)
1983: {
1984: int i,len;
1985: DP *e;
1986:
1987: len = p2->len;
1988: e = (DP *)MALLOC(p2->len*sizeof(DP));
1989: if ( !p1 ) {
1990: MKDPV(len,e,*pr);
1991: (*pr)->sugar = 0;
1992: } else {
1993: for ( i = 0; i < len; i++ )
1994: muld(vl,p1,p2->body[i],&e[i]);
1995: MKDPV(len,e,*pr);
1996: (*pr)->sugar = p1->sugar + p2->sugar;
1997: }
1998: }
1999:
2000: int compdv(VL vl,DPV p1,DPV p2)
2001: {
2002: int i,t,len;
2003:
2004: if ( p1->len != p2->len ) {
2005: error("compdv : size mismatch");
2006: return 0; /* XXX */
2007: } else {
2008: len = p1->len;
2009: for ( i = 0; i < len; i++ )
2010: if ( (t = compd(vl,p1->body[i],p2->body[i])) )
2011: return t;
2012: return 0;
2013: }
2014: }
2015:
2016: int ni_next(int *a,int n)
2017: {
2018: int i,j,k,kj;
2019:
2020: /* find the first nonzero a[j] */
2021: for ( j = 0; j < n && a[j] == 0; j++ );
2022: /* find the first zero a[k] after a[j] */
2023: for ( k = j; k < n && a[k] == 1; k++ );
2024: if ( k == n ) return 0;
2025: /* a[0] = 0, ... , a[j-1] = 0, a[j] = 1, ..., a[k-1] = 1, a[k] = 0 */
2026: /* a[0] = 1,..., a[k-j-2] = 1, a[k-j-1] = 0, ..., a[k-1] = 0, a[k] = 1 */
2027: kj = k-j-1;
2028: for ( i = 0; i < kj; i++ ) a[i] = 1;
2029: for ( ; i < k; i++ ) a[i] = 0;
2030: a[k] = 1;
2031: return 1;
2032: }
2033:
2034: int comp_nbm(NBM a,NBM b)
2035: {
2036: int d,i,ai,bi;
2037: unsigned int *ab,*bb;
2038:
2039: if ( a->d > b->d ) return 1;
2040: else if ( a->d < b->d ) return -1;
2041: else {
2042: d = a->d; ab = a->b; bb = b->b;
2043: #if 0
2044: w = (d+31)/32;
2045: for ( i = 0; i < w; i++ )
2046: if ( ab[i] > bb[i] ) return 1;
2047: else if ( ab[i] < bb[i] ) return -1;
2048: #else
2049: for ( i = 0; i < d; i++ ) {
2050: ai = NBM_GET(ab,i);
2051: bi = NBM_GET(bb,i);
2052: if ( ai > bi ) return 1;
2053: else if ( ai < bi ) return -1;
2054: }
2055: #endif
2056: return 0;
2057: }
2058: }
2059:
2060: NBM mul_nbm(NBM a,NBM b)
2061: {
2062: int ad,bd,d,i,j;
2063: unsigned int *ab,*bb,*mb;
2064: NBM m;
2065:
2066: ad = a->d; bd = b->d; ab = a->b; bb = b->b;
2067: d = ad + bd;
2068: NEWNBM(m); NEWNBMBDY(m,d);
2069: m->d = d; mulp(CO,a->c,b->c,&m->c); mb = m->b;
2070: j = 0;
2071: for ( i = 0; i < ad; i++, j++ )
2072: if ( NBM_GET(ab,i) ) NBM_SET(mb,j);
2073: else NBM_CLR(mb,j);
2074: for ( i = 0; i < bd; i++, j++ )
2075: if ( NBM_GET(bb,i) ) NBM_SET(mb,j);
2076: else NBM_CLR(mb,j);
2077: return m;
2078: }
2079:
2080: NBP nbmtonbp(NBM m)
2081: {
2082: NODE n;
2083: NBP u;
2084:
2085: MKNODE(n,m,0);
2086: MKNBP(u,n);
2087: return u;
2088: }
2089:
2090: /* a=c*x*rest -> a0= x*rest, ah=x, ar=rest */
2091:
2092: P separate_nbm(NBM a,NBP *a0,NBP *ah,NBP *ar)
2093: {
2094: int i,d1;
2095: NBM t;
2096:
2097: if ( !a->d ) error("separate_nbm : invalid argument");
2098:
2099: if ( a0 ) {
2100: NEWNBM(t); t->d = a->d; t->b = a->b; t->c = (P)ONE;
2101: *a0 = nbmtonbp(t);
2102: }
2103:
2104: if ( ah ) {
2105: NEWNBM(t); NEWNBMBDY(t,1); t->d = 1; t->c = (P)ONE;
2106: if ( NBM_GET(a->b,0) ) NBM_SET(t->b,0);
2107: else NBM_CLR(t->b,0);
2108: *ah = nbmtonbp(t);
2109: }
2110:
2111: if ( ar ) {
2112: d1 = a->d-1;
2113: NEWNBM(t); NEWNBMBDY(t,d1); t->d = d1; t->c = (P)ONE;
2114: for ( i = 0; i < d1; i++ ) {
2115: if ( NBM_GET(a->b,i+1) ) NBM_SET(t->b,i);
2116: else NBM_CLR(t->b,i);
2117: }
2118: *ar = nbmtonbp(t);
2119: }
2120:
2121: return a->c;
2122: }
2123:
2124: /* a=c*rest*x -> a0= rest*x, ar=rest, at=x */
2125:
2126: P separate_tail_nbm(NBM a,NBP *a0,NBP *ar,NBP *at)
2127: {
2128: int i,d,d1;
2129: NBM t;
2130:
2131: if ( !(d=a->d) ) error("separate_tail_nbm : invalid argument");
2132:
2133: if ( a0 ) {
2134: NEWNBM(t); t->d = a->d; t->b = a->b; t->c = (P)ONE;
2135: *a0 = nbmtonbp(t);
2136: }
2137:
2138: d1 = a->d-1;
2139: if ( at ) {
2140: NEWNBM(t); NEWNBMBDY(t,1); t->d = 1; t->c = (P)ONE;
2141: if ( NBM_GET(a->b,d1) ) NBM_SET(t->b,0);
2142: else NBM_CLR(t->b,0);
2143: *at = nbmtonbp(t);
2144: }
2145:
2146: if ( ar ) {
2147: NEWNBM(t); NEWNBMBDY(t,d1); t->d = d1; t->c = (P)ONE;
2148: for ( i = 0; i < d1; i++ ) {
2149: if ( NBM_GET(a->b,i) ) NBM_SET(t->b,i);
2150: else NBM_CLR(t->b,i);
2151: }
2152: *ar = nbmtonbp(t);
2153: }
2154:
2155: return a->c;
2156: }
2157:
2158: NBP make_xky(int k)
2159: {
2160: int k1,i;
2161: NBM t;
2162:
2163: NEWNBM(t); NEWNBMBDY(t,k); t->d = k; t->c = (P)ONE;
2164: k1 = k-1;
2165: for ( i = 0; i < k1; i++ ) NBM_SET(t->b,i);
2166: NBM_CLR(t->b,i);
2167: return nbmtonbp(t);
2168: }
2169:
2170: /* a=c*x^(k-1)*y*rest -> a0= x^(k-1)*y*rest, ah=x^(k-1)*y, ar=rest */
2171:
2172: P separate_xky_nbm(NBM a,NBP *a0,NBP *ah,NBP *ar)
2173: {
2174: int i,d1,k,k1;
2175: NBM t;
2176:
2177: if ( !a->d )
2178: error("separate_nbm : invalid argument");
2179: for ( i = 0; i < a->d && NBM_GET(a->b,i); i++ );
2180: if ( i == a->d )
2181: error("separate_nbm : invalid argument");
2182: k1 = i;
2183: k = i+1;
2184:
2185: if ( a0 ) {
2186: NEWNBM(t); t->d = a->d; t->b = a->b; t->c = (P)ONE;
2187: *a0 = nbmtonbp(t);
2188: }
2189:
2190: if ( ah ) {
2191: NEWNBM(t); NEWNBMBDY(t,k); t->d = k; t->c = (P)ONE;
2192: for ( i = 0; i < k1; i++ ) NBM_SET(t->b,i);
2193: NBM_CLR(t->b,i);
2194: *ah = nbmtonbp(t);
2195: }
2196:
2197: if ( ar ) {
2198: d1 = a->d-k;
2199: NEWNBM(t); NEWNBMBDY(t,d1); t->d = d1; t->c = (P)ONE;
2200: for ( i = 0; i < d1; i++ ) {
2201: if ( NBM_GET(a->b,i+k) ) NBM_SET(t->b,i);
2202: else NBM_CLR(t->b,i);
2203: }
2204: *ar = nbmtonbp(t);
2205: }
2206:
2207: return a->c;
2208: }
2209:
2210: void shuffle_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp);
2211: void harmonic_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp);
2212: void mulnbmnbp(VL vl,NBM m,NBP p, NBP *rp);
2213: void mulnbpnbm(VL vl,NBP p,NBM m, NBP *rp);
2214:
2215: NBP shuffle_mul_nbm(NBM a,NBM b)
2216: {
2217: NBP u,a0,ah,ar,b0,bh,br,a1,b1,t;
2218: P ac,bc,c;
2219:
2220: if ( !a->d || !b->d )
2221: u = nbmtonbp(mul_nbm(a,b));
2222: else {
2223: ac = separate_nbm(a,&a0,&ah,&ar);
2224: bc = separate_nbm(b,&b0,&bh,&br);
2225: mulp(CO,ac,bc,&c);
2226: shuffle_mulnbp(CO,ar,b0,&t); mulnbp(CO,ah,t,&a1);
2227: shuffle_mulnbp(CO,a0,br,&t); mulnbp(CO,bh,t,&b1);
2228: addnbp(CO,a1,b1,&t); mulnbp(CO,(NBP)c,t,&u);
2229: }
2230: return u;
2231: }
2232:
2233: NBP harmonic_mul_nbm(NBM a,NBM b)
2234: {
2235: NBP u,a0,ah,ar,b0,bh,br,a1,b1,t,s,abk,ab1;
2236: P ac,bc,c;
2237:
2238: if ( !a->d || !b->d )
2239: u = nbmtonbp(mul_nbm(a,b));
2240: else {
2241: mulp(CO,a->c,b->c,&c);
2242: ac = separate_xky_nbm(a,&a0,&ah,&ar);
2243: bc = separate_xky_nbm(b,&b0,&bh,&br);
2244: mulp(CO,ac,bc,&c);
2245: harmonic_mulnbp(CO,ar,b0,&t); mulnbp(CO,ah,t,&a1);
2246: harmonic_mulnbp(CO,a0,br,&t); mulnbp(CO,bh,t,&b1);
2247: abk = make_xky(((NBM)BDY(BDY(ah)))->d+((NBM)BDY(BDY(bh)))->d);
2248: harmonic_mulnbp(CO,ar,br,&t); mulnbp(CO,abk,t,&ab1);
2249: addnbp(CO,a1,b1,&t); addnbp(CO,t,ab1,&s); mulnbp(CO,(NBP)c,s,&u);
2250: }
2251: return u;
2252:
2253: }
2254:
2255: void addnbp(VL vl,NBP p1,NBP p2, NBP *rp)
2256: {
2257: NODE b1,b2,br=0,br0;
2258: NBM m1,m2,m;
2259: P c;
2260:
2261: if ( !p1 )
2262: *rp = p2;
2263: else if ( !p2 )
2264: *rp = p1;
2265: else {
2266: for ( b1 = BDY(p1), b2 = BDY(p2), br0 = 0; b1 && b2; ) {
2267: m1 = (NBM)BDY(b1); m2 = (NBM)BDY(b2);
2268: switch ( comp_nbm(m1,m2) ) {
2269: case 0:
2270: addp(CO,m1->c,m2->c,&c);
2271: if ( c ) {
2272: NEXTNODE(br0,br);
2273: NEWNBM(m); m->d = m1->d; m->c = c; m->b = m1->b;
2274: BDY(br) = (pointer)m;
2275: }
2276: b1 = NEXT(b1); b2 = NEXT(b2); break;
2277: case 1:
2278: NEXTNODE(br0,br); BDY(br) = BDY(b1);
2279: b1 = NEXT(b1); break;
2280: case -1:
2281: NEXTNODE(br0,br); BDY(br) = BDY(b2);
2282: b2 = NEXT(b2); break;
2283: }
2284: }
2285: if ( !br0 )
2286: if ( b1 )
2287: br0 = b1;
2288: else if ( b2 )
2289: br0 = b2;
2290: else {
2291: *rp = 0;
2292: return;
2293: }
2294: else if ( b1 )
2295: NEXT(br) = b1;
2296: else if ( b2 )
2297: NEXT(br) = b2;
2298: else
2299: NEXT(br) = 0;
2300: MKNBP(*rp,br0);
2301: }
2302: }
2303:
2304: void subnbp(VL vl,NBP p1,NBP p2, NBP *rp)
2305: {
2306: NBP t;
2307:
2308: chsgnnbp(p2,&t);
2309: addnbp(vl,p1,t,rp);
2310: }
2311:
2312: void chsgnnbp(NBP p,NBP *rp)
2313: {
2314: NODE r0,r=0,b;
2315: NBM m,m1;
2316:
2317: for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
2318: NEXTNODE(r0,r);
2319: m = (NBM)BDY(b);
2320: NEWNBM(m1); m1->d = m->d; m1->b = m->b; chsgnp(m->c,&m1->c);
2321: BDY(r) = m1;
2322: }
2323: if ( r0 ) NEXT(r) = 0;
2324: MKNBP(*rp,r0);
2325: }
2326:
2327: void mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
2328: {
2329: NODE b,n;
2330: NBP r,t,s;
2331: NBM m;
2332:
2333: if ( !p1 || !p2 ) {
2334: *rp = 0; return;
2335: }
2336: if ( OID(p1) != O_NBP ) {
2337: if ( !POLY(p1) )
2338: error("mulnbp : invalid argument");
2339: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
2340: MKNODE(n,m,0); MKNBP(p1,n);
2341: }
2342: if ( OID(p2) != O_NBP ) {
2343: if ( !POLY(p2) )
2344: error("mulnbp : invalid argument");
2345: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
2346: MKNODE(n,m,0); MKNBP(p2,n);
2347: }
2348: if ( length(BDY(p1)) < length(BDY(p2)) ) {
2349: for ( r = 0, b = BDY(p1); b; b = NEXT(b) ) {
2350: mulnbmnbp(vl,(NBM)BDY(b),p2,&t);
2351: addnbp(vl,r,t,&s); r = s;
2352: }
2353: *rp = r;
2354: } else {
2355: for ( r = 0, b = BDY(p2); b; b = NEXT(b) ) {
2356: mulnbpnbm(vl,p1,(NBM)BDY(b),&t);
2357: addnbp(vl,r,t,&s); r = s;
2358: }
2359: *rp = r;
2360: }
2361: }
2362:
2363: void mulnbmnbp(VL vl,NBM m,NBP p, NBP *rp)
2364: {
2365: NODE b,r0,r=0;
2366:
2367: if ( !p ) *rp = 0;
2368: else {
2369: for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
2370: NEXTNODE(r0,r);
2371: BDY(r) = mul_nbm(m,(NBM)BDY(b));
2372: }
2373: if ( r0 ) NEXT(r) = 0;
2374: MKNBP(*rp,r0);
2375: }
2376: }
2377:
2378: void mulnbpnbm(VL vl,NBP p,NBM m, NBP *rp)
2379: {
2380: NODE b,r0,r=0;
2381:
2382: if ( !p ) *rp = 0;
2383: else {
2384: for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
2385: NEXTNODE(r0,r);
2386: BDY(r) = mul_nbm((NBM)BDY(b),m);
2387: }
2388: if ( r0 ) NEXT(r) = 0;
2389: MKNBP(*rp,r0);
2390: }
2391: }
2392:
2393: void pwrnbp(VL vl,NBP a,Z q,NBP *c)
2394: {
2395: NBP a1,a2;
2396: Z q1,r1,two;
2397: NBM m;
2398: NODE r;
2399:
2400: if ( !q ) {
2401: NEWNBM(m); m->d = 0; m->c = (P)ONE; m->b = 0;
2402: MKNODE(r,m,0); MKNBP(*c,r);
2403: } else if ( !a )
2404: *c = 0;
2405: else if ( UNIQ(q) )
2406: *c = a;
2407: else {
1.2 noro 2408: STOZ(2,two);
1.1 noro 2409: divqrz(q,two,&q1,&r1);
2410: pwrnbp(vl,a,q1,&a1);
2411: mulnbp(vl,a1,a1,&a2);
2412: if ( r1 )
2413: mulnbp(vl,a2,a,c);
2414: else
2415: *c = a2;
2416: }
2417: }
2418:
2419: int compnbp(VL vl,NBP p1,NBP p2)
2420: {
2421: NODE n1,n2;
2422: NBM m1,m2;
2423: int t;
2424:
2425: if ( !p1 )
2426: return p2 ? -1 : 0;
2427: else if ( !p2 )
2428: return 1;
2429: else {
2430: for ( n1 = BDY(p1), n2 = BDY(p2);
2431: n1 && n2; n1 = NEXT(n1), n2 = NEXT(n2) ) {
2432: m1 = (NBM)BDY(n1); m2 = (NBM)BDY(n2);
2433: if ( (t = comp_nbm(m1,m2)) || (t = compp(CO,m1->c,m2->c) ) )
2434: return t;
2435: }
2436: if ( n1 )
2437: return 1;
2438: else if ( n2 )
2439: return -1;
2440: else
2441: return 0;
2442: }
2443: }
2444:
2445: void shuffle_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
2446: {
2447: NODE b1,b2,n;
2448: NBP r,t,s;
2449: NBM m;
2450:
2451: if ( !p1 || !p2 ) {
2452: *rp = 0; return;
2453: }
2454: if ( OID(p1) != O_NBP ) {
2455: if ( !POLY(p1) )
2456: error("shuffle_mulnbp : invalid argument");
2457: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
2458: MKNODE(n,m,0); MKNBP(p1,n);
2459: }
2460: if ( OID(p2) != O_NBP ) {
2461: if ( !POLY(p2) )
2462: error("shuffle_mulnbp : invalid argument");
2463: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
2464: MKNODE(n,m,0); MKNBP(p2,n);
2465: }
2466: for ( r = 0, b1 = BDY(p1); b1; b1 = NEXT(b1) )
2467: for ( m = BDY(b1), b2 = BDY(p2); b2; b2 = NEXT(b2) ) {
2468: t = shuffle_mul_nbm(m,(NBM)BDY(b2));
2469: addnbp(vl,r,t,&s); r = s;
2470: }
2471: *rp = r;
2472: }
2473:
2474: void harmonic_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
2475: {
2476: NODE b1,b2,n;
2477: NBP r,t,s;
2478: NBM m;
2479:
2480: if ( !p1 || !p2 ) {
2481: *rp = 0; return;
2482: }
2483: if ( OID(p1) != O_NBP ) {
2484: if ( !POLY(p1) )
2485: error("harmonic_mulnbp : invalid argument");
2486: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
2487: MKNODE(n,m,0); MKNBP(p1,n);
2488: }
2489: if ( OID(p2) != O_NBP ) {
2490: if ( !POLY(p2) )
2491: error("harmonic_mulnbp : invalid argument");
2492: NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
2493: MKNODE(n,m,0); MKNBP(p2,n);
2494: }
2495: for ( r = 0, b1 = BDY(p1); b1; b1 = NEXT(b1) )
2496: for ( m = BDY(b1), b2 = BDY(p2); b2; b2 = NEXT(b2) ) {
2497: t = harmonic_mul_nbm(m,(NBM)BDY(b2));
2498: addnbp(vl,r,t,&s); r = s;
2499: }
2500: *rp = r;
2501: }
2502:
2503: #if 0
2504: NBP shuffle_mul_nbm(NBM a,NBM b)
2505: {
2506: int ad,bd,d,i,ai,bi,bit,s;
2507: int *ab,*bb,*wmb,*w;
2508: NBM wm,tm;
2509: P c,c1;
2510: NODE r,t,t1,p;
2511: NBP u;
2512:
2513: ad = a->d; bd = b->d; ab = a->b; bb = b->b;
2514: d = ad + bd;
2515: w = (int *)ALLOCA(d*sizeof(int));
2516: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2517: for ( i = 0; i < ad; i++ ) w[i] = 1;
2518: for ( ; i < d; i++ ) w[i] = 0;
2519: mulp(CO,a->c,b->c,&c);
2520: r = 0;
2521: do {
2522: wm->d = d; wm->c = c;
2523: ai = 0; bi = 0;
2524: for ( i = 0; i < d; i++ ) {
2525: if ( w[i] ) { bit = NBM_GET(ab,ai); ai++; }
2526: else { bit = NBM_GET(bb,bi); bi++; }
2527: if ( bit ) NBM_SET(wmb,i);
2528: else NBM_CLR(wmb,i);
2529: }
2530: for ( p = 0, t = r; t; p = t, t = NEXT(t) ) {
2531: tm = (NBM)BDY(t);
2532: s = comp_nbm(tm,wm);
2533: if ( s < 0 ) {
2534: /* insert */
2535: MKNODE(t1,wm,t);
2536: if ( !p ) r = t1;
2537: else NEXT(p) = t1;
2538: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2539: break;
2540: } else if ( s == 0 ) {
2541: /* add coefs */
2542: addp(CO,tm->c,c,&c1);
2543: if ( c1 ) tm->c = c1;
2544: else NEXT(p) = NEXT(t);
2545: break;
2546: }
2547: }
2548: if ( !t ) {
2549: /* append */
2550: MKNODE(t1,wm,t);
2551: if ( !p ) r = t1;
2552: else NEXT(p) = t1;
2553: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2554: }
2555: } while ( ni_next(w,d) );
2556: MKNBP(u,r);
2557: return u;
2558: }
2559:
2560: int nbmtoxky(NBM a,int *b)
2561: {
2562: int d,i,j,k;
2563: int *p;
2564:
2565: d = a->d; p = a->b;
2566: for ( i = j = 0, k = 1; i < d; i++ ) {
2567: if ( !NBM_GET(p,i) ) {
2568: b[j++] = k;
2569: k = 1;
2570: } else k++;
2571: }
2572: return j;
2573: }
2574:
2575: NBP harmonic_mul_nbm(NBM a,NBM b)
2576: {
2577: int da,db,d,la,lb,lmax,lmin,l,lab,la1,lb1,lab1;
2578: int i,j,k,ia,ib,s;
2579: int *wa,*wb,*w,*wab,*wa1,*wmb;
2580: P c,c1;
2581: NBM wm,tm;
2582: NODE r,t1,t,p;
2583: NBP u;
2584:
2585: da = a->d; db = b->d; d = da+db;
2586: wa = (int *)ALLOCA(da*sizeof(int));
2587: wb = (int *)ALLOCA(db*sizeof(int));
2588: la = nbmtoxky(a,wa);
2589: lb = nbmtoxky(b,wb);
2590: mulp(CO,a->c,b->c,&c);
2591: /* wa[0],..,wa[la-1] <-> x^wa[0]y x^wa[1]y .. */
2592: /* lmax : total length */
2593: lmax = la+lb;
2594: lmin = la>lb?la:lb;
2595: w = (int *)ALLOCA(lmax*sizeof(int));
2596: /* position of a+b */
2597: wab = (int *)ALLOCA(lmax*sizeof(int));
2598: /* position of a */
2599: wa1 = (int *)ALLOCA(lmax*sizeof(int));
2600: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2601: for ( l = lmin, r = 0; l <= lmax; l++ ) {
2602: lab = lmax - l;
2603: la1 = la - lab;
2604: lb1 = lb - lab;
2605: lab1 = l-lab;
2606: /* partion l into three parts: a, b, a+b */
2607: /* initialize wab */
2608: for ( i = 0; i < lab; i++ ) wab[i] = 1;
2609: for ( ; i < l; i++ ) wab[i] = 0;
2610: do {
2611: /* initialize wa1 */
2612: for ( i = 0; i < la1; i++ ) wa1[i] = 1;
2613: for ( ; i < lab1; i++ ) wa1[i] = 0;
2614: do {
2615: ia = 0; ib = 0;
2616: for ( i = j = 0; i < l; i++ )
2617: if ( wab[i] ) w[i] = wa[ia++]+wb[ib++];
2618: else if ( wa1[j++] ) w[i] = wa[ia++];
2619: else w[i] = wb[ib++];
2620: for ( i = j = 0; i < l; i++ ) {
2621: for ( k = w[i]-1; k > 0; k--, j++ ) NBM_SET(wmb,j);
2622: NBM_CLR(wmb,j); j++;
2623: }
2624: wm->d = j; wm->c = c;
2625: for ( p = 0, t = r; t; p = t, t = NEXT(t) ) {
2626: tm = (NBM)BDY(t);
2627: s = comp_nbm(tm,wm);
2628: if ( s < 0 ) {
2629: /* insert */
2630: MKNODE(t1,wm,t);
2631: if ( !p ) r = t1;
2632: else NEXT(p) = t1;
2633: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2634: break;
2635: } else if ( s == 0 ) {
2636: /* add coefs */
2637: addp(CO,tm->c,c,&c1);
2638: if ( c1 ) tm->c = c1;
2639: else NEXT(p) = NEXT(t);
2640: break;
2641: }
2642: }
2643: if ( !t ) {
2644: /* append */
2645: MKNODE(t1,wm,t);
2646: if ( !p ) r = t1;
2647: else NEXT(p) = t1;
2648: NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
2649: }
2650: } while ( ni_next(wa1,lab1) );
2651: } while ( ni_next(wab,l) );
2652: }
2653: MKNBP(u,r);
2654: return u;
2655: }
2656: #endif
2657:
2658: /* DPM functions */
2659:
1.3 noro 2660: DMMstack dmm_stack;
1.9 noro 2661: int dpm_base_ordtype;;
1.3 noro 2662:
1.9 noro 2663: DMMstack push_schreyer_order(LIST data,DMMstack stack)
1.3 noro 2664: {
2665: DMMstack t;
1.14 noro 2666: DP dp;
2667: MP mp;
2668: DMM m0,m1;
2669: DPM dpm0,dpm1;
2670: int len,i,nv;
1.7 noro 2671: NODE in,t1;
1.9 noro 2672: LIST l;
1.4 noro 2673:
2674: /* data = [DPM,...,DPM] */
1.9 noro 2675: if ( !dmm_stack && ( !dp_current_spec || dp_current_spec->id < 256 ) )
2676: error("push_schreyer_order : base module order is not set");
1.4 noro 2677: in = BDY(data);
2678: len = length(in);
2679: NEWDMMstack(t);
2680: t->rank = len;
2681: t->in = (DMM *)MALLOC((len+1)*sizeof(DMM));
1.14 noro 2682: t->sum = (DMM *)MALLOC((len+1)*sizeof(DMM));
1.9 noro 2683: if ( stack ) {
2684: MKNODE(t1,data,BDY(stack->obj)); MKLIST(l,t1); t->obj = l;
1.14 noro 2685: for ( i = 1; i <= len; i++, in = NEXT(in) ) {
2686: m1 = t->in[i] = BDY((DPM)BDY(in));
2687: NEWMP(mp); mp->dl = m1->dl; mp->c = m1->c; NEXT(mp) = 0;
2688: nv = ((DPM)BDY(in))->nv;
2689: MKDP(nv,mp,dp); dp->sugar = mp->dl->td;
2690: m0 = stack->sum[m1->pos]; MKDPM(nv,m0,dpm0);
2691: mulobjdpm(CO,(Obj)dp,dpm0,&dpm1);
2692: t->sum[i] = BDY(dpm1);
2693: }
1.9 noro 2694: } else {
2695: MKNODE(t1,data,0); MKLIST(l,t1); t->obj = l;
1.14 noro 2696: for ( i = 1; i <= len; i++, in = NEXT(in) ) {
2697: t->sum[i] = t->in[i] = BDY((DPM)BDY(in));
2698: }
1.4 noro 2699: }
1.9 noro 2700: t->next = stack;;
2701: dpm_ordtype = 3;
2702: return t;
1.4 noro 2703: }
2704:
2705: // data=[Ink,...,In0]
2706: // Ini = a list of module monomials
2707:
2708: void set_schreyer_order(LIST data)
2709: {
2710: NODE in;
2711: LIST *w;
2712: int i,len;
1.3 noro 2713:
2714: if ( !data ) {
2715: dmm_stack = 0;
2716: if ( dp_current_spec && dp_current_spec->id >= 256 )
1.9 noro 2717: dpm_ordtype = dp_current_spec->module_ordtype;
1.3 noro 2718: else
2719: dpm_ordtype = 0;
2720: return;
2721: } else {
1.9 noro 2722: if ( !dp_current_spec || dp_current_spec->id < 256 )
2723: error("set_schreyer_order : base module order is not set");
1.4 noro 2724: dmm_stack = 0;
1.9 noro 2725: dpm_base_ordtype = dp_current_spec->module_ordtype;
1.4 noro 2726: in = BDY(data);
1.3 noro 2727: len = length(in);
1.4 noro 2728: w = (LIST *)MALLOC(len*sizeof(LIST));
2729: for ( i = 0; i < len; i++, in = NEXT(in) ) w[i] = (LIST)BDY(in);
1.9 noro 2730: for ( i = len-1; i >= 0; i-- ) dmm_stack = push_schreyer_order(w[i],dmm_stack);
1.3 noro 2731: }
2732: }
2733:
1.15 noro 2734: void set_schreyer_level(DMMstack_array array,int level)
2735: {
2736: if ( !level ) {
2737: dmm_stack = 0;
2738: if ( dp_current_spec && dp_current_spec->id >= 256 )
2739: dpm_ordtype = dp_current_spec->module_ordtype;
2740: else
2741: dpm_ordtype = 0;
2742: return;
2743: } else {
2744: if ( !dp_current_spec || dp_current_spec->id < 256 )
2745: error("set_schreyer_level : base module order is not set");
2746: if ( level > array->len )
2747: error("set_schreyer_level : invalid level");
2748: dmm_stack = array->body[level-1];
2749: dpm_base_ordtype = dp_current_spec->module_ordtype;
2750: dpm_ordtype = 3;
2751: }
2752: }
2753:
1.4 noro 2754: // construct a base of syz(g)
2755: // assuming the schrerer order is properly set
2756:
2757: DP dpm_sp_hm(DPM p1,DPM p2);
2758: void dpm_sp(DPM p1,DPM p2,DPM *sp,DP *t1,DP *t2);
1.12 noro 2759: DPM dpm_nf_and_quotient3(DPM sp,VECT psv,DPM *nf,P *dn);
2760: DPM dpm_nf_and_quotient4(DPM sp,DPM *ps,VECT psiv,DPM head,DPM *nf,P *dn);
2761: DPM dpm_sp_nf(VECT psv,VECT psiv,int i,int j,DPM *nf);
1.19 noro 2762: DPM dpm_sp_nf_zlist(VECT psv,VECT psiv,int i,int j,int top,DPM *nf);
1.13 noro 2763: DPM dpm_sp_nf_asir(VECT psv,int i,int j,DPM *nf);
1.4 noro 2764: void dpm_sort(DPM p,DPM *r);
2765:
2766: extern int DP_Multiple;
1.22 noro 2767: extern int DP_Print;
1.4 noro 2768:
2769: void dpm_nf_z(NODE b,DPM g,VECT psv,int full,int multiple,DPM *rp);
2770: NODE dpm_sort_list(NODE l);
2771: void dpm_ptozp(DPM p,Z *cont,DPM *r);
2772:
2773: NODE dpm_reduceall(NODE in)
2774: {
2775: int n,i;
2776: VECT psv;
2777: DPM *ps;
2778: NODE t,t1;
2779: DPM g,r;
2780: Z cont;
2781:
2782: n = length(in);
2783: MKVECT(psv,n);
2784: ps = (DPM *)BDY(psv);
2785: for ( i = 0, t = in; i < n; i++, t = NEXT(t) ) ps[i] = BDY(t);
2786: for ( i = 0; i < n; i++ ) {
2787: g = ps[i]; ps[i] = 0;
1.8 noro 2788: // dpm_nf_z(0,g,psv,1,DP_Multiple,&ps[i]);
2789: dpm_nf_z(0,g,psv,1,0,&ps[i]);
1.4 noro 2790: }
2791: t = 0;
2792: for ( i = n-1; i >= 0; i-- ) {
2793: dpm_ptozp(ps[i],&cont,&r);
2794: MKNODE(t1,r,t); t = t1;
2795: }
2796: return t;
2797: }
2798:
1.8 noro 2799: struct oEGT egra;
2800:
1.9 noro 2801: void dpm_ht(DPM d,DPM *r);
1.16 noro 2802: NODE reverse_node(NODE b);
1.9 noro 2803:
1.12 noro 2804: void dpm_schreyer_base(LIST g,LIST *s)
2805: {
2806: NODE nd,t0,t,b0,b;
2807: int n,i,j,k,nv,max,pos;
2808: LIST l;
2809: DP h,t1,t2;
2810: MP d;
2811: DMM r0,r,r1;
2812: DPM sp,nf,dpm;
2813: DPM *ps;
2814: VECT psv,psiv;
2815: DPM quo;
1.16 noro 2816: DP *mm;
1.12 noro 2817: NODE *psi;
1.13 noro 2818: NODE n1,n2,n3;
2819: int p1,p2,p3;
2820: struct oEGT eg0,eg1,egsp,egnf;
1.12 noro 2821: extern struct oEGT egred;
1.15 noro 2822: extern int sch_count,schrec_count,schlast_count;
1.12 noro 2823:
1.15 noro 2824: sch_count = schlast_count= 0;
1.12 noro 2825: init_eg(&egra);
1.13 noro 2826: init_eg(&egsp);
2827: init_eg(&egnf);
1.12 noro 2828: nd = BDY(g);
2829: n = length(nd);
2830: MKVECT(psv,n+1);
2831: ps = (DPM *)BDY(psv);
2832: for ( i = 1, t = nd; i <= n; i++, t = NEXT(t) ) ps[i] = (DPM)BDY(t);
2833: for ( i = 1, max = 0; i <= n; i++ )
2834: if ( (pos=BDY(ps[i])->pos) > max ) max = pos;
2835: MKVECT(psiv,max+1);
2836: psi = (NODE *)BDY(psiv);
2837: for ( i = n; i >= 1; i-- ) {
2838: pos = BDY(ps[i])->pos;
2839: MKNODE(nd,(long)i,psi[pos]); psi[pos] = nd;
2840: }
2841: nv = ps[1]->nv;
1.16 noro 2842: mm = (DP *)MALLOC((n+1)*sizeof(DP));
1.12 noro 2843: b0 = 0;
1.13 noro 2844: get_eg(&eg0);
2845: for ( i = 1; i <= max; i++ ) {
1.16 noro 2846: memset(mm,0,(n+1)*sizeof(DP));
1.13 noro 2847: for ( n1 = psi[i]; n1; n1 = NEXT(n1) ) {
2848: p1 = (long)BDY(n1);
2849: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
2850: p2 = (long)BDY(n2);
1.16 noro 2851: mm[p2] = dpm_sp_hm(ps[p1],ps[p2]);
1.13 noro 2852: }
2853: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
2854: p2 = (long)BDY(n2);
1.16 noro 2855: if ( !mm[p2] ) continue;
2856: for ( h = mm[p2], n3 = NEXT(n1); n3; n3 = NEXT(n3) ) {
1.13 noro 2857: p3 = (long)BDY(n3);
1.16 noro 2858: if ( n3 != n2 && mm[p3] && dp_redble(mm[p3],h) ) mm[p3] = 0;
2859: }
2860: }
2861: for ( j = p1+1; j <= n; j++ ) {
2862: if ( mm[j] ) {
2863: quo = dpm_sp_nf(psv,psiv,p1,j,&nf);
2864: if ( nf )
2865: error("dpm_schreyer_base : cannot happen");
2866: NEXTNODE(b0,b); BDY(b) = (pointer)quo;
1.13 noro 2867: }
2868: }
2869: }
2870: }
2871: get_eg(&eg1); add_eg(&egsp,&eg0,&eg1); print_eg("SP",&egsp);
2872: get_eg(&eg0);
2873: get_eg(&eg1); add_eg(&egnf,&eg0,&eg1); print_eg("NF",&egnf); printf("\n");
1.12 noro 2874: if ( b0 ) NEXT(b) = 0;
1.17 noro 2875: for ( t0 = 0, nd = BDY(g); nd; nd = NEXT(nd) ) {
1.12 noro 2876: dpm_ht((DPM)BDY(nd),&dpm); NEXTNODE(t0,t); BDY(t) = (pointer)dpm;
2877: }
2878: if ( t0 ) NEXT(t) = 0;
2879: MKLIST(l,t0);
2880: dmm_stack = push_schreyer_order(l,dmm_stack);
1.16 noro 2881: // b0 = dpm_sort_list(b0);
1.12 noro 2882: // get_eg(&eg0);
2883: // b0 = dpm_reduceall(b0);
2884: // get_eg(&eg1); add_eg(&egra,&eg0,&eg1); print_eg("RA",&egra);
1.4 noro 2885: MKLIST(*s,b0);
1.8 noro 2886: // print_eg("red",&egred); printf("\n");
1.15 noro 2887: printf("sch_count=%d, schlast_count=%d\n",sch_count,schlast_count);
2888: }
2889:
1.17 noro 2890: void dpm_list_to_array(LIST g,VECT *psvect,VECT *psindvect)
2891: {
2892: NODE nd,t;
2893: int n;
2894: VECT psv,psiv;
2895: DPM *ps;
2896: int i,max,pos;
2897: LIST *psi;
2898: LIST l;
2899: Z iz;
2900:
2901: nd = BDY(g);
2902: n = length(nd);
2903: MKVECT(psv,n+1);
2904: ps = (DPM *)BDY(psv);
2905: for ( i = 1, t = nd; i <= n; i++, t = NEXT(t) ) ps[i] = (DPM)BDY(t);
2906: for ( i = 1, max = 0; i <= n; i++ )
2907: if ( (pos=BDY(ps[i])->pos) > max ) max = pos;
2908: MKVECT(psiv,max+1);
2909: psi = (LIST *)BDY(psiv);
2910: for ( i = 0; i <= max; i++ ) {
2911: MKLIST(l,0); psi[i] = l;
2912: }
2913: for ( i = n; i >= 1; i-- ) {
2914: pos = BDY(ps[i])->pos;
2915: STOZ(i,iz); MKNODE(nd,iz,BDY(psi[pos])); BDY(psi[pos]) = nd;
2916: }
2917: *psvect = psv; *psindvect = psiv;
2918: }
2919:
1.19 noro 2920: #if 0
1.17 noro 2921: void dpm_insert_to_zlist(VECT psiv,int pos,int i)
2922: {
2923: LIST l;
2924: NODE prev,cur,nd;
2925: int curi;
2926: Z iz;
2927:
2928: l = (LIST)BDY(psiv)[pos];
2929: for ( prev = 0, cur = BDY(l); cur; cur = NEXT(cur) ) {
2930: curi = ZTOS((Q)BDY(cur));
2931: if ( curi == i )
2932: error("dpm_insert_to_list : invalid index");
2933: if ( i < curi ) break;
2934: prev = cur;
2935: }
2936: STOZ(i,iz); MKNODE(nd,iz,cur);
2937: if ( prev == 0 ) BDY(l) = nd;
2938: else NEXT(prev) = nd;
2939: }
1.19 noro 2940: #else
2941: void dpm_insert_to_zlist(VECT psiv,int pos,int i)
2942: {
2943: LIST l;
2944: NODE prev,cur,nd;
2945: int curi;
2946: Z iz;
2947:
2948: l = (LIST)BDY(psiv)[pos];
2949: for ( prev = 0, cur = BDY(l); cur; cur = NEXT(cur) ) {
2950: curi = ZTOS((Q)BDY(cur));
2951: if ( curi == i )
2952: error("dpm_insert_to_list : invalid index");
2953: prev = cur;
2954: }
2955: STOZ(i,iz); MKNODE(nd,iz,cur);
2956: if ( prev == 0 ) BDY(l) = nd;
2957: else NEXT(prev) = nd;
2958: }
2959: #endif
1.17 noro 2960:
2961: void dpm_schreyer_base_zlist(LIST g,LIST *s)
2962: {
2963: NODE nd,t0,t,b0,b;
2964: int n,i,j,k,nv,max,pos;
2965: LIST l;
2966: DP h,t1,t2;
2967: MP d;
2968: DMM r0,r,r1;
2969: DPM sp,nf,dpm;
2970: DPM *ps;
2971: VECT psv,psiv;
2972: DPM quo;
2973: DP *mm;
2974: LIST *psi;
2975: NODE n1,n2,n3;
2976: int p1,p2,p3;
2977: Z iz;
2978: struct oEGT eg0,eg1,egsp,egnf;
2979: extern struct oEGT egred;
2980: extern int sch_count,schrec_count,schlast_count;
2981:
2982: sch_count = schlast_count= 0;
2983: init_eg(&egra);
2984: init_eg(&egsp);
2985: init_eg(&egnf);
2986: dpm_list_to_array(g,&psv,&psiv);
2987: ps = (DPM *)BDY(psv);
2988: psi = (LIST *)BDY(psiv);
2989: nv = ps[1]->nv;
2990: n = psv->len-1;
2991: max = psiv->len-1;
2992: mm = (DP *)MALLOC((n+1)*sizeof(DP));
2993: b0 = 0;
2994: get_eg(&eg0);
2995: for ( i = 1; i <= max; i++ ) {
2996: memset(mm,0,(n+1)*sizeof(DP));
2997: for ( n1 = BDY((LIST)psi[i]); n1; n1 = NEXT(n1) ) {
2998: p1 = ZTOS((Q)BDY(n1));
2999: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
3000: p2 = ZTOS((Q)BDY(n2));
3001: mm[p2] = dpm_sp_hm(ps[p1],ps[p2]);
3002: }
3003: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
3004: p2 = ZTOS((Q)BDY(n2));
3005: if ( !mm[p2] ) continue;
3006: for ( h = mm[p2], n3 = NEXT(n1); n3; n3 = NEXT(n3) ) {
3007: p3 = ZTOS((Q)BDY(n3));
3008: if ( n3 != n2 && mm[p3] && dp_redble(mm[p3],h) ) mm[p3] = 0;
3009: }
3010: }
3011: for ( j = p1+1; j <= n; j++ ) {
3012: if ( mm[j] ) {
1.19 noro 3013: quo = dpm_sp_nf_zlist(psv,psiv,p1,j,0,&nf);
1.17 noro 3014: if ( nf )
3015: error("dpm_schreyer_base : cannot happen");
3016: NEXTNODE(b0,b); BDY(b) = (pointer)quo;
3017: }
3018: }
3019: }
3020: }
3021: get_eg(&eg1); add_eg(&egsp,&eg0,&eg1); print_eg("SP",&egsp);
3022: get_eg(&eg0);
3023: get_eg(&eg1); add_eg(&egnf,&eg0,&eg1); print_eg("NF",&egnf); printf("\n");
3024: if ( b0 ) NEXT(b) = 0;
3025: for ( t0 = 0, nd = BDY(g); nd; nd = NEXT(nd) ) {
3026: dpm_ht((DPM)BDY(nd),&dpm); NEXTNODE(t0,t); BDY(t) = (pointer)dpm;
3027: }
3028: if ( t0 ) NEXT(t) = 0;
3029: MKLIST(l,t0);
3030: dmm_stack = push_schreyer_order(l,dmm_stack);
3031: // b0 = dpm_sort_list(b0);
3032: // get_eg(&eg0);
3033: // b0 = dpm_reduceall(b0);
3034: // get_eg(&eg1); add_eg(&egra,&eg0,&eg1); print_eg("RA",&egra);
3035: MKLIST(*s,b0);
3036: // print_eg("red",&egred); printf("\n");
3037: printf("sch_count=%d, schlast_count=%d\n",sch_count,schlast_count);
3038: }
1.15 noro 3039:
1.19 noro 3040: static int compdp_nv;
3041:
3042: int compdp_revgradlex(DP *a,DP *b)
3043: {
3044: return -cmpdl_revgradlex(compdp_nv,BDY(*a)->dl,BDY(*b)->dl);
3045: }
3046:
3047: int compdp_lex(DP *a,DP *b)
3048: {
3049: return -cmpdl_lex(compdp_nv,BDY(*a)->dl,BDY(*b)->dl);
3050: }
3051:
1.22 noro 3052: DMMstack_array dpm_schreyer_frame(NODE g,int lex)
1.15 noro 3053: {
3054: LIST l;
3055: NODE nd,in,b0,b,n1,n2,n3,t;
3056: NODE *psi;
3057: long p1,p2,p3;
1.19 noro 3058: int nv,n,i,j,k,max,pos,level;
1.15 noro 3059: DMMstack s,s1;
3060: DMM m1,m0,dmm;
3061: MP mp;
3062: DP dp,h;
1.19 noro 3063: DP *m,*m2;
1.15 noro 3064: DPM dpm,dpm0,dpm1;
3065: VECT psv,psiv;
3066: DPM *ps;
3067: DMMstack_array dmmstack_array;
3068:
3069: nd = g;
1.19 noro 3070: compdp_nv = nv = ((DPM)BDY(nd))->nv;
1.15 noro 3071: s = 0;
3072: level = 0;
3073: while ( 1 ) {
3074: /* store the current nd to a DMMstack */
3075: n = length(nd);
3076: NEWDMMstack(s1);
3077: MKLIST(l,nd); s1->obj = l;
3078: s1->rank = n;
3079: s1->in = (DMM *)MALLOC((n+1)*sizeof(DMM));
3080: s1->sum = (DMM *)MALLOC((n+1)*sizeof(DMM));
3081: NEXT(s1) = s;
3082: if ( s ) {
3083: for ( i = 1, in = nd; i <= n; i++, in = NEXT(in) ) {
3084: m1 = s1->in[i] = BDY((DPM)BDY(in));
3085: NEWMP(mp); mp->dl = m1->dl; mp->c = m1->c; NEXT(mp) = 0;
3086: MKDP(nv,mp,dp); dp->sugar = mp->dl->td;
3087: m0 = s->sum[m1->pos]; MKDPM(nv,m0,dpm0);
3088: mulobjdpm(CO,(Obj)dp,dpm0,&dpm1);
3089: s1->sum[i] = BDY(dpm1);
3090: }
3091: } else {
1.18 noro 3092: for ( i = 1, in = nd; i <= n; i++, in = NEXT(in) ) {
3093: m0 = BDY((DPM)BDY(in));
3094: NEWDMM(m1); *m1 = *m0; m1->c = (Obj)ONE; NEXT(m1) = 0;
3095: s1->sum[i] = s1->in[i] = m1;
3096: }
1.15 noro 3097: }
3098: s = s1;
3099: level++;
1.22 noro 3100: if ( DP_Print ) printf("level=%d,len=%d\n",level,n);
1.15 noro 3101:
3102: /* create new list */
3103: MKVECT(psv,n+1);
3104: ps = (DPM *)BDY(psv);
3105: for ( i = 1, t = nd; i <= n; i++, t = NEXT(t) ) ps[i] = (DPM)BDY(t);
3106: for ( i = 1, max = 0; i <= n; i++ )
3107: if ( (pos=BDY(ps[i])->pos) > max ) max = pos;
3108: MKVECT(psiv,max+1);
3109: psi = (NODE *)BDY(psiv);
3110: for ( i = n; i >= 1; i-- ) {
3111: pos = BDY(ps[i])->pos;
3112: MKNODE(nd,(long)i,psi[pos]); psi[pos] = nd;
3113: }
3114: m = (DP *)MALLOC((n+1)*sizeof(DP));
1.19 noro 3115: m2 = (DP *)MALLOC((n+1)*sizeof(DP));
1.15 noro 3116: b0 = 0;
3117: for ( i = 1; i <= max; i++ ) {
3118: for ( n1 = psi[i]; n1; n1 = NEXT(n1) ) {
3119: bzero(m,(n+1)*sizeof(DP));
3120: p1 = (long)BDY(n1);
3121: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
3122: p2 = (long)BDY(n2);
3123: h = dpm_sp_hm(ps[p1],ps[p2]);
3124: for ( n3 = NEXT(n1); n3 != n2; n3 = NEXT(n3) ) {
3125: p3 = (long)BDY(n3);
3126: if ( m[p3] ) {
3127: if ( dp_redble(h,m[p3]) ) {
3128: h = 0; break;
3129: }
3130: if ( dp_redble(m[p3],h) ) m[p3] = 0;
3131: }
3132: }
3133: if ( h ) m[p2] = h;
3134: }
1.22 noro 3135: if ( lex ) {
3136: // compress m to m2
3137: for ( j = 0, n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
3138: p2 = (long)BDY(n2);
3139: if ( m[p2] ) m2[j++] = m[p2];
3140: }
3141: qsort(m2,j,sizeof(DP),(int (*)(const void *,const void *))compdp_lex);
3142: for ( k = 0; k < j; k++ ) {
3143: NEWDMM(dmm); dmm->dl = BDY(m2[k])->dl; dmm->pos = p1; dmm->c = (Obj)ONE;
1.15 noro 3144: MKDPM(nv,dmm,dpm);
3145: NEXTNODE(b0,b); BDY(b) = (pointer)dpm;
3146: }
1.22 noro 3147: } else {
3148: for ( n2 = NEXT(n1); n2; n2 = NEXT(n2) ) {
3149: p2 = (long)BDY(n2);
3150: if ( m[p2] ) {
3151: NEWDMM(dmm); dmm->dl = BDY(m[p2])->dl; dmm->pos = p1; dmm->c = (Obj)ONE;
3152: MKDPM(nv,dmm,dpm);
3153: NEXTNODE(b0,b); BDY(b) = (pointer)dpm;
3154: }
3155: }
1.15 noro 3156: }
3157: }
3158: }
3159: if ( !b0 ) {
3160: NEWDMMstack_array(dmmstack_array);
3161: dmmstack_array->len = level;
3162: dmmstack_array->body = (DMMstack *)MALLOC(level*sizeof(DMMstack));
3163: for ( i = level-1, s1 = s; i >= 0; i--, s1 = NEXT(s1) )
3164: dmmstack_array->body[i] = s1;
3165: return dmmstack_array;
3166: } else {
3167: NEXT(b) = 0;
3168: nd = b0;
3169: }
3170: }
1.4 noro 3171: }
1.15 noro 3172:
3173: int sch_count,schlast_count;
1.4 noro 3174:
1.3 noro 3175: int compdmm_schreyer(int n,DMM m1,DMM m2)
3176: {
1.15 noro 3177: int pos1,pos2,t,npos1,npos2;
3178: DMM *in,*sum;
3179: DMMstack s;
3180: static DL d1=0,d2=0;
3181: static int dlen=0;
3182:
3183: sch_count++;
3184: pos1 = m1->pos; pos2 = m2->pos;
3185: if ( pos1 == pos2 ) return (*cmpdl)(n,m1->dl,m2->dl);
3186: if ( n > dlen ) {
3187: NEWDL(d1,n); NEWDL(d2,n); dlen = n;
3188: }
3189: sum = dmm_stack->sum;
3190: _adddl(n,m1->dl,sum[pos1]->dl,d1);
3191: _adddl(n,m2->dl,sum[pos2]->dl,d2);
3192: t = (*cmpdl)(n,d1,d2);
3193: if ( sum[pos1]->pos == sum[pos2]->pos && t == 0 ) {
3194: for ( s = dmm_stack; s; s = NEXT(s) ) {
3195: in = s->in;
3196: npos1 = in[pos1]->pos;
3197: npos2 = in[pos2]->pos;
3198: if ( npos1 == npos2 ) break;
3199: else {
3200: pos1 = npos1;
3201: pos2 = npos2;
3202: }
3203: }
3204: // (pos1,pos2) = the last pair s.t. pos1 != pos2
3205: // simply compare pos1 and pos2
1.3 noro 3206: if ( pos1 < pos2 ) return 1;
3207: else if ( pos1 > pos2 ) return -1;
3208: } else {
1.15 noro 3209: schlast_count++;
3210: pos1 = sum[pos1]->pos;
3211: pos2 = sum[pos2]->pos;
3212: if ( dpm_base_ordtype == 1 ) {
3213: if ( pos1 < pos2 ) return 1;
3214: else if ( pos1 > pos2 ) return -1;
3215: else return t;
3216: } else {
3217: if ( t ) return t;
3218: else if ( pos1 < pos2 ) return 1;
3219: else if ( pos1 > pos2 ) return -1;
3220: else return 0;
3221: }
1.3 noro 3222: }
1.24 ! noro 3223: /* XXX */
! 3224: return 0;
1.3 noro 3225: }
3226:
1.20 noro 3227: int compdmm_schreyer_old(int n,DMM m1,DMM m2)
3228: {
3229: int pos1,pos2,t,npos1,npos2;
3230: DMM *in,*sum;
3231: DMMstack s;
3232: static DL d1=0,d2=0;
3233: static int dlen=0;
3234:
3235: sch_count++;
3236: pos1 = m1->pos; pos2 = m2->pos;
3237: if ( pos1 == pos2 ) return (*cmpdl)(n,m1->dl,m2->dl);
3238: if ( n > dlen ) {
3239: NEWDL(d1,n); NEWDL(d2,n); dlen = n;
3240: }
3241: sum = dmm_stack->sum;
3242: _copydl(n,m1->dl,d1);
3243: _copydl(n,m2->dl,d2);
3244: for ( s = dmm_stack; s; s = NEXT(s) ) {
3245: in = s->in;
3246: _addtodl(n,in[pos1]->dl,d1);
3247: _addtodl(n,in[pos2]->dl,d2);
3248: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(n,d1,d2)) {
3249: if ( pos1 < pos2 ) return 1;
3250: else if ( pos1 > pos2 ) return -1;
3251: else return 0;
3252: }
3253: pos1 = in[pos1]->pos;
3254: pos2 = in[pos2]->pos;
3255: if ( pos1 == pos2 ) return (*cmpdl)(n,d1,d2);
3256: }
3257: if ( dpm_base_ordtype == 1 ) {
3258: if ( pos1 < pos2 ) return 1;
3259: else if ( pos1 > pos2 ) return -1;
3260: else return (*cmpdl)(n,d1,d2);
3261: } else {
3262: t = (*cmpdl)(n,d1,d2);
3263: if ( t ) return t;
3264: else if ( pos1 < pos2 ) return 1;
3265: else if ( pos1 > pos2 ) return -1;
3266: else return 0;
3267: }
3268: }
3269:
3270: extern int NaiveSchreyer;
3271:
1.4 noro 3272: int compdmm(int n,DMM m1,DMM m2)
3273: {
1.20 noro 3274: int t,t1;
1.19 noro 3275: int *base_ord;
1.4 noro 3276:
3277: switch ( dpm_ordtype ) {
1.9 noro 3278: case 0: /* TOP ord->pos */
1.4 noro 3279: t = (*cmpdl)(n,m1->dl,m2->dl);
3280: if ( t ) return t;
3281: else if ( m1->pos < m2->pos ) return 1;
3282: else if ( m1->pos > m2->pos ) return -1;
3283: else return 0;
1.9 noro 3284: case 1: /* POT : pos->ord */
1.4 noro 3285: if ( m1->pos < m2->pos ) return 1;
3286: else if ( m1->pos > m2->pos ) return -1;
3287: else return (*cmpdl)(n,m1->dl,m2->dl);
1.9 noro 3288: case 2: /* wPOT: weight->pos->ord */
3289: if ( m1->dl->td > m2->dl->td ) return 1;
3290: else if ( m1->dl->td < m2->dl->td ) return 1;
3291: else if ( m1->pos < m2->pos ) return 1;
3292: else if ( m1->pos > m2->pos ) return -1;
3293: else return (*cmpdl)(n,m1->dl,m2->dl);
3294: case 3: /* Schreyer */
1.20 noro 3295: if ( NaiveSchreyer )
3296: t = compdmm_schreyer_old(n,m1,m2);
3297: else
3298: t = compdmm_schreyer(n,m1,m2);
3299: return t;
1.19 noro 3300: case 4: /* POT with base_ord */
3301: base_ord = dp_current_spec->module_base_ord;
3302: if ( base_ord[m1->pos] < base_ord[m2->pos] ) return 1;
3303: else if ( base_ord[m1->pos] > base_ord[m2->pos] ) return -1;
3304: else return (*cmpdl)(n,m1->dl,m2->dl);
1.4 noro 3305: default:
3306: error("compdmm : invalid dpm_ordtype");
1.24 ! noro 3307: return 0;
1.4 noro 3308: }
3309: }
1.1 noro 3310:
3311: void adddpm(VL vl,DPM p1,DPM p2,DPM *pr)
3312: {
1.4 noro 3313: int n,s;
1.1 noro 3314: DMM m1,m2,mr=0,mr0;
3315: Obj t;
3316: DL d;
3317:
3318: if ( !p1 )
3319: *pr = p2;
3320: else if ( !p2 )
3321: *pr = p1;
3322: else {
1.4 noro 3323: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
3324: s = compdmm(n,m1,m2);
3325: switch ( s ) {
1.1 noro 3326: case 0:
3327: arf_add(vl,C(m1),C(m2),&t);
3328: if ( t ) {
3329: NEXTDMM(mr0,mr); mr->pos = m1->pos; mr->dl = m1->dl; C(mr) = t;
3330: }
3331: m1 = NEXT(m1); m2 = NEXT(m2); break;
3332: case 1:
3333: NEXTDMM(mr0,mr); mr->pos = m1->pos; mr->dl = m1->dl; C(mr) = C(m1);
3334: m1 = NEXT(m1); break;
3335: case -1:
3336: NEXTDMM(mr0,mr); mr->pos = m2->pos; mr->dl = m2->dl; C(mr) = C(m2);
3337: m2 = NEXT(m2); break;
3338: }
1.4 noro 3339: }
1.1 noro 3340: if ( !mr0 )
3341: if ( m1 )
3342: mr0 = m1;
3343: else if ( m2 )
3344: mr0 = m2;
3345: else {
3346: *pr = 0;
3347: return;
3348: }
3349: else if ( m1 )
3350: NEXT(mr) = m1;
3351: else if ( m2 )
3352: NEXT(mr) = m2;
3353: else
3354: NEXT(mr) = 0;
3355: MKDPM(NV(p1),mr0,*pr);
3356: if ( *pr )
3357: (*pr)->sugar = MAX(p1->sugar,p2->sugar);
3358: }
3359: }
3360:
3361: void subdpm(VL vl,DPM p1,DPM p2,DPM *pr)
3362: {
3363: DPM t;
3364:
3365: if ( !p2 )
3366: *pr = p1;
3367: else {
3368: chsgndpm(p2,&t); adddpm(vl,p1,t,pr);
3369: }
3370: }
3371:
3372: void chsgndpm(DPM p,DPM *pr)
3373: {
3374: DMM m,mr=0,mr0;
3375: Obj r;
3376:
3377: if ( !p )
3378: *pr = 0;
3379: else {
3380: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
3381: NEXTDMM(mr0,mr); arf_chsgn(C(m),&C(mr)); mr->pos = m->pos; mr->dl = m->dl;
3382: }
3383: NEXT(mr) = 0; MKDPM(NV(p),mr0,*pr);
3384: if ( *pr )
3385: (*pr)->sugar = p->sugar;
3386: }
3387: }
3388:
1.8 noro 3389: void mulcmp(Obj c,MP m)
3390: {
3391: MP t;
3392: Obj c1;
3393:
3394: for ( t = m; t; t = NEXT(t) ) {
3395: arf_mul(CO,c,C(t),&c1); C(t) = c1;
3396: }
3397: }
3398:
3399: void mulcdmm(Obj c,DMM m)
3400: {
3401: DMM t;
3402: Obj c1;
3403:
3404: for ( t = m; t; t = NEXT(t) ) {
3405: arf_mul(CO,c,C(t),&c1); C(t) = c1;
3406: }
3407: }
3408:
1.1 noro 3409: void mulcdpm(VL vl,Obj c,DPM p,DPM *pr)
3410: {
3411: DMM m,mr=0,mr0;
3412:
3413: if ( !p || !c )
3414: *pr = 0;
3415: else if ( NUM(c) && UNIQ((Q)c) )
3416: *pr = p;
3417: else if ( NUM(c) && MUNIQ((Q)c) )
3418: chsgndpm(p,pr);
3419: else {
3420: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
3421: NEXTDMM(mr0,mr);
3422: arf_mul(vl,C(m),c,&C(mr));
3423: mr->pos = m->pos;
3424: mr->dl = m->dl;
3425: }
3426: NEXT(mr) = 0; MKDPM(NV(p),mr0,*pr);
3427: if ( *pr )
3428: (*pr)->sugar = p->sugar;
3429: }
3430: }
3431:
3432: void comm_mulmpdpm(VL vl,MP m0,DPM p,DPM *pr)
3433: {
3434: DMM m,mr=0,mr0;
3435: DL d;
3436: Obj c;
3437: int n;
3438:
3439: if ( !p )
3440: *pr = 0;
3441: else {
3442: n = NV(p);
3443: d = m0->dl;
3444: c = C(m0);
3445: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
3446: NEXTDMM(mr0,mr);
3447: arf_mul(vl,C(m),c,&C(mr));
3448: mr->pos = m->pos;
3449: adddl(n,m->dl,d,&mr->dl);
3450: }
3451: NEXT(mr) = 0; MKDPM(NV(p),mr0,*pr);
3452: if ( *pr )
3453: (*pr)->sugar = p->sugar;
3454: }
3455: }
3456:
3457: void weyl_mulmpdpm(VL vl,MP m0,DPM p,DPM *pr)
3458: {
3459: DPM r,t,t1;
3460: DMM m;
3461: DL d0;
3462: int n,n2,l,i,j,tlen;
3463: struct oMP mp;
3464: static DMM *w,*psum;
3465: static struct cdl *tab;
3466: static int wlen;
3467: static int rtlen;
3468:
3469: if ( !p )
3470: *pr = 0;
3471: else {
3472: for ( m = BDY(p), l = 0; m; m = NEXT(m), l++ );
3473: if ( l > wlen ) {
3474: if ( w ) GCFREE(w);
3475: w = (DMM *)MALLOC(l*sizeof(DMM));
3476: wlen = l;
3477: }
3478: for ( m = BDY(p), i = 0; i < l; m = NEXT(m), i++ )
3479: w[i] = m;
3480:
3481: n = NV(p); n2 = n>>1;
3482: d0 = m0->dl;
3483: for ( i = 0, tlen = 1; i < n2; i++ )
3484: tlen *= d0->d[n2+i]+1;
3485: if ( tlen > rtlen ) {
3486: if ( tab ) GCFREE(tab);
3487: if ( psum ) GCFREE(psum);
3488: rtlen = tlen;
3489: tab = (struct cdl *)MALLOC(rtlen*sizeof(struct cdl));
3490: psum = (DMM *)MALLOC(rtlen*sizeof(DMM));
3491: }
3492: bzero(psum,tlen*sizeof(DMM));
3493: for ( i = l-1; i >= 0; i-- ) {
3494: bzero(tab,tlen*sizeof(struct cdl));
3495: mp.dl = w[i]->dl; mp.c = C(w[i]); mp.next = 0;
3496: weyl_mulmm(vl,m0,&mp,n,tab,tlen);
3497: for ( j = 0; j < tlen; j++ ) {
3498: if ( tab[j].c ) {
3499: NEWDMM(m); m->dl = tab[j].d; m->pos = w[i]->pos; C(m) = (Obj)tab[j].c; NEXT(m) = psum[j];
3500: psum[j] = m;
3501: }
3502: }
3503: }
3504: for ( j = tlen-1, r = 0; j >= 0; j-- )
3505: if ( psum[j] ) {
3506: MKDPM(n,psum[j],t); adddpm(vl,r,t,&t1); r = t1;
3507: }
3508: if ( r )
3509: r->sugar = p->sugar + m0->dl->td;
3510: *pr = r;
3511: }
3512: }
3513:
3514: void mulobjdpm(VL vl,Obj p1,DPM p2,DPM *pr)
3515: {
3516: MP m;
3517: DPM s,t,u;
3518:
3519: if ( !p1 || !p2 )
3520: *pr = 0;
3521: else if ( OID(p1) != O_DP )
3522: mulcdpm(vl,p1,p2,pr);
3523: else {
3524: s = 0;
3525: for ( m = BDY((DP)p1); m; m = NEXT(m) ) {
3526: if ( do_weyl )
3527: weyl_mulmpdpm(vl,m,p2,&t);
3528: else
3529: comm_mulmpdpm(vl,m,p2,&t);
3530: adddpm(vl,s,t,&u); s = u;
3531: }
3532: *pr = s;
3533: }
3534: }
3535:
3536: int compdpm(VL vl,DPM p1,DPM p2)
3537: {
3538: int n,t;
3539: DMM m1,m2;
3540:
3541: if ( !p1 )
3542: return p2 ? -1 : 0;
3543: else if ( !p2 )
3544: return 1;
3545: else if ( NV(p1) != NV(p2) ) {
3546: error("compdpm : size mismatch");
3547: return 0; /* XXX */
3548: } else {
3549: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2);
3550: m1 && m2; m1 = NEXT(m1), m2 = NEXT(m2) )
3551: if ( (t = compdmm(n,m1,m2)) ||
3552: (t = arf_comp(vl,C(m1),C(m2)) ) )
3553: return t;
3554: if ( m1 )
3555: return 1;
3556: else if ( m2 )
3557: return -1;
3558: else
3559: return 0;
3560: }
3561: }
3562:
1.11 noro 3563: void dpm_removecont2(DPM p1,DPM p2,DPM *r1p,DPM *r2p,Z *contp);
3564:
1.5 noro 3565: // p = ...+c*<<0,...0:pos>>+...
3566: DPM dpm_eliminate_term(DPM a,DPM p,Obj c,int pos)
3567: {
3568: MP d0,d;
1.10 noro 3569: DL dl;
1.5 noro 3570: DMM m;
3571: DP f;
1.11 noro 3572: DPM a1,p1,r,r1,dmy;
3573: Z dmyz;
1.5 noro 3574:
3575: if ( !a ) return 0;
3576: d0 = 0;
3577: for ( m = BDY(a); m; m = NEXT(m) )
3578: if ( m->pos == pos ) {
1.10 noro 3579: NEXTMP(d0,d);
3580: arf_chsgn(m->c,&d->c);
1.19 noro 3581: if ( !dp_current_spec || !dp_current_spec->module_top_weight )
1.11 noro 3582: d->dl = m->dl;
1.10 noro 3583: else {
3584: NEWDL(dl,NV(a));
3585: _copydl(NV(a),m->dl,dl);
3586: dl->td -= dp_current_spec->module_top_weight[pos-1];
3587: d->dl = dl;
3588: }
1.5 noro 3589: }
3590: if ( d0 ) {
1.6 noro 3591: NEXT(d) = 0; MKDP(NV(a),d0,f);
3592: mulcdpm(CO,c,a,&a1);
3593: mulobjdpm(CO,(Obj)f,p,&p1);
3594: adddpm(CO,a1,p1,&r);
1.11 noro 3595: dpm_removecont2(0,r,&dmy,&r1,&dmyz);
3596: return r1;
1.5 noro 3597: } else
1.6 noro 3598: return a;
1.5 noro 3599: }
3600:
3601: // <<...:i>> -> <<...:tab[i]>>
3602: DPM dpm_compress(DPM p,int *tab)
3603: {
3604: DMM m,mr0,mr;
3605: DPM t;
3606:
3607: if ( !p ) return 0;
3608: else {
3609: for ( m = BDY(p), mr0 = 0; m; m = NEXT(m) ) {
3610: NEXTDMM(mr0,mr);
1.6 noro 3611: mr->dl = m->dl; mr->c = m->c; mr->pos = tab[m->pos];
1.5 noro 3612: if ( mr->pos <= 0 )
3613: error("dpm_compress : invalid position");
3614: }
3615: NEXT(mr) = 0;
3616: MKDPM(p->nv,mr0,t); t->sugar = p->sugar;
3617: return t;
3618: }
3619: }
3620:
3621: // input : s, s = syz(m) output simplified s, m
1.21 noro 3622: // assuming the term order is POT
1.10 noro 3623: void dpm_simplify_syz(LIST s,LIST m,LIST *s1,LIST *m1,LIST *w1)
1.5 noro 3624: {
1.9 noro 3625: int lm,ls,i,j,k,pos,nv;
1.5 noro 3626: DPM *am,*as;
3627: DPM p;
3628: DMM d;
3629: Obj c;
1.10 noro 3630: Z q;
3631: int *tab,*dd,*new_w;
1.5 noro 3632: NODE t,t1;
3633:
3634: lm = length(BDY(m));
3635: am = (DPM *)MALLOC((lm+1)*sizeof(DPM));
3636: ls = length(BDY(s));
3637: as = (DPM *)MALLOC(ls*sizeof(DPM));
3638: for ( i = 1, t = BDY(m); i <= lm; i++, t = NEXT(t) ) am[i] = (DPM)BDY(t);
1.6 noro 3639: for ( i = 0, t = BDY(s); i < ls; i++, t = NEXT(t) ) as[i] = (DPM)BDY(t);
1.5 noro 3640:
3641: for ( i = 0; i < ls; i++ ) {
3642: p = as[i];
1.6 noro 3643: if ( p == 0 ) continue;
1.9 noro 3644: nv = NV(p);
1.21 noro 3645: for ( d = BDY(p); d; ) {
1.9 noro 3646: dd = d->dl->d;
3647: for ( k = 0; k < nv; k++ ) if ( dd[k] ) break;
3648: if ( k == nv ) break;
1.21 noro 3649: pos = d->pos;
3650: while ( d && d->pos == pos ) d = NEXT(d);
1.9 noro 3651: }
1.5 noro 3652: if ( d ) {
3653: c = d->c; pos = d->pos;
3654: for ( j = 0; j < ls; j++ )
1.6 noro 3655: if ( j != i ) {
1.5 noro 3656: as[j] = dpm_eliminate_term(as[j],p,c,pos);
1.6 noro 3657: }
1.5 noro 3658: // remove m[i]
3659: am[pos] = 0;
3660: as[i] = 0;
3661: }
3662: }
3663: // compress s
3664: // create index table from am[]
3665: // (0 0 * 0 * ...) -> (0 0 1 0 2 ... ) which means 2->1, 4->2, ...
3666: tab = (int *)MALLOC((lm+1)*sizeof(int));
3667: for ( j = 0, i = 1; i <= lm; i++ ) {
3668: if ( am[i] ) { j++; tab[i] = j; }
1.10 noro 3669: else { tab[i] = 0; }
1.5 noro 3670: }
3671: t = 0;
3672: for ( i = ls-1; i >= 0; i-- )
3673: if ( as[i] ) {
3674: p = dpm_compress(as[i],tab);
3675: MKNODE(t1,(pointer)p,t); t = t1;
3676: }
3677: MKLIST(*s1,t);
1.10 noro 3678:
1.19 noro 3679: if ( dp_current_spec && dp_current_spec->module_top_weight ) {
1.10 noro 3680: new_w = (int *)MALLOC(j*sizeof(int));
3681: for ( j = 0, i = 1; i <= lm; i++ )
3682: if ( tab[i] ) { new_w[j++] = dp_current_spec->module_top_weight[i-1]; }
3683: t = 0;
3684: for ( i = j-1; i >= 0; i-- ) {
3685: STOZ(new_w[i],q);
3686: MKNODE(t1,q,t); t = t1;
3687: }
3688: } else
3689: t = 0;
3690: MKLIST(*w1,t);
3691:
1.5 noro 3692: t = 0;
3693: for ( i = lm; i >= 1; i-- )
3694: if ( am[i] ) {
3695: MKNODE(t1,(pointer)am[i],t); t = t1;
3696: }
3697: MKLIST(*m1,t);
3698: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>