[BACK]Return to dp-supp.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2018 / builtin

Annotation of OpenXM_contrib2/asir2018/builtin/dp-supp.c, Revision 1.19

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.19    ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2018/builtin/dp-supp.c,v 1.18 2022/09/10 04:04:50 noro Exp $
1.1       noro       49: */
                     50: #include "ca.h"
                     51: #include "base.h"
                     52: #include "inline.h"
                     53: #include "parse.h"
                     54: #include "ox.h"
                     55:
                     56: #define HMAG(p) (p_mag((P)BDY(p)->c))
                     57:
                     58: extern int (*cmpdl)();
                     59: extern double pz_t_e,pz_t_d,pz_t_d1,pz_t_c;
                     60: extern int dp_nelim,dp_fcoeffs;
                     61: extern int NoGCD;
                     62: extern int GenTrace;
                     63: extern NODE TraceList;
                     64:
                     65: int show_orderspec;
                     66:
                     67: void print_composite_order_spec(struct order_spec *spec);
                     68: void dpm_rest(DPM,DPM *);
                     69:
                     70: /*
                     71:  * content reduction
                     72:  *
                     73:  */
                     74:
                     75: static NODE RatDenomList;
                     76:
                     77: void init_denomlist()
                     78: {
                     79:   RatDenomList = 0;
                     80: }
                     81:
                     82: void add_denomlist(P f)
                     83: {
                     84:   NODE n;
                     85:
                     86:   if ( OID(f)==O_P ) {
                     87:     MKNODE(n,f,RatDenomList); RatDenomList = n;
                     88:   }
                     89: }
                     90:
                     91: LIST get_denomlist()
                     92: {
                     93:   LIST l;
                     94:
                     95:   MKLIST(l,RatDenomList); RatDenomList = 0;
                     96:   return l;
                     97: }
                     98:
1.18      noro       99: int dp_iszp(DP p)
                    100: {
                    101:   MP m;
                    102:
                    103:   if ( !p ) return 1;
                    104:   for ( m = BDY(p); m; m = NEXT(m))
                    105:     if ( !INT(m->c) ) return 0;
                    106:   return 1;
                    107: }
                    108:
1.1       noro      109: void dp_ptozp(DP p,DP *rp)
                    110: {
                    111:   MP m,mr,mr0;
                    112:   int i,n;
                    113:   Q *w;
                    114:   Z dvr;
                    115:   P t;
                    116:
                    117:   if ( !p )
                    118:     *rp = 0;
                    119:   else {
                    120:     for ( m =BDY(p), n = 0; m; m = NEXT(m), n++ );
                    121:     w = (Q *)ALLOCA(n*sizeof(Q));
                    122:     for ( m =BDY(p), i = 0; i < n; m = NEXT(m), i++ )
                    123:       if ( NUM(m->c) )
                    124:         w[i] = (Q)m->c;
                    125:       else
                    126:         ptozp((P)m->c,1,&w[i],&t);
                    127:     sortbynm(w,n);
                    128:     qltozl(w,n,&dvr);
                    129:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    130:       NEXTMP(mr0,mr); divsp(CO,(P)m->c,(P)dvr,(P *)&mr->c); mr->dl = m->dl;
                    131:     }
                    132:     NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                    133:   }
                    134: }
                    135:
                    136: void dp_ptozp2(DP p0,DP p1,DP *hp,DP *rp)
                    137: {
                    138:   DP t,s,h,r;
                    139:   MP m,mr,mr0,m0;
                    140:
                    141:   addd(CO,p0,p1,&t); dp_ptozp(t,&s);
                    142:   if ( !p0 ) {
                    143:     h = 0; r = s;
                    144:   } else if ( !p1 ) {
                    145:     h = s; r = 0;
                    146:   } else {
                    147:     for ( mr0 = 0, m = BDY(s), m0 = BDY(p0); m0;
                    148:       m = NEXT(m), m0 = NEXT(m0) ) {
                    149:       NEXTMP(mr0,mr); mr->c = m->c; mr->dl = m->dl;
                    150:     }
                    151:     NEXT(mr) = 0; MKDP(p0->nv,mr0,h); MKDP(p0->nv,m,r);
                    152:   }
                    153:   if ( h )
                    154:     h->sugar = p0->sugar;
                    155:   if ( r )
                    156:     r->sugar = p1->sugar;
                    157:   *hp = h; *rp = r;
                    158: }
                    159:
1.18      noro      160: int dpm_iszp(DPM p)
                    161: {
                    162:   DMM m;
                    163:
                    164:   if ( !p ) return 1;
                    165:   for ( m = BDY(p); m; m = NEXT(m))
                    166:     if ( !INT(m->c) ) return 0;
                    167:   return 1;
                    168: }
                    169:
1.3       noro      170: void dpm_ptozp(DPM p,Z *cont,DPM *rp)
1.1       noro      171: {
                    172:   DMM m,mr,mr0;
                    173:   int i,n;
                    174:   Q *w;
                    175:   Z dvr;
                    176:   P t;
                    177:
1.3       noro      178:   if ( !p ) {
                    179:     *rp = 0; *cont = ONE;
                    180:   } else {
1.1       noro      181:     for ( m =BDY(p), n = 0; m; m = NEXT(m), n++ );
                    182:     w = (Q *)ALLOCA(n*sizeof(Q));
                    183:     for ( m =BDY(p), i = 0; i < n; m = NEXT(m), i++ )
                    184:       if ( NUM(m->c) )
                    185:         w[i] = (Q)m->c;
                    186:       else
                    187:         ptozp((P)m->c,1,&w[i],&t);
                    188:     sortbynm(w,n);
                    189:     qltozl(w,n,&dvr);
                    190:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    191:       NEXTDMM(mr0,mr); divsp(CO,(P)m->c,(P)dvr,(P *)&mr->c); mr->dl = m->dl; mr->pos = m->pos;
                    192:     }
                    193:     NEXT(mr) = 0; MKDPM(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
1.3       noro      194:     *cont = dvr;
1.1       noro      195:   }
                    196: }
                    197:
                    198: void dpm_ptozp2(DPM p0,DPM p1,DPM *hp,DPM *rp)
                    199: {
                    200:   DPM t,s,h,r;
                    201:   DMM m,mr,mr0,m0;
1.3       noro      202:   Z cont;
1.1       noro      203:
1.3       noro      204:   adddpm(CO,p0,p1,&t); dpm_ptozp(t,&cont,&s);
1.1       noro      205:   if ( !p0 ) {
                    206:     h = 0; r = s;
                    207:   } else if ( !p1 ) {
                    208:     h = s; r = 0;
                    209:   } else {
                    210:     for ( mr0 = 0, m = BDY(s), m0 = BDY(p0); m0;
                    211:       m = NEXT(m), m0 = NEXT(m0) ) {
                    212:       NEXTDMM(mr0,mr); mr->c = m->c; mr->dl = m->dl; mr->pos = m->pos;
                    213:     }
                    214:     NEXT(mr) = 0; MKDPM(p0->nv,mr0,h); MKDPM(p0->nv,m,r);
                    215:   }
                    216:   if ( h )
                    217:     h->sugar = p0->sugar;
                    218:   if ( r )
                    219:     r->sugar = p1->sugar;
                    220:   *hp = h; *rp = r;
                    221: }
                    222:
                    223:
                    224: void dp_ptozp3(DP p,Z *dvr,DP *rp)
                    225: {
                    226:   MP m,mr,mr0;
                    227:   int i,n;
                    228:   Q *w;
                    229:   P t;
                    230:
                    231:   if ( !p ) {
                    232:     *rp = 0; *dvr = 0;
                    233:   }else {
                    234:     for ( m =BDY(p), n = 0; m; m = NEXT(m), n++ );
                    235:     w = (Q *)ALLOCA(n*sizeof(Q));
                    236:     for ( m =BDY(p), i = 0; i < n; m = NEXT(m), i++ )
                    237:       if ( NUM(m->c) )
                    238:         w[i] = (Q)m->c;
                    239:       else
                    240:         ptozp((P)m->c,1,&w[i],&t);
                    241:     sortbynm(w,n);
                    242:     qltozl(w,n,dvr);
                    243:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    244:       NEXTMP(mr0,mr); divsp(CO,(P)m->c,(P)(*dvr),(P *)&mr->c); mr->dl = m->dl;
                    245:     }
                    246:     NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                    247:   }
                    248: }
                    249:
                    250: void dp_idiv(DP p,Z c,DP *rp)
                    251: {
                    252:   MP mr0,m,mr;
                    253:
                    254:   if ( !p )
                    255:     *rp = 0;
                    256:   else if ( MUNIQ((Q)c) )
                    257:     *rp = p;
                    258:   else if ( MUNIQ((Q)c) )
                    259:     chsgnd(p,rp);
                    260:   else {
                    261:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    262:       NEXTMP(mr0,mr);
1.2       noro      263:       divsz((Z)(m->c),c,(Z *)&mr->c);
1.1       noro      264:       mr->dl = m->dl;
                    265:     }
                    266:     NEXT(mr) = 0; MKDP(p->nv,mr0,*rp);
                    267:     if ( *rp )
                    268:       (*rp)->sugar = p->sugar;
                    269:   }
                    270: }
                    271:
                    272: void dp_mbase(NODE hlist,NODE *mbase)
                    273: {
                    274:   DL *dl;
                    275:   DL d;
                    276:   int *t;
                    277:   int i,j,k,n,nvar,td;
                    278:
                    279:   n = length(hlist); nvar = ((DP)BDY(hlist))->nv;
                    280:   dl = (DL *)MALLOC(n*sizeof(DL));
                    281:   NEWDL(d,nvar); *mbase = 0;
                    282:   for ( i = 0; i < n; i++, hlist = NEXT(hlist) ) {
                    283:     dl[i] = BDY((DP)BDY(hlist))->dl;
                    284:     /* trivial ideal check */
                    285:     if ( (*cmpdl)(nvar,d,dl[i]) == 0 ) {
                    286:       return;
                    287:     }
                    288:   }
                    289:   /* zero-dim. ideal check */
                    290:   for ( i = 0; i < nvar; i++ ) {
                    291:     for ( j = 0; j < n; j++ ) {
                    292:       for ( k = 0, t = dl[j]->d; k < nvar; k++ )
                    293:         if ( k != i && t[k] != 0 ) break;
                    294:       if ( k == nvar ) break;
                    295:     }
                    296:     if ( j == n )
                    297:       error("dp_mbase : input ideal is not zero-dimensional");
                    298:   }
                    299:   while ( 1 ) {
                    300:     insert_to_node(d,mbase,nvar);
                    301:     for ( i = nvar-1; i >= 0; ) {
                    302:       d->d[i]++;
                    303:       d->td += MUL_WEIGHT(1,i);
                    304:       for ( j = 0; j < n; j++ ) {
                    305:         if ( _dl_redble(dl[j],d,nvar) )
                    306:           break;
                    307:       }
                    308:       if ( j < n ) {
                    309:         for ( j = nvar-1; j >= i; j-- )
                    310:           d->d[j] = 0;
                    311:         for ( j = 0, td = 0; j < i; j++ )
                    312:           td += MUL_WEIGHT(d->d[j],j);
                    313:         d->td = td;
                    314:         i--;
                    315:       } else
                    316:         break;
                    317:     }
                    318:     if ( i < 0 )
                    319:       break;
                    320:   }
                    321: }
                    322:
                    323: int _dl_redble(DL d1,DL d2,int nvar)
                    324: {
                    325:   int i;
                    326:
                    327:   if ( d1->td > d2->td )
                    328:     return 0;
                    329:   for ( i = 0; i < nvar; i++ )
                    330:     if ( d1->d[i] > d2->d[i] )
                    331:       break;
                    332:   if ( i < nvar )
                    333:     return 0;
                    334:   else
                    335:     return 1;
                    336: }
                    337:
1.14      noro      338: int _dl_redble_ext(DL d1,DL d2,DL quo,int nvar)
                    339: {
                    340:   int i;
                    341:
                    342:   if ( (quo->td = d2->td-d1->td) < 0 )
                    343:     return 0;
                    344:   for ( i = 0; i < nvar; i++ )
                    345:     if ( (quo->d[i] = d2->d[i]-d1->d[i]) < 0 )
                    346:       break;
                    347:   if ( i < nvar )
                    348:     return 0;
                    349:   else
                    350:     return 1;
                    351: }
                    352:
1.1       noro      353: void insert_to_node(DL d,NODE *n,int nvar)
                    354: {
                    355:   DL d1;
                    356:   MP m;
                    357:   DP dp;
                    358:   NODE n0,n1,n2;
                    359:
                    360:   NEWDL(d1,nvar); d1->td = d->td;
                    361:   bcopy((char *)d->d,(char *)d1->d,nvar*sizeof(int));
                    362:   NEWMP(m); m->dl = d1; m->c = (Obj)ONE; NEXT(m) = 0;
                    363:   MKDP(nvar,m,dp); dp->sugar = d->td;
                    364:   if ( !(*n) ) {
                    365:     MKNODE(n1,dp,0); *n = n1;
                    366:   } else {
                    367:     for ( n1 = *n, n0 = 0; n1; n0 = n1, n1 = NEXT(n1) )
                    368:       if ( (*cmpdl)(nvar,d,BDY((DP)BDY(n1))->dl) > 0 ) {
                    369:         MKNODE(n2,dp,n1);
                    370:         if ( !n0 )
                    371:           *n = n2;
                    372:         else
                    373:           NEXT(n0) = n2;
                    374:         break;
                    375:       }
                    376:     if ( !n1 ) {
                    377:       MKNODE(n2,dp,0); NEXT(n0) = n2;
                    378:     }
                    379:   }
                    380: }
                    381:
                    382: void dp_vtod(Q *c,DP p,DP *rp)
                    383: {
                    384:   MP mr0,m,mr;
                    385:   int i;
                    386:
                    387:   if ( !p )
                    388:     *rp = 0;
                    389:   else {
                    390:     for ( mr0 = 0, m = BDY(p), i = 0; m; m = NEXT(m), i++ ) {
                    391:       NEXTMP(mr0,mr); mr->c = (Obj)c[i]; mr->dl = m->dl;
                    392:     }
                    393:     NEXT(mr) = 0; MKDP(p->nv,mr0,*rp);
                    394:     (*rp)->sugar = p->sugar;
                    395:   }
                    396: }
                    397:
                    398: int have_sf_coef(P p)
                    399: {
                    400:   DCP dc;
                    401:
                    402:   if ( !p )
                    403:     return 0;
                    404:   else if ( NUM(p) )
                    405:     return NID((Num)p) == N_GFS ? 1 : 0;
                    406:   else {
                    407:     for ( dc = DC(p); dc; dc = NEXT(dc) )
                    408:       if ( have_sf_coef(COEF(dc)) )
                    409:         return 1;
                    410:     return 0;
                    411:   }
                    412: }
                    413:
                    414: void head_coef(P p,Num *c)
                    415: {
                    416:   if ( !p )
                    417:     *c = 0;
                    418:   else if ( NUM(p) )
                    419:     *c = (Num)p;
                    420:   else
                    421:     head_coef(COEF(DC(p)),c);
                    422: }
                    423:
                    424: void dp_monic_sf(DP p,DP *rp)
                    425: {
                    426:   Num c;
                    427:
                    428:   if ( !p )
                    429:     *rp = 0;
                    430:   else {
                    431:     head_coef((P)BDY(p)->c,&c);
                    432:     divsdc(CO,p,(P)c,rp);
                    433:   }
                    434: }
                    435:
                    436: void dp_prim(DP p,DP *rp)
                    437: {
                    438:   P t,g;
                    439:   DP p1;
                    440:   MP m,mr,mr0;
                    441:   int i,n;
                    442:   P *w;
                    443:   Q *c;
                    444:   Z dvr;
                    445:   NODE tn;
                    446:
                    447:   if ( !p )
                    448:     *rp = 0;
                    449:   else if ( dp_fcoeffs == N_GFS ) {
                    450:     for ( m = BDY(p); m; m = NEXT(m) )
                    451:       if ( OID(m->c) == O_N ) {
                    452:         /* GCD of coeffs = 1 */
                    453:         dp_monic_sf(p,rp);
                    454:         return;
                    455:       } else break;
                    456:     /* compute GCD over the finite fieid */
                    457:     for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
                    458:     w = (P *)ALLOCA(n*sizeof(P));
                    459:     for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ )
                    460:       w[i] = (P)m->c;
                    461:     gcdsf(CO,w,n,&g);
                    462:     if ( NUM(g) )
                    463:       dp_monic_sf(p,rp);
                    464:     else {
                    465:       for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    466:         NEXTMP(mr0,mr); divsp(CO,(P)m->c,g,(P *)&mr->c); mr->dl = m->dl;
                    467:       }
                    468:       NEXT(mr) = 0; MKDP(p->nv,mr0,p1); p1->sugar = p->sugar;
                    469:       dp_monic_sf(p1,rp);
                    470:     }
                    471:     return;
                    472:   } else if ( dp_fcoeffs )
                    473:     *rp = p;
                    474:   else if ( NoGCD )
                    475:     dp_ptozp(p,rp);
                    476:   else {
                    477:     dp_ptozp(p,&p1); p = p1;
                    478:     for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
                    479:     if ( n == 1 ) {
                    480:       m = BDY(p);
                    481:       NEWMP(mr); mr->dl = m->dl; mr->c = (Obj)ONE; NEXT(mr) = 0;
                    482:       MKDP(p->nv,mr,*rp); (*rp)->sugar = p->sugar;
                    483:       return;
                    484:     }
                    485:     w = (P *)ALLOCA(n*sizeof(P));
                    486:     c = (Q *)ALLOCA(n*sizeof(Q));
                    487:     for ( m =BDY(p), i = 0; i < n; m = NEXT(m), i++ )
                    488:       if ( NUM(m->c) ) {
                    489:         c[i] = (Q)m->c; w[i] = (P)ONE;
                    490:       } else
                    491:         ptozp((P)m->c,1,&c[i],&w[i]);
                    492:     qltozl(c,n,&dvr); heu_nezgcdnpz(CO,w,n,&t); mulp(CO,t,(P)dvr,&g);
                    493:     if ( NUM(g) )
                    494:       *rp = p;
                    495:     else {
                    496:       for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    497:         NEXTMP(mr0,mr); divsp(CO,(P)m->c,g,(P *)&mr->c); mr->dl = m->dl;
                    498:       }
                    499:       NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                    500:       add_denomlist(g);
                    501:     }
                    502:   }
                    503: }
                    504:
                    505: void heu_nezgcdnpz(VL vl,P *pl,int m,P *pr)
                    506: {
                    507:   int i,r;
                    508:   P gcd,t,s1,s2,u;
                    509:   Z rq;
                    510:   DCP dc;
                    511:   extern int DP_Print;
                    512:
                    513:   while ( 1 ) {
                    514:     for ( i = 0, s1 = 0; i < m; i++ ) {
1.2       noro      515:       r = random(); UTOZ(r,rq);
1.1       noro      516:       mulp(vl,pl[i],(P)rq,&t); addp(vl,s1,t,&u); s1 = u;
                    517:     }
                    518:     for ( i = 0, s2 = 0; i < m; i++ ) {
1.2       noro      519:       r = random(); UTOZ(r,rq);
1.1       noro      520:       mulp(vl,pl[i],(P)rq,&t); addp(vl,s2,t,&u); s2 = u;
                    521:     }
                    522:     ezgcdp(vl,s1,s2,&gcd);
                    523:     if ( DP_Print > 2 )
                    524:       { fprintf(asir_out,"(%d)",nmonop(gcd)); fflush(asir_out); }
                    525:     for ( i = 0; i < m; i++ ) {
                    526:       if ( !divtpz(vl,pl[i],gcd,&t) )
                    527:         break;
                    528:     }
                    529:     if ( i == m )
                    530:       break;
                    531:   }
                    532:   *pr = gcd;
                    533: }
                    534:
                    535: void dp_prim_mod(DP p,int mod,DP *rp)
                    536: {
                    537:   P t,g;
                    538:   MP m,mr,mr0;
                    539:
                    540:   if ( !p )
                    541:     *rp = 0;
                    542:   else if ( NoGCD )
                    543:     *rp = p;
                    544:   else {
                    545:     for ( m = BDY(p), g = (P)m->c, m = NEXT(m); m; m = NEXT(m) ) {
                    546:       gcdprsmp(CO,mod,g,(P)m->c,&t); g = t;
                    547:     }
                    548:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                    549:       NEXTMP(mr0,mr); divsmp(CO,mod,(P)m->c,g,(P *)&mr->c); mr->dl = m->dl;
                    550:     }
                    551:     NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                    552:   }
                    553: }
                    554:
                    555: void dp_cont(DP p,Z *rp)
                    556: {
                    557:   VECT v;
                    558:
                    559:   dp_dtov(p,&v); gcdvz(v,rp);
                    560: }
                    561:
                    562: void dp_dtov(DP dp,VECT *rp)
                    563: {
                    564:   MP m,t;
                    565:   int i,n;
                    566:   VECT v;
                    567:   pointer *p;
                    568:
                    569:   m = BDY(dp);
                    570:   for ( t = m, n = 0; t; t = NEXT(t), n++ );
                    571:   MKVECT(v,n);
                    572:   for ( i = 0, p = BDY(v), t = m; i < n; t = NEXT(t), i++ )
                    573:     p[i] = (pointer)(t->c);
                    574:   *rp = v;
                    575: }
                    576:
                    577: /*
                    578:  * s-poly computation
                    579:  *
                    580:  */
                    581:
                    582: void dp_sp(DP p1,DP p2,DP *rp)
                    583: {
                    584:   int i,n,td;
                    585:   int *w;
                    586:   DL d1,d2,d;
                    587:   MP m;
                    588:   DP t,s1,s2,u;
                    589:   Z c,c1,c2;
                    590:   Z gn;
                    591:
                    592:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    593:   w = (int *)ALLOCA(n*sizeof(int));
                    594:   for ( i = 0, td = 0; i < n; i++ ) {
                    595:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    596:   }
                    597:
                    598:   NEWDL(d,n); d->td = td - d1->td;
                    599:   for ( i = 0; i < n; i++ )
                    600:     d->d[i] = w[i] - d1->d[i];
                    601:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    602:   if ( INT(c1) && INT(c2) ) {
                    603:     gcdz(c1,c2,&gn);
                    604:     if ( !UNIQ(gn) ) {
1.2       noro      605:       divsz(c1,gn,&c); c1 = c;
                    606:       divsz(c2,gn,&c);c2 = c;
1.1       noro      607:     }
                    608:   }
                    609:
                    610:   NEWMP(m); m->dl = d; m->c = (Obj)c2; NEXT(m) = 0;
                    611:   MKDP(n,m,s1); s1->sugar = d->td; muld(CO,s1,p1,&t);
                    612:
                    613:   NEWDL(d,n); d->td = td - d2->td;
                    614:   for ( i = 0; i < n; i++ )
                    615:     d->d[i] = w[i] - d2->d[i];
                    616:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0;
                    617:   MKDP(n,m,s2); s2->sugar = d->td; muld(CO,s2,p2,&u);
                    618:
                    619:   subd(CO,t,u,rp);
                    620:   if ( GenTrace ) {
                    621:     LIST hist;
                    622:     NODE node;
                    623:
                    624:     node = mknode(4,ONE,NULLP,s1,ONE);
                    625:     MKLIST(hist,node);
                    626:     MKNODE(TraceList,hist,0);
                    627:
                    628:     node = mknode(4,ONE,NULLP,NULLP,ONE);
                    629:     chsgnd(s2,(DP *)&ARG2(node));
                    630:     MKLIST(hist,node);
                    631:     MKNODE(node,hist,TraceList); TraceList = node;
                    632:   }
                    633: }
                    634:
1.3       noro      635: void dpm_sp(DPM p1,DPM p2,DPM *rp,DP *mul1,DP *mul2)
1.1       noro      636: {
                    637:   int i,n,td;
                    638:   int *w;
                    639:   DL d1,d2,d;
                    640:   MP m;
                    641:   DP s1,s2;
                    642:   DPM t,u;
                    643:   Z c,c1,c2;
                    644:   Z gn;
                    645:
                    646:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    647:   if ( BDY(p1)->pos != BDY(p2)->pos ) {
1.3       noro      648:     *mul1 = 0; *mul2 = 0; *rp = 0;
1.1       noro      649:     return;
                    650:   }
                    651:   w = (int *)ALLOCA(n*sizeof(int));
                    652:   for ( i = 0, td = 0; i < n; i++ ) {
                    653:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    654:   }
                    655:
                    656:   NEWDL(d,n); d->td = td - d1->td;
                    657:   for ( i = 0; i < n; i++ )
                    658:     d->d[i] = w[i] - d1->d[i];
                    659:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    660:   if ( INT(c1) && INT(c2) ) {
                    661:     gcdz(c1,c2,&gn);
                    662:     if ( !UNIQ(gn) ) {
1.2       noro      663:       divsz(c1,gn,&c); c1 = c;
                    664:       divsz(c2,gn,&c);c2 = c;
1.1       noro      665:     }
                    666:   }
                    667:
                    668:   NEWMP(m); m->dl = d; m->c = (Obj)c2; NEXT(m) = 0;
                    669:   MKDP(n,m,s1); s1->sugar = d->td; mulobjdpm(CO,(Obj)s1,p1,&t);
1.3       noro      670:   *mul1 = s1;
1.1       noro      671:
                    672:   NEWDL(d,n); d->td = td - d2->td;
                    673:   for ( i = 0; i < n; i++ )
                    674:     d->d[i] = w[i] - d2->d[i];
                    675:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0;
                    676:   MKDP(n,m,s2); s2->sugar = d->td; mulobjdpm(CO,(Obj)s2,p2,&u);
1.3       noro      677:   *mul2 = s2;
1.1       noro      678:
                    679:   subdpm(CO,t,u,rp);
                    680:   if ( GenTrace ) {
                    681:     LIST hist;
                    682:     NODE node;
                    683:
                    684:     node = mknode(4,ONE,NULLP,s1,ONE);
                    685:     MKLIST(hist,node);
                    686:     MKNODE(TraceList,hist,0);
                    687:
                    688:     node = mknode(4,ONE,NULLP,NULLP,ONE);
                    689:     chsgnd(s2,(DP *)&ARG2(node));
                    690:     MKLIST(hist,node);
                    691:     MKNODE(node,hist,TraceList); TraceList = node;
                    692:   }
                    693: }
                    694:
1.4       noro      695: DP dpm_sp_hm(DPM p1,DPM p2)
                    696: {
                    697:   int i,n,td;
                    698:   int *w;
                    699:   DL d1,d2,d;
                    700:   MP m;
                    701:   DP s1;
                    702:
                    703:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    704:   if ( BDY(p1)->pos != BDY(p2)->pos ) {
                    705:     return 0;
                    706:   }
                    707:   w = (int *)ALLOCA(n*sizeof(int));
                    708:   for ( i = 0, td = 0; i < n; i++ ) {
                    709:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    710:   }
                    711:
                    712:   NEWDL(d,n); d->td = td - d1->td;
                    713:   for ( i = 0; i < n; i++ )
                    714:     d->d[i] = w[i] - d1->d[i];
                    715:
                    716:   NEWMP(m); m->dl = d; m->c = (Obj)ONE; NEXT(m) = 0;
                    717:   MKDP(n,m,s1); s1->sugar = d->td;
                    718:   return s1;
                    719: }
                    720:
1.1       noro      721: void _dp_sp_dup(DP p1,DP p2,DP *rp)
                    722: {
                    723:   int i,n,td;
                    724:   int *w;
                    725:   DL d1,d2,d;
                    726:   MP m;
                    727:   DP t,s1,s2,u;
                    728:   Z c,c1,c2;
                    729:   Z gn;
                    730:
                    731:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    732:   w = (int *)ALLOCA(n*sizeof(int));
                    733:   for ( i = 0, td = 0; i < n; i++ ) {
                    734:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    735:   }
                    736:
                    737:   _NEWDL(d,n); d->td = td - d1->td;
                    738:   for ( i = 0; i < n; i++ )
                    739:     d->d[i] = w[i] - d1->d[i];
                    740:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    741:   if ( INT(c1) && INT(c2) ) {
                    742:     gcdz(c1,c2,&gn);
                    743:     if ( !UNIQ(gn) ) {
1.2       noro      744:       divsz(c1,gn,&c); c1 = c;
                    745:       divsz(c2,gn,&c);c2 = c;
1.1       noro      746:     }
                    747:   }
                    748:
                    749:   _NEWMP(m); m->dl = d; m->c = (Obj)c2; NEXT(m) = 0;
                    750:   _MKDP(n,m,s1); s1->sugar = d->td; _muld_dup(CO,s1,p1,&t); _free_dp(s1);
                    751:
                    752:   _NEWDL(d,n); d->td = td - d2->td;
                    753:   for ( i = 0; i < n; i++ )
                    754:     d->d[i] = w[i] - d2->d[i];
                    755:   _NEWMP(m); m->dl = d; chsgnp((P)c1,(P *)&m->c); NEXT(m) = 0;
                    756:   _MKDP(n,m,s2); s2->sugar = d->td; _muld_dup(CO,s2,p2,&u); _free_dp(s2);
                    757:
                    758:   _addd_destructive(CO,t,u,rp);
                    759:   if ( GenTrace ) {
                    760:     LIST hist;
                    761:     NODE node;
                    762:
                    763:     node = mknode(4,ONE,NULLP,s1,ONE);
                    764:     MKLIST(hist,node);
                    765:     MKNODE(TraceList,hist,0);
                    766:
                    767:     node = mknode(4,ONE,NULLP,NULLP,ONE);
                    768:     chsgnd(s2,(DP *)&ARG2(node));
                    769:     MKLIST(hist,node);
                    770:     MKNODE(node,hist,TraceList); TraceList = node;
                    771:   }
                    772: }
                    773:
                    774: void dp_sp_mod(DP p1,DP p2,int mod,DP *rp)
                    775: {
                    776:   int i,n,td;
                    777:   int *w;
                    778:   DL d1,d2,d;
                    779:   MP m;
                    780:   DP t,s,u;
                    781:
                    782:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    783:   w = (int *)ALLOCA(n*sizeof(int));
                    784:   for ( i = 0, td = 0; i < n; i++ ) {
                    785:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    786:   }
                    787:   NEWDL_NOINIT(d,n); d->td = td - d1->td;
                    788:   for ( i = 0; i < n; i++ )
                    789:     d->d[i] = w[i] - d1->d[i];
                    790:   NEWMP(m); m->dl = d; m->c = (Obj)BDY(p2)->c; NEXT(m) = 0;
                    791:   MKDP(n,m,s); s->sugar = d->td; mulmd(CO,mod,p1,s,&t);
                    792:   NEWDL_NOINIT(d,n); d->td = td - d2->td;
                    793:   for ( i = 0; i < n; i++ )
                    794:     d->d[i] = w[i] - d2->d[i];
                    795:   NEWMP(m); m->dl = d; m->c = (Obj)BDY(p1)->c; NEXT(m) = 0;
                    796:   MKDP(n,m,s); s->sugar = d->td; mulmd(CO,mod,p2,s,&u);
                    797:   submd(CO,mod,t,u,rp);
                    798: }
                    799:
                    800: void _dp_sp_mod_dup(DP p1,DP p2,int mod,DP *rp)
                    801: {
                    802:   int i,n,td;
                    803:   int *w;
                    804:   DL d1,d2,d;
                    805:   MP m;
                    806:   DP t,s,u;
                    807:
                    808:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    809:   w = (int *)ALLOCA(n*sizeof(int));
                    810:   for ( i = 0, td = 0; i < n; i++ ) {
                    811:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    812:   }
                    813:   _NEWDL(d,n); d->td = td - d1->td;
                    814:   for ( i = 0; i < n; i++ )
                    815:     d->d[i] = w[i] - d1->d[i];
                    816:   _NEWMP(m); m->dl = d; m->c = BDY(p2)->c; NEXT(m) = 0;
                    817:   _MKDP(n,m,s); s->sugar = d->td; _mulmd_dup(mod,s,p1,&t); _free_dp(s);
                    818:   _NEWDL(d,n); d->td = td - d2->td;
                    819:   for ( i = 0; i < n; i++ )
                    820:     d->d[i] = w[i] - d2->d[i];
                    821:   _NEWMP(m); m->dl = d; m->c = (Obj)STOI(mod - ITOS(BDY(p1)->c)); NEXT(m) = 0;
                    822:   _MKDP(n,m,s); s->sugar = d->td; _mulmd_dup(mod,s,p2,&u); _free_dp(s);
                    823:   _addmd_destructive(mod,t,u,rp);
                    824: }
                    825:
                    826: void _dp_sp_mod(DP p1,DP p2,int mod,DP *rp)
                    827: {
                    828:   int i,n,td;
                    829:   int *w;
                    830:   DL d1,d2,d;
                    831:   MP m;
                    832:   DP t,s,u;
                    833:
                    834:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    835:   w = (int *)ALLOCA(n*sizeof(int));
                    836:   for ( i = 0, td = 0; i < n; i++ ) {
                    837:     w[i] = MAX(d1->d[i],d2->d[i]); td += MUL_WEIGHT(w[i],i);
                    838:   }
                    839:   NEWDL(d,n); d->td = td - d1->td;
                    840:   for ( i = 0; i < n; i++ )
                    841:     d->d[i] = w[i] - d1->d[i];
                    842:   NEWMP(m); m->dl = d; m->c = BDY(p2)->c; NEXT(m) = 0;
                    843:   MKDP(n,m,s); s->sugar = d->td; mulmd_dup(mod,s,p1,&t);
                    844:   NEWDL(d,n); d->td = td - d2->td;
                    845:   for ( i = 0; i < n; i++ )
                    846:     d->d[i] = w[i] - d2->d[i];
                    847:   NEWMP(m); m->dl = d; m->c = (Obj)STOI(mod - ITOS(BDY(p1)->c)); NEXT(m) = 0;
                    848:   MKDP(n,m,s); s->sugar = d->td; mulmd_dup(mod,s,p2,&u);
                    849:   addmd_destructive(mod,t,u,rp);
                    850: }
                    851:
                    852: /*
                    853:  * m-reduction
                    854:  * do content reduction over Z or Q(x,...)
                    855:  * do nothing over finite fields
                    856:  *
1.3       noro      857:  * head+rest = dn*(p0+p1)+mult*p2
1.1       noro      858:  */
                    859:
                    860: void dp_red(DP p0,DP p1,DP p2,DP *head,DP *rest,P *dnp,DP *multp)
                    861: {
                    862:   int i,n;
                    863:   DL d1,d2,d;
                    864:   MP m;
                    865:   DP t,s,r,h;
                    866:   Z c,c1,c2,gn;
                    867:   P g,a;
                    868:   P p[2];
                    869:
                    870:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                    871:   NEWDL(d,n); d->td = d1->td - d2->td;
                    872:   for ( i = 0; i < n; i++ )
                    873:     d->d[i] = d1->d[i]-d2->d[i];
                    874:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    875:   if ( dp_fcoeffs == N_GFS ) {
                    876:     p[0] = (P)c1; p[1] = (P)c2;
                    877:     gcdsf(CO,p,2,&g);
                    878:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    879:   } else if ( dp_fcoeffs ) {
                    880:     /* do nothing */
                    881:   } else if ( INT(c1) && INT(c2) ) {
                    882:     gcdz(c1,c2,&gn);
                    883:     if ( !UNIQ(gn) ) {
1.2       noro      884:       divsz(c1,gn,&c); c1 = c;
                    885:       divsz(c2,gn,&c); c2 = c;
1.1       noro      886:     }
                    887:   } else {
1.19    ! noro      888:     ezgcdp(CO,(P)c1,(P)c2,&g);
1.1       noro      889:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    890:     add_denomlist(g);
                    891:   }
                    892:   NEWMP(m); m->dl = d; chsgnp((P)c1,(P *)&m->c); NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
                    893:   *multp = s;
                    894:   muld(CO,s,p2,&t); muldc(CO,p1,(Obj)c2,&s); addd(CO,s,t,&r);
                    895:   muldc(CO,p0,(Obj)c2,&h);
                    896:   *head = h; *rest = r; *dnp = (P)c2;
                    897: }
                    898:
1.3       noro      899: // head+rest = dn*(p0+p1)-mult*p2
1.1       noro      900: void dpm_red(DPM p0,DPM p1,DPM p2,DPM *head,DPM *rest,P *dnp,DP *multp)
                    901: {
                    902:   int i,n,pos;
                    903:   DL d1,d2,d;
                    904:   MP m;
1.4       noro      905:   DP s,ms;
1.1       noro      906:   DPM t,r,h,u,w;
                    907:   Z c,c1,c2,gn;
                    908:   P g,a;
                    909:   P p[2];
                    910:
                    911:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl; pos = BDY(p1)->pos;
                    912:   if ( pos != BDY(p2)->pos )
                    913:     error("dpm_red : cannot happen");
                    914:   NEWDL(d,n); d->td = d1->td - d2->td;
                    915:   for ( i = 0; i < n; i++ )
                    916:     d->d[i] = d1->d[i]-d2->d[i];
                    917:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    918:   if ( dp_fcoeffs == N_GFS ) {
                    919:     p[0] = (P)c1; p[1] = (P)c2;
                    920:     gcdsf(CO,p,2,&g);
                    921:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    922:   } else if ( dp_fcoeffs ) {
                    923:     /* do nothing */
                    924:   } else if ( INT(c1) && INT(c2) ) {
                    925:     gcdz(c1,c2,&gn);
                    926:     if ( !UNIQ(gn) ) {
1.2       noro      927:       divsz(c1,gn,&c); c1 = c;
                    928:       divsz(c2,gn,&c); c2 = c;
1.1       noro      929:     }
                    930:   } else {
1.19    ! noro      931:     ezgcdp(CO,(P)c1,(P)c2,&g);
1.1       noro      932:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    933:     add_denomlist(g);
                    934:   }
1.3       noro      935:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
1.1       noro      936:   *multp = s;
1.4       noro      937:   chsgnd(s,&ms); mulobjdpm(CO,(Obj)ms,p2,&u); mulobjdpm(CO,(Obj)c2,p1,&w); adddpm(CO,w,u,&r);
1.1       noro      938:   mulobjdpm(CO,(Obj)c2,p0,&h);
                    939:   *head = h; *rest = r; *dnp = (P)c2;
                    940: }
                    941:
1.5       noro      942: void dpm_red2(DPM p1,DPM p2,DPM *rest,P *dnp,DP *multp)
                    943: {
                    944:   int i,n,pos;
                    945:   DL d1,d2,d;
                    946:   MP m;
                    947:   DP s,ms;
                    948:   DPM t,r,h,u,w;
                    949:   Z c,c1,c2,gn;
                    950:   P g,a;
                    951:   P p[2];
                    952:
                    953:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl; pos = BDY(p1)->pos;
                    954:   if ( pos != BDY(p2)->pos )
                    955:     error("dpm_red : cannot happen");
                    956:   NEWDL(d,n); d->td = d1->td - d2->td;
                    957:   for ( i = 0; i < n; i++ )
                    958:     d->d[i] = d1->d[i]-d2->d[i];
                    959:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(p2)->c;
                    960:   if ( dp_fcoeffs == N_GFS ) {
                    961:     p[0] = (P)c1; p[1] = (P)c2;
                    962:     gcdsf(CO,p,2,&g);
                    963:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    964:   } else if ( dp_fcoeffs ) {
                    965:     /* do nothing */
                    966:   } else if ( INT(c1) && INT(c2) ) {
                    967:     gcdz(c1,c2,&gn);
                    968:     if ( !UNIQ(gn) ) {
                    969:       divsz(c1,gn,&c); c1 = c;
                    970:       divsz(c2,gn,&c); c2 = c;
                    971:     }
                    972:   } else {
1.19    ! noro      973:     ezgcdp(CO,(P)c1,(P)c2,&g);
1.5       noro      974:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                    975:     add_denomlist(g);
                    976:   }
                    977:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
                    978:   *multp = s;
                    979:   chsgnd(s,&ms); mulobjdpm(CO,(Obj)ms,p2,&u); mulobjdpm(CO,(Obj)c2,p1,&w); adddpm(CO,w,u,&r);
                    980:   *rest = r; *dnp = (P)c2;
                    981: }
1.1       noro      982:
                    983: /*
                    984:  * m-reduction by a marked poly
                    985:  * do content reduction over Z or Q(x,...)
                    986:  * do nothing over finite fields
                    987:  *
                    988:  */
                    989:
                    990:
                    991: void dp_red_marked(DP p0,DP p1,DP p2,DP hp2,DP *head,DP *rest,P *dnp,DP *multp)
                    992: {
                    993:   int i,n;
                    994:   DL d1,d2,d;
                    995:   MP m;
                    996:   DP t,s,r,h;
                    997:   Z c,c1,c2,gn;
                    998:   P g,a;
                    999:   P p[2];
                   1000:
                   1001:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(hp2)->dl;
                   1002:   NEWDL(d,n); d->td = d1->td - d2->td;
                   1003:   for ( i = 0; i < n; i++ )
                   1004:     d->d[i] = d1->d[i]-d2->d[i];
                   1005:   c1 = (Z)BDY(p1)->c; c2 = (Z)BDY(hp2)->c;
                   1006:   if ( dp_fcoeffs == N_GFS ) {
                   1007:     p[0] = (P)c1; p[1] = (P)c2;
                   1008:     gcdsf(CO,p,2,&g);
                   1009:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                   1010:   } else if ( dp_fcoeffs ) {
                   1011:     /* do nothing */
                   1012:   } else if ( INT(c1) && INT(c2) ) {
                   1013:     gcdz(c1,c2,&gn);
                   1014:     if ( !UNIQ(gn) ) {
1.2       noro     1015:       divsz(c1,gn,&c); c1 = c;
                   1016:       divsz(c2,gn,&c); c2 = c;
1.1       noro     1017:     }
                   1018:   } else {
1.19    ! noro     1019:     ezgcdp(CO,(P)c1,(P)c2,&g);
1.1       noro     1020:     divsp(CO,(P)c1,g,&a); c1 = (Z)a; divsp(CO,(P)c2,g,&a); c2 = (Z)a;
                   1021:   }
                   1022:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
                   1023:   *multp = s;
                   1024:   muld(CO,s,p2,&t); muldc(CO,p1,(Obj)c2,&s); subd(CO,s,t,&r);
                   1025:   muldc(CO,p0,(Obj)c2,&h);
                   1026:   *head = h; *rest = r; *dnp = (P)c2;
                   1027: }
                   1028:
                   1029: void dp_red_marked_mod(DP p0,DP p1,DP p2,DP hp2,int mod,DP *head,DP *rest,P *dnp,DP *multp)
                   1030: {
                   1031:   int i,n;
                   1032:   DL d1,d2,d;
                   1033:   MP m;
                   1034:   DP t,s,r,h;
                   1035:   P c1,c2,g,u;
                   1036:
                   1037:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(hp2)->dl;
                   1038:   NEWDL(d,n); d->td = d1->td - d2->td;
                   1039:   for ( i = 0; i < n; i++ )
                   1040:     d->d[i] = d1->d[i]-d2->d[i];
                   1041:   c1 = (P)BDY(p1)->c; c2 = (P)BDY(hp2)->c;
                   1042:   gcdprsmp(CO,mod,c1,c2,&g);
                   1043:   divsmp(CO,mod,c1,g,&u); c1 = u; divsmp(CO,mod,c2,g,&u); c2 = u;
                   1044:   if ( NUM(c2) ) {
                   1045:     divsmp(CO,mod,c1,c2,&u); c1 = u; c2 = (P)ONEM;
                   1046:   }
                   1047:   NEWMP(m); m->dl = d; m->c = (Obj)c1; NEXT(m) = 0;
                   1048:   MKDP(n,m,s); s->sugar = d->td;
                   1049:   *multp = s;
                   1050:   mulmd(CO,mod,s,p2,&t);
                   1051:   if ( NUM(c2) ) {
                   1052:     submd(CO,mod,p1,t,&r); h = p0;
                   1053:   } else {
                   1054:     mulmdc(CO,mod,p1,c2,&s); submd(CO,mod,s,t,&r); mulmdc(CO,mod,p0,c2,&h);
                   1055:   }
                   1056:   *head = h; *rest = r; *dnp = c2;
                   1057: }
                   1058:
                   1059: /* m-reduction over a field */
                   1060:
                   1061: void dp_red_f(DP p1,DP p2,DP *rest)
                   1062: {
                   1063:   int i,n;
                   1064:   DL d1,d2,d;
                   1065:   MP m;
                   1066:   DP t,s;
                   1067:   Obj a,b;
                   1068:
                   1069:   n = p1->nv;
                   1070:   d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   1071:
                   1072:   NEWDL(d,n); d->td = d1->td - d2->td;
                   1073:   for ( i = 0; i < n; i++ )
                   1074:     d->d[i] = d1->d[i]-d2->d[i];
                   1075:
                   1076:   NEWMP(m); m->dl = d;
                   1077:   divr(CO,(Obj)BDY(p1)->c,(Obj)BDY(p2)->c,&a); chsgnr(a,&b);
                   1078:   C(m) = (Obj)b;
                   1079:   NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
                   1080:
                   1081:   muld(CO,s,p2,&t); addd(CO,p1,t,rest);
                   1082: }
                   1083:
                   1084: void dpm_red_f(DPM p1,DPM p2,DPM *rest)
                   1085: {
                   1086:   int i,n;
                   1087:   DL d1,d2,d;
                   1088:   MP m;
                   1089:   DPM t;
                   1090:   DP s;
                   1091:   Obj a,b;
                   1092:
                   1093:   n = p1->nv;
                   1094:   d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   1095:
                   1096:   NEWDL(d,n); d->td = d1->td - d2->td;
                   1097:   for ( i = 0; i < n; i++ )
                   1098:     d->d[i] = d1->d[i]-d2->d[i];
                   1099:
                   1100:   NEWMP(m); m->dl = d;
                   1101:   arf_div(CO,(Obj)BDY(p1)->c,(Obj)BDY(p2)->c,&a); arf_chsgn(a,&b);
                   1102:   C(m) = b;
                   1103:   NEXT(m) = 0; MKDP(n,m,s); s->sugar = d->td;
                   1104:
                   1105:   mulobjdpm(CO,(Obj)s,p2,&t); adddpm(CO,p1,t,rest);
                   1106: }
                   1107:
                   1108:
                   1109: void dp_red_mod(DP p0,DP p1,DP p2,int mod,DP *head,DP *rest,P *dnp)
                   1110: {
                   1111:   int i,n;
                   1112:   DL d1,d2,d;
                   1113:   MP m;
                   1114:   DP t,s,r,h;
                   1115:   P c1,c2,g,u;
                   1116:
                   1117:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   1118:   NEWDL(d,n); d->td = d1->td - d2->td;
                   1119:   for ( i = 0; i < n; i++ )
                   1120:     d->d[i] = d1->d[i]-d2->d[i];
                   1121:   c1 = (P)BDY(p1)->c; c2 = (P)BDY(p2)->c;
                   1122:   gcdprsmp(CO,mod,c1,c2,&g);
                   1123:   divsmp(CO,mod,c1,g,&u); c1 = u; divsmp(CO,mod,c2,g,&u); c2 = u;
                   1124:   if ( NUM(c2) ) {
                   1125:     divsmp(CO,mod,c1,c2,&u); c1 = u; c2 = (P)ONEM;
                   1126:   }
                   1127:   NEWMP(m); m->dl = d; chsgnmp(mod,(P)c1,(P *)&m->c); NEXT(m) = 0;
                   1128:   MKDP(n,m,s); s->sugar = d->td; mulmd(CO,mod,s,p2,&t);
                   1129:   if ( NUM(c2) ) {
                   1130:     addmd(CO,mod,p1,t,&r); h = p0;
                   1131:   } else {
                   1132:     mulmdc(CO,mod,p1,c2,&s); addmd(CO,mod,s,t,&r); mulmdc(CO,mod,p0,c2,&h);
                   1133:   }
                   1134:   *head = h; *rest = r; *dnp = c2;
                   1135: }
                   1136:
                   1137: struct oEGT eg_red_mod;
                   1138:
                   1139: void _dp_red_mod_destructive(DP p1,DP p2,int mod,DP *rp)
                   1140: {
                   1141:   int i,n;
                   1142:   DL d1,d2,d;
                   1143:   MP m;
                   1144:   DP t,s;
                   1145:   int c,c1,c2;
                   1146:   extern int do_weyl;
                   1147:
                   1148:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   1149:   _NEWDL(d,n); d->td = d1->td - d2->td;
                   1150:   for ( i = 0; i < n; i++ )
                   1151:     d->d[i] = d1->d[i]-d2->d[i];
                   1152:   c = invm(ITOS(BDY(p2)->c),mod);
                   1153:   c2 = ITOS(BDY(p1)->c);
                   1154:   DMAR(c,c2,0,mod,c1);
                   1155:   _NEWMP(m); m->dl = d; m->c = (Obj)STOI(mod-c1); NEXT(m) = 0;
                   1156: #if 0
                   1157:   _MKDP(n,m,s); s->sugar = d->td;
                   1158:   _mulmd_dup(mod,s,p2,&t); _free_dp(s);
                   1159: #else
                   1160:   if ( do_weyl ) {
                   1161:     _MKDP(n,m,s); s->sugar = d->td;
                   1162:     _mulmd_dup(mod,s,p2,&t); _free_dp(s);
                   1163:   } else {
                   1164:     _mulmdm_dup(mod,p2,m,&t); _FREEMP(m);
                   1165:   }
                   1166: #endif
                   1167: /* get_eg(&t0); */
                   1168:   _addmd_destructive(mod,p1,t,rp);
                   1169: /* get_eg(&t1); add_eg(&eg_red_mod,&t0,&t1); */
                   1170: }
                   1171:
                   1172: /*
                   1173:  * normal form computation
                   1174:  *
                   1175:  */
                   1176:
                   1177: void dp_true_nf(NODE b,DP g,DP *ps,int full,DP *rp,P *dnp)
                   1178: {
                   1179:   DP u,p,d,s,t,dmy;
                   1180:   NODE l;
                   1181:   MP m,mr;
                   1182:   int i,n;
                   1183:   int *wb;
                   1184:   int sugar,psugar;
                   1185:   P dn,tdn,tdn1;
                   1186:
                   1187:   dn = (P)ONE;
                   1188:   if ( !g ) {
                   1189:     *rp = 0; *dnp = dn; return;
                   1190:   }
                   1191:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   1192:   wb = (int *)ALLOCA(n*sizeof(int));
                   1193:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     1194:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     1195:   sugar = g->sugar;
                   1196:   for ( d = 0; g; ) {
                   1197:     for ( u = 0, i = 0; i < n; i++ ) {
                   1198:       if ( dp_redble(g,p = ps[wb[i]]) ) {
                   1199:         dp_red(d,g,p,&t,&u,&tdn,&dmy);
                   1200:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1201:         sugar = MAX(sugar,psugar);
                   1202:         if ( !u ) {
                   1203:           if ( d )
                   1204:             d->sugar = sugar;
                   1205:           *rp = d; *dnp = dn; return;
                   1206:         } else {
                   1207:           d = t;
                   1208:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1209:         }
                   1210:         break;
                   1211:       }
                   1212:     }
                   1213:     if ( u )
                   1214:       g = u;
                   1215:     else if ( !full ) {
                   1216:       if ( g ) {
                   1217:         MKDP(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   1218:       }
                   1219:       *rp = g; *dnp = dn; return;
                   1220:     } else {
                   1221:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   1222:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   1223:       addd(CO,d,t,&s); d = s;
                   1224:       dp_rest(g,&t); g = t;
                   1225:     }
                   1226:   }
                   1227:   if ( d )
                   1228:     d->sugar = sugar;
                   1229:   *rp = d; *dnp = dn;
                   1230: }
                   1231:
                   1232: void dp_removecont2(DP p1,DP p2,DP *r1p,DP *r2p,Z *contp)
                   1233: {
                   1234:   struct oVECT v;
                   1235:   int i,n1,n2,n;
                   1236:   MP m,m0,t;
                   1237:   Z *w;
                   1238:   Z h;
                   1239:
                   1240:   if ( p1 ) {
                   1241:     for ( i = 0, m = BDY(p1); m; m = NEXT(m), i++ );
                   1242:     n1 = i;
                   1243:   } else
                   1244:     n1 = 0;
                   1245:   if ( p2 ) {
                   1246:     for ( i = 0, m = BDY(p2); m; m = NEXT(m), i++ );
                   1247:     n2 = i;
                   1248:   } else
                   1249:     n2 = 0;
                   1250:   n = n1+n2;
                   1251:   if ( !n ) {
                   1252:     *r1p = 0; *r2p = 0; *contp = ONE; return;
                   1253:   }
                   1254:   w = (Z *)ALLOCA(n*sizeof(Q));
                   1255:   v.len = n;
                   1256:   v.body = (pointer *)w;
                   1257:   i = 0;
                   1258:   if ( p1 )
                   1259:     for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = (Z)m->c;
                   1260:   if ( p2 )
                   1261:     for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = (Z)m->c;
1.2       noro     1262:   h = w[0]; removecont_array((P *)w,n,1); divsz(h,w[0],contp);
1.1       noro     1263:   i = 0;
                   1264:   if ( p1 ) {
                   1265:     for ( m0 = 0, t = BDY(p1); i < n1; i++, t = NEXT(t) ) {
                   1266:       NEXTMP(m0,m); m->c = (Obj)w[i]; m->dl = t->dl;
                   1267:     }
                   1268:     NEXT(m) = 0;
                   1269:     MKDP(p1->nv,m0,*r1p); (*r1p)->sugar = p1->sugar;
                   1270:   } else
                   1271:     *r1p = 0;
                   1272:   if ( p2 ) {
                   1273:     for ( m0 = 0, t = BDY(p2); i < n; i++, t = NEXT(t) ) {
                   1274:       NEXTMP(m0,m); m->c = (Obj)w[i]; m->dl = t->dl;
                   1275:     }
                   1276:     NEXT(m) = 0;
                   1277:     MKDP(p2->nv,m0,*r2p); (*r2p)->sugar = p2->sugar;
                   1278:   } else
                   1279:     *r2p = 0;
                   1280: }
                   1281:
1.8       noro     1282: void dpm_removecont2(DPM p1,DPM p2,DPM *r1p,DPM *r2p,Z *contp)
                   1283: {
                   1284:   struct oVECT v;
                   1285:   int i,n1,n2,n;
                   1286:   DMM m,m0,t;
                   1287:   Z *w;
                   1288:   Z h;
                   1289:
                   1290:   if ( p1 ) {
                   1291:     for ( i = 0, m = BDY(p1); m; m = NEXT(m), i++ );
                   1292:     n1 = i;
                   1293:   } else
                   1294:     n1 = 0;
                   1295:   if ( p2 ) {
                   1296:     for ( i = 0, m = BDY(p2); m; m = NEXT(m), i++ );
                   1297:     n2 = i;
                   1298:   } else
                   1299:     n2 = 0;
                   1300:   n = n1+n2;
                   1301:   if ( !n ) {
                   1302:     *r1p = 0; *r2p = 0; *contp = ONE; return;
                   1303:   }
                   1304:   w = (Z *)ALLOCA(n*sizeof(Q));
                   1305:   v.len = n;
                   1306:   v.body = (pointer *)w;
                   1307:   i = 0;
                   1308:   if ( p1 )
                   1309:     for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = (Z)m->c;
                   1310:   if ( p2 )
                   1311:     for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = (Z)m->c;
                   1312:   h = w[0]; removecont_array((P *)w,n,1); divsz(h,w[0],contp);
                   1313:   i = 0;
                   1314:   if ( p1 ) {
                   1315:     for ( m0 = 0, t = BDY(p1); i < n1; i++, t = NEXT(t) ) {
                   1316:       NEXTDMM(m0,m); m->c = (Obj)w[i]; m->dl = t->dl; m->pos = t->pos;
                   1317:     }
                   1318:     NEXT(m) = 0;
                   1319:     MKDPM(p1->nv,m0,*r1p); (*r1p)->sugar = p1->sugar;
                   1320:   } else
                   1321:     *r1p = 0;
                   1322:   if ( p2 ) {
                   1323:     for ( m0 = 0, t = BDY(p2); i < n; i++, t = NEXT(t) ) {
                   1324:       NEXTDMM(m0,m); m->c = (Obj)w[i]; m->dl = t->dl; m->pos = t->pos;
                   1325:     }
                   1326:     NEXT(m) = 0;
                   1327:     MKDPM(p2->nv,m0,*r2p); (*r2p)->sugar = p2->sugar;
                   1328:   } else
                   1329:     *r2p = 0;
                   1330: }
                   1331:
1.1       noro     1332: /* true nf by a marked GB */
                   1333:
                   1334: void dp_true_nf_marked(NODE b,DP g,DP *ps,DP *hps,DP *rp,P *nmp,P *dnp)
                   1335: {
                   1336:   DP u,p,d,s,t,dmy,hp;
                   1337:   NODE l;
                   1338:   MP m,mr;
                   1339:   int i,n,hmag;
                   1340:   int *wb;
                   1341:   int sugar,psugar,multiple;
                   1342:   P nm,tnm1,dn,tdn,tdn1;
                   1343:   Z cont;
                   1344:
                   1345:   multiple = 0;
                   1346:   hmag = multiple*HMAG(g);
                   1347:   nm = (P)ONE;
                   1348:   dn = (P)ONE;
                   1349:   if ( !g ) {
                   1350:     *rp = 0; *dnp = dn; return;
                   1351:   }
                   1352:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   1353:   wb = (int *)ALLOCA(n*sizeof(int));
                   1354:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     1355:     wb[i] = ZTOS((Z)BDY(l));
1.1       noro     1356:   sugar = g->sugar;
                   1357:   for ( d = 0; g; ) {
                   1358:     for ( u = 0, i = 0; i < n; i++ ) {
                   1359:       if ( dp_redble(g,hp = hps[wb[i]]) ) {
                   1360:         p = ps[wb[i]];
                   1361:         dp_red_marked(d,g,p,hp,&t,&u,&tdn,&dmy);
                   1362:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1363:         sugar = MAX(sugar,psugar);
                   1364:         if ( !u ) {
                   1365:           goto last;
                   1366:         } else {
                   1367:           d = t;
                   1368:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1369:         }
                   1370:         break;
                   1371:       }
                   1372:     }
                   1373:     if ( u ) {
                   1374:       g = u;
                   1375:       if ( multiple && ((d && HMAG(d)>hmag) || (HMAG(g)>hmag)) ) {
                   1376:         dp_removecont2(d,g,&t,&u,&cont); d = t; g = u;
                   1377:         mulp(CO,nm,(P)cont,&tnm1); nm = tnm1;
                   1378:         if ( d )
                   1379:           hmag = multiple*HMAG(d);
                   1380:         else
                   1381:           hmag = multiple*HMAG(g);
                   1382:       }
                   1383:     } else {
                   1384:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   1385:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   1386:       addd(CO,d,t,&s); d = s;
                   1387:       dp_rest(g,&t); g = t;
                   1388:     }
                   1389:   }
                   1390: last:
                   1391:   if ( d ) {
                   1392:     dp_removecont2(d,0,&t,&u,&cont); d = t;
                   1393:     mulp(CO,nm,(P)cont,&tnm1); nm = tnm1;
                   1394:     d->sugar = sugar;
                   1395:   }
                   1396:   *rp = d; *nmp = nm; *dnp = dn;
                   1397: }
                   1398:
                   1399: void dp_true_nf_marked_mod(NODE b,DP g,DP *ps,DP *hps,int mod,DP *rp,P *dnp)
                   1400: {
                   1401:   DP hp,u,p,d,s,t,dmy;
                   1402:   NODE l;
                   1403:   MP m,mr;
                   1404:   int i,n;
                   1405:   int *wb;
                   1406:   int sugar,psugar;
                   1407:   P dn,tdn,tdn1;
                   1408:
                   1409:   dn = (P)ONEM;
                   1410:   if ( !g ) {
                   1411:     *rp = 0; *dnp = dn; return;
                   1412:   }
1.3       noro     1413:   for ( n = 0, l = b; l; l = NEXT(l), n++ )
                   1414:     ;
                   1415:   wb = (int *)ALLOCA(n*sizeof(int));
1.1       noro     1416:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     1417:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     1418:   sugar = g->sugar;
                   1419:   for ( d = 0; g; ) {
                   1420:     for ( u = 0, i = 0; i < n; i++ ) {
                   1421:       if ( dp_redble(g,hp = hps[wb[i]]) ) {
                   1422:         p = ps[wb[i]];
                   1423:         dp_red_marked_mod(d,g,p,hp,mod,&t,&u,&tdn,&dmy);
                   1424:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1425:         sugar = MAX(sugar,psugar);
                   1426:         if ( !u ) {
                   1427:           if ( d )
                   1428:             d->sugar = sugar;
                   1429:           *rp = d; *dnp = dn; return;
                   1430:         } else {
                   1431:           d = t;
                   1432:           mulmp(CO,mod,dn,tdn,&tdn1); dn = tdn1;
                   1433:         }
                   1434:         break;
                   1435:       }
                   1436:     }
                   1437:     if ( u )
                   1438:       g = u;
                   1439:     else {
                   1440:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   1441:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   1442:       addmd(CO,mod,d,t,&s); d = s;
                   1443:       dp_rest(g,&t); g = t;
                   1444:     }
                   1445:   }
                   1446:   if ( d )
                   1447:     d->sugar = sugar;
                   1448:   *rp = d; *dnp = dn;
                   1449: }
                   1450:
                   1451: /* true nf by a marked GB and collect quotients */
                   1452:
                   1453: DP *dp_true_nf_and_quotient_marked (NODE b,DP g,DP *ps,DP *hps,DP *rp,P *dnp)
                   1454: {
                   1455:   DP u,p,d,s,t,dmy,hp,mult;
                   1456:   DP *q;
                   1457:   NODE l;
                   1458:   MP m,mr;
                   1459:   int i,n,j;
                   1460:   int *wb;
                   1461:   int sugar,psugar,multiple;
                   1462:   P nm,tnm1,dn,tdn,tdn1;
                   1463:   Q cont;
                   1464:
                   1465:   dn = (P)ONE;
                   1466:   if ( !g ) {
                   1467:     *rp = 0; *dnp = dn; return 0;
                   1468:   }
                   1469:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   1470:   wb = (int *)ALLOCA(n*sizeof(int));
                   1471:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     1472:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     1473:   q = (DP *)MALLOC(n*sizeof(DP));
                   1474:   for ( i = 0; i < n; i++ ) q[i] = 0;
                   1475:   sugar = g->sugar;
                   1476:   for ( d = 0; g; ) {
                   1477:     for ( u = 0, i = 0; i < n; i++ ) {
                   1478:       if ( dp_redble(g,hp = hps[wb[i]]) ) {
                   1479:         p = ps[wb[i]];
                   1480:         dp_red_marked(d,g,p,hp,&t,&u,&tdn,&mult);
                   1481:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1482:         sugar = MAX(sugar,psugar);
                   1483:         for ( j = 0; j < n; j++ ) {
                   1484:           muldc(CO,q[j],(Obj)tdn,&dmy); q[j] = dmy;
                   1485:         }
                   1486:         addd(CO,q[wb[i]],mult,&dmy); q[wb[i]] = dmy;
                   1487:         mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1488:         d = t;
                   1489:         if ( !u ) goto last;
                   1490:         break;
                   1491:       }
                   1492:     }
                   1493:     if ( u ) {
                   1494:       g = u;
                   1495:     } else {
                   1496:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   1497:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   1498:       addd(CO,d,t,&s); d = s;
                   1499:       dp_rest(g,&t); g = t;
                   1500:     }
                   1501:   }
                   1502: last:
                   1503:   if ( d ) d->sugar = sugar;
                   1504:   *rp = d; *dnp = dn;
                   1505:   return q;
                   1506: }
                   1507:
1.5       noro     1508: struct oEGT egred;
                   1509:
                   1510: void mulcmp(Obj c,MP m);
                   1511: void mulcdmm(Obj c,DMM m);
                   1512:
                   1513: DP appendd(DP d,DP m)
                   1514: {
                   1515:   MP t;
                   1516:
                   1517:   if ( !d ) return m;
                   1518:   for ( t = BDY(d); NEXT(t); t = NEXT(t) );
                   1519:   NEXT(t) = BDY(m);
                   1520:   return d;
                   1521: }
                   1522:
                   1523: DPM appenddpm(DPM d,DPM m)
                   1524: {
                   1525:   DMM t;
                   1526:
                   1527:   if ( !d ) return m;
                   1528:   for ( t = BDY(d); NEXT(t); t = NEXT(t) );
                   1529:   NEXT(t) = BDY(m);
                   1530:   return d;
                   1531: }
1.4       noro     1532:
1.3       noro     1533: DP *dpm_nf_and_quotient(NODE b,DPM g,VECT psv,DPM *rp,P *dnp)
                   1534: {
1.5       noro     1535:   DPM u,p,s,t,d;
                   1536:   DP dmy,mult,zzz;
1.3       noro     1537:   DPM *ps;
                   1538:   DP *q;
                   1539:   NODE l;
                   1540:   DMM m,mr;
1.5       noro     1541:   MP mp;
                   1542:   int i,n,j,len,nv;
1.3       noro     1543:   int *wb;
                   1544:   int sugar,psugar,multiple;
                   1545:   P nm,tnm1,dn,tdn,tdn1;
                   1546:   Q cont;
1.4       noro     1547:   struct oEGT eg0,eg1;
1.3       noro     1548:
                   1549:   dn = (P)ONE;
                   1550:   if ( !g ) {
                   1551:     *rp = 0; *dnp = dn; return 0;
                   1552:   }
1.5       noro     1553:   nv = NV(g);
1.3       noro     1554:   ps = (DPM *)BDY(psv);
                   1555:   len = psv->len;
                   1556:   if ( b ) {
                   1557:     for ( n = 0, l = b; l; l = NEXT(l), n++ )
                   1558:       ;
                   1559:     wb = (int *)ALLOCA(n*sizeof(int));
                   1560:     for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
                   1561:       wb[i] = ZTOS((Q)BDY(l));
                   1562:   } else {
                   1563:     wb = (int *)ALLOCA(len*sizeof(int));
                   1564:     for ( i = j = 0; i < len; i++ )
                   1565:       if ( ps[i] ) wb[j++] = i;
                   1566:     n = j;
                   1567:   }
                   1568:   q = (DP *)MALLOC(len*sizeof(DP));
                   1569:   for ( i = 0; i < len; i++ ) q[i] = 0;
                   1570:   sugar = g->sugar;
                   1571:   for ( d = 0; g; ) {
                   1572:     for ( u = 0, i = 0; i < n; i++ ) {
                   1573:       if ( dpm_redble(g,p = ps[wb[i]]) ) {
1.5       noro     1574: // get_eg(&eg0);
                   1575:         dpm_red2(g,p,&u,&tdn,&mult);
                   1576: // get_eg(&eg1); add_eg(&egred,&eg0,&eg1);
1.3       noro     1577:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1578:         sugar = MAX(sugar,psugar);
                   1579:         for ( j = 0; j < len; j++ ) {
1.5       noro     1580:           if ( q[j] ) { mulcmp((Obj)tdn,BDY(q[j])); }
1.3       noro     1581:         }
1.5       noro     1582:         q[wb[i]] = appendd(q[wb[i]],mult);
1.3       noro     1583:         mulp(CO,dn,tdn,&tdn1); dn = tdn1;
1.5       noro     1584:         if ( d ) mulcdmm((Obj)tdn,BDY(d));
1.3       noro     1585:         if ( !u ) goto last;
                   1586:         break;
                   1587:       }
                   1588:     }
                   1589:     if ( u ) {
                   1590:       g = u;
                   1591:     } else {
                   1592:       m = BDY(g); NEWDMM(mr); mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1593:       NEXT(mr) = 0; MKDPM(g->nv,mr,t); t->sugar = mr->dl->td;
1.5       noro     1594:       d = appenddpm(d,t);
1.3       noro     1595:       dpm_rest(g,&t); g = t;
                   1596:     }
                   1597:   }
                   1598: last:
                   1599:   if ( d ) d->sugar = sugar;
                   1600:   *rp = d; *dnp = dn;
                   1601:   return q;
                   1602: }
                   1603:
1.9       noro     1604: DPM dpm_nf_and_quotient2(NODE b,DPM g,VECT psv,DPM *rp,P *dnp)
                   1605: {
                   1606:   DPM u,p,s,t,d,q;
                   1607:   DP dmy,mult,zzz;
                   1608:   DPM *ps;
                   1609:   NODE l;
                   1610:   DMM mr0,mq0,mr,mq,m;
                   1611:   MP mp;
                   1612:   int i,n,j,len,nv;
                   1613:   int *wb;
                   1614:   int sugar,psugar,multiple;
                   1615:   P nm,tnm1,dn,tdn,tdn1;
                   1616:   Q cont;
                   1617:   Obj c1;
                   1618:   struct oEGT eg0,eg1;
                   1619:
                   1620:   dn = (P)ONE;
                   1621:   if ( !g ) {
                   1622:     *rp = 0; *dnp = dn; return 0;
                   1623:   }
                   1624:   nv = NV(g);
                   1625:   ps = (DPM *)BDY(psv);
                   1626:   len = psv->len;
                   1627:   if ( b ) {
                   1628:     for ( n = 0, l = b; l; l = NEXT(l), n++ )
                   1629:       ;
                   1630:     wb = (int *)ALLOCA(n*sizeof(int));
                   1631:     for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
                   1632:       wb[i] = ZTOS((Q)BDY(l));
                   1633:   } else {
                   1634:     wb = (int *)ALLOCA(len*sizeof(int));
                   1635:     for ( i = j = 0; i < len; i++ )
                   1636:       if ( ps[i] ) wb[j++] = i;
                   1637:     n = j;
                   1638:   }
                   1639:   sugar = g->sugar;
                   1640:   mq0 = 0;
                   1641:   mr0 = 0;
                   1642:   for ( ; g; ) {
                   1643:     for ( u = 0, i = 0; i < n; i++ ) {
                   1644:       if ( dpm_redble(g,p = ps[wb[i]]) ) {
                   1645:         dpm_red2(g,p,&u,&tdn,&mult);
                   1646:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1647:         sugar = MAX(sugar,psugar);
                   1648:         for ( m = mq0; m; m = NEXT(m) ) {
                   1649:           arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1650:         }
                   1651:         for ( m = mr0; m; m = NEXT(m) ) {
                   1652:           arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1653:         }
                   1654:         NEXTDMM(mq0,mq);
                   1655:         mq->c = BDY(mult)->c; mq->dl = BDY(mult)->dl; mq->pos = wb[i]+1;
                   1656:         mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1657:         if ( !u ) goto last;
                   1658:         break;
                   1659:       }
                   1660:     }
                   1661:     if ( u ) {
                   1662:       g = u;
                   1663:     } else {
                   1664:       m = BDY(g);
                   1665:       NEXTDMM(mr0,mr);
                   1666:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1667:       dpm_rest(g,&t); g = t;
                   1668:     }
                   1669:   }
                   1670: last:
                   1671:   if ( mr0 ) {
                   1672:     NEXT(mr) = 0;
                   1673:     MKDPM(nv,mr0,d); d->sugar = sugar;
                   1674:   } else
                   1675:     d = 0;
                   1676:   if ( mq0 ) {
                   1677:     NEXT(mq) = 0;
                   1678:     MKDPM(nv,mq0,q); q->sugar = sugar;
                   1679:   } else
                   1680:     q = 0;
                   1681:   *rp = d; *dnp = dn;
                   1682:   return q;
                   1683: }
                   1684:
                   1685: DPM dpm_nf_and_quotient3(DPM g,VECT psv,DPM *rp,P *dnp)
                   1686: {
                   1687:   DPM u,p,s,t,d,q;
                   1688:   DP dmy,mult,zzz;
                   1689:   DPM *ps;
                   1690:   NODE2 nd;
                   1691:   DMM mr0,mq0,mr,mq,m;
                   1692:   MP mp;
                   1693:   int i,n,j,len,nv,pos,max;
                   1694:   int *wb;
                   1695:   int sugar,psugar,multiple;
                   1696:   P nm,tnm1,dn,tdn,tdn1;
                   1697:   Q cont;
                   1698:   Obj c1;
                   1699:   struct oEGT eg0,eg1;
                   1700:
                   1701:   dn = (P)ONE;
                   1702:   if ( !g ) {
                   1703:     *rp = 0; *dnp = dn; return 0;
                   1704:   }
                   1705:   nv = NV(g);
                   1706:   sugar = g->sugar;
                   1707:   mq0 = 0;
                   1708:   mr0 = 0;
                   1709:   max = psv->len;
                   1710:   for ( ; g; ) {
                   1711:     pos = BDY(g)->pos;
                   1712:     u = 0;
                   1713:     if ( pos < max ) {
                   1714:       nd = (NODE2)BDY(psv)[pos];
                   1715:       for ( u = 0; nd; nd = NEXT(nd) ) {
                   1716:         if ( dpm_redble(g,p = (DPM)(nd->body1)) ) {
                   1717:           dpm_red2(g,p,&u,&tdn,&mult);
                   1718:           psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1719:           sugar = MAX(sugar,psugar);
                   1720:           if ( !UNIZ(tdn) ) {
                   1721:             for ( m = mq0; m; m = NEXT(m) ) {
                   1722:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1723:             }
                   1724:             for ( m = mr0; m; m = NEXT(m) ) {
                   1725:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1726:             }
                   1727:           }
                   1728:           NEXTDMM(mq0,mq);
                   1729:           mq->c = BDY(mult)->c; mq->dl = BDY(mult)->dl; mq->pos = (long)nd->body2;
                   1730:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1731:           if ( !u ) goto last;
                   1732:           break;
                   1733:         }
                   1734:       }
                   1735:     }
                   1736:     if ( u ) {
                   1737:       g = u;
                   1738:     } else {
                   1739:       m = BDY(g);
                   1740:       NEXTDMM(mr0,mr);
                   1741:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1742:       dpm_rest(g,&t); g = t;
                   1743:     }
                   1744:   }
                   1745: last:
                   1746:   if ( mr0 ) {
                   1747:     NEXT(mr) = 0;
                   1748:     MKDPM(nv,mr0,d); d->sugar = sugar;
                   1749:   } else
                   1750:     d = 0;
                   1751:   if ( mq0 ) {
                   1752:     NEXT(mq) = 0;
                   1753:     MKDPM(nv,mq0,q); q->sugar = sugar;
                   1754:   } else
                   1755:     q = 0;
                   1756:   *rp = d; *dnp = dn;
                   1757:   return q;
                   1758: }
                   1759:
                   1760: DPM dpm_nf_and_quotient4(DPM g,DPM *ps,VECT psiv,DPM head,DPM *rp,P *dnp)
                   1761: {
                   1762:   DPM u,p,s,t,d,q;
                   1763:   DP dmy,mult,zzz;
                   1764:   NODE nd;
                   1765:   DMM mr0,mq0,mr,mq,m;
                   1766:   MP mp;
                   1767:   int i,n,j,len,nv,pos,max;
                   1768:   int *wb;
                   1769:   int sugar,psugar,multiple;
                   1770:   P nm,tnm1,dn,tdn,tdn1,c;
                   1771:   Q cont;
                   1772:   Obj c1;
                   1773:   struct oEGT eg0,eg1;
                   1774:
                   1775:   dn = (P)ONE;
                   1776:   if ( !g ) {
                   1777:     *rp = 0; *dnp = dn; return 0;
                   1778:   }
                   1779:   nv = NV(g);
                   1780:   sugar = g->sugar;
                   1781:   mq0 = 0;
                   1782:   if ( head ) {
                   1783:     for ( m = BDY(head); m; m = NEXT(m) ) {
                   1784:       NEXTDMM(mq0,mq);
                   1785:       mq->c = m->c; mq->dl = m->dl; mq->pos = m->pos;
                   1786:     }
                   1787:   }
                   1788:   mr0 = 0;
                   1789:   max = psiv->len;
                   1790:   for ( ; g; ) {
                   1791:     pos = BDY(g)->pos;
                   1792:     u = 0;
                   1793:     if ( pos < max ) {
                   1794:       nd = (NODE)BDY(psiv)[pos];
                   1795:       for ( u = 0; nd; nd = NEXT(nd) ) {
                   1796:         if ( dpm_redble(g,p = ps[(long)(BDY(nd))-1]) ) {
                   1797:           dpm_red2(g,p,&u,&tdn,&mult);
                   1798:           psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1799:           sugar = MAX(sugar,psugar);
                   1800:           if ( !UNIZ(tdn) ) {
                   1801:             for ( m = mq0; m; m = NEXT(m) ) {
                   1802:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1803:             }
                   1804:             for ( m = mr0; m; m = NEXT(m) ) {
                   1805:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1806:             }
                   1807:           }
                   1808:           NEXTDMM(mq0,mq);
                   1809:           mq->c = BDY(mult)->c;
                   1810:           mq->dl = BDY(mult)->dl; mq->pos = (long)BDY(nd);
                   1811:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1812:           if ( !u ) goto last;
                   1813:           break;
                   1814:         }
                   1815:       }
                   1816:     }
                   1817:     if ( u ) {
                   1818:       g = u;
                   1819:     } else {
                   1820:       m = BDY(g);
                   1821:       NEXTDMM(mr0,mr);
                   1822:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1823:       dpm_rest(g,&t); g = t;
                   1824:     }
                   1825:   }
                   1826: last:
                   1827:   if ( mr0 ) {
                   1828:     NEXT(mr) = 0;
                   1829:     MKDPM(nv,mr0,d); d->sugar = sugar;
                   1830:   } else
                   1831:     d = 0;
                   1832:   if ( mq0 ) {
                   1833:     NEXT(mq) = 0;
                   1834:     MKDPM(nv,mq0,q); q->sugar = sugar;
                   1835:   } else
                   1836:     q = 0;
                   1837:   *rp = d; *dnp = dn;
                   1838:   return q;
                   1839: }
                   1840:
1.10      noro     1841: /* an intermediate version for calling from the user language */
1.11      noro     1842: /* XXX : i, j must be positive */
1.10      noro     1843:
                   1844: DPM dpm_sp_nf_asir(VECT psv,int i,int j,DPM *nf)
                   1845: {
                   1846:   DPM *ps;
1.11      noro     1847:   int n,k,nv,s1,s2,sugar,max,pos,psugar;
1.10      noro     1848:   DPM g,u,p,d,q,t;
                   1849:   DMM mq0,mq,mr0,mr,m;
                   1850:   DP mult,t1,t2;
                   1851:   P dn,tdn,tdn1;
                   1852:   NODE nd;
                   1853:   Obj c1;
                   1854:
                   1855:   ps = (DPM *)BDY(psv);
                   1856:   n = psv->len;
                   1857:   nv = ps[1]->nv;
                   1858:   dpm_sp(ps[i],ps[j],&g,&t1,&t2);
                   1859:   mq0 = 0;
                   1860:   NEXTDMM(mq0,mq); mq->c = BDY(t1)->c; mq->pos = i; mq->dl = BDY(t1)->dl;
                   1861:   NEXTDMM(mq0,mq); chsgnp((P)BDY(t2)->c,(P *)&mq->c); mq->pos = j; mq->dl = BDY(t2)->dl;
                   1862:
                   1863:   if ( !g ) {
                   1864:     NEXT(mq) = 0;
                   1865:     MKDPM(nv,mq0,d);
                   1866:     s1 = BDY(t1)->dl->td + ps[i]->sugar;
                   1867:     s2 = BDY(t2)->dl->td + ps[j]->sugar;
                   1868:     d->sugar = MAX(s1,s2);
                   1869:     *nf = 0;
                   1870:     return d;
                   1871:   }
                   1872:
                   1873:   dn = (P)ONE;
                   1874:   sugar = g->sugar;
                   1875:   mr0 = 0;
                   1876:   while ( g ) {
1.11      noro     1877:     pos = BDY(g)->pos;
                   1878:     for ( u = 0, k = 1; k < n; k++ ) {
                   1879:       if ( (p=ps[k])!=0 && pos == BDY(p)->pos && dpm_redble(g,p) ) {
1.10      noro     1880:         dpm_red2(g,p,&u,&tdn,&mult);
                   1881:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1882:         sugar = MAX(sugar,psugar);
                   1883:         if ( !UNIZ(tdn) ) {
                   1884:           for ( m = mq0; m; m = NEXT(m) ) {
                   1885:             arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1886:           }
                   1887:           for ( m = mr0; m; m = NEXT(m) ) {
                   1888:             arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1889:           }
                   1890:         }
                   1891:         NEXTDMM(mq0,mq);
                   1892:         chsgnp((P)BDY(mult)->c,(P *)&mq->c);
1.11      noro     1893:         mq->dl = BDY(mult)->dl; mq->pos = k;
1.10      noro     1894:         mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1895:         if ( !u ) goto last;
                   1896:         break;
                   1897:       }
                   1898:     }
                   1899:     if ( u ) {
                   1900:       g = u;
                   1901:     } else {
                   1902:       m = BDY(g);
                   1903:       NEXTDMM(mr0,mr);
                   1904:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1905:       dpm_rest(g,&t); g = t;
                   1906:     }
                   1907:   }
                   1908: last:
                   1909:   if ( mr0 ) {
                   1910:     NEXT(mr) = 0; MKDPM(nv,mr0,d); d->sugar = sugar;
                   1911:   } else
                   1912:     d = 0;
                   1913:   NEXT(mq) = 0; MKDPM(nv,mq0,q); q->sugar = sugar;
                   1914:   *nf = d;
                   1915:   return q;
                   1916: }
                   1917:
1.9       noro     1918: DPM dpm_sp_nf(VECT psv,VECT psiv,int i,int j,DPM *nf)
                   1919: {
                   1920:   DPM *ps;
                   1921:   int n,nv,s1,s2,sugar,max,pos,psugar;
                   1922:   DPM g,u,p,d,q,t;
                   1923:   DMM mq0,mq,mr0,mr,m;
                   1924:   DP mult,t1,t2;
                   1925:   P dn,tdn,tdn1;
                   1926:   NODE nd;
                   1927:   Obj c1;
                   1928:
                   1929:   ps = (DPM *)BDY(psv);
                   1930:   n = psv->len;
1.12      noro     1931:   nv = ps[i]->nv;
1.9       noro     1932:   dpm_sp(ps[i],ps[j],&g,&t1,&t2);
                   1933:   mq0 = 0;
                   1934:   NEXTDMM(mq0,mq); mq->c = BDY(t1)->c; mq->pos = i; mq->dl = BDY(t1)->dl;
                   1935:   NEXTDMM(mq0,mq); chsgnp((P)BDY(t2)->c,(P *)&mq->c); mq->pos = j; mq->dl = BDY(t2)->dl;
                   1936:
                   1937:   if ( !g ) {
                   1938:     NEXT(mq) = 0;
                   1939:     MKDPM(nv,mq0,d);
                   1940:     s1 = BDY(t1)->dl->td + ps[i]->sugar;
                   1941:     s2 = BDY(t2)->dl->td + ps[j]->sugar;
                   1942:     d->sugar = MAX(s1,s2);
                   1943:     *nf = 0;
                   1944:     return d;
                   1945:   }
                   1946:
                   1947:   dn = (P)ONE;
                   1948:   sugar = g->sugar;
                   1949:   mr0 = 0;
                   1950:   max = psiv->len;
                   1951:   while ( g ) {
                   1952:     pos = BDY(g)->pos;
                   1953:     u = 0;
                   1954:     if ( pos < max ) {
                   1955:       nd = (NODE)BDY(psiv)[pos];
                   1956:       for ( u = 0; nd; nd = NEXT(nd) ) {
                   1957:         if ( dpm_redble(g,p = ps[(long)(BDY(nd))]) ) {
                   1958:           dpm_red2(g,p,&u,&tdn,&mult);
                   1959:           psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   1960:           sugar = MAX(sugar,psugar);
                   1961:           if ( !UNIZ(tdn) ) {
                   1962:             for ( m = mq0; m; m = NEXT(m) ) {
                   1963:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1964:             }
                   1965:             for ( m = mr0; m; m = NEXT(m) ) {
                   1966:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   1967:             }
                   1968:           }
                   1969:           NEXTDMM(mq0,mq);
                   1970:           chsgnp((P)BDY(mult)->c,(P *)&mq->c);
                   1971:           mq->dl = BDY(mult)->dl; mq->pos = (long)BDY(nd);
                   1972:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   1973:           if ( !u ) goto last;
                   1974:           break;
                   1975:         }
                   1976:       }
                   1977:     }
                   1978:     if ( u ) {
                   1979:       g = u;
                   1980:     } else {
                   1981:       m = BDY(g);
                   1982:       NEXTDMM(mr0,mr);
                   1983:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   1984:       dpm_rest(g,&t); g = t;
                   1985:     }
                   1986:   }
                   1987: last:
                   1988:   if ( mr0 ) {
                   1989:     NEXT(mr) = 0; MKDPM(nv,mr0,d); d->sugar = sugar;
                   1990:   } else
                   1991:     d = 0;
                   1992:   NEXT(mq) = 0; MKDPM(nv,mq0,q); q->sugar = sugar;
                   1993:   *nf = d;
                   1994:   return q;
                   1995: }
                   1996:
1.11      noro     1997: /* psiv is a vector of lists of Z */
                   1998:
1.13      noro     1999: DPM dpm_sp_nf_zlist(VECT psv,VECT psiv,int i,int j,int top,DPM *nf)
1.11      noro     2000: {
                   2001:   DPM *ps;
                   2002:   int n,nv,s1,s2,sugar,max,pos,psugar;
                   2003:   DPM g,u,p,d,q,t;
                   2004:   DMM mq0,mq,mr0,mr,m;
                   2005:   DP mult,t1,t2;
                   2006:   P dn,tdn,tdn1;
                   2007:   NODE nd;
                   2008:   Obj c1;
                   2009:
                   2010:   ps = (DPM *)BDY(psv);
                   2011:   n = psv->len;
1.12      noro     2012:   nv = ps[i]->nv;
1.11      noro     2013:   dpm_sp(ps[i],ps[j],&g,&t1,&t2);
                   2014:   mq0 = 0;
                   2015:   NEXTDMM(mq0,mq); mq->c = BDY(t1)->c; mq->pos = i; mq->dl = BDY(t1)->dl;
                   2016:   NEXTDMM(mq0,mq); chsgnp((P)BDY(t2)->c,(P *)&mq->c); mq->pos = j; mq->dl = BDY(t2)->dl;
                   2017:
                   2018:   if ( !g ) {
                   2019:     NEXT(mq) = 0;
                   2020:     MKDPM(nv,mq0,d);
                   2021:     s1 = BDY(t1)->dl->td + ps[i]->sugar;
                   2022:     s2 = BDY(t2)->dl->td + ps[j]->sugar;
                   2023:     d->sugar = MAX(s1,s2);
                   2024:     *nf = 0;
                   2025:     return d;
                   2026:   }
                   2027:
                   2028:   dn = (P)ONE;
                   2029:   sugar = g->sugar;
                   2030:   mr0 = 0;
                   2031:   max = psiv->len;
                   2032:   while ( g ) {
                   2033:     pos = BDY(g)->pos;
                   2034:     u = 0;
                   2035:     if ( pos < max ) {
                   2036:       nd = BDY((LIST)BDY(psiv)[pos]);
                   2037:       for ( u = 0; nd; nd = NEXT(nd) ) {
                   2038:         if ( dpm_redble(g,p = ps[ZTOS((Q)BDY(nd))]) ) {
                   2039:           dpm_red2(g,p,&u,&tdn,&mult);
                   2040:           psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2041:           sugar = MAX(sugar,psugar);
                   2042:           if ( !UNIZ(tdn) ) {
                   2043:             for ( m = mq0; m; m = NEXT(m) ) {
                   2044:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   2045:             }
                   2046:             for ( m = mr0; m; m = NEXT(m) ) {
                   2047:               arf_mul(CO,(Obj)tdn,m->c,&c1); m->c = c1;
                   2048:             }
                   2049:           }
                   2050:           NEXTDMM(mq0,mq);
                   2051:           chsgnp((P)BDY(mult)->c,(P *)&mq->c);
                   2052:           mq->dl = BDY(mult)->dl; mq->pos = ZTOS((Q)BDY(nd));
                   2053:           mulp(CO,dn,tdn,&tdn1); dn = tdn1;
                   2054:           if ( !u ) goto last;
                   2055:           break;
                   2056:         }
                   2057:       }
                   2058:     }
                   2059:     if ( u ) {
                   2060:       g = u;
1.13      noro     2061:     } else if ( !top ) {
1.11      noro     2062:       m = BDY(g);
                   2063:       NEXTDMM(mr0,mr);
                   2064:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   2065:       dpm_rest(g,&t); g = t;
1.13      noro     2066:     } else {
1.12      noro     2067:       *nf = g;
                   2068:       if ( mq0 ) {
                   2069:         NEXT(mq) = 0; MKDPM(nv,mq0,q); q->sugar = sugar;
                   2070:       } else
                   2071:         q = 0;
                   2072:       return q;
1.11      noro     2073:     }
                   2074:   }
                   2075: last:
                   2076:   if ( mr0 ) {
                   2077:     NEXT(mr) = 0; MKDPM(nv,mr0,d); d->sugar = sugar;
                   2078:   } else
                   2079:     d = 0;
                   2080:   NEXT(mq) = 0; MKDPM(nv,mq0,q); q->sugar = sugar;
                   2081:   *nf = d;
                   2082:   return q;
                   2083: }
                   2084:
1.1       noro     2085: DP *dp_true_nf_and_quotient_marked_mod(NODE b,DP g,DP *ps,DP *hps,int mod,DP *rp,P *dnp)
                   2086: {
                   2087:   DP u,p,d,s,t,dmy,hp,mult;
                   2088:   DP *q;
                   2089:   NODE l;
                   2090:   MP m,mr;
                   2091:   int i,n,j;
                   2092:   int *wb;
                   2093:   int sugar,psugar;
                   2094:   P dn,tdn,tdn1;
                   2095:
                   2096:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   2097:   q = (DP *)MALLOC(n*sizeof(DP));
                   2098:   for ( i = 0; i < n; i++ ) q[i] = 0;
                   2099:   dn = (P)ONEM;
                   2100:   if ( !g ) {
                   2101:     *rp = 0; *dnp = dn; return 0;
                   2102:   }
                   2103:   wb = (int *)ALLOCA(n*sizeof(int));
                   2104:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     2105:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     2106:   sugar = g->sugar;
                   2107:   for ( d = 0; g; ) {
                   2108:     for ( u = 0, i = 0; i < n; i++ ) {
                   2109:       if ( dp_redble(g,hp = hps[wb[i]]) ) {
                   2110:         p = ps[wb[i]];
                   2111:         dp_red_marked_mod(d,g,p,hp,mod,&t,&u,&tdn,&mult);
                   2112:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2113:         sugar = MAX(sugar,psugar);
                   2114:         for ( j = 0; j < n; j++ ) {
                   2115:           mulmdc(CO,mod,q[j],(P)tdn,&dmy); q[j] = dmy;
                   2116:         }
                   2117:         addmd(CO,mod,q[wb[i]],mult,&dmy); q[wb[i]] = dmy;
                   2118:         mulmp(CO,mod,dn,tdn,&tdn1); dn = tdn1;
                   2119:         d = t;
                   2120:         if ( !u ) goto last;
                   2121:         break;
                   2122:       }
                   2123:     }
                   2124:     if ( u )
                   2125:       g = u;
                   2126:     else {
                   2127:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   2128:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   2129:       addmd(CO,mod,d,t,&s); d = s;
                   2130:       dp_rest(g,&t); g = t;
                   2131:     }
                   2132:   }
                   2133: last:
                   2134:   if ( d )
                   2135:     d->sugar = sugar;
                   2136:   *rp = d; *dnp = dn;
                   2137:   return q;
                   2138: }
                   2139:
                   2140: /* nf computation over Z */
                   2141:
                   2142: void dp_nf_z(NODE b,DP g,DP *ps,int full,int multiple,DP *rp)
                   2143: {
                   2144:   DP u,p,d,s,t,dmy1;
                   2145:   P dmy;
                   2146:   NODE l;
                   2147:   MP m,mr;
                   2148:   int i,n;
                   2149:   int *wb;
                   2150:   int hmag;
                   2151:   int sugar,psugar;
                   2152:
                   2153:   if ( !g ) {
                   2154:     *rp = 0; return;
                   2155:   }
                   2156:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   2157:   wb = (int *)ALLOCA(n*sizeof(int));
                   2158:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     2159:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     2160:
                   2161:   hmag = multiple*HMAG(g);
                   2162:   sugar = g->sugar;
                   2163:
                   2164:   for ( d = 0; g; ) {
                   2165:     for ( u = 0, i = 0; i < n; i++ ) {
                   2166:       if ( dp_redble(g,p = ps[wb[i]]) ) {
                   2167:         dp_red(d,g,p,&t,&u,&dmy,&dmy1);
                   2168:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2169:         sugar = MAX(sugar,psugar);
                   2170:         if ( !u ) {
                   2171:           if ( d )
                   2172:             d->sugar = sugar;
                   2173:           *rp = d; return;
                   2174:         }
                   2175:         d = t;
                   2176:         break;
                   2177:       }
                   2178:     }
                   2179:     if ( u ) {
                   2180:       g = u;
                   2181:       if ( d ) {
                   2182:         if ( multiple && HMAG(d) > hmag ) {
                   2183:           dp_ptozp2(d,g,&t,&u); d = t; g = u;
                   2184:           hmag = multiple*HMAG(d);
                   2185:         }
                   2186:       } else {
                   2187:         if ( multiple && HMAG(g) > hmag ) {
                   2188:           dp_ptozp(g,&t); g = t;
                   2189:           hmag = multiple*HMAG(g);
                   2190:         }
                   2191:       }
                   2192:     }
                   2193:     else if ( !full ) {
                   2194:       if ( g ) {
                   2195:         MKDP(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2196:       }
                   2197:       *rp = g; return;
                   2198:     } else {
                   2199:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   2200:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   2201:       addd(CO,d,t,&s); d = s;
                   2202:       dp_rest(g,&t); g = t;
                   2203:
                   2204:     }
                   2205:   }
                   2206:   if ( d )
                   2207:     d->sugar = sugar;
                   2208:   *rp = d;
                   2209: }
                   2210:
1.4       noro     2211: void dpm_nf_z(NODE b,DPM g,VECT psv,int full,int multiple,DPM *rp)
1.1       noro     2212: {
1.4       noro     2213:   DPM *ps;
1.1       noro     2214:   DPM u,p,d,s,t;
                   2215:   DP dmy1;
                   2216:   P dmy;
1.3       noro     2217:   Z cont;
1.1       noro     2218:   NODE l;
                   2219:   DMM m,mr;
                   2220:   int i,n;
                   2221:   int *wb;
                   2222:   int hmag;
                   2223:   int sugar,psugar;
                   2224:
                   2225:   if ( !g ) {
                   2226:     *rp = 0; return;
                   2227:   }
1.4       noro     2228:   if ( b ) {
                   2229:     for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   2230:     wb = (int *)ALLOCA(n*sizeof(int));
                   2231:     for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
                   2232:       wb[i] = ZTOS((Q)BDY(l));
                   2233:     ps = (DPM *)BDY(psv);
                   2234:   } else {
                   2235:     n = psv->len;
                   2236:     wb = (int *)MALLOC(n*sizeof(int));
                   2237:     for ( i = 0; i < n; i++ ) wb[i] = i;
                   2238:     ps = (DPM *)BDY(psv);
                   2239:   }
1.1       noro     2240:
                   2241:   hmag = multiple*HMAG(g);
                   2242:   sugar = g->sugar;
                   2243:
                   2244:   for ( d = 0; g; ) {
                   2245:     for ( u = 0, i = 0; i < n; i++ ) {
1.4       noro     2246:       if ( (p=ps[wb[i]])!=0 && dpm_redble(g,p) ) {
1.5       noro     2247:         dpm_red2(g,p,&u,&dmy,&dmy1);
1.1       noro     2248:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2249:         sugar = MAX(sugar,psugar);
1.5       noro     2250:         if ( d ) mulcdmm((Obj)dmy,BDY(d));
1.1       noro     2251:         if ( !u ) {
                   2252:           if ( d )
                   2253:             d->sugar = sugar;
                   2254:           *rp = d; return;
                   2255:         }
                   2256:         break;
                   2257:       }
                   2258:     }
                   2259:     if ( u ) {
                   2260:       g = u;
                   2261:       if ( d ) {
                   2262:         if ( multiple && HMAG(d) > hmag ) {
                   2263:           dpm_ptozp2(d,g,&t,&u); d = t; g = u;
                   2264:           hmag = multiple*HMAG(d);
                   2265:         }
                   2266:       } else {
                   2267:         if ( multiple && HMAG(g) > hmag ) {
1.3       noro     2268:           dpm_ptozp(g,&cont,&t); g = t;
1.1       noro     2269:           hmag = multiple*HMAG(g);
                   2270:         }
                   2271:       }
                   2272:     }
                   2273:     else if ( !full ) {
                   2274:       if ( g ) {
                   2275:         MKDPM(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2276:       }
                   2277:       *rp = g; return;
                   2278:     } else {
                   2279:       m = BDY(g); NEWDMM(mr); mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   2280:       NEXT(mr) = 0; MKDPM(g->nv,mr,t); t->sugar = mr->dl->td;
1.5       noro     2281:       d = appenddpm(d,t);
1.1       noro     2282:       dpm_rest(g,&t); g = t;
                   2283:     }
                   2284:   }
                   2285:   if ( d )
                   2286:     d->sugar = sugar;
                   2287:   *rp = d;
                   2288: }
                   2289:
1.3       noro     2290: void dpm_shift(DPM p,int s,DPM *r)
                   2291: {
                   2292:   DMM m,mr0,mr;
                   2293:   DPM t;
                   2294:
                   2295:   if ( !p ) *r = 0;
                   2296:   else {
                   2297:     for ( m = BDY(p), mr0 = 0; m; m = NEXT(m) ) {
                   2298:       NEXTDMM(mr0,mr);
                   2299:       mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos-s;
                   2300:       if ( mr->pos <= 0 )
                   2301:         error("dpm_shift : too large shift value");
                   2302:     }
                   2303:     NEXT(mr) = 0;
                   2304:     MKDPM(p->nv,mr0,t); t->sugar = p->sugar;
                   2305:     *r = t;
                   2306:   }
                   2307: }
                   2308:
                   2309: // up=sum{c*<<...:i>>|i<=s}, lo=sum{c*<<...:i>>|i>s}
                   2310:
                   2311: void dpm_split(DPM p,int s,DPM *up,DPM *lo)
                   2312: {
                   2313:   DMM m,mu0,mu,ml0,ml;
                   2314:   DPM t;
                   2315:
                   2316:   if ( !p ) {
                   2317:     *up = 0; *lo = 0;
                   2318:   } else {
                   2319:     for ( m = BDY(p), mu0 = ml0 = 0; m; m = NEXT(m) ) {
                   2320:       if ( m->pos <= s ) {
                   2321:         NEXTDMM(mu0,mu);
                   2322:         mu->dl = m->dl; mu->c = m->c; mu->pos = m->pos;
                   2323:       } else {
                   2324:         NEXTDMM(ml0,ml);
                   2325:         ml->dl = m->dl; ml->c = m->c; ml->pos = m->pos;
                   2326:       }
                   2327:     }
                   2328:     if ( mu0 ) {
                   2329:       NEXT(mu) = 0; MKDPM(p->nv,mu0,t); t->sugar = p->sugar;
                   2330:       *up = t;
                   2331:     } else
                   2332:       *up = 0;
                   2333:     if ( ml0 ) {
                   2334:       NEXT(ml) = 0; MKDPM(p->nv,ml0,t); t->sugar = p->sugar;
                   2335:       *lo = t;
                   2336:     } else
                   2337:       *lo = 0;
                   2338:   }
                   2339: }
                   2340:
1.13      noro     2341: /* extract the component in DP of position s */
                   2342: void dpm_extract(DPM p,int s,DP *r)
                   2343: {
                   2344:   DMM m;
                   2345:   MP mu0,mu;
                   2346:   DP t;
                   2347:
                   2348:   if ( !p ) {
                   2349:     *r = 0; return;
                   2350:   }
                   2351:   for ( m = BDY(p), mu0 = 0; m; m = NEXT(m) ) {
                   2352:     if ( m->pos == s ) {
                   2353:       NEXTMP(mu0,mu);
                   2354:       mu->dl = m->dl; mu->c = m->c;
                   2355:     }
                   2356:   }
                   2357:   if ( mu0 ) {
                   2358:     NEXT(mu) = 0; MKDP(p->nv,mu0,t); t->sugar = p->sugar;
                   2359:     *r = t;
                   2360:   } else
                   2361:     *r = 0;
                   2362: }
                   2363:
1.1       noro     2364: /* nf computation over a field */
                   2365:
                   2366: void dp_nf_f(NODE b,DP g,DP *ps,int full,DP *rp)
                   2367: {
                   2368:   DP u,p,d,s,t;
                   2369:   NODE l;
                   2370:   MP m,mr;
                   2371:   int i,n;
                   2372:   int *wb;
                   2373:   int sugar,psugar;
                   2374:
                   2375:   if ( !g ) {
                   2376:     *rp = 0; return;
                   2377:   }
                   2378:   for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   2379:   wb = (int *)ALLOCA(n*sizeof(int));
                   2380:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     2381:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     2382:
                   2383:   sugar = g->sugar;
                   2384:   for ( d = 0; g; ) {
                   2385:     for ( u = 0, i = 0; i < n; i++ ) {
                   2386:       if ( dp_redble(g,p = ps[wb[i]]) ) {
                   2387:         dp_red_f(g,p,&u);
                   2388:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2389:         sugar = MAX(sugar,psugar);
                   2390:         if ( !u ) {
                   2391:           if ( d )
                   2392:             d->sugar = sugar;
                   2393:           *rp = d; return;
                   2394:         }
                   2395:         break;
                   2396:       }
                   2397:     }
                   2398:     if ( u )
                   2399:       g = u;
                   2400:     else if ( !full ) {
                   2401:       if ( g ) {
                   2402:         MKDP(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2403:       }
                   2404:       *rp = g; return;
                   2405:     } else {
                   2406:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   2407:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   2408:       addd(CO,d,t,&s); d = s;
                   2409:       dp_rest(g,&t); g = t;
                   2410:     }
                   2411:   }
                   2412:   if ( d )
                   2413:     d->sugar = sugar;
                   2414:   *rp = d;
                   2415: }
                   2416:
1.4       noro     2417: void dpm_nf_f(NODE b,DPM g,VECT psv,int full,DPM *rp)
1.1       noro     2418: {
1.4       noro     2419:   DPM *ps;
1.1       noro     2420:   DPM u,p,d,s,t;
                   2421:   NODE l;
                   2422:   DMM m,mr;
                   2423:   int i,n;
                   2424:   int *wb;
                   2425:   int sugar,psugar;
                   2426:
                   2427:   if ( !g ) {
                   2428:     *rp = 0; return;
                   2429:   }
1.4       noro     2430:   if ( b ) {
                   2431:     for ( n = 0, l = b; l; l = NEXT(l), n++ );
                   2432:     wb = (int *)ALLOCA(n*sizeof(int));
                   2433:     for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
                   2434:       wb[i] = ZTOS((Q)BDY(l));
                   2435:     ps = (DPM *)BDY(psv);
                   2436:   } else {
                   2437:     n = psv->len;
                   2438:     wb = (int *)MALLOC(n*sizeof(int));
                   2439:     for ( i = 0; i < n; i++ ) wb[i] = i;
                   2440:     ps = (DPM *)BDY(psv);
                   2441:   }
1.1       noro     2442:
                   2443:   sugar = g->sugar;
                   2444:   for ( d = 0; g; ) {
                   2445:     for ( u = 0, i = 0; i < n; i++ ) {
1.4       noro     2446:       if ( ( (p=ps[wb[i]]) != 0 ) && dpm_redble(g,p) ) {
1.1       noro     2447:         dpm_red_f(g,p,&u);
                   2448:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2449:         sugar = MAX(sugar,psugar);
                   2450:         if ( !u ) {
                   2451:           if ( d )
                   2452:             d->sugar = sugar;
                   2453:           *rp = d; return;
                   2454:         }
                   2455:         break;
                   2456:       }
                   2457:     }
                   2458:     if ( u )
                   2459:       g = u;
                   2460:     else if ( !full ) {
                   2461:       if ( g ) {
                   2462:         MKDPM(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2463:       }
                   2464:       *rp = g; return;
                   2465:     } else {
                   2466:       m = BDY(g); NEWDMM(mr); mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos;
                   2467:       NEXT(mr) = 0; MKDPM(g->nv,mr,t); t->sugar = mr->dl->td;
                   2468:       adddpm(CO,d,t,&s); d = s;
                   2469:       dpm_rest(g,&t); g = t;
                   2470:     }
                   2471:   }
                   2472:   if ( d )
                   2473:     d->sugar = sugar;
                   2474:   *rp = d;
                   2475: }
                   2476:
                   2477: /* nf computation over GF(mod) (only for internal use) */
                   2478:
                   2479: void dp_nf_mod(NODE b,DP g,DP *ps,int mod,int full,DP *rp)
                   2480: {
                   2481:   DP u,p,d,s,t;
                   2482:   P dmy;
                   2483:   NODE l;
                   2484:   MP m,mr;
                   2485:   int sugar,psugar;
                   2486:
                   2487:   if ( !g ) {
                   2488:     *rp = 0; return;
                   2489:   }
                   2490:   sugar = g->sugar;
                   2491:   for ( d = 0; g; ) {
                   2492:     for ( u = 0, l = b; l; l = NEXT(l) ) {
                   2493:       if ( dp_redble(g,p = ps[(long)BDY(l)]) ) {
                   2494:         dp_red_mod(d,g,p,mod,&t,&u,&dmy);
                   2495:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2496:         sugar = MAX(sugar,psugar);
                   2497:         if ( !u ) {
                   2498:           if ( d )
                   2499:             d->sugar = sugar;
                   2500:           *rp = d; return;
                   2501:         }
                   2502:         d = t;
                   2503:         break;
                   2504:       }
                   2505:     }
                   2506:     if ( u )
                   2507:       g = u;
                   2508:     else if ( !full ) {
                   2509:       if ( g ) {
                   2510:         MKDP(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2511:       }
                   2512:       *rp = g; return;
                   2513:     } else {
                   2514:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   2515:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   2516:       addmd(CO,mod,d,t,&s); d = s;
                   2517:       dp_rest(g,&t); g = t;
                   2518:     }
                   2519:   }
                   2520:   if ( d )
                   2521:     d->sugar = sugar;
                   2522:   *rp = d;
                   2523: }
                   2524:
                   2525: void dp_true_nf_mod(NODE b,DP g,DP *ps,int mod,int full,DP *rp,P *dnp)
                   2526: {
                   2527:   DP u,p,d,s,t;
                   2528:   NODE l;
                   2529:   MP m,mr;
                   2530:   int i,n;
                   2531:   int *wb;
                   2532:   int sugar,psugar;
                   2533:   P dn,tdn,tdn1;
                   2534:
                   2535:   dn = (P)ONEM;
                   2536:   if ( !g ) {
                   2537:     *rp = 0; *dnp = dn; return;
                   2538:   }
1.3       noro     2539:   for ( n = 0, l = b; l; l = NEXT(l), n++ )
                   2540:     ;
                   2541:   wb = (int *)ALLOCA(n*sizeof(int));
1.1       noro     2542:   for ( i = 0, l = b; i < n; l = NEXT(l), i++ )
1.2       noro     2543:     wb[i] = ZTOS((Q)BDY(l));
1.1       noro     2544:   sugar = g->sugar;
                   2545:   for ( d = 0; g; ) {
                   2546:     for ( u = 0, i = 0; i < n; i++ ) {
                   2547:       if ( dp_redble(g,p = ps[wb[i]]) ) {
                   2548:         dp_red_mod(d,g,p,mod,&t,&u,&tdn);
                   2549:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2550:         sugar = MAX(sugar,psugar);
                   2551:         if ( !u ) {
                   2552:           if ( d )
                   2553:             d->sugar = sugar;
                   2554:           *rp = d; *dnp = dn; return;
                   2555:         } else {
                   2556:           d = t;
                   2557:           mulmp(CO,mod,dn,tdn,&tdn1); dn = tdn1;
                   2558:         }
                   2559:         break;
                   2560:       }
                   2561:     }
                   2562:     if ( u )
                   2563:       g = u;
                   2564:     else if ( !full ) {
                   2565:       if ( g ) {
                   2566:         MKDP(g->nv,BDY(g),t); t->sugar = sugar; g = t;
                   2567:       }
                   2568:       *rp = g; *dnp = dn; return;
                   2569:     } else {
                   2570:       m = BDY(g); NEWMP(mr); mr->dl = m->dl; mr->c = m->c;
                   2571:       NEXT(mr) = 0; MKDP(g->nv,mr,t); t->sugar = mr->dl->td;
                   2572:       addmd(CO,mod,d,t,&s); d = s;
                   2573:       dp_rest(g,&t); g = t;
                   2574:     }
                   2575:   }
                   2576:   if ( d )
                   2577:     d->sugar = sugar;
                   2578:   *rp = d; *dnp = dn;
                   2579: }
                   2580:
                   2581: void _dp_nf_mod_destructive(NODE b,DP g,DP *ps,int mod,int full,DP *rp)
                   2582: {
                   2583:   DP u,p,d;
                   2584:   NODE l;
                   2585:   MP m,mrd;
                   2586:   int sugar,psugar,n,h_reducible;
                   2587:
                   2588:   if ( !g ) {
                   2589:     *rp = 0; return;
                   2590:   }
                   2591:   sugar = g->sugar;
                   2592:   n = g->nv;
                   2593:   for ( d = 0; g; ) {
                   2594:     for ( h_reducible = 0, l = b; l; l = NEXT(l) ) {
                   2595:       if ( dp_redble(g,p = ps[(long)BDY(l)]) ) {
                   2596:         h_reducible = 1;
                   2597:         psugar = (BDY(g)->dl->td - BDY(p)->dl->td) + p->sugar;
                   2598:         _dp_red_mod_destructive(g,p,mod,&u); g = u;
                   2599:         sugar = MAX(sugar,psugar);
                   2600:         if ( !g ) {
                   2601:           if ( d )
                   2602:             d->sugar = sugar;
                   2603:           _dptodp(d,rp); _free_dp(d); return;
                   2604:         }
                   2605:         break;
                   2606:       }
                   2607:     }
                   2608:     if ( !h_reducible ) {
                   2609:       /* head term is not reducible */
                   2610:       if ( !full ) {
                   2611:         if ( g )
                   2612:           g->sugar = sugar;
                   2613:         _dptodp(g,rp); _free_dp(g); return;
                   2614:       } else {
                   2615:         m = BDY(g);
                   2616:         if ( NEXT(m) ) {
                   2617:           BDY(g) = NEXT(m); NEXT(m) = 0;
                   2618:         } else {
                   2619:           _FREEDP(g); g = 0;
                   2620:         }
                   2621:         if ( d ) {
                   2622:           for ( mrd = BDY(d); NEXT(mrd); mrd = NEXT(mrd) );
                   2623:           NEXT(mrd) = m;
                   2624:         } else {
                   2625:           _MKDP(n,m,d);
                   2626:         }
                   2627:       }
                   2628:     }
                   2629:   }
                   2630:   if ( d )
                   2631:     d->sugar = sugar;
                   2632:   _dptodp(d,rp); _free_dp(d);
                   2633: }
                   2634:
                   2635: /* reduction by linear base over a field */
                   2636:
                   2637: void dp_lnf_f(DP p1,DP p2,NODE g,DP *r1p,DP *r2p)
                   2638: {
                   2639:   DP r1,r2,b1,b2,t,s;
                   2640:   Obj c,c1,c2;
                   2641:   NODE l,b;
                   2642:   int n;
                   2643:
                   2644:   if ( !p1 ) {
                   2645:     *r1p = p1; *r2p = p2; return;
                   2646:   }
                   2647:   n = p1->nv;
                   2648:   for ( l = g, r1 = p1, r2 = p2; l; l = NEXT(l) ) {
                   2649:       if ( !r1 ) {
                   2650:         *r1p = r1; *r2p = r2; return;
                   2651:       }
                   2652:       b = BDY((LIST)BDY(l)); b1 = (DP)BDY(b);
                   2653:       if ( dl_equal(n,BDY(r1)->dl,BDY(b1)->dl) ) {
                   2654:         b2 = (DP)BDY(NEXT(b));
                   2655:         divr(CO,(Obj)ONE,(Obj)BDY(b1)->c,&c1);
                   2656:         mulr(CO,c1,(Obj)BDY(r1)->c,&c2); chsgnr(c2,&c);
                   2657:         muldc(CO,b1,(Obj)c,&t); addd(CO,r1,t,&s); r1 = s;
                   2658:         muldc(CO,b2,(Obj)c,&t); addd(CO,r2,t,&s); r2 = s;
                   2659:       }
                   2660:   }
                   2661:   *r1p = r1; *r2p = r2;
                   2662: }
                   2663:
                   2664: /* reduction by linear base over GF(mod) */
                   2665:
                   2666: void dp_lnf_mod(DP p1,DP p2,NODE g,int mod,DP *r1p,DP *r2p)
                   2667: {
                   2668:   DP r1,r2,b1,b2,t,s;
                   2669:   P c;
                   2670:   MQ c1,c2;
                   2671:   NODE l,b;
                   2672:   int n;
                   2673:
                   2674:   if ( !p1 ) {
                   2675:     *r1p = p1; *r2p = p2; return;
                   2676:   }
                   2677:   n = p1->nv;
                   2678:   for ( l = g, r1 = p1, r2 = p2; l; l = NEXT(l) ) {
                   2679:       if ( !r1 ) {
                   2680:         *r1p = r1; *r2p = r2; return;
                   2681:       }
                   2682:       b = BDY((LIST)BDY(l)); b1 = (DP)BDY(b);
                   2683:       if ( dl_equal(n,BDY(r1)->dl,BDY(b1)->dl) ) {
                   2684:         b2 = (DP)BDY(NEXT(b));
                   2685:         invmq(mod,(MQ)BDY(b1)->c,&c1);
                   2686:         mulmq(mod,c1,(MQ)BDY(r1)->c,&c2); chsgnmp(mod,(P)c2,&c);
                   2687:         mulmdc(CO,mod,b1,c,&t); addmd(CO,mod,r1,t,&s); r1 = s;
                   2688:         mulmdc(CO,mod,b2,c,&t); addmd(CO,mod,r2,t,&s); r2 = s;
                   2689:       }
                   2690:   }
                   2691:   *r1p = r1; *r2p = r2;
                   2692: }
                   2693:
                   2694: void dp_nf_tab_mod(DP p,LIST *tab,int mod,DP *rp)
                   2695: {
                   2696:   DP s,t,u;
                   2697:   MP m;
                   2698:   DL h;
                   2699:   int i,n;
                   2700:
                   2701:   if ( !p ) {
                   2702:     *rp = p; return;
                   2703:   }
                   2704:   n = p->nv;
                   2705:   for ( s = 0, i = 0, m = BDY(p); m; m = NEXT(m) ) {
                   2706:     h = m->dl;
                   2707:     while ( !dl_equal(n,h,BDY((DP)BDY(BDY(tab[i])))->dl ) )
                   2708:       i++;
                   2709:     mulmdc(CO,mod,(DP)BDY(NEXT(BDY(tab[i]))),(P)m->c,&t);
                   2710:     addmd(CO,mod,s,t,&u); s = u;
                   2711:   }
                   2712:   *rp = s;
                   2713: }
                   2714:
                   2715: void dp_nf_tab_f(DP p,LIST *tab,DP *rp)
                   2716: {
                   2717:   DP s,t,u;
                   2718:   MP m;
                   2719:   DL h;
                   2720:   int i,n;
                   2721:
                   2722:   if ( !p ) {
                   2723:     *rp = p; return;
                   2724:   }
                   2725:   n = p->nv;
                   2726:   for ( s = 0, i = 0, m = BDY(p); m; m = NEXT(m) ) {
                   2727:     h = m->dl;
                   2728:     while ( !dl_equal(n,h,BDY((DP)BDY(BDY(tab[i])))->dl ) )
                   2729:       i++;
                   2730:     muldc(CO,(DP)BDY(NEXT(BDY(tab[i]))),m->c,&t);
                   2731:     addd(CO,s,t,&u); s = u;
                   2732:   }
                   2733:   *rp = s;
                   2734: }
                   2735:
                   2736: /*
                   2737:  * setting flags
                   2738:  * call create_order_spec with vl=0 to set old type order.
                   2739:  *
                   2740:  */
                   2741:
                   2742: int create_order_spec(VL vl,Obj obj,struct order_spec **specp)
                   2743: {
                   2744:   int i,j,n,s,row,col,ret,wlen;
                   2745:   struct order_spec *spec;
                   2746:   struct order_pair *l;
                   2747:   Obj wp,wm;
                   2748:   NODE node,t,tn,wpair;
                   2749:   MAT m;
                   2750:   VECT v;
                   2751:   pointer **b,*bv;
                   2752:   int **w;
                   2753:
                   2754:   if ( vl && obj && OID(obj) == O_LIST ) {
                   2755:     ret = create_composite_order_spec(vl,(LIST)obj,specp);
                   2756:     if ( show_orderspec )
                   2757:       print_composite_order_spec(*specp);
                   2758:     return ret;
                   2759:   }
                   2760:
                   2761:   *specp = spec = (struct order_spec *)MALLOC(sizeof(struct order_spec));
                   2762:   if ( !obj || NUM(obj) ) {
                   2763:     spec->id = 0; spec->obj = obj;
1.2       noro     2764:     spec->ord.simple = ZTOS((Q)obj);
1.1       noro     2765:     return 1;
                   2766:   } else if ( OID(obj) == O_LIST ) {
1.6       noro     2767:     /* module order */
1.1       noro     2768:     node = BDY((LIST)obj);
                   2769:     if ( !BDY(node) || NUM(BDY(node)) ) {
                   2770:       switch ( length(node) ) {
1.6       noro     2771:       case 2: /* [n,ord] */
1.1       noro     2772:         create_order_spec(0,(Obj)BDY(NEXT(node)),&spec);
                   2773:         spec->id += 256; spec->obj = obj;
                   2774:         spec->top_weight = 0;
                   2775:         spec->module_rank = 0;
                   2776:         spec->module_top_weight = 0;
1.6       noro     2777:         spec->module_ordtype = ZTOS((Z)BDY(node));
                   2778:         if ( spec->module_ordtype < 0  ) {
                   2779:             spec->pot_nelim = -spec->module_ordtype;
                   2780:             spec->module_ordtype = 1;
                   2781:         } else
                   2782:             spec->pot_nelim = 0;
                   2783:         break;
                   2784:
1.17      noro     2785:       case 3: /* [n,[mlist1,mlist2,...],ord] or [n,[wv,wm],ord] */
1.6       noro     2786:         spec->module_ordtype = ZTOS((Z)BDY(node));
                   2787:         if ( spec->module_ordtype < 0  ) {
                   2788:             spec->pot_nelim = -spec->module_ordtype;
                   2789:             spec->module_ordtype = 1;
                   2790:         } else
1.1       noro     2791:             spec->pot_nelim = 0;
1.6       noro     2792:
                   2793:         if ( spec->module_ordtype == 3 ) { /* schreyer order */
                   2794:           Obj baseobj;
                   2795:           struct order_spec *basespec;
                   2796:           int len;
                   2797:           NODE in;
                   2798:           LIST *la;
                   2799:           DMMstack stack;
                   2800:           DMMstack push_schreyer_order(LIST l,DMMstack s);
                   2801:
                   2802:           spec->id = 300; spec->obj = obj;
                   2803:           node = NEXT(node);
                   2804:           if ( !BDY(node) || OID(BDY(node)) != O_LIST )
                   2805:             error("create_order_spec : [mlist1,mlist,...] must be specified for defining a schreyer order");
                   2806:           stack = 0;
                   2807:           in = BDY((LIST)BDY(node));
                   2808:           len = length(in);
                   2809:           la = (LIST *)MALLOC(len*sizeof(LIST));
                   2810:           for ( i = 0; i < len; i++, in = NEXT(in) ) la[i] = (LIST)(BDY(in));
                   2811:           for ( i = len-1; i >= 0; i-- ) stack = push_schreyer_order(la[i],stack);
                   2812:           spec->dmmstack = stack;
                   2813:
                   2814:           node = NEXT(node);
                   2815:           baseobj = (Obj)BDY(node);
                   2816:           create_order_spec(0,baseobj,&basespec);
                   2817:           basespec->obj = baseobj;
                   2818:           spec->base = basespec;
1.13      noro     2819:         } else if ( spec->module_ordtype == 4 ) {  /* POT with base order [n,bord,ord] */
                   2820:           NODE base_ord;
                   2821:           int rank;
                   2822:
                   2823:           create_order_spec(0,(Obj)BDY(NEXT(NEXT(node))),&spec);
                   2824:           spec->id += 256; spec->obj = obj;
                   2825:           spec->top_weight = 0;
                   2826:           spec->module_rank = 0;
                   2827:           spec->module_top_weight = 0;
                   2828:           spec->pot_nelim = 0;
                   2829:           spec->module_ordtype = 4;
                   2830:           node = NEXT(node);
                   2831:           if ( !BDY(node) || OID(BDY(node)) != O_LIST )
                   2832:             error("create_order_spec : a permitation list must be specified");
                   2833:           base_ord = BDY((LIST)BDY(node));
                   2834:           spec->module_rank = rank = length(base_ord);
                   2835:           spec->module_base_ord = (int *)MALLOC_ATOMIC((rank+1)*sizeof(int));
                   2836:           for ( i = 1, t = base_ord; i <= rank; i++, t = NEXT(t) )
                   2837:             spec->module_base_ord[ZTOS((Q)BDY(t))] = i;
                   2838:           break;
                   2839:         } else {  /* weighted order * [n,[wv,wm],ord] */
1.7       noro     2840:           int ordtype;
                   2841:
                   2842:           ordtype = spec->module_ordtype;
1.6       noro     2843:           create_order_spec(0,(Obj)BDY(NEXT(NEXT(node))),&spec);
1.7       noro     2844:           spec->module_ordtype = ordtype;
                   2845:           spec->id += 256; spec->obj = obj;
1.6       noro     2846:           node = NEXT(node);
                   2847:           if ( !BDY(node) || OID(BDY(node)) != O_LIST )
                   2848:             error("create_order_spec : [weight_for_poly,weight_for_modlue] must be specified as a module topweight");
                   2849:           wpair = BDY((LIST)BDY(node));
                   2850:           if ( length(wpair) != 2 )
                   2851:             error("create_order_spec : [weight_for_poly,weight_for_modlue] must be specified as a module topweight");
                   2852:
                   2853:           wp = BDY(wpair);
                   2854:           wm = BDY(NEXT(wpair));
                   2855:           if ( !wp || OID(wp) != O_LIST || !wm || OID(wm) != O_LIST )
                   2856:             error("create_order_spec : [weight_for_poly,weight_for_modlue] must be specified as a module topweight");
                   2857:           spec->nv = length(BDY((LIST)wp));
                   2858:           spec->top_weight = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));
                   2859:           for ( i = 0, t = BDY((LIST)wp); i < spec->nv; t = NEXT(t), i++ )
                   2860:             spec->top_weight[i] = ZTOS((Q)BDY(t));
                   2861:
                   2862:           spec->module_rank = length(BDY((LIST)wm));
                   2863:           spec->module_top_weight = (int *)MALLOC_ATOMIC(spec->module_rank*sizeof(int));
                   2864:           for ( i = 0, t = BDY((LIST)wm); i < spec->module_rank; t = NEXT(t), i++ )
                   2865:             spec->module_top_weight[i] = ZTOS((Q)BDY(t));
1.1       noro     2866:         }
                   2867:         break;
                   2868:
                   2869:       default:
                   2870:         error("create_order_spec : invalid arguments for module order");
                   2871:       }
                   2872:
                   2873:       *specp = spec;
                   2874:       return 1;
                   2875:     } else {
                   2876:       /* block order in polynomial ring */
                   2877:       for ( n = 0, t = node; t; t = NEXT(t), n++ );
                   2878:       l = (struct order_pair *)MALLOC_ATOMIC(n*sizeof(struct order_pair));
                   2879:       for ( i = 0, t = node, s = 0; i < n; t = NEXT(t), i++ ) {
1.2       noro     2880:         tn = BDY((LIST)BDY(t)); l[i].order = ZTOS((Q)BDY(tn));
                   2881:         tn = NEXT(tn); l[i].length = ZTOS((Q)BDY(tn));
1.1       noro     2882:         s += l[i].length;
                   2883:       }
                   2884:       spec->id = 1; spec->obj = obj;
                   2885:       spec->ord.block.order_pair = l;
                   2886:       spec->ord.block.length = n; spec->nv = s;
                   2887:       return 1;
                   2888:     }
                   2889:   } else if ( OID(obj) == O_MAT ) {
                   2890:     m = (MAT)obj; row = m->row; col = m->col; b = BDY(m);
                   2891:     w = almat(row,col);
                   2892:     for ( i = 0; i < row; i++ )
                   2893:       for ( j = 0; j < col; j++ )
1.2       noro     2894:         w[i][j] = ZTOS((Q)b[i][j]);
1.1       noro     2895:     spec->id = 2; spec->obj = obj;
                   2896:     spec->nv = col; spec->ord.matrix.row = row;
                   2897:     spec->ord.matrix.matrix = w;
                   2898:     return 1;
                   2899:   } else
                   2900:     return 0;
                   2901: }
                   2902:
                   2903: void print_composite_order_spec(struct order_spec *spec)
                   2904: {
                   2905:   int nv,n,len,i,j,k,start;
                   2906:   struct weight_or_block *worb;
                   2907:
                   2908:   nv = spec->nv;
                   2909:   n = spec->ord.composite.length;
                   2910:   worb = spec->ord.composite.w_or_b;
                   2911:   for ( i = 0; i < n; i++, worb++ ) {
                   2912:     len = worb->length;
                   2913:     printf("[ ");
                   2914:     switch ( worb->type ) {
                   2915:       case IS_DENSE_WEIGHT:
                   2916:         for ( j = 0; j < len; j++ )
                   2917:           printf("%d ",worb->body.dense_weight[j]);
                   2918:         for ( ; j < nv; j++ )
                   2919:           printf("0 ");
                   2920:         break;
                   2921:       case IS_SPARSE_WEIGHT:
                   2922:         for ( j = 0, k = 0; j < nv; j++ )
                   2923:           if ( j == worb->body.sparse_weight[k].pos )
                   2924:             printf("%d ",worb->body.sparse_weight[k++].value);
                   2925:           else
                   2926:             printf("0 ");
                   2927:         break;
                   2928:       case IS_BLOCK:
                   2929:         start = worb->body.block.start;
                   2930:         for ( j = 0; j < start; j++ ) printf("0 ");
                   2931:         switch ( worb->body.block.order ) {
                   2932:           case 0:
                   2933:             for ( k = 0; k < len; k++, j++ ) printf("R ");
                   2934:             break;
                   2935:           case 1:
                   2936:             for ( k = 0; k < len; k++, j++ ) printf("G ");
                   2937:             break;
                   2938:           case 2:
                   2939:             for ( k = 0; k < len; k++, j++ ) printf("L ");
                   2940:             break;
                   2941:         }
                   2942:         for ( ; j < nv; j++ ) printf("0 ");
                   2943:         break;
                   2944:     }
                   2945:     printf("]\n");
                   2946:   }
                   2947: }
                   2948:
                   2949: struct order_spec *append_block(struct order_spec *spec,
                   2950:   int nv,int nalg,int ord)
                   2951: {
                   2952:   MAT m,mat;
                   2953:   int i,j,row,col,n;
                   2954:   Z **b,**wp;
                   2955:   int **w;
                   2956:   NODE t,s,s0;
                   2957:   struct order_pair *l,*l0;
                   2958:   int n0,nv0;
                   2959:   LIST list0,list1,list;
                   2960:   Z oq,nq;
                   2961:   struct order_spec *r;
                   2962:
                   2963:   r = (struct order_spec *)MALLOC(sizeof(struct order_spec));
                   2964:   switch ( spec->id ) {
                   2965:     case 0:
1.2       noro     2966:       STOZ(spec->ord.simple,oq); STOZ(nv,nq);
1.1       noro     2967:       t = mknode(2,oq,nq); MKLIST(list0,t);
1.2       noro     2968:       STOZ(ord,oq); STOZ(nalg,nq);
1.1       noro     2969:       t = mknode(2,oq,nq); MKLIST(list1,t);
                   2970:       t = mknode(2,list0,list1); MKLIST(list,t);
                   2971:       l = (struct order_pair *)MALLOC_ATOMIC(2*sizeof(struct order_pair));
                   2972:       l[0].order = spec->ord.simple; l[0].length = nv;
                   2973:       l[1].order = ord; l[1].length = nalg;
                   2974:       r->id = 1;  r->obj = (Obj)list;
                   2975:       r->ord.block.order_pair = l;
                   2976:       r->ord.block.length = 2;
                   2977:       r->nv = nv+nalg;
                   2978:       break;
                   2979:     case 1:
                   2980:       if ( spec->nv != nv )
                   2981:         error("append_block : number of variables mismatch");
                   2982:       l0 = spec->ord.block.order_pair;
                   2983:       n0 = spec->ord.block.length;
                   2984:       nv0 = spec->nv;
                   2985:       list0 = (LIST)spec->obj;
                   2986:       n = n0+1;
                   2987:       l = (struct order_pair *)MALLOC_ATOMIC(n*sizeof(struct order_pair));
                   2988:       for ( i = 0; i < n0; i++ )
                   2989:         l[i] = l0[i];
                   2990:       l[i].order = ord; l[i].length = nalg;
                   2991:        for ( t = BDY(list0), s0 = 0; t; t = NEXT(t) ) {
                   2992:         NEXTNODE(s0,s); BDY(s) = BDY(t);
                   2993:       }
1.2       noro     2994:       STOZ(ord,oq); STOZ(nalg,nq);
1.1       noro     2995:       t = mknode(2,oq,nq); MKLIST(list,t);
                   2996:       NEXTNODE(s0,s); BDY(s) = (pointer)list; NEXT(s) = 0;
                   2997:       MKLIST(list,s0);
                   2998:       r->id = 1;  r->obj = (Obj)list;
                   2999:       r->ord.block.order_pair = l;
                   3000:       r->ord.block.length = n;
                   3001:       r->nv = nv+nalg;
                   3002:       break;
                   3003:     case 2:
                   3004:       if ( spec->nv != nv )
                   3005:         error("append_block : number of variables mismatch");
                   3006:       m = (MAT)spec->obj;
                   3007:       row = m->row; col = m->col; b = (Z **)BDY(m);
                   3008:       w = almat(row+nalg,col+nalg);
                   3009:       MKMAT(mat,row+nalg,col+nalg); wp = (Z **)BDY(mat);
                   3010:       for ( i = 0; i < row; i++ )
                   3011:         for ( j = 0; j < col; j++ ) {
1.2       noro     3012:           w[i][j] = ZTOS(b[i][j]);
1.1       noro     3013:           wp[i][j] = b[i][j];
                   3014:         }
                   3015:       for ( i = 0; i < nalg; i++ ) {
                   3016:         w[i+row][i+col] = 1;
                   3017:         wp[i+row][i+col] = ONE;
                   3018:       }
                   3019:       r->id = 2; r->obj = (Obj)mat;
                   3020:       r->nv = col+nalg; r->ord.matrix.row = row+nalg;
                   3021:       r->ord.matrix.matrix = w;
                   3022:       break;
                   3023:     case 3:
                   3024:     default:
                   3025:       /* XXX */
                   3026:       error("append_block : not implemented yet");
                   3027:   }
                   3028:   return r;
                   3029: }
                   3030:
                   3031: int comp_sw(struct sparse_weight *a, struct sparse_weight *b)
                   3032: {
                   3033:   if ( a->pos > b->pos ) return 1;
                   3034:   else if ( a->pos < b->pos ) return -1;
                   3035:   else return 0;
                   3036: }
                   3037:
                   3038: /* order = [w_or_b, w_or_b, ... ] */
                   3039: /* w_or_b = w or b                */
                   3040: /* w = [1,2,...] or [x,1,y,2,...] */
                   3041: /* b = [@lex,x,y,...,z] etc       */
                   3042:
                   3043: int create_composite_order_spec(VL vl,LIST order,struct order_spec **specp)
                   3044: {
                   3045:   NODE wb,t,p;
                   3046:   struct order_spec *spec;
                   3047:   VL tvl;
                   3048:   int n,i,j,k,l,start,end,len,w;
                   3049:   int *dw;
                   3050:   struct sparse_weight *sw;
                   3051:   struct weight_or_block *w_or_b;
                   3052:   Obj a0;
                   3053:   NODE a;
                   3054:   V v,sv,ev;
                   3055:   SYMBOL sym;
                   3056:   int *top;
                   3057:
                   3058:   /* l = number of vars in vl */
                   3059:   for ( l = 0, tvl = vl; tvl; tvl = NEXT(tvl), l++ );
                   3060:   /* n = number of primitives in order */
                   3061:   wb = BDY(order);
                   3062:   n = length(wb);
                   3063:   *specp = spec = (struct order_spec *)MALLOC(sizeof(struct order_spec));
                   3064:   spec->id = 3;
                   3065:   spec->obj = (Obj)order;
                   3066:   spec->nv = l;
                   3067:   spec->ord.composite.length = n;
                   3068:   w_or_b = spec->ord.composite.w_or_b = (struct weight_or_block *)
                   3069:     MALLOC(sizeof(struct weight_or_block)*(n+1));
                   3070:
                   3071:   /* top : register the top variable in each w_or_b specification */
                   3072:   top = (int *)ALLOCA(l*sizeof(int));
                   3073:   for ( i = 0; i < l; i++ ) top[i] = 0;
                   3074:
                   3075:   for ( t = wb, i = 0; t; t = NEXT(t), i++ ) {
                   3076:     if ( !BDY(t) || OID((Obj)BDY(t)) != O_LIST )
                   3077:       error("a list of lists must be specified for the key \"order\"");
                   3078:     a = BDY((LIST)BDY(t));
                   3079:     len = length(a);
                   3080:     a0 = (Obj)BDY(a);
                   3081:     if ( !a0 || OID(a0) == O_N ) {
                   3082:       /* a is a dense weight vector */
                   3083:       dw = (int *)MALLOC(sizeof(int)*len);
                   3084:       for ( j = 0, p = a; j < len; p = NEXT(p), j++ ) {
                   3085:         if ( !INT((Q)BDY(p)) )
                   3086:           error("a dense weight vector must be specified as a list of integers");
1.2       noro     3087:         dw[j] = ZTOS((Q)BDY(p));
1.1       noro     3088:       }
                   3089:       w_or_b[i].type = IS_DENSE_WEIGHT;
                   3090:       w_or_b[i].length = len;
                   3091:       w_or_b[i].body.dense_weight = dw;
                   3092:
                   3093:       /* find the top */
                   3094:       for ( k = 0; k < len && !dw[k]; k++ );
                   3095:       if ( k < len ) top[k] = 1;
                   3096:
                   3097:     } else if ( OID(a0) == O_P ) {
                   3098:       /* a is a sparse weight vector */
                   3099:       len >>= 1;
                   3100:       sw = (struct sparse_weight *)
                   3101:         MALLOC(sizeof(struct sparse_weight)*len);
                   3102:       for ( j = 0, p = a; j < len; j++ ) {
                   3103:         if ( !BDY(p) || OID((P)BDY(p)) != O_P )
                   3104:           error("a sparse weight vector must be specified as [var1,weight1,...]");
                   3105:         v = VR((P)BDY(p)); p = NEXT(p);
                   3106:         for ( tvl = vl, k = 0; tvl && tvl->v != v;
                   3107:           k++, tvl = NEXT(tvl) );
                   3108:         if ( !tvl )
                   3109:           error("invalid variable name in a sparse weight vector");
                   3110:         sw[j].pos = k;
                   3111:         if ( !INT((Q)BDY(p)) )
                   3112:           error("a sparse weight vector must be specified as [var1,weight1,...]");
1.2       noro     3113:         sw[j].value = ZTOS((Q)BDY(p)); p = NEXT(p);
1.1       noro     3114:       }
                   3115:       qsort(sw,len,sizeof(struct sparse_weight),
                   3116:         (int (*)(const void *,const void *))comp_sw);
                   3117:       w_or_b[i].type = IS_SPARSE_WEIGHT;
                   3118:       w_or_b[i].length = len;
                   3119:       w_or_b[i].body.sparse_weight = sw;
                   3120:
                   3121:       /* find the top */
                   3122:       for ( k = 0; k < len && !sw[k].value; k++ );
                   3123:       if ( k < len ) top[sw[k].pos] = 1;
                   3124:     } else if ( OID(a0) == O_RANGE ) {
                   3125:       /* [range(v1,v2),w] */
                   3126:       sv = VR((P)(((RANGE)a0)->start));
                   3127:       ev = VR((P)(((RANGE)a0)->end));
                   3128:       for ( tvl = vl, start = 0; tvl && tvl->v != sv; start++, tvl = NEXT(tvl) );
                   3129:       if ( !tvl )
                   3130:         error("invalid range");
                   3131:       for ( end = start; tvl && tvl->v != ev; end++, tvl = NEXT(tvl) );
                   3132:       if ( !tvl )
                   3133:         error("invalid range");
                   3134:       len = end-start+1;
                   3135:       sw = (struct sparse_weight *)
                   3136:         MALLOC(sizeof(struct sparse_weight)*len);
1.2       noro     3137:       w = ZTOS((Q)BDY(NEXT(a)));
1.1       noro     3138:       for ( tvl = vl, k = 0; k < start; k++, tvl = NEXT(tvl) );
                   3139:       for ( j = 0 ; k <= end; k++, tvl = NEXT(tvl), j++ ) {
                   3140:         sw[j].pos = k;
                   3141:         sw[j].value = w;
                   3142:       }
                   3143:       w_or_b[i].type = IS_SPARSE_WEIGHT;
                   3144:       w_or_b[i].length = len;
                   3145:       w_or_b[i].body.sparse_weight = sw;
                   3146:
                   3147:       /* register the top */
                   3148:       if ( w ) top[start] = 1;
                   3149:     } else if ( OID(a0) == O_SYMBOL ) {
                   3150:       /* a is a block */
                   3151:       sym = (SYMBOL)a0; a = NEXT(a); len--;
                   3152:       if ( OID((Obj)BDY(a)) == O_RANGE ) {
                   3153:         sv = VR((P)(((RANGE)BDY(a))->start));
                   3154:         ev = VR((P)(((RANGE)BDY(a))->end));
                   3155:         for ( tvl = vl, start = 0; tvl && tvl->v != sv; start++, tvl = NEXT(tvl) );
                   3156:         if ( !tvl )
                   3157:           error("invalid range");
                   3158:         for ( end = start; tvl && tvl->v != ev; end++, tvl = NEXT(tvl) );
                   3159:         if ( !tvl )
                   3160:           error("invalid range");
                   3161:         len = end-start+1;
                   3162:       } else {
                   3163:         for ( start = 0, tvl = vl; tvl->v != VR((P)BDY(a));
                   3164:         tvl = NEXT(tvl), start++ );
                   3165:         for ( p = NEXT(a), tvl = NEXT(tvl); p;
                   3166:           p = NEXT(p), tvl = NEXT(tvl) ) {
                   3167:           if ( !BDY(p) || OID((P)BDY(p)) != O_P )
                   3168:             error("a block must be specified as [ordsymbol,var1,var2,...]");
                   3169:           if ( tvl->v != VR((P)BDY(p)) ) break;
                   3170:         }
                   3171:         if ( p )
                   3172:           error("a block must be contiguous in the variable list");
                   3173:       }
                   3174:       w_or_b[i].type = IS_BLOCK;
                   3175:       w_or_b[i].length = len;
                   3176:       w_or_b[i].body.block.start = start;
                   3177:       if ( !strcmp(sym->name,"@grlex") )
                   3178:         w_or_b[i].body.block.order = 0;
                   3179:       else if ( !strcmp(sym->name,"@glex") )
                   3180:         w_or_b[i].body.block.order = 1;
                   3181:       else if ( !strcmp(sym->name,"@lex") )
                   3182:         w_or_b[i].body.block.order = 2;
                   3183:       else
                   3184:         error("invalid ordername");
                   3185:       /* register the tops */
                   3186:       for ( j = 0, k = start; j < len; j++, k++ )
                   3187:         top[k] = 1;
                   3188:     }
                   3189:   }
                   3190:   for ( k = 0; k < l && top[k]; k++ );
                   3191:   if ( k < l ) {
                   3192:     /* incomplete order specification; add @grlex */
                   3193:     w_or_b[n].type = IS_BLOCK;
                   3194:     w_or_b[n].length = l;
                   3195:     w_or_b[n].body.block.start = 0;
                   3196:     w_or_b[n].body.block.order = 0;
                   3197:     spec->ord.composite.length = n+1;
                   3198:   }
1.3       noro     3199:   return 1;
1.1       noro     3200: }
                   3201:
                   3202: /* module order spec */
                   3203:
                   3204: void create_modorder_spec(int id,LIST shift,struct modorder_spec **s)
                   3205: {
                   3206:   struct modorder_spec *spec;
                   3207:   NODE n,t;
                   3208:   LIST list;
                   3209:   int *ds;
                   3210:   int i,l;
                   3211:   Z q;
                   3212:
                   3213:   *s = spec = (struct modorder_spec *)MALLOC(sizeof(struct modorder_spec));
                   3214:   spec->id = id;
                   3215:   if ( shift ) {
                   3216:     n = BDY(shift);
                   3217:     spec->len = l = length(n);
                   3218:     spec->degree_shift = ds = (int *)MALLOC_ATOMIC(l*sizeof(int));
                   3219:     for ( t = n, i = 0; t; t = NEXT(t), i++ )
1.2       noro     3220:       ds[i] = ZTOS((Q)BDY(t));
1.1       noro     3221:   } else {
                   3222:     spec->len = 0;
                   3223:     spec->degree_shift = 0;
                   3224:   }
1.2       noro     3225:   STOZ(id,q);
1.1       noro     3226:   n = mknode(2,q,shift);
                   3227:   MKLIST(list,n);
                   3228:   spec->obj = (Obj)list;
                   3229: }
                   3230:
                   3231: /*
                   3232:  * converters
                   3233:  *
                   3234:  */
                   3235:
1.7       noro     3236: void dpm_homo(DPM p,DPM *rp)
                   3237: {
                   3238:   DMM m,mr,mr0,t;
                   3239:   int i,n,nv,td;
                   3240:   DL dl,dlh;
                   3241:
                   3242:   if ( !p )
                   3243:     *rp = 0;
                   3244:   else {
                   3245:     n = p->nv; nv = n + 1;
                   3246:     m = BDY(p);
                   3247:     td = 0;
                   3248:     for ( t = m; t; t = NEXT(t) )
                   3249:       if ( m->dl->td > td ) td = m->dl->td;
                   3250:     for ( mr0 = 0; m; m = NEXT(m) ) {
                   3251:       NEXTDMM(mr0,mr); mr->c = m->c; mr->pos = m->pos;
                   3252:       dl = m->dl;
                   3253:       mr->dl = dlh = (DL)MALLOC_ATOMIC((nv+1)*sizeof(int));
                   3254:       dlh->td = td;
                   3255:       for ( i = 0; i < n; i++ )
                   3256:         dlh->d[i] = dl->d[i];
                   3257:       dlh->d[n] = td - dl->td;
                   3258:     }
                   3259:     NEXT(mr) = 0; MKDPM(nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3260:   }
                   3261: }
                   3262:
                   3263: void dpm_dehomo(DPM p,DPM *rp)
                   3264: {
                   3265:   DMM m,mr,mr0;
                   3266:   int i,n,nv;
                   3267:   DL dl,dlh;
                   3268:
                   3269:   if ( !p )
                   3270:     *rp = 0;
                   3271:   else {
                   3272:     n = p->nv; nv = n - 1;
                   3273:     m = BDY(p);
                   3274:     for ( mr0 = 0; m; m = NEXT(m) ) {
                   3275:       NEXTDMM(mr0,mr); mr->c = m->c; mr->pos = m->pos;
                   3276:       dlh = m->dl;
                   3277:       mr->dl = dl = (DL)MALLOC_ATOMIC((nv+1)*sizeof(int));
                   3278:       dl->td = dlh->td - dlh->d[nv];
                   3279:       for ( i = 0; i < nv; i++ )
                   3280:         dl->d[i] = dlh->d[i];
                   3281:     }
                   3282:     NEXT(mr) = 0; MKDPM(nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3283:   }
                   3284: }
                   3285:
1.1       noro     3286: void dp_homo(DP p,DP *rp)
                   3287: {
                   3288:   MP m,mr,mr0;
                   3289:   int i,n,nv,td;
                   3290:   DL dl,dlh;
                   3291:
                   3292:   if ( !p )
                   3293:     *rp = 0;
                   3294:   else {
                   3295:     n = p->nv; nv = n + 1;
                   3296:     m = BDY(p); td = sugard(m);
                   3297:     for ( mr0 = 0; m; m = NEXT(m) ) {
                   3298:       NEXTMP(mr0,mr); mr->c = m->c;
                   3299:       dl = m->dl;
                   3300:       mr->dl = dlh = (DL)MALLOC_ATOMIC((nv+1)*sizeof(int));
                   3301:       dlh->td = td;
                   3302:       for ( i = 0; i < n; i++ )
                   3303:         dlh->d[i] = dl->d[i];
                   3304:       dlh->d[n] = td - dl->td;
                   3305:     }
                   3306:     NEXT(mr) = 0; MKDP(nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3307:   }
                   3308: }
                   3309:
                   3310: void dp_dehomo(DP p,DP *rp)
                   3311: {
                   3312:   MP m,mr,mr0;
                   3313:   int i,n,nv;
                   3314:   DL dl,dlh;
                   3315:
                   3316:   if ( !p )
                   3317:     *rp = 0;
                   3318:   else {
                   3319:     n = p->nv; nv = n - 1;
                   3320:     m = BDY(p);
                   3321:     for ( mr0 = 0; m; m = NEXT(m) ) {
                   3322:       NEXTMP(mr0,mr); mr->c = m->c;
                   3323:       dlh = m->dl;
                   3324:       mr->dl = dl = (DL)MALLOC_ATOMIC((nv+1)*sizeof(int));
                   3325:       dl->td = dlh->td - dlh->d[nv];
                   3326:       for ( i = 0; i < nv; i++ )
                   3327:         dl->d[i] = dlh->d[i];
                   3328:     }
                   3329:     NEXT(mr) = 0; MKDP(nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3330:   }
                   3331: }
                   3332:
1.7       noro     3333:
1.1       noro     3334: void dp_mod(DP p,int mod,NODE subst,DP *rp)
                   3335: {
                   3336:   MP m,mr,mr0;
                   3337:   P t,s,s1;
                   3338:   V v;
                   3339:   NODE tn;
                   3340:
                   3341:   if ( !p )
                   3342:     *rp = 0;
                   3343:   else {
                   3344:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                   3345:       for ( tn = subst, s = (P)m->c; tn; tn = NEXT(tn) ) {
                   3346:         v = VR((P)BDY(tn)); tn = NEXT(tn);
                   3347:         substp(CO,s,v,(P)BDY(tn),&s1); s = s1;
                   3348:       }
                   3349:       ptomp(mod,s,&t);
                   3350:       if ( t ) {
                   3351:         NEXTMP(mr0,mr); mr->c = (Obj)t; mr->dl = m->dl;
                   3352:       }
                   3353:     }
                   3354:     if ( mr0 ) {
                   3355:       NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3356:     } else
                   3357:       *rp = 0;
                   3358:   }
                   3359: }
                   3360:
1.15      noro     3361: void dpm_mod(DPM p,int mod,DPM *rp)
                   3362: {
                   3363:   DMM m,mr,mr0;
                   3364:   P t;
                   3365:   V v;
                   3366:   NODE tn;
                   3367:
                   3368:   if ( !p )
                   3369:     *rp = 0;
                   3370:   else {
                   3371:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                   3372:       ptomp(mod,(P)m->c,&t);
                   3373:       if ( t ) {
                   3374:         NEXTDMM(mr0,mr); mr->c = (Obj)t; mr->dl = m->dl;
                   3375:       }
                   3376:     }
                   3377:     if ( mr0 ) {
                   3378:       NEXT(mr) = 0; MKDPM(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3379:     } else
                   3380:       *rp = 0;
                   3381:   }
                   3382: }
                   3383:
1.1       noro     3384: void dp_rat(DP p,DP *rp)
                   3385: {
                   3386:   MP m,mr,mr0;
                   3387:
                   3388:   if ( !p )
                   3389:     *rp = 0;
                   3390:   else {
                   3391:     for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                   3392:       NEXTMP(mr0,mr); mptop((P)m->c,(P *)&mr->c); mr->dl = m->dl;
                   3393:     }
                   3394:     if ( mr0 ) {
                   3395:       NEXT(mr) = 0; MKDP(p->nv,mr0,*rp); (*rp)->sugar = p->sugar;
                   3396:     } else
                   3397:       *rp = 0;
                   3398:   }
                   3399: }
                   3400:
                   3401:
                   3402: void homogenize_order(struct order_spec *old,int n,struct order_spec **newp)
                   3403: {
                   3404:   struct order_pair *l;
                   3405:   int length,nv,row,i,j;
                   3406:   int **newm,**oldm;
                   3407:   struct order_spec *new;
                   3408:   int onv,nnv,nlen,olen,owlen;
                   3409:   struct weight_or_block *owb,*nwb;
                   3410:
                   3411:   *newp = new = (struct order_spec *)MALLOC(sizeof(struct order_spec));
1.6       noro     3412:   bcopy((char *)old,(char *)new,sizeof(struct order_spec));
1.1       noro     3413:   switch ( old->id ) {
                   3414:     case 0:
                   3415:       switch ( old->ord.simple ) {
                   3416:         case 0:
1.6       noro     3417:           break;
1.1       noro     3418:         case 1:
                   3419:           l = (struct order_pair *)
                   3420:             MALLOC_ATOMIC(2*sizeof(struct order_pair));
                   3421:           l[0].length = n; l[0].order = 1;
                   3422:           l[1].length = 1; l[1].order = 2;
                   3423:           new->id = 1;
                   3424:           new->ord.block.order_pair = l;
                   3425:           new->ord.block.length = 2; new->nv = n+1;
                   3426:           break;
                   3427:         case 2:
1.6       noro     3428:           new->ord.simple = 1; break;
1.1       noro     3429:         case 3: case 4: case 5:
1.6       noro     3430:           new->ord.simple = old->ord.simple+3;
1.1       noro     3431:           dp_nelim = n-1; break;
                   3432:         case 6: case 7: case 8: case 9:
1.6       noro     3433:           break;
1.1       noro     3434:         default:
                   3435:           error("homogenize_order : invalid input");
                   3436:       }
                   3437:       break;
                   3438:     case 1: case 257:
                   3439:       length = old->ord.block.length;
                   3440:       l = (struct order_pair *)
                   3441:         MALLOC_ATOMIC((length+1)*sizeof(struct order_pair));
                   3442:       bcopy((char *)old->ord.block.order_pair,(char *)l,length*sizeof(struct order_pair));
                   3443:       l[length].order = 2; l[length].length = 1;
1.6       noro     3444:       new->nv = n+1;
1.1       noro     3445:       new->ord.block.order_pair = l;
                   3446:       new->ord.block.length = length+1;
                   3447:       break;
                   3448:     case 2: case 258:
                   3449:       nv = old->nv; row = old->ord.matrix.row;
                   3450:       oldm = old->ord.matrix.matrix; newm = almat(row+1,nv+1);
                   3451:       for ( i = 0; i <= nv; i++ )
                   3452:         newm[0][i] = 1;
                   3453:       for ( i = 0; i < row; i++ ) {
                   3454:         for ( j = 0; j < nv; j++ )
                   3455:           newm[i+1][j] = oldm[i][j];
                   3456:         newm[i+1][j] = 0;
                   3457:       }
1.6       noro     3458:       new->nv = nv+1;
1.1       noro     3459:       new->ord.matrix.row = row+1; new->ord.matrix.matrix = newm;
                   3460:       break;
                   3461:     case 3: case 259:
                   3462:       onv = old->nv;
                   3463:       nnv = onv+1;
                   3464:       olen = old->ord.composite.length;
                   3465:       nlen = olen+1;
                   3466:       owb = old->ord.composite.w_or_b;
                   3467:       nwb = (struct weight_or_block *)
                   3468:         MALLOC(nlen*sizeof(struct weight_or_block));
                   3469:       for ( i = 0; i < olen; i++ ) {
                   3470:         nwb[i].type = owb[i].type;
                   3471:         switch ( owb[i].type ) {
                   3472:           case IS_DENSE_WEIGHT:
                   3473:             owlen = owb[i].length;
                   3474:             nwb[i].length = owlen+1;
                   3475:             nwb[i].body.dense_weight = (int *)MALLOC((owlen+1)*sizeof(int));
                   3476:             for ( j = 0; j < owlen; j++ )
                   3477:               nwb[i].body.dense_weight[j] = owb[i].body.dense_weight[j];
                   3478:             nwb[i].body.dense_weight[owlen] = 0;
                   3479:             break;
                   3480:           case IS_SPARSE_WEIGHT:
                   3481:             nwb[i].length = owb[i].length;
                   3482:             nwb[i].body.sparse_weight = owb[i].body.sparse_weight;
                   3483:             break;
                   3484:           case IS_BLOCK:
                   3485:             nwb[i].length = owb[i].length;
                   3486:             nwb[i].body.block = owb[i].body.block;
                   3487:             break;
                   3488:         }
                   3489:       }
                   3490:       nwb[i].type = IS_SPARSE_WEIGHT;
                   3491:       nwb[i].body.sparse_weight =
                   3492:         (struct sparse_weight *)MALLOC(sizeof(struct sparse_weight));
                   3493:       nwb[i].body.sparse_weight[0].pos = onv;
                   3494:       nwb[i].body.sparse_weight[0].value = 1;
                   3495:       new->nv = nnv;
                   3496:       new->ord.composite.length = nlen;
                   3497:       new->ord.composite.w_or_b = nwb;
                   3498:       print_composite_order_spec(new);
                   3499:       break;
                   3500:     case 256: /* simple module order */
                   3501:       switch ( old->ord.simple ) {
                   3502:         case 0:
1.6       noro     3503:           break;
1.1       noro     3504:         case 1:
                   3505:           l = (struct order_pair *)
                   3506:             MALLOC_ATOMIC(2*sizeof(struct order_pair));
                   3507:           l[0].length = n; l[0].order = old->ord.simple;
                   3508:           l[1].length = 1; l[1].order = 2;
                   3509:           new->id = 257;
                   3510:           new->ord.block.order_pair = l;
                   3511:           new->ord.block.length = 2; new->nv = n+1;
                   3512:           break;
                   3513:         case 2:
1.6       noro     3514:           new->ord.simple = 1; break;
1.1       noro     3515:         default:
                   3516:           error("homogenize_order : invalid input");
                   3517:       }
                   3518:       break;
                   3519:     default:
                   3520:       error("homogenize_order : invalid input");
                   3521:   }
                   3522: }
                   3523:
                   3524: int comp_nm(Q *a,Q *b)
                   3525: {
                   3526:   Z z,nma,nmb;
                   3527:
                   3528:   nmq(*a,&z); absz(z,&nma);
                   3529:   nmq(*b,&z); absz(z,&nmb);
                   3530:   return cmpz(nma,nmb);
                   3531: }
                   3532:
                   3533: void sortbynm(Q *w,int n)
                   3534: {
                   3535:   qsort(w,n,sizeof(Q),(int (*)(const void *,const void *))comp_nm);
                   3536: }
                   3537:
                   3538:
                   3539: /*
                   3540:  * simple operations
                   3541:  *
                   3542:  */
                   3543:
                   3544: int dp_redble(DP p1,DP p2)
                   3545: {
                   3546:   int i,n;
                   3547:   DL d1,d2;
                   3548:
                   3549:   d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   3550:   if ( d1->td < d2->td )
                   3551:     return 0;
                   3552:   else {
                   3553:     for ( i = 0, n = p1->nv; i < n; i++ )
                   3554:       if ( d1->d[i] < d2->d[i] )
                   3555:         return 0;
                   3556:     return 1;
                   3557:   }
                   3558: }
                   3559:
                   3560: int dpm_redble(DPM p1,DPM p2)
                   3561: {
                   3562:   int i,n;
                   3563:   DL d1,d2;
                   3564:
                   3565:   if ( BDY(p1)->pos != BDY(p2)->pos ) return 0;
                   3566:   d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   3567:   if ( d1->td < d2->td )
                   3568:     return 0;
                   3569:   else {
                   3570:     for ( i = 0, n = p1->nv; i < n; i++ )
                   3571:       if ( d1->d[i] < d2->d[i] )
                   3572:         return 0;
                   3573:     return 1;
                   3574:   }
                   3575: }
                   3576:
                   3577:
                   3578: void dp_subd(DP p1,DP p2,DP *rp)
                   3579: {
                   3580:   int i,n;
                   3581:   DL d1,d2,d;
                   3582:   MP m;
                   3583:   DP s;
                   3584:
                   3585:   n = p1->nv; d1 = BDY(p1)->dl; d2 = BDY(p2)->dl;
                   3586:   NEWDL(d,n); d->td = d1->td - d2->td;
                   3587:   for ( i = 0; i < n; i++ )
                   3588:     d->d[i] = d1->d[i]-d2->d[i];
                   3589:   NEWMP(m); m->dl = d; m->c = (Obj)ONE; NEXT(m) = 0;
                   3590:   MKDP(n,m,s); s->sugar = d->td;
                   3591:   *rp = s;
                   3592: }
                   3593:
                   3594: void dltod(DL d,int n,DP *rp)
                   3595: {
                   3596:   MP m;
                   3597:   DP s;
                   3598:
                   3599:   NEWMP(m); m->dl = d; m->c = (Obj)ONE; NEXT(m) = 0;
                   3600:   MKDP(n,m,s); s->sugar = d->td;
                   3601:   *rp = s;
                   3602: }
                   3603:
                   3604: void dp_hm(DP p,DP *rp)
                   3605: {
                   3606:   MP m,mr;
                   3607:
                   3608:   if ( !p )
                   3609:     *rp = 0;
                   3610:   else {
                   3611:     m = BDY(p);
                   3612:     NEWMP(mr); mr->dl = m->dl; mr->c = m->c; NEXT(mr) = 0;
                   3613:     MKDP(p->nv,mr,*rp); (*rp)->sugar = mr->dl->td;   /* XXX */
                   3614:   }
                   3615: }
                   3616:
                   3617: void dp_ht(DP p,DP *rp)
                   3618: {
                   3619:   MP m,mr;
                   3620:
                   3621:   if ( !p )
                   3622:     *rp = 0;
                   3623:   else {
                   3624:     m = BDY(p);
                   3625:     NEWMP(mr); mr->dl = m->dl; mr->c = (Obj)ONE; NEXT(mr) = 0;
                   3626:     MKDP(p->nv,mr,*rp); (*rp)->sugar = mr->dl->td;   /* XXX */
                   3627:   }
                   3628: }
                   3629:
                   3630: void dpm_hm(DPM p,DPM *rp)
                   3631: {
                   3632:   DMM m,mr;
                   3633:
                   3634:   if ( !p )
                   3635:     *rp = 0;
                   3636:   else {
                   3637:     m = BDY(p);
                   3638:     NEWDMM(mr); mr->dl = m->dl; mr->c = m->c; mr->pos = m->pos; NEXT(mr) = 0;
                   3639:     MKDPM(p->nv,mr,*rp); (*rp)->sugar = mr->dl->td;   /* XXX */
                   3640:   }
                   3641: }
                   3642:
                   3643: void dpm_ht(DPM p,DPM *rp)
                   3644: {
                   3645:   DMM m,mr;
                   3646:
                   3647:   if ( !p )
                   3648:     *rp = 0;
                   3649:   else {
                   3650:     m = BDY(p);
                   3651:     NEWDMM(mr); mr->dl = m->dl; mr->pos = m->pos; mr->c = (Obj)ONE; NEXT(mr) = 0;
                   3652:     MKDPM(p->nv,mr,*rp); (*rp)->sugar = mr->dl->td;   /* XXX */
                   3653:   }
                   3654: }
                   3655:
                   3656:
                   3657: void dp_rest(DP p,DP *rp)
                   3658: {
                   3659:   MP m;
                   3660:
                   3661:   m = BDY(p);
                   3662:   if ( !NEXT(m) )
                   3663:     *rp = 0;
                   3664:   else {
                   3665:     MKDP(p->nv,NEXT(m),*rp);
                   3666:     if ( *rp )
                   3667:       (*rp)->sugar = p->sugar;
                   3668:   }
                   3669: }
                   3670:
                   3671: void dpm_rest(DPM p,DPM *rp)
                   3672: {
                   3673:   DMM m;
                   3674:
                   3675:   m = BDY(p);
                   3676:   if ( !NEXT(m) )
                   3677:     *rp = 0;
                   3678:   else {
                   3679:     MKDPM(p->nv,NEXT(m),*rp);
                   3680:     if ( *rp )
                   3681:       (*rp)->sugar = p->sugar;
                   3682:   }
                   3683: }
                   3684:
1.16      noro     3685: int dp_getdeg(DP p)
                   3686: {
                   3687:   int max,n,i;
                   3688:   MP m;
                   3689:   int *d;
                   3690:
                   3691:   if ( !p ) return 0;
                   3692:   n = p->nv;
                   3693:   max = 0;
                   3694:   for ( m = BDY(p); m; m = NEXT(m) ) {
                   3695:     d = m->dl->d;
                   3696:     for ( i = 0; i < n; i++ )
                   3697:       if ( d[i] > max ) max = d[i];
                   3698:   }
                   3699:   return max;
                   3700: }
                   3701:
1.3       noro     3702: int dpm_getdeg(DPM p,int *r)
                   3703: {
                   3704:   int max,n,i,rank;
                   3705:   DMM m;
                   3706:   int *d;
                   3707:
                   3708:   if ( !p ) return 0;
                   3709:   n = p->nv;
                   3710:   max = 0;
                   3711:   rank = 0;
                   3712:   for ( m = BDY(p); m; m = NEXT(m) ) {
                   3713:     d = m->dl->d;
                   3714:     for ( i = 0; i < n; i++ )
                   3715:       if ( d[i] > max ) max = d[i];
                   3716:     rank = MAX(rank,m->pos);
                   3717:   }
                   3718:   *r = rank;
                   3719:   return max;
                   3720: }
                   3721:
1.1       noro     3722: DL lcm_of_DL(int nv,DL dl1,DL dl2,DL dl)
                   3723: {
                   3724:   register int i, *d1, *d2, *d, td;
                   3725:
                   3726:   if ( !dl ) NEWDL(dl,nv);
                   3727:   d = dl->d,  d1 = dl1->d,  d2 = dl2->d;
                   3728:   for ( td = 0, i = 0; i < nv; d1++, d2++, d++, i++ ) {
                   3729:     *d = *d1 > *d2 ? *d1 : *d2;
                   3730:     td += MUL_WEIGHT(*d,i);
                   3731:   }
                   3732:   dl->td = td;
                   3733:   return dl;
                   3734: }
                   3735:
                   3736: int dl_equal(int nv,DL dl1,DL dl2)
                   3737: {
                   3738:     register int *d1, *d2, n;
                   3739:
                   3740:     if ( dl1->td != dl2->td ) return 0;
                   3741:     for ( d1 = dl1->d, d2 = dl2->d, n = nv; --n >= 0; d1++, d2++ )
                   3742:         if ( *d1 != *d2 ) return 0;
                   3743:     return 1;
                   3744: }
                   3745:
                   3746: int dp_nt(DP p)
                   3747: {
                   3748:   int i;
                   3749:   MP m;
                   3750:
                   3751:   if ( !p )
                   3752:     return 0;
                   3753:   else {
                   3754:     for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
                   3755:     return i;
                   3756:   }
                   3757: }
                   3758:
                   3759: int dp_homogeneous(DP p)
                   3760: {
                   3761:   MP m;
                   3762:   int d;
                   3763:
                   3764:   if ( !p )
                   3765:     return 1;
                   3766:   else {
                   3767:     m = BDY(p);
                   3768:     d = m->dl->td;
                   3769:     m = NEXT(m);
                   3770:     for ( ; m; m = NEXT(m) ) {
                   3771:       if ( m->dl->td != d )
                   3772:         return 0;
                   3773:     }
                   3774:     return 1;
                   3775:   }
                   3776: }
                   3777:
                   3778: void _print_mp(int nv,MP m)
                   3779: {
                   3780:   int i;
                   3781:
                   3782:   if ( !m )
                   3783:     return;
                   3784:   for ( ; m; m = NEXT(m) ) {
1.3       noro     3785:     fprintf(stderr,"%ld<",ITOS(C(m)));
1.1       noro     3786:     for ( i = 0; i < nv; i++ ) {
                   3787:       fprintf(stderr,"%d",m->dl->d[i]);
                   3788:       if ( i != nv-1 )
                   3789:         fprintf(stderr," ");
                   3790:     }
1.3       noro     3791:     fprintf(stderr,">");
1.1       noro     3792:   }
                   3793:   fprintf(stderr,"\n");
                   3794: }
                   3795:
                   3796: static int cmp_mp_nvar;
                   3797:
                   3798: int comp_mp(MP *a,MP *b)
                   3799: {
                   3800:   return -(*cmpdl)(cmp_mp_nvar,(*a)->dl,(*b)->dl);
                   3801: }
                   3802:
                   3803: void dp_sort(DP p,DP *rp)
                   3804: {
                   3805:   MP t,mp,mp0;
                   3806:   int i,n;
                   3807:   DP r;
                   3808:   MP *w;
                   3809:
                   3810:   if ( !p ) {
                   3811:     *rp = 0;
                   3812:     return;
                   3813:   }
                   3814:   for ( t = BDY(p), n = 0; t; t = NEXT(t), n++ );
                   3815:   w = (MP *)ALLOCA(n*sizeof(MP));
                   3816:   for ( t = BDY(p), i = 0; i < n; t = NEXT(t), i++ )
                   3817:     w[i] = t;
                   3818:   cmp_mp_nvar = NV(p);
                   3819:   qsort(w,n,sizeof(MP),(int (*)(const void *,const void *))comp_mp);
                   3820:   mp0 = 0;
                   3821:   for ( i = n-1; i >= 0; i-- ) {
                   3822:     NEWMP(mp); mp->dl = w[i]->dl; C(mp) = C(w[i]);
                   3823:     NEXT(mp) = mp0; mp0 = mp;
                   3824:   }
                   3825:   MKDP(p->nv,mp0,r);
                   3826:   r->sugar = p->sugar;
                   3827:   *rp = r;
                   3828: }
                   3829:
                   3830: DP extract_initial_term_from_dp(DP p,int *weight,int n);
                   3831: LIST extract_initial_term(LIST f,int *weight,int n);
                   3832:
                   3833: DP extract_initial_term_from_dp(DP p,int *weight,int n)
                   3834: {
                   3835:   int w,t,i,top;
                   3836:   MP m,r0,r;
                   3837:   DP dp;
                   3838:
                   3839:   if ( !p ) return 0;
                   3840:   top = 1;
                   3841:   for ( m = BDY(p); m; m = NEXT(m) ) {
                   3842:     for ( i = 0, t = 0; i < n; i++ )
                   3843:       t += weight[i]*m->dl->d[i];
                   3844:     if ( top || t > w ) {
                   3845:       r0 = 0;
                   3846:       w = t;
                   3847:       top = 0;
                   3848:     }
                   3849:     if ( t == w ) {
                   3850:       NEXTMP(r0,r);
                   3851:       r->dl = m->dl;
                   3852:       r->c = m->c;
                   3853:     }
                   3854:   }
                   3855:   NEXT(r) = 0;
                   3856:   MKDP(p->nv,r0,dp);
                   3857:   return dp;
                   3858: }
                   3859:
                   3860: LIST extract_initial_term(LIST f,int *weight,int n)
                   3861: {
                   3862:   NODE nd,r0,r;
                   3863:   Obj p;
                   3864:   LIST l;
                   3865:
                   3866:   nd = BDY(f);
                   3867:   for ( r0 = 0; nd; nd = NEXT(nd) ) {
                   3868:     NEXTNODE(r0,r);
                   3869:     p = (Obj)BDY(nd);
                   3870:     BDY(r) = (pointer)extract_initial_term_from_dp((DP)p,weight,n);
                   3871:   }
                   3872:   if ( r0 ) NEXT(r) = 0;
                   3873:   MKLIST(l,r0);
                   3874:   return l;
                   3875: }
                   3876:
                   3877: LIST dp_initial_term(LIST f,struct order_spec *ord)
                   3878: {
                   3879:   int n,l,i;
                   3880:   struct weight_or_block *worb;
                   3881:   int *weight;
                   3882:
                   3883:   switch ( ord->id ) {
                   3884:     case 2: /* matrix order */
                   3885:       /* extract the first row */
                   3886:       n = ord->nv;
                   3887:       weight = ord->ord.matrix.matrix[0];
                   3888:       return extract_initial_term(f,weight,n);
                   3889:     case 3: /* composite order */
                   3890:       /* the first w_or_b */
                   3891:       worb = ord->ord.composite.w_or_b;
                   3892:       switch ( worb->type ) {
                   3893:         case IS_DENSE_WEIGHT:
                   3894:           n = worb->length;
                   3895:           weight = worb->body.dense_weight;
                   3896:           return extract_initial_term(f,weight,n);
                   3897:         case IS_SPARSE_WEIGHT:
                   3898:           n = ord->nv;
                   3899:           weight = (int *)ALLOCA(n*sizeof(int));
                   3900:           for ( i = 0; i < n; i++ ) weight[i] = 0;
                   3901:           l = worb->length;
                   3902:           for ( i = 0; i < l; i++ )
                   3903:             weight[worb->body.sparse_weight[i].pos]
                   3904:               =  worb->body.sparse_weight[i].value;
                   3905:           return extract_initial_term(f,weight,n);
                   3906:         default:
                   3907:           error("dp_initial_term : unsupported order");
                   3908:       }
                   3909:     default:
                   3910:       error("dp_initial_term : unsupported order");
                   3911:   }
1.3       noro     3912:   return 0;
1.1       noro     3913: }
                   3914:
                   3915: int highest_order_dp(DP p,int *weight,int n);
                   3916: LIST highest_order(LIST f,int *weight,int n);
                   3917:
                   3918: int highest_order_dp(DP p,int *weight,int n)
                   3919: {
                   3920:   int w,t,i,top;
                   3921:   MP m;
                   3922:
                   3923:   if ( !p ) return -1;
                   3924:   top = 1;
                   3925:   for ( m = BDY(p); m; m = NEXT(m) ) {
                   3926:     for ( i = 0, t = 0; i < n; i++ )
                   3927:       t += weight[i]*m->dl->d[i];
                   3928:     if ( top || t > w ) {
                   3929:       w = t;
                   3930:       top = 0;
                   3931:     }
                   3932:   }
                   3933:   return w;
                   3934: }
                   3935:
                   3936: LIST highest_order(LIST f,int *weight,int n)
                   3937: {
                   3938:   int h;
                   3939:   NODE nd,r0,r;
                   3940:   Obj p;
                   3941:   LIST l;
                   3942:   Z q;
                   3943:
                   3944:   nd = BDY(f);
                   3945:   for ( r0 = 0; nd; nd = NEXT(nd) ) {
                   3946:     NEXTNODE(r0,r);
                   3947:     p = (Obj)BDY(nd);
                   3948:     h = highest_order_dp((DP)p,weight,n);
1.2       noro     3949:     STOZ(h,q);
1.1       noro     3950:     BDY(r) = (pointer)q;
                   3951:   }
                   3952:   if ( r0 ) NEXT(r) = 0;
                   3953:   MKLIST(l,r0);
                   3954:   return l;
                   3955: }
                   3956:
                   3957: LIST dp_order(LIST f,struct order_spec *ord)
                   3958: {
                   3959:   int n,l,i;
                   3960:   struct weight_or_block *worb;
                   3961:   int *weight;
                   3962:
                   3963:   switch ( ord->id ) {
                   3964:     case 2: /* matrix order */
                   3965:       /* extract the first row */
                   3966:       n = ord->nv;
                   3967:       weight = ord->ord.matrix.matrix[0];
                   3968:       return highest_order(f,weight,n);
                   3969:     case 3: /* composite order */
                   3970:       /* the first w_or_b */
                   3971:       worb = ord->ord.composite.w_or_b;
                   3972:       switch ( worb->type ) {
                   3973:         case IS_DENSE_WEIGHT:
                   3974:           n = worb->length;
                   3975:           weight = worb->body.dense_weight;
                   3976:           return highest_order(f,weight,n);
                   3977:         case IS_SPARSE_WEIGHT:
                   3978:           n = ord->nv;
                   3979:           weight = (int *)ALLOCA(n*sizeof(int));
                   3980:           for ( i = 0; i < n; i++ ) weight[i] = 0;
                   3981:           l = worb->length;
                   3982:           for ( i = 0; i < l; i++ )
                   3983:             weight[worb->body.sparse_weight[i].pos]
                   3984:               =  worb->body.sparse_weight[i].value;
                   3985:           return highest_order(f,weight,n);
                   3986:         default:
                   3987:           error("dp_initial_term : unsupported order");
                   3988:       }
                   3989:     default:
                   3990:       error("dp_initial_term : unsupported order");
                   3991:   }
1.3       noro     3992:   return 0;
1.1       noro     3993: }
                   3994:
                   3995: int dpv_ht(DPV p,DP *h)
                   3996: {
                   3997:   int len,max,maxi,i,t;
                   3998:   DP *e;
                   3999:   MP m,mr;
                   4000:
                   4001:   len = p->len;
                   4002:   e = p->body;
                   4003:   max = -1;
                   4004:   maxi = -1;
                   4005:   for ( i = 0; i < len; i++ )
                   4006:     if ( e[i] && (t = BDY(e[i])->dl->td) > max ) {
                   4007:       max = t;
                   4008:       maxi = i;
                   4009:     }
                   4010:   if ( max < 0 ) {
                   4011:     *h = 0;
                   4012:     return -1;
                   4013:   } else {
                   4014:     m = BDY(e[maxi]);
                   4015:     NEWMP(mr); mr->dl = m->dl; mr->c = (Obj)ONE; NEXT(mr) = 0;
                   4016:     MKDP(e[maxi]->nv,mr,*h); (*h)->sugar = mr->dl->td;  /* XXX */
                   4017:     return maxi;
                   4018:   }
                   4019: }
                   4020:
                   4021: /* return 1 if 0 <_w1 v && v <_w2 0 */
                   4022:
                   4023: int in_c12(int n,int *v,int row1,int **w1,int row2, int **w2)
                   4024: {
                   4025:   int t1,t2;
                   4026:
                   4027:   t1 = compare_zero(n,v,row1,w1);
                   4028:   t2 = compare_zero(n,v,row2,w2);
                   4029:   if ( t1 > 0 && t2 < 0 ) return 1;
                   4030:   else return 0;
                   4031: }
                   4032:
                   4033: /* 0 < u => 1, 0 > u => -1 */
                   4034:
                   4035: int compare_zero(int n,int *u,int row,int **w)
                   4036: {
                   4037:   int i,j,t;
                   4038:   int *wi;
                   4039:
                   4040:   for ( i = 0; i < row; i++ ) {
                   4041:     wi = w[i];
                   4042:     for ( j = 0, t = 0; j < n; j++ ) t += u[j]*wi[j];
                   4043:     if ( t > 0 ) return 1;
                   4044:     else if ( t < 0 ) return -1;
                   4045:   }
                   4046:   return 0;
                   4047: }
                   4048:
                   4049: /* functions for generic groebner walk */
                   4050: /* u=0 means u=-infty */
                   4051:
                   4052: int compare_facet_preorder(int n,int *u,int *v,
                   4053:   int row1,int **w1,int row2,int **w2)
                   4054: {
                   4055:   int i,j,s,t,tu,tv;
                   4056:   int *w2i,*uv;
                   4057:
                   4058:   if ( !u ) return 1;
                   4059:   uv = W_ALLOC(n);
                   4060:   for ( i = 0; i < row2; i++ ) {
                   4061:     w2i = w2[i];
                   4062:     for ( j = 0, tu = tv = 0; j < n; j++ )
1.3       noro     4063:       if ( (s = w2i[j]) != 0 ) {
1.1       noro     4064:         tu += s*u[j]; tv += s*v[j];
                   4065:       }
                   4066:     for ( j = 0; j < n; j++ ) uv[j] = u[j]*tv-v[j]*tu;
                   4067:     t = compare_zero(n,uv,row1,w1);
                   4068:     if ( t > 0 ) return 1;
                   4069:     else if ( t < 0 ) return 0;
                   4070:   }
                   4071:   return 1;
                   4072: }
                   4073:
                   4074: Q inner_product_with_small_vector(VECT w,int *v)
                   4075: {
                   4076:   int n,i;
                   4077:   Z q;
                   4078:   Q s,t,u;
                   4079:
                   4080:   n = w->len;
                   4081:   s = 0;
                   4082:   for ( i = 0; i < n; i++ ) {
1.2       noro     4083:     STOZ(v[i],q); mulq((Q)w->body[i],(Q)q,&t); addq(t,s,&u); s = u;
1.1       noro     4084:   }
                   4085:   return s;
                   4086: }
                   4087:
                   4088: Q compute_last_t(NODE g,NODE gh,Q t,VECT w1,VECT w2,NODE *homo,VECT *wp)
                   4089: {
                   4090:   int n,i;
                   4091:   int *wt;
                   4092:   Q last,d1,d2,dn,nm,s,t1;
                   4093:   VECT wd,wt1,wt2,w;
                   4094:   NODE tg,tgh;
                   4095:   MP f;
                   4096:   int *h;
                   4097:   NODE r0,r;
                   4098:   MP m0,m;
                   4099:   DP d;
                   4100:
                   4101:   n = w1->len;
                   4102:   wt = W_ALLOC(n);
                   4103:   last = (Q)ONE;
                   4104:   /* t1 = 1-t */
                   4105:   for ( tg = g, tgh = gh; tg; tg = NEXT(tg), tgh = NEXT(tgh ) ) {
                   4106:     f = BDY((DP)BDY(tg));
                   4107:     h = BDY((DP)BDY(tgh))->dl->d;
                   4108:     for ( ; f; f = NEXT(f) ) {
                   4109:       for ( i = 0; i < n; i++ ) wt[i] = h[i]-f->dl->d[i];
                   4110:       for ( i = 0; i < n && !wt[i]; i++ );
                   4111:       if ( i == n ) continue;
                   4112:       d1 = inner_product_with_small_vector(w1,wt);
                   4113:       d2 = inner_product_with_small_vector(w2,wt);
                   4114:       nm = d1; subq(d1,d2,&dn);
                   4115:       /* if d1=d2 then nothing happens */
                   4116:       if ( !dn ) continue;
                   4117:       /* s satisfies ds = 0*/
                   4118:       divq(nm,dn,&s);
                   4119:
                   4120:       if ( cmpq(s,t) > 0 && cmpq(s,last) < 0 )
                   4121:         last = s;
                   4122:       else if ( !cmpq(s,t) ) {
                   4123:         if ( cmpq(d2,0) < 0 ) {
                   4124:           last = t;
                   4125:           break;
                   4126:         }
                   4127:       }
                   4128:     }
                   4129:   }
                   4130:   nmq(last,(Z *)&nm);
                   4131:   dnq(last,(Z *)&dn);
                   4132:   /* (1-n/d)*w1+n/d*w2 -> w=(d-n)*w1+n*w2 */
                   4133:   subq(dn,nm,&t1); mulvect(CO,(Obj)w1,(Obj)t1,(Obj *)&wt1);
                   4134:   mulvect(CO,(Obj)w2,(Obj)nm,(Obj *)&wt2); addvect(CO,wt1,wt2,&w);
                   4135:
                   4136:   r0 = 0;
                   4137:   for ( tg = g, tgh = gh; tg; tg = NEXT(tg), tgh = NEXT(tgh ) ) {
                   4138:     f = BDY((DP)BDY(tg));
                   4139:     h = BDY((DP)BDY(tgh))->dl->d;
                   4140:     for ( m0 = 0; f; f = NEXT(f) ) {
                   4141:       for ( i = 0; i < n; i++ ) wt[i] = h[i]-f->dl->d[i];
                   4142:       for ( i = 0; i < n && !wt[i]; i++ );
                   4143:       if ( !inner_product_with_small_vector(w,wt) ) {
                   4144:         NEXTMP(m0,m); m->c = f->c; m->dl = f->dl;
                   4145:       }
                   4146:     }
                   4147:     NEXT(m) = 0;
                   4148:     MKDP(((DP)BDY(tg))->nv,m0,d);  d->sugar = ((DP)BDY(tg))->sugar;
                   4149:     NEXTNODE(r0,r); BDY(r) = (pointer)d;
                   4150:   }
                   4151:   NEXT(r) = 0;
                   4152:   *homo = r0;
                   4153:   *wp = w;
                   4154:   return last;
                   4155: }
                   4156:
                   4157: /* return 0 if last_w = infty */
                   4158:
                   4159: NODE compute_last_w(NODE g,NODE gh,int n,int **w,
                   4160:   int row1,int **w1,int row2,int **w2)
                   4161: {
                   4162:   DP d;
                   4163:   MP f,m0,m;
                   4164:   int *wt,*v,*h;
                   4165:   NODE t,s,n0,tn,n1,r0,r;
                   4166:   int i;
                   4167:
                   4168:   wt = W_ALLOC(n);
                   4169:   n0 = 0;
                   4170:   for ( t = g, s = gh; t; t = NEXT(t), s = NEXT(s) ) {
                   4171:     f = BDY((DP)BDY(t));
                   4172:     h = BDY((DP)BDY(s))->dl->d;
                   4173:     for ( ; f; f = NEXT(f) ) {
                   4174:       for ( i = 0; i < n; i++ ) wt[i] = h[i]-f->dl->d[i];
                   4175:       for ( i = 0; i < n && !wt[i]; i++ );
                   4176:       if ( i == n ) continue;
                   4177:
                   4178:       if ( in_c12(n,wt,row1,w1,row2,w2) &&
                   4179:         compare_facet_preorder(n,*w,wt,row1,w1,row2,w2) ) {
                   4180:         v = (int *)MALLOC_ATOMIC(n*sizeof(int));
                   4181:         for ( i = 0; i < n; i++ ) v[i] = wt[i];
                   4182:         MKNODE(n1,v,n0); n0 = n1;
                   4183:       }
                   4184:     }
                   4185:   }
                   4186:   if ( !n0 ) return 0;
                   4187:   for ( t = n0; t; t = NEXT(t) ) {
                   4188:     v = (int *)BDY(t);
                   4189:     for ( s = n0; s; s = NEXT(s) )
                   4190:       if ( !compare_facet_preorder(n,v,(int *)BDY(s),row1,w1,row2,w2) )
                   4191:         break;
                   4192:     if ( !s ) {
                   4193:       *w = v;
                   4194:       break;
                   4195:     }
                   4196:   }
                   4197:   if ( !t )
                   4198:     error("compute_last_w : cannot happen");
                   4199:   r0 = 0;
                   4200:   for ( t = g, s = gh; t; t = NEXT(t), s = NEXT(s) ) {
                   4201:     f = BDY((DP)BDY(t));
                   4202:     h = BDY((DP)BDY(s))->dl->d;
                   4203:     for ( m0 = 0; f; f = NEXT(f) ) {
                   4204:       for ( i = 0; i < n; i++ ) wt[i] = h[i]-f->dl->d[i];
                   4205:       for ( i = 0; i < n && !wt[i]; i++ );
                   4206:       if ( i == n  ||
                   4207:         (compare_facet_preorder(n,wt,*w,row1,w1,row2,w2)
                   4208:         && compare_facet_preorder(n,*w,wt,row1,w1,row2,w2)) ) {
                   4209:         NEXTMP(m0,m); m->c = f->c; m->dl = f->dl;
                   4210:       }
                   4211:     }
                   4212:     NEXT(m) = 0;
                   4213:     MKDP(((DP)BDY(t))->nv,m0,d);  d->sugar = ((DP)BDY(t))->sugar;
                   4214:     NEXTNODE(r0,r); BDY(r) = (pointer)d;
                   4215:   }
                   4216:   NEXT(r) = 0;
                   4217:   return r0;
                   4218: }
                   4219:
                   4220: /* compute a sufficient set of d(f)=u-v */
                   4221:
                   4222: NODE compute_essential_df(DP *g,DP *gh,int ng)
                   4223: {
                   4224:   int nv,i,j,k,t,lj;
                   4225:   NODE r,r1,ri,rt,r0;
                   4226:   MP m;
                   4227:   MP *mj;
                   4228:   DL di,hj,dl,dlt;
                   4229:   int *d,*dt;
                   4230:   LIST l;
                   4231:   Z q;
                   4232:
                   4233:   nv = g[0]->nv;
                   4234:   r = 0;
                   4235:   for ( j = 0; j < ng; j++ ) {
                   4236:     for ( m = BDY(g[j]), lj = 0; m; m = NEXT(m), lj++ );
                   4237:     mj = (MP *)ALLOCA(lj*sizeof(MP));
                   4238:     for ( m = BDY(g[j]), k = 0; m; m = NEXT(m), k++ )
                   4239:       mj[k] = m;
                   4240:     for ( i = 0; i < lj; i++ ) {
                   4241:       for ( di = mj[i]->dl, k = i+1; k < lj; k++ )
                   4242:         if ( _dl_redble(di,mj[k]->dl,nv) ) break;
                   4243:       if ( k < lj ) mj[i] = 0;
                   4244:     }
                   4245:     hj = BDY(gh[j])->dl;
                   4246:     _NEWDL(dl,nv); d = dl->d;
                   4247:     r0 = r;
                   4248:     for ( i = 0; i < lj; i++ ) {
                   4249:       if ( mj[i] && !dl_equal(nv,di=mj[i]->dl,hj) ) {
                   4250:         for ( k = 0, t = 0; k < nv; k++ ) {
                   4251:           d[k] = hj->d[k]-di->d[k];
                   4252:           t += d[k];
                   4253:         }
                   4254:         dl->td = t;
                   4255: #if 1
                   4256:         for ( rt = r0; rt; rt = NEXT(rt) ) {
                   4257:           dlt = (DL)BDY(rt);
                   4258:           if ( dlt->td != dl->td ) continue;
                   4259:           for ( dt = dlt->d, k = 0; k < nv; k++ )
                   4260:             if ( d[k] != dt[k] ) break;
                   4261:           if ( k == nv ) break;
                   4262:         }
                   4263: #else
                   4264:         rt = 0;
                   4265: #endif
                   4266:         if ( !rt ) {
                   4267:           MKNODE(r1,dl,r); r = r1;
                   4268:           _NEWDL(dl,nv); d = dl->d;
                   4269:         }
                   4270:       }
                   4271:     }
                   4272:   }
                   4273:   for ( rt = r; rt; rt = NEXT(rt) ) {
                   4274:     dl = (DL)BDY(rt); d = dl->d;
                   4275:     ri = 0;
                   4276:     for ( k = nv-1; k >= 0; k-- ) {
1.2       noro     4277:       STOZ(d[k],q);
1.1       noro     4278:       MKNODE(r1,q,ri); ri = r1;
                   4279:     }
                   4280:     MKNODE(r1,0,ri); MKLIST(l,r1);
                   4281:     BDY(rt) = (pointer)l;
                   4282:   }
                   4283:   return r;
                   4284: }
                   4285:
                   4286: int comp_bits_divisible(int *a,int *b,int n)
                   4287: {
                   4288:   int bpi,i,wi,bi;
                   4289:
                   4290:   bpi = (sizeof(int)/sizeof(char))*8;
                   4291:   for ( i = 0; i < n; i++ ) {
                   4292:     wi = i/bpi; bi = i%bpi;
                   4293:     if ( !(a[wi]&(1<<bi)) && (b[wi]&(1<<bi)) ) return 0;
                   4294:   }
                   4295:   return 1;
                   4296: }
                   4297:
                   4298: int comp_bits_lex(int *a,int *b,int n)
                   4299: {
                   4300:   int bpi,i,wi,ba,bb,bi;
                   4301:
                   4302:   bpi = (sizeof(int)/sizeof(char))*8;
                   4303:   for ( i = 0; i < n; i++ ) {
                   4304:     wi = i/bpi; bi = i%bpi;
                   4305:     ba = (a[wi]&(1<<bi))?1:0;
                   4306:     bb = (b[wi]&(1<<bi))?1:0;
                   4307:     if ( ba > bb ) return 1;
                   4308:     else if ( ba < bb ) return -1;
                   4309:   }
                   4310:   return 0;
                   4311: }
                   4312:
                   4313: NODE mono_raddec(NODE ideal)
                   4314: {
                   4315:   DP p;
                   4316:   int nv,w,i,bpi,di,c,len;
                   4317:   int *d,*s,*u,*new;
                   4318:   NODE t,t1,v,r,rem,prev;
                   4319:
                   4320:   if( !ideal ) return 0;
                   4321:   p = (DP)BDY(ideal);
                   4322:   nv = NV(p);
                   4323:   bpi = (sizeof(int)/sizeof(char))*8;
                   4324:   w = (nv+(bpi-1))/bpi;
                   4325:   d = p->body->dl->d;
                   4326:   if ( !NEXT(ideal) )  {
                   4327:     for ( t = 0, i = nv-1; i >= 0; i-- ) {
                   4328:       if ( d[i] ) {
                   4329:         s = (int *)CALLOC(w,sizeof(int));
                   4330:         s[i/bpi] |= 1<<(i%bpi);
                   4331:         MKNODE(t1,s,t);
                   4332:         t = t1;
                   4333:       }
                   4334:     }
                   4335:     return t;
                   4336:   }
                   4337:   rem = mono_raddec(NEXT(ideal));
                   4338:   r = 0;
                   4339:   len = w*sizeof(int);
                   4340:   u = (int *)CALLOC(w,sizeof(int));
                   4341:   for ( i = nv-1; i >= 0; i-- ) {
                   4342:     if ( d[i] ) {
                   4343:       for ( t = rem; t; t = NEXT(t) ) {
                   4344:         bcopy((char *)BDY(t),(char *)u,len);
                   4345:         u[i/bpi] |= 1<<(i%bpi);
                   4346:         for ( v = r; v; v = NEXT(v) ) {
                   4347:           if ( comp_bits_divisible(u,(int *)BDY(v),nv) ) break;
                   4348:         }
                   4349:         if ( v ) continue;
                   4350:         for ( v = r, prev = 0; v; v = NEXT(v) ) {
                   4351:           if ( comp_bits_divisible((int *)BDY(v),u,nv) ) {
                   4352:             if ( prev ) NEXT(prev) = NEXT(v);
                   4353:             else r = NEXT(r);
                   4354:           } else prev =v;
                   4355:         }
                   4356:         for ( v = r, prev = 0; v; prev = v, v = NEXT(v) ) {
                   4357:           if ( comp_bits_lex(u,(int *)BDY(v),nv) < 0 ) break;
                   4358:         }
                   4359:         new = (int *)CALLOC(w,sizeof(int));
                   4360:         bcopy((char *)u,(char *)new,len);
                   4361:         MKNODE(t1,new,v);
                   4362:         if ( prev ) NEXT(prev) = t1;
                   4363:         else r = t1;
                   4364:       }
                   4365:     }
                   4366:   }
                   4367:   return r;
                   4368: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>