[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.14

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

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