[BACK]Return to nd.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / engine

Annotation of OpenXM_contrib2/asir2000/engine/nd.c, Revision 1.157

1.157   ! noro        1: /* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.156 2008/05/23 01:24:21 noro Exp $ */
1.2       noro        2:
1.94      noro        3: #include "nd.h"
1.63      noro        4:
1.131     noro        5: int diag_period = 6;
1.61      noro        6: int (*ndl_compare_function)(UINT *a1,UINT *a2);
1.94      noro        7: int nd_dcomp;
                      8: NM _nm_free_list;
                      9: ND _nd_free_list;
                     10: ND_pairs _ndp_free_list;
1.150     noro       11: NODE nd_hcf;
1.32      noro       12:
1.146     noro       13: static NODE nd_subst;
                     14: static VL nd_vc;
1.121     noro       15: static int nd_ntrans;
1.117     noro       16: static int nd_nalg;
1.103     noro       17: #if 0
1.74      noro       18: static int ndv_alloc;
1.103     noro       19: #endif
1.87      noro       20: #if 1
1.69      noro       21: static int nd_f4_nsp=0x7fffffff;
1.87      noro       22: #else
                     23: static int nd_f4_nsp=50;
                     24: #endif
1.42      noro       25: static double nd_scale=2;
1.61      noro       26: static UINT **nd_bound;
1.42      noro       27: static struct order_spec *nd_ord;
                     28: static EPOS nd_epos;
1.43      noro       29: static BlockMask nd_blockmask;
1.42      noro       30: static int nd_nvar;
                     31: static int nd_isrlex;
                     32: static int nd_epw,nd_bpe,nd_wpd,nd_exporigin;
1.61      noro       33: static UINT nd_mask[32];
                     34: static UINT nd_mask0,nd_mask1;
1.42      noro       35:
1.20      noro       36: static NDV *nd_ps;
1.53      noro       37: static NDV *nd_ps_trace;
1.42      noro       38: static RHist *nd_psh;
                     39: static int nd_psn,nd_pslen;
                     40: static RHist *nd_red;
1.96      noro       41: static int *nd_work_vector;
                     42: static int **nd_matrix;
                     43: static int nd_matrix_len;
1.97      noro       44: static struct weight_or_block *nd_worb;
                     45: static int nd_worb_len;
1.42      noro       46: static int nd_found,nd_create,nd_notfirst;
                     47: static int nmv_adv;
1.77      noro       48: static int nd_demand;
1.157   ! noro       49: static int nd_module,nd_istop,nd_mpos;
1.1       noro       50:
1.119     noro       51: NumberField get_numberfield();
1.114     noro       52: UINT *nd_det_compute_bound(NDV **dm,int n,int j);
                     53: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d);
1.152     ohara      54: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr);
1.118     noro       55: int nd_monic(int m,ND *p);
1.129     noro       56: NDV plain_vect_to_ndv_q(Q *mat,int col,UINT *s0vect);
1.157   ! noro       57: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank);
        !            58: NDV pltondv(VL vl,VL dvl,LIST p);
        !            59: void pltozpl(LIST l,Q *cont,LIST *pp);
        !            60: void ndl_lcm_nocheck(UINT *d1,unsigned *d2,UINT *d);
1.114     noro       61:
1.149     noro       62: extern int Denominator,DP_Multiple;
                     63:
1.1       noro       64: void nd_free_private_storage()
                     65: {
1.157   ! noro       66:     _nm_free_list = 0;
        !            67:     _ndp_free_list = 0;
1.71      noro       68: #if 0
1.157   ! noro       69:     GC_gcollect();
1.71      noro       70: #endif
1.1       noro       71: }
                     72:
                     73: void _NM_alloc()
                     74: {
1.157   ! noro       75:     NM p;
        !            76:     int i;
1.1       noro       77:
1.157   ! noro       78:     for ( i = 0; i < 1024; i++ ) {
        !            79:         p = (NM)GC_malloc(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
        !            80:         p->next = _nm_free_list; _nm_free_list = p;
        !            81:     }
1.1       noro       82: }
                     83:
                     84: void _ND_alloc()
                     85: {
1.157   ! noro       86:     ND p;
        !            87:     int i;
1.1       noro       88:
1.157   ! noro       89:     for ( i = 0; i < 1024; i++ ) {
        !            90:         p = (ND)GC_malloc(sizeof(struct oND));
        !            91:         p->body = (NM)_nd_free_list; _nd_free_list = p;
        !            92:     }
1.1       noro       93: }
                     94:
                     95: void _NDP_alloc()
                     96: {
1.157   ! noro       97:     ND_pairs p;
        !            98:     int i;
1.1       noro       99:
1.157   ! noro      100:     for ( i = 0; i < 1024; i++ ) {
        !           101:         p = (ND_pairs)GC_malloc(sizeof(struct oND_pairs)
        !           102:             +(nd_wpd-1)*sizeof(UINT));
        !           103:         p->next = _ndp_free_list; _ndp_free_list = p;
        !           104:     }
1.1       noro      105: }
                    106:
1.30      noro      107: INLINE int nd_length(ND p)
1.1       noro      108: {
1.157   ! noro      109:     NM m;
        !           110:     int i;
1.1       noro      111:
1.157   ! noro      112:     if ( !p )
        !           113:         return 0;
        !           114:     else {
        !           115:         for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
        !           116:         return i;
        !           117:     }
1.1       noro      118: }
                    119:
1.61      noro      120: INLINE int ndl_reducible(UINT *d1,UINT *d2)
1.1       noro      121: {
1.157   ! noro      122:     UINT u1,u2;
        !           123:     int i,j;
1.1       noro      124:
1.157   ! noro      125:     if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
        !           126:
        !           127:     if ( TD(d1) < TD(d2) ) return 0;
1.65      noro      128: #if USE_UNROLL
1.157   ! noro      129:     switch ( nd_bpe ) {
        !           130:         case 3:
        !           131:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           132:                 u1 = d1[i]; u2 = d2[i];
        !           133:                 if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
        !           134:                 if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
        !           135:                 if ( (u1&  0xe00000) < (u2&  0xe00000) ) return 0;
        !           136:                 if ( (u1&  0x1c0000) < (u2&  0x1c0000) ) return 0;
        !           137:                 if ( (u1&   0x38000) < (u2&   0x38000) ) return 0;
        !           138:                 if ( (u1&    0x7000) < (u2&    0x7000) ) return 0;
        !           139:                 if ( (u1&     0xe00) < (u2&     0xe00) ) return 0;
        !           140:                 if ( (u1&     0x1c0) < (u2&     0x1c0) ) return 0;
        !           141:                 if ( (u1&      0x38) < (u2&      0x38) ) return 0;
        !           142:                 if ( (u1&       0x7) < (u2&       0x7) ) return 0;
        !           143:             }
        !           144:             return 1;
        !           145:             break;
        !           146:         case 4:
        !           147:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           148:                 u1 = d1[i]; u2 = d2[i];
        !           149:                 if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
        !           150:                 if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
        !           151:                 if ( (u1&  0xf00000) < (u2&  0xf00000) ) return 0;
        !           152:                 if ( (u1&   0xf0000) < (u2&   0xf0000) ) return 0;
        !           153:                 if ( (u1&    0xf000) < (u2&    0xf000) ) return 0;
        !           154:                 if ( (u1&     0xf00) < (u2&     0xf00) ) return 0;
        !           155:                 if ( (u1&      0xf0) < (u2&      0xf0) ) return 0;
        !           156:                 if ( (u1&       0xf) < (u2&       0xf) ) return 0;
        !           157:             }
        !           158:             return 1;
        !           159:             break;
        !           160:         case 6:
        !           161:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           162:                 u1 = d1[i]; u2 = d2[i];
        !           163:                 if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
        !           164:                 if ( (u1&  0xfc0000) < (u2&  0xfc0000) ) return 0;
        !           165:                 if ( (u1&   0x3f000) < (u2&   0x3f000) ) return 0;
        !           166:                 if ( (u1&     0xfc0) < (u2&     0xfc0) ) return 0;
        !           167:                 if ( (u1&      0x3f) < (u2&      0x3f) ) return 0;
        !           168:             }
        !           169:             return 1;
        !           170:             break;
        !           171:         case 8:
        !           172:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           173:                 u1 = d1[i]; u2 = d2[i];
        !           174:                 if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
        !           175:                 if ( (u1&  0xff0000) < (u2&  0xff0000) ) return 0;
        !           176:                 if ( (u1&    0xff00) < (u2&    0xff00) ) return 0;
        !           177:                 if ( (u1&      0xff) < (u2&      0xff) ) return 0;
        !           178:             }
        !           179:             return 1;
        !           180:             break;
        !           181:         case 16:
        !           182:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           183:                 u1 = d1[i]; u2 = d2[i];
        !           184:                 if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
        !           185:                 if ( (u1&    0xffff) < (u2&    0xffff) ) return 0;
        !           186:             }
        !           187:             return 1;
        !           188:             break;
        !           189:         case 32:
        !           190:             for ( i = nd_exporigin; i < nd_wpd; i++ )
        !           191:                 if ( d1[i] < d2[i] ) return 0;
        !           192:             return 1;
        !           193:             break;
        !           194:         default:
        !           195:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           196:                 u1 = d1[i]; u2 = d2[i];
        !           197:                 for ( j = 0; j < nd_epw; j++ )
        !           198:                     if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
        !           199:             }
        !           200:             return 1;
        !           201:     }
1.65      noro      202: #else
1.157   ! noro      203:     for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           204:         u1 = d1[i]; u2 = d2[i];
        !           205:         for ( j = 0; j < nd_epw; j++ )
        !           206:             if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
        !           207:     }
        !           208:     return 1;
1.65      noro      209: #endif
1.1       noro      210: }
                    211:
1.61      noro      212: /*
                    213:  * If the current order is a block order,
                    214:  * then the last block is length 1 and contains
                    215:  * the homo variable. Otherwise, the original
                    216:  * order is either 0 or 2.
                    217:  */
                    218:
                    219: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int weight)
1.23      noro      220: {
1.157   ! noro      221:     int w,i,e,n,omask0;
1.61      noro      222:
1.157   ! noro      223:     omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
        !           224:     n = nd_nvar-1;
        !           225:     ndl_zero(r);
        !           226:     for ( i = 0; i < n; i++ ) {
        !           227:         e = GET_EXP_OLD(d,i);
        !           228:         PUT_EXP(r,i,e);
        !           229:     }
        !           230:     w = TD(d);
        !           231:     PUT_EXP(r,nd_nvar-1,weight-w);
        !           232:     TD(r) = weight;
        !           233:     if ( nd_blockmask ) ndl_weight_mask(r);
        !           234:     if ( nd_module ) MPOS(r) = MPOS(d);
1.61      noro      235: }
                    236:
                    237: void ndl_dehomogenize(UINT *d)
                    238: {
1.157   ! noro      239:     UINT mask;
        !           240:     UINT h;
        !           241:     int i,bits;
        !           242:
        !           243:     if ( nd_blockmask ) {
        !           244:         h = GET_EXP(d,nd_nvar-1);
        !           245:         XOR_EXP(d,nd_nvar-1,h);
        !           246:         TD(d) -= h;
        !           247:         ndl_weight_mask(d);
        !           248:     } else {
        !           249:         if ( nd_isrlex ) {
        !           250:             if ( nd_bpe == 32 ) {
        !           251:                 h = d[nd_exporigin];
        !           252:                 for ( i = nd_exporigin+1; i < nd_wpd; i++ )
        !           253:                     d[i-1] = d[i];
        !           254:                 d[i-1] = 0;
        !           255:                 TD(d) -= h;
        !           256:             } else {
        !           257:                 bits = nd_epw*nd_bpe;
        !           258:                 mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
        !           259:                 h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
        !           260:                 for ( i = nd_exporigin; i < nd_wpd; i++ )
        !           261:                     d[i] = ((d[i]<<nd_bpe)&mask)
        !           262:                         |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
        !           263:                 TD(d) -= h;
        !           264:             }
        !           265:         } else {
        !           266:             h = GET_EXP(d,nd_nvar-1);
        !           267:             XOR_EXP(d,nd_nvar-1,h);
        !           268:             TD(d) -= h;
        !           269:         }
        !           270:     }
1.23      noro      271: }
                    272:
1.61      noro      273: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
1.1       noro      274: {
1.157   ! noro      275:     UINT t1,t2,u,u1,u2;
        !           276:     int i,j,l;
        !           277:
        !           278:     if ( nd_module && (MPOS(d1) != MPOS(d2)) )
        !           279:         error("ndl_lcm : inconsistent monomials");
        !           280: #if USE_UNROLL
        !           281:     switch ( nd_bpe ) {
        !           282:         case 3:
        !           283:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           284:                 u1 = d1[i]; u2 = d2[i];
        !           285:                 t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
        !           286:                 t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
        !           287:                 t1 = (u1&  0xe00000); t2 = (u2&  0xe00000); u |= t1>t2?t1:t2;
        !           288:                 t1 = (u1&  0x1c0000); t2 = (u2&  0x1c0000); u |= t1>t2?t1:t2;
        !           289:                 t1 = (u1&   0x38000); t2 = (u2&   0x38000); u |= t1>t2?t1:t2;
        !           290:                 t1 = (u1&    0x7000); t2 = (u2&    0x7000); u |= t1>t2?t1:t2;
        !           291:                 t1 = (u1&     0xe00); t2 = (u2&     0xe00); u |= t1>t2?t1:t2;
        !           292:                 t1 = (u1&     0x1c0); t2 = (u2&     0x1c0); u |= t1>t2?t1:t2;
        !           293:                 t1 = (u1&      0x38); t2 = (u2&      0x38); u |= t1>t2?t1:t2;
        !           294:                 t1 = (u1&       0x7); t2 = (u2&       0x7); u |= t1>t2?t1:t2;
        !           295:                 d[i] = u;
        !           296:             }
        !           297:             break;
        !           298:         case 4:
        !           299:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           300:                 u1 = d1[i]; u2 = d2[i];
        !           301:                 t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
        !           302:                 t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
        !           303:                 t1 = (u1&  0xf00000); t2 = (u2&  0xf00000); u |= t1>t2?t1:t2;
        !           304:                 t1 = (u1&   0xf0000); t2 = (u2&   0xf0000); u |= t1>t2?t1:t2;
        !           305:                 t1 = (u1&    0xf000); t2 = (u2&    0xf000); u |= t1>t2?t1:t2;
        !           306:                 t1 = (u1&     0xf00); t2 = (u2&     0xf00); u |= t1>t2?t1:t2;
        !           307:                 t1 = (u1&      0xf0); t2 = (u2&      0xf0); u |= t1>t2?t1:t2;
        !           308:                 t1 = (u1&       0xf); t2 = (u2&       0xf); u |= t1>t2?t1:t2;
        !           309:                 d[i] = u;
        !           310:             }
        !           311:             break;
        !           312:         case 6:
        !           313:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           314:                 u1 = d1[i]; u2 = d2[i];
        !           315:                 t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
        !           316:                 t1 = (u1&  0xfc0000); t2 = (u2&  0xfc0000); u |= t1>t2?t1:t2;
        !           317:                 t1 = (u1&   0x3f000); t2 = (u2&   0x3f000); u |= t1>t2?t1:t2;
        !           318:                 t1 = (u1&     0xfc0); t2 = (u2&     0xfc0); u |= t1>t2?t1:t2;
        !           319:                 t1 = (u1&      0x3f); t2 = (u2&      0x3f); u |= t1>t2?t1:t2;
        !           320:                 d[i] = u;
        !           321:             }
        !           322:             break;
        !           323:         case 8:
        !           324:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           325:                 u1 = d1[i]; u2 = d2[i];
        !           326:                 t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
        !           327:                 t1 = (u1&  0xff0000); t2 = (u2&  0xff0000); u |= t1>t2?t1:t2;
        !           328:                 t1 = (u1&    0xff00); t2 = (u2&    0xff00); u |= t1>t2?t1:t2;
        !           329:                 t1 = (u1&      0xff); t2 = (u2&      0xff); u |= t1>t2?t1:t2;
        !           330:                 d[i] = u;
        !           331:             }
        !           332:             break;
        !           333:         case 16:
        !           334:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           335:                 u1 = d1[i]; u2 = d2[i];
        !           336:                 t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
        !           337:                 t1 = (u1&    0xffff); t2 = (u2&    0xffff); u |= t1>t2?t1:t2;
        !           338:                 d[i] = u;
        !           339:             }
        !           340:             break;
        !           341:         case 32:
        !           342:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           343:                 u1 = d1[i]; u2 = d2[i];
        !           344:                 d[i] = u1>u2?u1:u2;
        !           345:             }
        !           346:             break;
        !           347:         default:
        !           348:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           349:                 u1 = d1[i]; u2 = d2[i];
        !           350:                 for ( j = 0, u = 0; j < nd_epw; j++ ) {
        !           351:                     t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
        !           352:                 }
        !           353:                 d[i] = u;
        !           354:             }
        !           355:             break;
        !           356:     }
        !           357: #else
        !           358:     for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           359:         u1 = d1[i]; u2 = d2[i];
        !           360:         for ( j = 0, u = 0; j < nd_epw; j++ ) {
        !           361:             t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
        !           362:         }
        !           363:         d[i] = u;
        !           364:     }
        !           365: #endif
        !           366:     TD(d) = ndl_weight(d);
        !           367:     if ( nd_blockmask ) ndl_weight_mask(d);
        !           368:     if ( nd_module ) MPOS(d) = MPOS(d1);
        !           369: }
        !           370:
        !           371: void ndl_lcm_nocheck(UINT *d1,unsigned *d2,UINT *d)
        !           372: {
        !           373:     UINT t1,t2,u,u1,u2;
        !           374:     int i,j,l;
1.1       noro      375:
1.65      noro      376: #if USE_UNROLL
1.157   ! noro      377:     switch ( nd_bpe ) {
        !           378:         case 3:
        !           379:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           380:                 u1 = d1[i]; u2 = d2[i];
        !           381:                 t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
        !           382:                 t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
        !           383:                 t1 = (u1&  0xe00000); t2 = (u2&  0xe00000); u |= t1>t2?t1:t2;
        !           384:                 t1 = (u1&  0x1c0000); t2 = (u2&  0x1c0000); u |= t1>t2?t1:t2;
        !           385:                 t1 = (u1&   0x38000); t2 = (u2&   0x38000); u |= t1>t2?t1:t2;
        !           386:                 t1 = (u1&    0x7000); t2 = (u2&    0x7000); u |= t1>t2?t1:t2;
        !           387:                 t1 = (u1&     0xe00); t2 = (u2&     0xe00); u |= t1>t2?t1:t2;
        !           388:                 t1 = (u1&     0x1c0); t2 = (u2&     0x1c0); u |= t1>t2?t1:t2;
        !           389:                 t1 = (u1&      0x38); t2 = (u2&      0x38); u |= t1>t2?t1:t2;
        !           390:                 t1 = (u1&       0x7); t2 = (u2&       0x7); u |= t1>t2?t1:t2;
        !           391:                 d[i] = u;
        !           392:             }
        !           393:             break;
        !           394:         case 4:
        !           395:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           396:                 u1 = d1[i]; u2 = d2[i];
        !           397:                 t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
        !           398:                 t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
        !           399:                 t1 = (u1&  0xf00000); t2 = (u2&  0xf00000); u |= t1>t2?t1:t2;
        !           400:                 t1 = (u1&   0xf0000); t2 = (u2&   0xf0000); u |= t1>t2?t1:t2;
        !           401:                 t1 = (u1&    0xf000); t2 = (u2&    0xf000); u |= t1>t2?t1:t2;
        !           402:                 t1 = (u1&     0xf00); t2 = (u2&     0xf00); u |= t1>t2?t1:t2;
        !           403:                 t1 = (u1&      0xf0); t2 = (u2&      0xf0); u |= t1>t2?t1:t2;
        !           404:                 t1 = (u1&       0xf); t2 = (u2&       0xf); u |= t1>t2?t1:t2;
        !           405:                 d[i] = u;
        !           406:             }
        !           407:             break;
        !           408:         case 6:
        !           409:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           410:                 u1 = d1[i]; u2 = d2[i];
        !           411:                 t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
        !           412:                 t1 = (u1&  0xfc0000); t2 = (u2&  0xfc0000); u |= t1>t2?t1:t2;
        !           413:                 t1 = (u1&   0x3f000); t2 = (u2&   0x3f000); u |= t1>t2?t1:t2;
        !           414:                 t1 = (u1&     0xfc0); t2 = (u2&     0xfc0); u |= t1>t2?t1:t2;
        !           415:                 t1 = (u1&      0x3f); t2 = (u2&      0x3f); u |= t1>t2?t1:t2;
        !           416:                 d[i] = u;
        !           417:             }
        !           418:             break;
        !           419:         case 8:
        !           420:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           421:                 u1 = d1[i]; u2 = d2[i];
        !           422:                 t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
        !           423:                 t1 = (u1&  0xff0000); t2 = (u2&  0xff0000); u |= t1>t2?t1:t2;
        !           424:                 t1 = (u1&    0xff00); t2 = (u2&    0xff00); u |= t1>t2?t1:t2;
        !           425:                 t1 = (u1&      0xff); t2 = (u2&      0xff); u |= t1>t2?t1:t2;
        !           426:                 d[i] = u;
        !           427:             }
        !           428:             break;
        !           429:         case 16:
        !           430:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           431:                 u1 = d1[i]; u2 = d2[i];
        !           432:                 t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
        !           433:                 t1 = (u1&    0xffff); t2 = (u2&    0xffff); u |= t1>t2?t1:t2;
        !           434:                 d[i] = u;
        !           435:             }
        !           436:             break;
        !           437:         case 32:
        !           438:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           439:                 u1 = d1[i]; u2 = d2[i];
        !           440:                 d[i] = u1>u2?u1:u2;
        !           441:             }
        !           442:             break;
        !           443:         default:
        !           444:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           445:                 u1 = d1[i]; u2 = d2[i];
        !           446:                 for ( j = 0, u = 0; j < nd_epw; j++ ) {
        !           447:                     t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
        !           448:                 }
        !           449:                 d[i] = u;
        !           450:             }
        !           451:             break;
        !           452:     }
1.65      noro      453: #else
1.157   ! noro      454:     for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           455:         u1 = d1[i]; u2 = d2[i];
        !           456:         for ( j = 0, u = 0; j < nd_epw; j++ ) {
        !           457:             t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
        !           458:         }
        !           459:         d[i] = u;
        !           460:     }
1.65      noro      461: #endif
1.157   ! noro      462:     TD(d) = ndl_weight(d);
        !           463:     if ( nd_blockmask ) ndl_weight_mask(d);
        !           464:     if ( nd_module ) MPOS(d) = MPOS(d1);
1.57      noro      465: }
                    466:
1.61      noro      467: int ndl_weight(UINT *d)
1.1       noro      468: {
1.157   ! noro      469:     UINT t,u;
        !           470:     int i,j;
1.1       noro      471:
1.157   ! noro      472:     if ( current_dl_weight_vector )
        !           473:         for ( i = 0, t = 0; i < nd_nvar; i++ ) {
        !           474:             u = GET_EXP(d,i);
        !           475:             t += MUL_WEIGHT(u,i);
        !           476:         }
        !           477:     else
        !           478:         for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
        !           479:             u = d[i];
        !           480:             for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
        !           481:                 t += (u&nd_mask0);
        !           482:         }
        !           483:     return t;
1.1       noro      484: }
                    485:
1.61      noro      486: void ndl_weight_mask(UINT *d)
1.43      noro      487: {
1.157   ! noro      488:     UINT t,u;
        !           489:     UINT *mask;
        !           490:     int i,j,k,l;
        !           491:
        !           492:     l = nd_blockmask->n;
        !           493:     for ( k = 0; k < l; k++ ) {
        !           494:         mask = nd_blockmask->mask[k];
        !           495:         if ( current_dl_weight_vector )
        !           496:             for ( i = 0, t = 0; i < nd_nvar; i++ ) {
        !           497:                 u = GET_EXP_MASK(d,i,mask);
        !           498:                 t += MUL_WEIGHT(u,i);
        !           499:             }
        !           500:         else
        !           501:             for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
        !           502:                 u = d[i]&mask[i];
        !           503:                 for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
        !           504:                     t += (u&nd_mask0);
        !           505:             }
        !           506:         d[k+1] = t;
        !           507:     }
1.43      noro      508: }
                    509:
1.61      noro      510: int ndl_lex_compare(UINT *d1,UINT *d2)
1.1       noro      511: {
1.157   ! noro      512:     int i;
1.1       noro      513:
1.157   ! noro      514:     d1 += nd_exporigin;
        !           515:     d2 += nd_exporigin;
        !           516:     for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
        !           517:         if ( *d1 > *d2 )
        !           518:             return nd_isrlex ? -1 : 1;
        !           519:         else if ( *d1 < *d2 )
        !           520:             return nd_isrlex ? 1 : -1;
        !           521:     return 0;
1.1       noro      522: }
                    523:
1.61      noro      524: int ndl_block_compare(UINT *d1,UINT *d2)
1.43      noro      525: {
1.157   ! noro      526:     int i,l,j,ord_o,ord_l;
        !           527:     struct order_pair *op;
        !           528:     UINT t1,t2,m;
        !           529:     UINT *mask;
        !           530:
        !           531:     l = nd_blockmask->n;
        !           532:     op = nd_blockmask->order_pair;
        !           533:     for ( j = 0; j < l; j++ ) {
        !           534:         mask = nd_blockmask->mask[j];
        !           535:         ord_o = op[j].order;
        !           536:         if ( ord_o < 2 )
        !           537:             if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
        !           538:             else if ( t1 < t2 ) return -1;
        !           539:         for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           540:             m = mask[i];
        !           541:             t1 = d1[i]&m;
        !           542:             t2 = d2[i]&m;
        !           543:             if ( t1 > t2 )
        !           544:                 return !ord_o ? -1 : 1;
        !           545:             else if ( t1 < t2 )
        !           546:                 return !ord_o ? 1 : -1;
        !           547:         }
        !           548:     }
        !           549:     return 0;
1.43      noro      550: }
                    551:
1.96      noro      552: int ndl_matrix_compare(UINT *d1,UINT *d2)
                    553: {
1.157   ! noro      554:     int i,j,s;
        !           555:     int *v;
1.96      noro      556:
1.157   ! noro      557:     for ( j = 0; j < nd_nvar; j++ )
        !           558:         nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
        !           559:     for ( i = 0; i < nd_matrix_len; i++ ) {
        !           560:         v = nd_matrix[i];
        !           561:         for ( j = 0, s = 0; j < nd_nvar; j++ )
        !           562:             s += v[j]*nd_work_vector[j];
        !           563:         if ( s > 0 ) return 1;
        !           564:         else if ( s < 0 ) return -1;
        !           565:     }
        !           566:     return 0;
1.96      noro      567: }
                    568:
1.97      noro      569: int ndl_composite_compare(UINT *d1,UINT *d2)
                    570: {
1.157   ! noro      571:     int i,j,s,start,end,len,o;
        !           572:     int *v;
        !           573:     struct sparse_weight *sw;
        !           574:
        !           575:     for ( j = 0; j < nd_nvar; j++ )
        !           576:         nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
        !           577:     for ( i = 0; i < nd_worb_len; i++ ) {
        !           578:         len = nd_worb[i].length;
        !           579:         switch ( nd_worb[i].type ) {
        !           580:             case IS_DENSE_WEIGHT:
        !           581:                 v = nd_worb[i].body.dense_weight;
        !           582:                 for ( j = 0, s = 0; j < len; j++ )
        !           583:                     s += v[j]*nd_work_vector[j];
        !           584:                 if ( s > 0 ) return 1;
        !           585:                 else if ( s < 0 ) return -1;
        !           586:                 break;
        !           587:             case IS_SPARSE_WEIGHT:
        !           588:                 sw = nd_worb[i].body.sparse_weight;
        !           589:                 for ( j = 0, s = 0; j < len; j++ )
        !           590:                     s += sw[j].value*nd_work_vector[sw[j].pos];
        !           591:                 if ( s > 0 ) return 1;
        !           592:                 else if ( s < 0 ) return -1;
        !           593:                 break;
        !           594:             case IS_BLOCK:
        !           595:                 o = nd_worb[i].body.block.order;
        !           596:                 start = nd_worb[i].body.block.start;
        !           597:                 switch ( o ) {
        !           598:                     case 0:
        !           599:                         end = start+len;
        !           600:                         for ( j = start, s = 0; j < end; j++ )
        !           601:                             s += MUL_WEIGHT(nd_work_vector[j],j);
        !           602:                         if ( s > 0 ) return 1;
        !           603:                         else if ( s < 0 ) return -1;
        !           604:                         for ( j = end-1; j >= start; j-- )
        !           605:                             if ( nd_work_vector[j] < 0 ) return 1;
        !           606:                             else if ( nd_work_vector[j] > 0 ) return -1;
        !           607:                         break;
        !           608:                     case 1:
        !           609:                         end = start+len;
        !           610:                         for ( j = start, s = 0; j < end; j++ )
        !           611:                             s += MUL_WEIGHT(nd_work_vector[j],j);
        !           612:                         if ( s > 0 ) return 1;
        !           613:                         else if ( s < 0 ) return -1;
        !           614:                         for ( j = start; j < end; j++ )
        !           615:                             if ( nd_work_vector[j] > 0 ) return 1;
        !           616:                             else if ( nd_work_vector[j] < 0 ) return -1;
        !           617:                         break;
        !           618:                     case 2:
        !           619:                         for ( j = start; j < end; j++ )
        !           620:                             if ( nd_work_vector[j] > 0 ) return 1;
        !           621:                             else if ( nd_work_vector[j] < 0 ) return -1;
        !           622:                         break;
        !           623:                 }
        !           624:                 break;
        !           625:         }
        !           626:     }
        !           627:     return 0;
1.97      noro      628: }
                    629:
1.58      noro      630: /* TDH -> WW -> TD-> RL */
                    631:
1.61      noro      632: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
1.58      noro      633: {
1.157   ! noro      634:     int i,m,e1,e2;
1.58      noro      635:
1.157   ! noro      636:     if ( TD(d1) > TD(d2) ) return 1;
        !           637:     else if ( TD(d1) < TD(d2) ) return -1;
        !           638:     m = nd_nvar>>1;
        !           639:     for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
        !           640:         e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
        !           641:         e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
        !           642:     }
        !           643:     if ( e1 > e2 ) return 1;
        !           644:     else if ( e1 < e2 ) return -1;
        !           645:     return ndl_lex_compare(d1,d2);
        !           646: }
        !           647:
        !           648: int ndl_module_grlex_compare(UINT *d1,UINT *d2)
        !           649: {
        !           650:     int i;
        !           651:
        !           652:     if ( nd_istop ) {
        !           653:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           654:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           655:     }
        !           656:     if ( TD(d1) > TD(d2) ) return 1;
        !           657:     else if ( TD(d1) < TD(d2) ) return -1;
        !           658:     for ( i = nd_nvar-1; i >= 0; i-- )
        !           659:         if ( GET_EXP(d1,i) < GET_EXP(d2,i) ) return 1;
        !           660:         else if ( GET_EXP(d1,i) > GET_EXP(d2,i) ) return -1;
        !           661:     if ( !nd_istop ) {
        !           662:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           663:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           664:     }
        !           665:     return 0;
        !           666: }
        !           667:
        !           668: int ndl_module_glex_compare(UINT *d1,UINT *d2)
        !           669: {
        !           670:     int i;
        !           671:
        !           672:     if ( nd_istop ) {
        !           673:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           674:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           675:     }
        !           676:     if ( TD(d1) > TD(d2) ) return 1;
        !           677:     else if ( TD(d1) < TD(d2) ) return -1;
        !           678:     for ( i = 0; i < nd_nvar; i++ )
        !           679:         if ( GET_EXP(d1,i) > GET_EXP(d2,i) ) return 1;
        !           680:         else if ( GET_EXP(d1,i) < GET_EXP(d2,i) ) return -1;
        !           681:     if ( !nd_istop ) {
        !           682:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           683:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           684:     }
        !           685:     return 0;
        !           686: }
        !           687:
        !           688: int ndl_module_lex_compare(UINT *d1,UINT *d2)
        !           689: {
        !           690:     int i;
        !           691:
        !           692:     if ( nd_istop ) {
        !           693:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           694:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           695:     }
        !           696:     for ( i = 0; i < nd_nvar; i++ )
        !           697:         if ( GET_EXP(d1,i) > GET_EXP(d2,i) ) return 1;
        !           698:         else if ( GET_EXP(d1,i) < GET_EXP(d2,i) ) return -1;
        !           699:     if ( !nd_istop ) {
        !           700:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           701:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           702:     }
        !           703:     return 0;
        !           704: }
        !           705:
        !           706: int ndl_module_block_compare(UINT *d1,UINT *d2)
        !           707: {
        !           708:     int i,c;
        !           709:
        !           710:     if ( nd_istop ) {
        !           711:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           712:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           713:     }
        !           714:     if ( c = ndl_block_compare(d1,d2) ) return c;
        !           715:     if ( !nd_istop ) {
        !           716:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           717:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           718:     }
        !           719:     return 0;
        !           720: }
        !           721:
        !           722: int ndl_module_matrix_compare(UINT *d1,UINT *d2)
        !           723: {
        !           724:     int i,c;
        !           725:
        !           726:     if ( nd_istop ) {
        !           727:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           728:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           729:     }
        !           730:     if ( c = ndl_matrix_compare(d1,d2) ) return c;
        !           731:     if ( !nd_istop ) {
        !           732:         if ( MPOS(d1) < MPOS(d2) ) return 1;
        !           733:         else if ( MPOS(d1) > MPOS(d2) ) return -1;
        !           734:     }
        !           735:     return 0;
        !           736: }
        !           737:
        !           738: int ndl_module_composite_compare(UINT *d1,UINT *d2)
        !           739: {
        !           740:     int i,c;
        !           741:
        !           742:     if ( nd_istop ) {
        !           743:         if ( MPOS(d1) > MPOS(d2) ) return 1;
        !           744:         else if ( MPOS(d1) < MPOS(d2) ) return -1;
        !           745:     }
        !           746:     if ( c = ndl_composite_compare(d1,d2) ) return c;
        !           747:     if ( !nd_istop ) {
        !           748:         if ( MPOS(d1) > MPOS(d2) ) return 1;
        !           749:         else if ( MPOS(d1) < MPOS(d2) ) return -1;
        !           750:     }
        !           751:     return 0;
1.58      noro      752: }
                    753:
1.61      noro      754: INLINE int ndl_equal(UINT *d1,UINT *d2)
1.1       noro      755: {
1.157   ! noro      756:     int i;
1.1       noro      757:
1.157   ! noro      758:     switch ( nd_wpd ) {
        !           759:         case 2:
        !           760:             if ( TD(d2) != TD(d1) ) return 0;
        !           761:             if ( d2[1] != d1[1] ) return 0;
        !           762:             return 1;
        !           763:             break;
        !           764:         case 3:
        !           765:             if ( TD(d2) != TD(d1) ) return 0;
        !           766:             if ( d2[1] != d1[1] ) return 0;
        !           767:             if ( d2[2] != d1[2] ) return 0;
        !           768:             return 1;
        !           769:             break;
        !           770:         default:
        !           771:             for ( i = 0; i < nd_wpd; i++ )
        !           772:                 if ( *d1++ != *d2++ ) return 0;
        !           773:             return 1;
        !           774:             break;
        !           775:     }
1.1       noro      776: }
                    777:
1.61      noro      778: INLINE void ndl_copy(UINT *d1,UINT *d2)
1.6       noro      779: {
1.157   ! noro      780:     int i;
1.6       noro      781:
1.157   ! noro      782:     switch ( nd_wpd ) {
        !           783:         case 2:
        !           784:             TD(d2) = TD(d1);
        !           785:             d2[1] = d1[1];
        !           786:             break;
        !           787:         case 3:
        !           788:             TD(d2) = TD(d1);
        !           789:             d2[1] = d1[1];
        !           790:             d2[2] = d1[2];
        !           791:             break;
        !           792:         default:
        !           793:             for ( i = 0; i < nd_wpd; i++ )
        !           794:                 d2[i] = d1[i];
        !           795:             break;
        !           796:     }
1.6       noro      797: }
                    798:
1.61      noro      799: INLINE void ndl_zero(UINT *d)
                    800: {
1.157   ! noro      801:     int i;
        !           802:     for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
1.61      noro      803: }
                    804:
                    805: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
1.1       noro      806: {
1.157   ! noro      807:     int i;
1.1       noro      808:
1.43      noro      809: #if 1
1.157   ! noro      810:     switch ( nd_wpd ) {
        !           811:         case 2:
        !           812:             TD(d) = TD(d1)+TD(d2);
        !           813:             d[1] = d1[1]+d2[1];
        !           814:             break;
        !           815:         case 3:
        !           816:             TD(d) = TD(d1)+TD(d2);
        !           817:             d[1] = d1[1]+d2[1];
        !           818:             d[2] = d1[2]+d2[2];
        !           819:             break;
        !           820:         default:
        !           821:             for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
        !           822:             break;
        !           823:     }
1.43      noro      824: #else
1.157   ! noro      825:     for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
1.43      noro      826: #endif
1.157   ! noro      827:     if ( nd_module ) {
        !           828:         if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
        !           829:            error("ndl_add : invalid operation");
        !           830:         MPOS(d) = MPOS(d1);
        !           831:     }
1.6       noro      832: }
                    833:
1.55      noro      834: /* d1 += d2 */
1.61      noro      835: INLINE void ndl_addto(UINT *d1,UINT *d2)
1.55      noro      836: {
1.157   ! noro      837:     int i;
1.55      noro      838:
                    839: #if 1
1.157   ! noro      840:     switch ( nd_wpd ) {
        !           841:         case 2:
        !           842:             TD(d1) += TD(d2);
        !           843:             d1[1] += d2[1];
        !           844:             break;
        !           845:         case 3:
        !           846:             TD(d1) += TD(d2);
        !           847:             d1[1] += d2[1];
        !           848:             d1[2] += d2[2];
        !           849:             break;
        !           850:         default:
        !           851:             for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
        !           852:             break;
        !           853:     }
1.55      noro      854: #else
1.157   ! noro      855:     for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
1.55      noro      856: #endif
1.157   ! noro      857:     if ( nd_module ) {
        !           858:         if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
        !           859:             error("ndl_addto : invalid operation");
        !           860:         MPOS(d1) = MPOS(d2);
        !           861:     }
1.55      noro      862: }
                    863:
1.61      noro      864: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
1.6       noro      865: {
1.157   ! noro      866:     int i;
1.6       noro      867:
1.157   ! noro      868:     for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
1.1       noro      869: }
                    870:
1.61      noro      871: int ndl_disjoint(UINT *d1,UINT *d2)
1.1       noro      872: {
1.157   ! noro      873:     UINT t1,t2,u,u1,u2;
        !           874:     int i,j;
1.1       noro      875:
1.157   ! noro      876:     if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
1.65      noro      877: #if USE_UNROLL
1.157   ! noro      878:     switch ( nd_bpe ) {
        !           879:         case 3:
        !           880:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           881:                 u1 = d1[i]; u2 = d2[i];
        !           882:                 t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
        !           883:                 t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
        !           884:                 t1 = u1&  0xe00000; t2 = u2&  0xe00000; if ( t1&&t2 ) return 0;
        !           885:                 t1 = u1&  0x1c0000; t2 = u2&  0x1c0000; if ( t1&&t2 ) return 0;
        !           886:                 t1 = u1&   0x38000; t2 = u2&   0x38000; if ( t1&&t2 ) return 0;
        !           887:                 t1 = u1&    0x7000; t2 = u2&    0x7000; if ( t1&&t2 ) return 0;
        !           888:                 t1 = u1&     0xe00; t2 = u2&     0xe00; if ( t1&&t2 ) return 0;
        !           889:                 t1 = u1&     0x1c0; t2 = u2&     0x1c0; if ( t1&&t2 ) return 0;
        !           890:                 t1 = u1&      0x38; t2 = u2&      0x38; if ( t1&&t2 ) return 0;
        !           891:                 t1 = u1&       0x7; t2 = u2&       0x7; if ( t1&&t2 ) return 0;
        !           892:             }
        !           893:             return 1;
        !           894:             break;
        !           895:         case 4:
        !           896:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           897:                 u1 = d1[i]; u2 = d2[i];
        !           898:                 t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
        !           899:                 t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
        !           900:                 t1 = u1&  0xf00000; t2 = u2&  0xf00000; if ( t1&&t2 ) return 0;
        !           901:                 t1 = u1&   0xf0000; t2 = u2&   0xf0000; if ( t1&&t2 ) return 0;
        !           902:                 t1 = u1&    0xf000; t2 = u2&    0xf000; if ( t1&&t2 ) return 0;
        !           903:                 t1 = u1&     0xf00; t2 = u2&     0xf00; if ( t1&&t2 ) return 0;
        !           904:                 t1 = u1&      0xf0; t2 = u2&      0xf0; if ( t1&&t2 ) return 0;
        !           905:                 t1 = u1&       0xf; t2 = u2&       0xf; if ( t1&&t2 ) return 0;
        !           906:             }
        !           907:             return 1;
        !           908:             break;
        !           909:         case 6:
        !           910:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           911:                 u1 = d1[i]; u2 = d2[i];
        !           912:                 t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
        !           913:                 t1 = u1&  0xfc0000; t2 = u2&  0xfc0000; if ( t1&&t2 ) return 0;
        !           914:                 t1 = u1&   0x3f000; t2 = u2&   0x3f000; if ( t1&&t2 ) return 0;
        !           915:                 t1 = u1&     0xfc0; t2 = u2&     0xfc0; if ( t1&&t2 ) return 0;
        !           916:                 t1 = u1&      0x3f; t2 = u2&      0x3f; if ( t1&&t2 ) return 0;
        !           917:             }
        !           918:             return 1;
        !           919:             break;
        !           920:         case 8:
        !           921:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           922:                 u1 = d1[i]; u2 = d2[i];
        !           923:                 t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
        !           924:                 t1 = u1&  0xff0000; t2 = u2&  0xff0000; if ( t1&&t2 ) return 0;
        !           925:                 t1 = u1&    0xff00; t2 = u2&    0xff00; if ( t1&&t2 ) return 0;
        !           926:                 t1 = u1&      0xff; t2 = u2&      0xff; if ( t1&&t2 ) return 0;
        !           927:             }
        !           928:             return 1;
        !           929:             break;
        !           930:         case 16:
        !           931:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           932:                 u1 = d1[i]; u2 = d2[i];
        !           933:                 t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
        !           934:                 t1 = u1&    0xffff; t2 = u2&    0xffff; if ( t1&&t2 ) return 0;
        !           935:             }
        !           936:             return 1;
        !           937:             break;
        !           938:         case 32:
        !           939:             for ( i = nd_exporigin; i < nd_wpd; i++ )
        !           940:                 if ( d1[i] && d2[i] ) return 0;
        !           941:             return 1;
        !           942:             break;
        !           943:         default:
        !           944:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           945:                 u1 = d1[i]; u2 = d2[i];
        !           946:                 for ( j = 0; j < nd_epw; j++ ) {
        !           947:                     if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
        !           948:                     u1 >>= nd_bpe; u2 >>= nd_bpe;
        !           949:                 }
        !           950:             }
        !           951:             return 1;
        !           952:             break;
        !           953:     }
1.65      noro      954: #else
1.157   ! noro      955:     for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           956:         u1 = d1[i]; u2 = d2[i];
        !           957:         for ( j = 0; j < nd_epw; j++ ) {
        !           958:             if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
        !           959:             u1 >>= nd_bpe; u2 >>= nd_bpe;
        !           960:         }
        !           961:     }
        !           962:     return 1;
1.65      noro      963: #endif
1.1       noro      964: }
                    965:
1.114     noro      966: int ndl_check_bound(UINT *d1,UINT *d2)
1.1       noro      967: {
1.157   ! noro      968:     UINT u2;
        !           969:     int i,j,ind,k;
1.1       noro      970:
1.157   ! noro      971:     ind = 0;
1.65      noro      972: #if USE_UNROLL
1.157   ! noro      973:     switch ( nd_bpe ) {
        !           974:         case 3:
        !           975:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           976:                 u2 = d2[i];
        !           977:                 if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
        !           978:                 if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
        !           979:                 if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
        !           980:                 if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
        !           981:                 if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
        !           982:                 if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
        !           983:                 if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
        !           984:                 if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
        !           985:                 if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
        !           986:                 if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
        !           987:             }
        !           988:             return 0;
        !           989:             break;
        !           990:         case 4:
        !           991:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !           992:                 u2 = d2[i];
        !           993:                 if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
        !           994:                 if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
        !           995:                 if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
        !           996:                 if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
        !           997:                 if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
        !           998:                 if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
        !           999:                 if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
        !          1000:                 if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
        !          1001:             }
        !          1002:             return 0;
        !          1003:             break;
        !          1004:         case 6:
        !          1005:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !          1006:                 u2 = d2[i];
        !          1007:                 if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
        !          1008:                 if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
        !          1009:                 if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
        !          1010:                 if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
        !          1011:                 if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
        !          1012:             }
        !          1013:             return 0;
        !          1014:             break;
        !          1015:         case 8:
        !          1016:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !          1017:                 u2 = d2[i];
        !          1018:                 if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
        !          1019:                 if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
        !          1020:                 if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
        !          1021:                 if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
        !          1022:             }
        !          1023:             return 0;
        !          1024:             break;
        !          1025:         case 16:
        !          1026:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !          1027:                 u2 = d2[i];
        !          1028:                 if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
        !          1029:                 if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
        !          1030:             }
        !          1031:             return 0;
        !          1032:             break;
        !          1033:         case 32:
        !          1034:             for ( i = nd_exporigin; i < nd_wpd; i++ )
        !          1035:                 if ( d1[i]+d2[i]<d1[i] ) return 1;
        !          1036:             return 0;
        !          1037:             break;
        !          1038:         default:
        !          1039:             for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !          1040:                 u2 = d2[i];
        !          1041:                 k = (nd_epw-1)*nd_bpe;
        !          1042:                 for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
        !          1043:                     if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
        !          1044:             }
        !          1045:             return 0;
        !          1046:             break;
        !          1047:     }
1.65      noro     1048: #else
1.157   ! noro     1049:     for ( i = nd_exporigin; i < nd_wpd; i++ ) {
        !          1050:         u2 = d2[i];
        !          1051:         k = (nd_epw-1)*nd_bpe;
        !          1052:         for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
        !          1053:             if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
        !          1054:     }
        !          1055:     return 0;
1.65      noro     1056: #endif
1.1       noro     1057: }
                   1058:
1.114     noro     1059: int ndl_check_bound2(int index,UINT *d2)
                   1060: {
1.157   ! noro     1061:     return ndl_check_bound(nd_bound[index],d2);
1.114     noro     1062: }
                   1063:
1.61      noro     1064: INLINE int ndl_hash_value(UINT *d)
1.1       noro     1065: {
1.157   ! noro     1066:     int i;
        !          1067:     int r;
1.1       noro     1068:
1.157   ! noro     1069:     r = 0;
        !          1070:     for ( i = 0; i < nd_wpd; i++ )
        !          1071:         r = ((r<<16)+d[i])%REDTAB_LEN;
        !          1072:     return r;
1.1       noro     1073: }
                   1074:
1.63      noro     1075: INLINE int ndl_find_reducer(UINT *dg)
1.1       noro     1076: {
1.157   ! noro     1077:     RHist r;
        !          1078:     int d,k,i;
1.1       noro     1079:
1.157   ! noro     1080:     d = ndl_hash_value(dg);
        !          1081:     for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
        !          1082:         if ( ndl_equal(dg,DL(r)) ) {
        !          1083:             if ( k > 0 ) nd_notfirst++;
        !          1084:             nd_found++;
        !          1085:             return r->index;
        !          1086:         }
        !          1087:     }
        !          1088:     if ( Reverse )
        !          1089:         for ( i = nd_psn-1; i >= 0; i-- ) {
        !          1090:             r = nd_psh[i];
        !          1091:             if ( ndl_reducible(dg,DL(r)) ) {
        !          1092:                 nd_create++;
        !          1093:                 nd_append_red(dg,i);
        !          1094:                 return i;
        !          1095:             }
        !          1096:         }
        !          1097:     else
        !          1098:         for ( i = 0; i < nd_psn; i++ ) {
        !          1099:             r = nd_psh[i];
        !          1100:             if ( ndl_reducible(dg,DL(r)) ) {
        !          1101:                 nd_create++;
        !          1102:                 nd_append_red(dg,i);
        !          1103:                 return i;
        !          1104:             }
        !          1105:         }
        !          1106:     return -1;
1.1       noro     1107: }
                   1108:
1.63      noro     1109: ND nd_merge(ND p1,ND p2)
                   1110: {
1.157   ! noro     1111:     int n,c;
        !          1112:     int t,can,td1,td2;
        !          1113:     ND r;
        !          1114:     NM m1,m2,mr0,mr,s;
        !          1115:
        !          1116:     if ( !p1 ) return p2;
        !          1117:     else if ( !p2 ) return p1;
        !          1118:     else {
        !          1119:         can = 0;
        !          1120:         for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
        !          1121:             c = DL_COMPARE(DL(m1),DL(m2));
        !          1122:             switch ( c ) {
        !          1123:                 case 0:
        !          1124:                     s = m1; m1 = NEXT(m1);
        !          1125:                     can++; NEXTNM2(mr0,mr,s);
        !          1126:                     s = m2; m2 = NEXT(m2); FREENM(s);
        !          1127:                     break;
        !          1128:                 case 1:
        !          1129:                     s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
        !          1130:                     break;
        !          1131:                 case -1:
        !          1132:                     s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
        !          1133:                     break;
        !          1134:             }
        !          1135:         }
        !          1136:         if ( !mr0 )
        !          1137:             if ( m1 ) mr0 = m1;
        !          1138:             else if ( m2 ) mr0 = m2;
        !          1139:             else return 0;
        !          1140:         else if ( m1 ) NEXT(mr) = m1;
        !          1141:         else if ( m2 ) NEXT(mr) = m2;
        !          1142:         else NEXT(mr) = 0;
        !          1143:         BDY(p1) = mr0;
        !          1144:         SG(p1) = MAX(SG(p1),SG(p2));
        !          1145:         LEN(p1) = LEN(p1)+LEN(p2)-can;
        !          1146:         FREEND(p2);
        !          1147:         return p1;
        !          1148:     }
1.63      noro     1149: }
                   1150:
1.31      noro     1151: ND nd_add(int mod,ND p1,ND p2)
1.1       noro     1152: {
1.157   ! noro     1153:     int n,c;
        !          1154:     int t,can,td1,td2;
        !          1155:     ND r;
        !          1156:     NM m1,m2,mr0,mr,s;
        !          1157:
        !          1158:     if ( !p1 ) return p2;
        !          1159:     else if ( !p2 ) return p1;
        !          1160:     else if ( mod == -1 ) return nd_add_sf(p1,p2);
        !          1161:     else if ( !mod ) return nd_add_q(p1,p2);
        !          1162:     else {
        !          1163:         can = 0;
        !          1164:         for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
        !          1165:             c = DL_COMPARE(DL(m1),DL(m2));
        !          1166:             switch ( c ) {
        !          1167:                 case 0:
        !          1168:                     t = ((CM(m1))+(CM(m2))) - mod;
        !          1169:                     if ( t < 0 ) t += mod;
        !          1170:                     s = m1; m1 = NEXT(m1);
        !          1171:                     if ( t ) {
        !          1172:                         can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
        !          1173:                     } else {
        !          1174:                         can += 2; FREENM(s);
        !          1175:                     }
        !          1176:                     s = m2; m2 = NEXT(m2); FREENM(s);
        !          1177:                     break;
        !          1178:                 case 1:
        !          1179:                     s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
        !          1180:                     break;
        !          1181:                 case -1:
        !          1182:                     s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
        !          1183:                     break;
        !          1184:             }
        !          1185:         }
        !          1186:         if ( !mr0 )
        !          1187:             if ( m1 ) mr0 = m1;
        !          1188:             else if ( m2 ) mr0 = m2;
        !          1189:             else return 0;
        !          1190:         else if ( m1 ) NEXT(mr) = m1;
        !          1191:         else if ( m2 ) NEXT(mr) = m2;
        !          1192:         else NEXT(mr) = 0;
        !          1193:         BDY(p1) = mr0;
        !          1194:         SG(p1) = MAX(SG(p1),SG(p2));
        !          1195:         LEN(p1) = LEN(p1)+LEN(p2)-can;
        !          1196:         FREEND(p2);
        !          1197:         return p1;
        !          1198:     }
1.95      noro     1199: }
                   1200:
                   1201: /* XXX on opteron, the inlined manipulation of destructive additon of
                   1202:  * two NM seems to make gcc optimizer get confused, so the part is
                   1203:  * done in a function.
                   1204:  */
                   1205:
1.113     noro     1206: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1.95      noro     1207: {
1.157   ! noro     1208:     NM s;
        !          1209:     P t;
        !          1210:     int can;
        !          1211:
        !          1212:     addp(nd_vc,CP(*m1),CP(*m2),&t);
        !          1213:     s = *m1; *m1 = NEXT(*m1);
        !          1214:     if ( t ) {
        !          1215:         can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
        !          1216:     } else {
        !          1217:         can = 2; FREENM(s);
        !          1218:     }
        !          1219:     s = *m2; *m2 = NEXT(*m2); FREENM(s);
        !          1220:     return can;
1.95      noro     1221: }
                   1222:
1.113     noro     1223: ND nd_add_q(ND p1,ND p2)
1.95      noro     1224: {
1.157   ! noro     1225:     int n,c,can;
        !          1226:     ND r;
        !          1227:     NM m1,m2,mr0,mr,s;
        !          1228:     P t;
        !          1229:
        !          1230:     if ( !p1 ) return p2;
        !          1231:     else if ( !p2 ) return p1;
        !          1232:     else {
        !          1233:         can = 0;
        !          1234:         for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
        !          1235:             c = DL_COMPARE(DL(m1),DL(m2));
        !          1236:             switch ( c ) {
        !          1237:                 case 0:
1.95      noro     1238: #if defined(__x86_64__)
1.157   ! noro     1239:                     can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1.95      noro     1240: #else
1.157   ! noro     1241:                     addp(nd_vc,CP(m1),CP(m2),&t);
        !          1242:                     s = m1; m1 = NEXT(m1);
        !          1243:                     if ( t ) {
        !          1244:                         can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
        !          1245:                     } else {
        !          1246:                         can += 2; FREENM(s);
        !          1247:                     }
        !          1248:                     s = m2; m2 = NEXT(m2); FREENM(s);
1.95      noro     1249: #endif
1.157   ! noro     1250:                     break;
        !          1251:                 case 1:
        !          1252:                     s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
        !          1253:                     break;
        !          1254:                 case -1:
        !          1255:                     s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
        !          1256:                     break;
        !          1257:             }
        !          1258:         }
        !          1259:         if ( !mr0 )
        !          1260:             if ( m1 ) mr0 = m1;
        !          1261:             else if ( m2 ) mr0 = m2;
        !          1262:             else return 0;
        !          1263:         else if ( m1 ) NEXT(mr) = m1;
        !          1264:         else if ( m2 ) NEXT(mr) = m2;
        !          1265:         else NEXT(mr) = 0;
        !          1266:         BDY(p1) = mr0;
        !          1267:         SG(p1) = MAX(SG(p1),SG(p2));
        !          1268:         LEN(p1) = LEN(p1)+LEN(p2)-can;
        !          1269:         FREEND(p2);
        !          1270:         return p1;
        !          1271:     }
1.17      noro     1272: }
                   1273:
1.71      noro     1274: ND nd_add_sf(ND p1,ND p2)
                   1275: {
1.157   ! noro     1276:     int n,c,can;
        !          1277:     ND r;
        !          1278:     NM m1,m2,mr0,mr,s;
        !          1279:     int t;
        !          1280:
        !          1281:     if ( !p1 ) return p2;
        !          1282:     else if ( !p2 ) return p1;
        !          1283:     else {
        !          1284:         can = 0;
        !          1285:         for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
        !          1286:             c = DL_COMPARE(DL(m1),DL(m2));
        !          1287:             switch ( c ) {
        !          1288:                 case 0:
        !          1289:                     t = _addsf(CM(m1),CM(m2));
        !          1290:                     s = m1; m1 = NEXT(m1);
        !          1291:                     if ( t ) {
        !          1292:                         can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
        !          1293:                     } else {
        !          1294:                         can += 2; FREENM(s);
        !          1295:                     }
        !          1296:                     s = m2; m2 = NEXT(m2); FREENM(s);
        !          1297:                     break;
        !          1298:                 case 1:
        !          1299:                     s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
        !          1300:                     break;
        !          1301:                 case -1:
        !          1302:                     s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
        !          1303:                     break;
        !          1304:             }
        !          1305:         }
        !          1306:         if ( !mr0 )
        !          1307:             if ( m1 ) mr0 = m1;
        !          1308:             else if ( m2 ) mr0 = m2;
        !          1309:             else return 0;
        !          1310:         else if ( m1 ) NEXT(mr) = m1;
        !          1311:         else if ( m2 ) NEXT(mr) = m2;
        !          1312:         else NEXT(mr) = 0;
        !          1313:         BDY(p1) = mr0;
        !          1314:         SG(p1) = MAX(SG(p1),SG(p2));
        !          1315:         LEN(p1) = LEN(p1)+LEN(p2)-can;
        !          1316:         FREEND(p2);
        !          1317:         return p1;
        !          1318:     }
1.71      noro     1319: }
                   1320:
1.146     noro     1321: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn)
                   1322: {
1.157   ! noro     1323:     int c,c1,c2;
        !          1324:     Q cg,cred,gcd,tq;
        !          1325:     P cgp,credp,gcdp;
        !          1326:     Obj tr,tr1;
        !          1327:
        !          1328:     if ( mod == -1 )
        !          1329:         CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
        !          1330:     else if ( mod ) {
        !          1331:         c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
        !          1332:         DMAR(c1,c2,0,mod,c); CM(mul) = c;
        !          1333:     } else if ( nd_vc ) {
        !          1334:         ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
        !          1335:         divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
        !          1336:         chsgnp(cgp,&CP(mul));
        !          1337:         nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
        !          1338:         if ( dn ) {
        !          1339:             mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
        !          1340:             reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
        !          1341:         }
        !          1342:     } else {
        !          1343:         igcd_cofactor(HCQ(g),HCQ(p),&gcd,&cg,&cred);
        !          1344:         chsgnq(cg,&CQ(mul));
        !          1345:         nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
        !          1346:         if ( dn ) {
        !          1347:             mulq(dn->z,cred,&tq); dn->z = tq;
        !          1348:         }
        !          1349:     }
        !          1350:     return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1.146     noro     1351: }
                   1352:
1.1       noro     1353: /* ret=1 : success, ret=0 : overflow */
1.146     noro     1354: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,NDC dn,ND *rp)
1.1       noro     1355: {
1.157   ! noro     1356:     NM m,mrd,tail;
        !          1357:     NM mul;
        !          1358:     int n,sugar,psugar,sugar0,stat,index;
        !          1359:     int c,c1,c2,dummy;
        !          1360:     RHist h;
        !          1361:     NDV p,red;
        !          1362:     Q cg,cred,gcd,tq,qq;
        !          1363:     double hmag;
        !          1364:     P tp,tp1;
        !          1365:     Obj tr,tr1;
        !          1366:
        !          1367:     if ( dn ) {
        !          1368:         if ( mod )
        !          1369:             dn->m = 1;
        !          1370:         else if ( nd_vc )
        !          1371:             dn->r = (R)ONE;
        !          1372:         else
        !          1373:             dn->z = ONE;
        !          1374:     }
        !          1375:     if ( !g ) {
        !          1376:         *rp = d;
        !          1377:         return 1;
        !          1378:     }
        !          1379:     if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
        !          1380:
        !          1381:     sugar0 = sugar = SG(g);
        !          1382:     n = NV(g);
        !          1383:     mul = (NM)ALLOCA(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
        !          1384:     if ( d )
        !          1385:         for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
        !          1386:     for ( ; g; ) {
        !          1387:         index = ndl_find_reducer(HDL(g));
        !          1388:         if ( index >= 0 ) {
        !          1389:             h = nd_psh[index];
        !          1390:             ndl_sub(HDL(g),DL(h),DL(mul));
        !          1391:             if ( ndl_check_bound2(index,DL(mul)) ) {
        !          1392:                 nd_free(g); nd_free(d);
        !          1393:                 return 0;
        !          1394:             }
        !          1395:             p = nd_demand ? ndv_load(index) : ps[index];
        !          1396:             g = nd_reduce2(mod,d,g,p,mul,dn);
        !          1397:             sugar = MAX(sugar,SG(p)+TD(DL(mul)));
        !          1398:             if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
        !          1399:                 tp = HCP(g);
        !          1400:                 nd_removecont2(d,g);
        !          1401:                 if ( dn ) {
        !          1402:                     if ( nd_vc ) {
        !          1403:                         divsp(nd_vc,tp,HCP(g),&tp1);
        !          1404:                         divr(nd_vc,(Obj)dn->r,(Obj)tp1,&tr);
        !          1405:                         reductr(nd_vc,(Obj)tr,&tr1); dn->r = (R)tr1;
        !          1406:                     } else {
        !          1407:                         divq((Q)tp,HCQ(g),&qq);
        !          1408:                         divq(dn->z,qq,&tq); dn->z = tq;
        !          1409:                     }
        !          1410:                 }
        !          1411:                 hmag = ((double)p_mag(HCP(g)))*nd_scale;
        !          1412:             }
        !          1413:         } else if ( !full ) {
        !          1414:             *rp = g;
        !          1415:             return 1;
        !          1416:         } else {
        !          1417:             m = BDY(g);
        !          1418:             if ( NEXT(m) ) {
        !          1419:                 BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
        !          1420:             } else {
        !          1421:                 FREEND(g); g = 0;
        !          1422:             }
        !          1423:             if ( d ) {
        !          1424:                 NEXT(tail)=m; tail=m; LEN(d)++;
        !          1425:             } else {
        !          1426:                 MKND(n,m,1,d); tail = BDY(d);
        !          1427:             }
        !          1428:         }
        !          1429:     }
        !          1430:     if ( d ) SG(d) = sugar;
        !          1431:     *rp = d;
        !          1432:     return 1;
1.1       noro     1433: }
1.28      noro     1434:
1.53      noro     1435: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1.25      noro     1436: {
1.157   ! noro     1437:     int hindex,index;
        !          1438:     NDV p;
        !          1439:     ND u,d,red;
        !          1440:     NODE l;
        !          1441:     NM mul,m,mrd,tail;
        !          1442:     int sugar,psugar,n,h_reducible;
        !          1443:     PGeoBucket bucket;
        !          1444:     int c,c1,c2;
        !          1445:     Q cg,cred,gcd,zzz;
        !          1446:     RHist h;
        !          1447:     double hmag,gmag;
        !          1448:     int count = 0;
        !          1449:     int hcount = 0;
        !          1450:
        !          1451:     if ( !g ) {
        !          1452:         *rp = 0;
        !          1453:         return 1;
        !          1454:     }
        !          1455:     sugar = SG(g);
        !          1456:     n = NV(g);
        !          1457:     if ( !mod ) hmag = ((double)p_mag((P)HCQ(g)))*nd_scale;
        !          1458:     bucket = create_pbucket();
        !          1459:     add_pbucket(mod,bucket,g);
        !          1460:     d = 0;
        !          1461:     mul = (NM)ALLOCA(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
        !          1462:     while ( 1 ) {
        !          1463:         hindex = mod?head_pbucket(mod,bucket):head_pbucket_q(bucket);
        !          1464:         if ( hindex < 0 ) {
        !          1465:             if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
        !          1466:             if ( d ) SG(d) = sugar;
        !          1467:             *rp = d;
        !          1468:             return 1;
        !          1469:         }
        !          1470:         g = bucket->body[hindex];
        !          1471:         index = ndl_find_reducer(HDL(g));
        !          1472:         if ( index >= 0 ) {
        !          1473:             count++;
        !          1474:             if ( !d ) hcount++;
        !          1475:             h = nd_psh[index];
        !          1476:             ndl_sub(HDL(g),DL(h),DL(mul));
        !          1477:             if ( ndl_check_bound2(index,DL(mul)) ) {
        !          1478:                 nd_free(d);
        !          1479:                 free_pbucket(bucket);
        !          1480:                 *rp = 0;
        !          1481:                 return 0;
        !          1482:             }
        !          1483:             p = ps[index];
        !          1484:             if ( mod == -1 )
        !          1485:                 CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
        !          1486:              else if ( mod ) {
        !          1487:                 c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
        !          1488:                 DMAR(c1,c2,0,mod,c); CM(mul) = c;
        !          1489:             } else {
        !          1490:                 igcd_cofactor(HCQ(g),HCQ(p),&gcd,&cg,&cred);
        !          1491:                 chsgnq(cg,&CQ(mul));
        !          1492:                 nd_mul_c_q(d,(P)cred);
        !          1493:                 mulq_pbucket(bucket,cred);
        !          1494:                 g = bucket->body[hindex];
        !          1495:                 gmag = (double)p_mag((P)HCQ(g));
        !          1496:             }
        !          1497:             red = ndv_mul_nm(mod,mul,p);
        !          1498:             bucket->body[hindex] = nd_remove_head(g);
        !          1499:             red = nd_remove_head(red);
        !          1500:             add_pbucket(mod,bucket,red);
        !          1501:             psugar = SG(p)+TD(DL(mul));
        !          1502:             sugar = MAX(sugar,psugar);
        !          1503:             if ( !mod && hmag && (gmag > hmag) ) {
        !          1504:                 g = normalize_pbucket(mod,bucket);
        !          1505:                 if ( !g ) {
        !          1506:                     if ( d ) SG(d) = sugar;
        !          1507:                     *rp = d;
        !          1508:                     return 1;
        !          1509:                 }
        !          1510:                 nd_removecont2(d,g);
        !          1511:                 hmag = ((double)p_mag((P)HCQ(g)))*nd_scale;
        !          1512:                 add_pbucket(mod,bucket,g);
        !          1513:             }
        !          1514:         } else if ( !full ) {
        !          1515:             g = normalize_pbucket(mod,bucket);
        !          1516:             if ( g ) SG(g) = sugar;
        !          1517:             *rp = g;
        !          1518:             return 1;
        !          1519:         } else {
        !          1520:             m = BDY(g);
        !          1521:             if ( NEXT(m) ) {
        !          1522:                 BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
        !          1523:             } else {
        !          1524:                 FREEND(g); g = 0;
        !          1525:             }
        !          1526:             bucket->body[hindex] = g;
        !          1527:             NEXT(m) = 0;
        !          1528:             if ( d ) {
        !          1529:                 NEXT(tail)=m; tail=m; LEN(d)++;
        !          1530:             } else {
        !          1531:                 MKND(n,m,1,d); tail = BDY(d);
        !          1532:             }
        !          1533:         }
        !          1534:     }
1.25      noro     1535: }
1.27      noro     1536:
1.61      noro     1537: /* input : list of NDV, cand : list of NDV */
1.28      noro     1538:
1.61      noro     1539: int ndv_check_candidate(NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1.28      noro     1540: {
1.157   ! noro     1541:     int n,i,stat;
        !          1542:     ND nf,d;
        !          1543:     NDV r;
        !          1544:     NODE t,s;
        !          1545:     union oNDC dn;
1.45      noro     1546:
1.157   ! noro     1547:     ndv_setup(0,0,cand,0,1);
        !          1548:     n = length(cand);
1.28      noro     1549:
1.157   ! noro     1550:     /* membercheck : list is a subset of Id(cand) ? */
        !          1551:     for ( t = input; t; t = NEXT(t) ) {
1.45      noro     1552: again:
1.157   ! noro     1553:         if ( nd_bpe > obpe )
        !          1554:             r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
        !          1555:         else
        !          1556:             r = (NDV)BDY(t);
        !          1557:         d = ndvtond(0,r);
        !          1558:         stat = nd_nf(0,0,d,nd_ps,0,0,&nf);
        !          1559:         if ( !stat ) {
        !          1560:             nd_reconstruct(0,0);
        !          1561:             goto again;
        !          1562:         } else if ( nf ) return 0;
        !          1563:         if ( DP_Print ) { printf("."); fflush(stdout); }
        !          1564:     }
        !          1565:     if ( DP_Print ) { printf("\n"); }
        !          1566:     /* gbcheck : cand is a GB of Id(cand) ? */
        !          1567:     if ( !nd_gb(0,0,1) ) return 0;
        !          1568:     /* XXX */
        !          1569:     return 1;
1.23      noro     1570: }
1.1       noro     1571:
                   1572: ND nd_remove_head(ND p)
                   1573: {
1.157   ! noro     1574:     NM m;
1.1       noro     1575:
1.157   ! noro     1576:     m = BDY(p);
        !          1577:     if ( !NEXT(m) ) {
        !          1578:         FREEND(p); p = 0;
        !          1579:     } else {
        !          1580:         BDY(p) = NEXT(m); LEN(p)--;
        !          1581:     }
        !          1582:     FREENM(m);
        !          1583:     return p;
1.1       noro     1584: }
                   1585:
1.69      noro     1586: ND nd_separate_head(ND p,ND *head)
                   1587: {
1.157   ! noro     1588:     NM m,m0;
        !          1589:     ND r;
1.69      noro     1590:
1.157   ! noro     1591:     m = BDY(p);
        !          1592:     if ( !NEXT(m) ) {
        !          1593:         *head = p; p = 0;
        !          1594:     } else {
        !          1595:         m0 = m;
        !          1596:         BDY(p) = NEXT(m); LEN(p)--;
        !          1597:         NEXT(m0) = 0;
        !          1598:         MKND(NV(p),m0,1,r);
        !          1599:         *head = r;
        !          1600:     }
        !          1601:     return p;
1.69      noro     1602: }
                   1603:
1.1       noro     1604: PGeoBucket create_pbucket()
                   1605: {
                   1606:     PGeoBucket g;
1.157   ! noro     1607:
        !          1608:     g = CALLOC(1,sizeof(struct oPGeoBucket));
        !          1609:     g->m = -1;
        !          1610:     return g;
1.1       noro     1611: }
                   1612:
1.25      noro     1613: void free_pbucket(PGeoBucket b) {
1.157   ! noro     1614:     int i;
1.25      noro     1615:
1.157   ! noro     1616:     for ( i = 0; i <= b->m; i++ )
        !          1617:         if ( b->body[i] ) {
        !          1618:             nd_free(b->body[i]);
        !          1619:             b->body[i] = 0;
        !          1620:         }
        !          1621:     GC_free(b);
1.25      noro     1622: }
                   1623:
1.63      noro     1624: void add_pbucket_symbolic(PGeoBucket g,ND d)
                   1625: {
1.157   ! noro     1626:     int l,i,k,m;
1.63      noro     1627:
1.157   ! noro     1628:     if ( !d )
        !          1629:         return;
        !          1630:     l = LEN(d);
        !          1631:     for ( k = 0, m = 1; l > m; k++, m <<= 1 );
        !          1632:     /* 2^(k-1) < l <= 2^k (=m) */
        !          1633:     d = nd_merge(g->body[k],d);
        !          1634:     for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
        !          1635:         g->body[k] = 0;
        !          1636:         d = nd_merge(g->body[k+1],d);
        !          1637:     }
        !          1638:     g->body[k] = d;
        !          1639:     g->m = MAX(g->m,k);
1.63      noro     1640: }
                   1641:
1.31      noro     1642: void add_pbucket(int mod,PGeoBucket g,ND d)
1.1       noro     1643: {
1.157   ! noro     1644:     int l,i,k,m;
1.1       noro     1645:
1.157   ! noro     1646:     if ( !d )
        !          1647:         return;
        !          1648:     l = LEN(d);
        !          1649:     for ( k = 0, m = 1; l > m; k++, m <<= 1 );
        !          1650:     /* 2^(k-1) < l <= 2^k (=m) */
        !          1651:     d = nd_add(mod,g->body[k],d);
        !          1652:     for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
        !          1653:         g->body[k] = 0;
        !          1654:         d = nd_add(mod,g->body[k+1],d);
        !          1655:     }
        !          1656:     g->body[k] = d;
        !          1657:     g->m = MAX(g->m,k);
1.1       noro     1658: }
                   1659:
1.113     noro     1660: void mulq_pbucket(PGeoBucket g,Q c)
1.26      noro     1661: {
1.157   ! noro     1662:     int k;
1.26      noro     1663:
1.157   ! noro     1664:     for ( k = 0; k <= g->m; k++ )
        !          1665:         nd_mul_c_q(g->body[k],(P)c);
1.26      noro     1666: }
                   1667:
1.63      noro     1668: NM remove_head_pbucket_symbolic(PGeoBucket g)
                   1669: {
1.157   ! noro     1670:     int j,i,k,c;
        !          1671:     NM head;
        !          1672:
        !          1673:     k = g->m;
        !          1674:     j = -1;
        !          1675:     for ( i = 0; i <= k; i++ ) {
        !          1676:         if ( !g->body[i] ) continue;
        !          1677:         if ( j < 0 ) j = i;
        !          1678:         else {
        !          1679:             c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
        !          1680:             if ( c > 0 )
        !          1681:                 j = i;
        !          1682:             else if ( c == 0 )
        !          1683:                 g->body[i] = nd_remove_head(g->body[i]);
        !          1684:         }
        !          1685:     }
        !          1686:     if ( j < 0 ) return 0;
        !          1687:     else {
        !          1688:         head = BDY(g->body[j]);
        !          1689:         if ( !NEXT(head) ) {
        !          1690:             FREEND(g->body[j]);
        !          1691:             g->body[j] = 0;
        !          1692:         } else {
        !          1693:             BDY(g->body[j]) = NEXT(head);
        !          1694:             LEN(g->body[j])--;
        !          1695:         }
        !          1696:         return head;
        !          1697:     }
1.63      noro     1698: }
                   1699:
1.19      noro     1700: int head_pbucket(int mod,PGeoBucket g)
1.1       noro     1701: {
1.157   ! noro     1702:     int j,i,c,k,nv,sum;
        !          1703:     UINT *di,*dj;
        !          1704:     ND gi,gj;
        !          1705:
        !          1706:     k = g->m;
        !          1707:     while ( 1 ) {
        !          1708:         j = -1;
        !          1709:         for ( i = 0; i <= k; i++ ) {
        !          1710:             if ( !(gi = g->body[i]) )
        !          1711:                 continue;
        !          1712:             if ( j < 0 ) {
        !          1713:                 j = i;
        !          1714:                 gj = g->body[j];
        !          1715:                 dj = HDL(gj);
        !          1716:                 sum = HCM(gj);
        !          1717:             } else {
        !          1718:                 c = DL_COMPARE(HDL(gi),dj);
        !          1719:                 if ( c > 0 ) {
        !          1720:                     if ( sum ) HCM(gj) = sum;
        !          1721:                     else g->body[j] = nd_remove_head(gj);
        !          1722:                     j = i;
        !          1723:                     gj = g->body[j];
        !          1724:                     dj = HDL(gj);
        !          1725:                     sum = HCM(gj);
        !          1726:                 } else if ( c == 0 ) {
        !          1727:                     if ( mod == -1 )
        !          1728:                         sum = _addsf(sum,HCM(gi));
        !          1729:                     else {
        !          1730:                         sum = sum+HCM(gi)-mod;
        !          1731:                         if ( sum < 0 ) sum += mod;
        !          1732:                     }
        !          1733:                     g->body[i] = nd_remove_head(gi);
        !          1734:                 }
        !          1735:             }
        !          1736:         }
        !          1737:         if ( j < 0 ) return -1;
        !          1738:         else if ( sum ) {
        !          1739:             HCM(gj) = sum;
        !          1740:             return j;
        !          1741:         } else
        !          1742:             g->body[j] = nd_remove_head(gj);
        !          1743:     }
1.26      noro     1744: }
                   1745:
1.113     noro     1746: int head_pbucket_q(PGeoBucket g)
1.26      noro     1747: {
1.157   ! noro     1748:     int j,i,c,k,nv;
        !          1749:     Q sum,t;
        !          1750:     ND gi,gj;
        !          1751:
        !          1752:     k = g->m;
        !          1753:     while ( 1 ) {
        !          1754:         j = -1;
        !          1755:         for ( i = 0; i <= k; i++ ) {
        !          1756:             if ( !(gi = g->body[i]) ) continue;
        !          1757:             if ( j < 0 ) {
        !          1758:                 j = i;
        !          1759:                 gj = g->body[j];
        !          1760:                 sum = HCQ(gj);
        !          1761:             } else {
        !          1762:                 nv = NV(gi);
        !          1763:                 c = DL_COMPARE(HDL(gi),HDL(gj));
        !          1764:                 if ( c > 0 ) {
        !          1765:                     if ( sum ) HCQ(gj) = sum;
        !          1766:                     else g->body[j] = nd_remove_head(gj);
        !          1767:                     j = i;
        !          1768:                     gj = g->body[j];
        !          1769:                     sum = HCQ(gj);
        !          1770:                 } else if ( c == 0 ) {
        !          1771:                     addq(sum,HCQ(gi),&t);
        !          1772:                     sum = t;
        !          1773:                     g->body[i] = nd_remove_head(gi);
        !          1774:                 }
        !          1775:             }
        !          1776:         }
        !          1777:         if ( j < 0 ) return -1;
        !          1778:         else if ( sum ) {
        !          1779:             HCQ(gj) = sum;
        !          1780:             return j;
        !          1781:         } else
        !          1782:             g->body[j] = nd_remove_head(gj);
        !          1783:     }
1.1       noro     1784: }
                   1785:
1.25      noro     1786: ND normalize_pbucket(int mod,PGeoBucket g)
1.1       noro     1787: {
1.157   ! noro     1788:     int i;
        !          1789:     ND r,t;
1.1       noro     1790:
1.157   ! noro     1791:     r = 0;
        !          1792:     for ( i = 0; i <= g->m; i++ ) {
        !          1793:         r = nd_add(mod,r,g->body[i]);
        !          1794:         g->body[i] = 0;
        !          1795:     }
        !          1796:     g->m = -1;
        !          1797:     return r;
1.1       noro     1798: }
                   1799:
1.150     noro     1800: #if 0
                   1801: void register_hcf(NDV p)
                   1802: {
1.157   ! noro     1803:     DCP dc,t;
        !          1804:     P hc,h;
        !          1805:     int c;
        !          1806:     NODE l,l1,prev;
        !          1807:
        !          1808:     hc = p->body->c.p;
        !          1809:     if ( !nd_vc || NUM(hc) ) return;
        !          1810:     fctrp(nd_vc,hc,&dc);
        !          1811:     for ( t = dc; t; t = NEXT(t) ) {
        !          1812:         h = t->c;
        !          1813:         if ( NUM(h) ) continue;
        !          1814:         for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
        !          1815:             c = compp(nd_vc,h,(P)BDY(l));
        !          1816:             if ( c >= 0 ) break;
        !          1817:         }
        !          1818:         if ( !l || c > 0  ) {
        !          1819:             MKNODE(l1,h,l);
        !          1820:             if ( !prev )
        !          1821:                 nd_hcf = l1;
        !          1822:             else
        !          1823:                 NEXT(prev) = l1;
        !          1824:         }
        !          1825:     }
1.150     noro     1826: }
                   1827: #else
                   1828: void register_hcf(NDV p)
                   1829: {
1.157   ! noro     1830:     DCP dc,t;
        !          1831:     P hc,h,q;
        !          1832:     Q dmy;
        !          1833:     int c;
        !          1834:     NODE l,l1,prev;
        !          1835:
        !          1836:     hc = p->body->c.p;
        !          1837:     if ( NUM(hc) ) return;
        !          1838:     ptozp(hc,1,&dmy,&h);
1.150     noro     1839: #if 1
1.157   ! noro     1840:     for ( l = nd_hcf; l; l = NEXT(l) ) {
        !          1841:         while ( 1 ) {
        !          1842:             if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
        !          1843:             else break;
        !          1844:         }
        !          1845:     }
        !          1846:     if ( NUM(h) ) return;
1.150     noro     1847: #endif
1.157   ! noro     1848:     for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
        !          1849:         c = compp(nd_vc,h,(P)BDY(l));
        !          1850:         if ( c >= 0 ) break;
        !          1851:     }
        !          1852:     if ( !l || c > 0  ) {
        !          1853:         MKNODE(l1,h,l);
        !          1854:         if ( !prev )
        !          1855:             nd_hcf = l1;
        !          1856:         else
        !          1857:             NEXT(prev) = l1;
        !          1858:     }
1.150     noro     1859: }
                   1860: #endif
                   1861:
1.122     noro     1862: int do_diagonalize(int sugar,int m)
1.92      noro     1863: {
1.157   ! noro     1864:     int i,nh,stat;
        !          1865:     NODE r,g,t;
        !          1866:     ND h,nf,s,head;
        !          1867:     NDV nfv;
        !          1868:     Q q,num,den;
        !          1869:     P nm,nmp,dn,mnp,dnp;
        !          1870:
        !          1871:     for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
        !          1872:         if ( nd_demand )
        !          1873:             nfv = ndv_load(i);
        !          1874:         else
        !          1875:             nfv = nd_ps[i];
        !          1876:         s = ndvtond(m,nfv);
        !          1877:         s = nd_separate_head(s,&head);
        !          1878:         stat = nd_nf(m,head,s,nd_ps,1,0,&nf);
        !          1879:         if ( !stat ) return 0;
        !          1880:         ndv_free(nfv);
        !          1881:         nd_removecont(m,nf);
        !          1882:         nfv = ndtondv(m,nf);
        !          1883:         nd_free(nf);
        !          1884:         nd_bound[i] = ndv_compute_bound(nfv);
        !          1885:         if ( !m ) register_hcf(nfv);
        !          1886:         if ( nd_demand ) {
        !          1887:             ndv_save(nfv,i);
        !          1888:             ndv_free(nfv);
        !          1889:         } else
        !          1890:             nd_ps[i] = nfv;
        !          1891:     }
        !          1892:     return 1;
1.92      noro     1893: }
                   1894:
1.27      noro     1895: /* return value = 0 => input is not a GB */
                   1896:
1.77      noro     1897: NODE nd_gb(int m,int ishomo,int checkonly)
1.1       noro     1898: {
1.157   ! noro     1899:     int i,nh,sugar,stat;
        !          1900:     NODE r,g,t;
        !          1901:     ND_pairs d;
        !          1902:     ND_pairs l;
        !          1903:     ND h,nf,s,head,nf1;
        !          1904:     NDV nfv;
        !          1905:     Q q,num,den;
        !          1906:     union oNDC dn;
        !          1907:     int diag_count = 0;
        !          1908:
        !          1909:     g = 0; d = 0;
        !          1910:     for ( i = 0; i < nd_psn; i++ ) {
        !          1911:         d = update_pairs(d,g,i);
        !          1912:         g = update_base(g,i);
        !          1913:     }
        !          1914:     sugar = 0;
        !          1915:     while ( d ) {
1.1       noro     1916: again:
1.157   ! noro     1917:         l = nd_minp(d,&d);
        !          1918:         if ( SG(l) != sugar ) {
        !          1919:             if ( ishomo ) {
        !          1920:                 diag_count = 0;
        !          1921:                 stat = do_diagonalize(sugar,m);
        !          1922:                 if ( !stat ) {
        !          1923:                     NEXT(l) = d; d = l;
        !          1924:                     d = nd_reconstruct(0,d);
        !          1925:                     goto again;
        !          1926:                 }
        !          1927:             }
        !          1928:             sugar = SG(l);
        !          1929:             if ( DP_Print ) fprintf(asir_out,"%d",sugar);
        !          1930:         }
        !          1931:         stat = nd_sp(m,0,l,&h);
        !          1932:         if ( !stat ) {
        !          1933:             NEXT(l) = d; d = l;
        !          1934:             d = nd_reconstruct(0,d);
        !          1935:             goto again;
        !          1936:         }
1.41      noro     1937: #if USE_GEOBUCKET
1.157   ! noro     1938:         stat = m?nd_nf_pbucket(m,h,nd_ps,!Top,&nf):nd_nf(m,0,h,nd_ps,!Top,0,&nf);
1.41      noro     1939: #else
1.157   ! noro     1940:         stat = nd_nf(m,0,h,nd_ps,!Top,0,&nf);
1.41      noro     1941: #endif
1.157   ! noro     1942:         if ( !stat ) {
        !          1943:             NEXT(l) = d; d = l;
        !          1944:             d = nd_reconstruct(0,d);
        !          1945:             goto again;
        !          1946:         } else if ( nf ) {
        !          1947:             if ( checkonly ) return 0;
        !          1948:             if ( DP_Print ) { printf("+"); fflush(stdout); }
        !          1949:             nd_removecont(m,nf);
        !          1950:             if ( !m && nd_nalg ) {
        !          1951:                 nd_monic(0,&nf);
        !          1952:                 nd_removecont(m,nf);
        !          1953:             }
        !          1954:             nfv = ndtondv(m,nf); nd_free(nf);
        !          1955:             nh = ndv_newps(m,nfv,0);
        !          1956:             if ( !m && (ishomo && ++diag_count == diag_period) ) {
        !          1957:                 diag_count = 0;
        !          1958:                 stat = do_diagonalize(sugar,m);
        !          1959:                 if ( !stat ) {
        !          1960:                     NEXT(l) = d; d = l;
        !          1961:                     d = nd_reconstruct(1,d);
        !          1962:                     goto again;
        !          1963:                 }
        !          1964:             }
        !          1965:             d = update_pairs(d,g,nh);
        !          1966:             g = update_base(g,nh);
        !          1967:             FREENDP(l);
        !          1968:         } else {
        !          1969:             if ( DP_Print ) { printf("."); fflush(stdout); }
        !          1970:             FREENDP(l);
        !          1971:         }
        !          1972:     }
        !          1973:     if ( nd_demand )
        !          1974:         for ( t = g; t; t = NEXT(t) )
        !          1975:             BDY(t) = (pointer)ndv_load((int)BDY(t));
        !          1976:     else
        !          1977:         for ( t = g; t; t = NEXT(t) )
        !          1978:             BDY(t) = (pointer)nd_ps[(int)BDY(t)];
        !          1979:     if ( !checkonly && DP_Print ) { printf("nd_gb done.\n"); fflush(stdout); }
        !          1980:     return g;
1.1       noro     1981: }
                   1982:
1.122     noro     1983: int do_diagonalize_trace(int sugar,int m)
1.91      noro     1984: {
1.157   ! noro     1985:     int i,nh,stat;
        !          1986:     NODE r,g,t;
        !          1987:     ND h,nf,nfq,s,head;
        !          1988:     NDV nfv,nfqv;
        !          1989:     Q q,den,num;
        !          1990:
        !          1991:     for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
        !          1992:         /* for nd_ps */
        !          1993:         s = ndvtond(m,nd_ps[i]);
        !          1994:         s = nd_separate_head(s,&head);
        !          1995:         stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
        !          1996:         if ( !stat ) return 0;
        !          1997:         nf = nd_add(m,head,nf);
        !          1998:         ndv_free(nd_ps[i]);
        !          1999:         nd_ps[i] = ndtondv(m,nf);
        !          2000:         nd_free(nf);
        !          2001:
        !          2002:         /* for nd_ps_trace */
        !          2003:         if ( nd_demand )
        !          2004:             nfv = ndv_load(i);
        !          2005:         else
        !          2006:             nfv = nd_ps_trace[i];
        !          2007:         s = ndvtond(0,nfv);
        !          2008:         s = nd_separate_head(s,&head);
        !          2009:         stat = nd_nf(0,head,s,nd_ps_trace,1,0,&nf);
        !          2010:         if ( !stat ) return 0;
        !          2011:         ndv_free(nfv);
        !          2012:         nd_removecont(0,nf);
        !          2013:         nfv = ndtondv(0,nf);
        !          2014:         nd_free(nf);
        !          2015:         nd_bound[i] = ndv_compute_bound(nfv);
        !          2016:         register_hcf(nfv);
        !          2017:         if ( nd_demand ) {
        !          2018:             ndv_save(nfv,i);
        !          2019:             ndv_free(nfv);
        !          2020:         } else
        !          2021:             nd_ps_trace[i] = nfv;
        !          2022:     }
        !          2023:     return 1;
1.91      noro     2024: }
                   2025:
1.118     noro     2026: static struct oEGT eg_invdalg;
                   2027: struct oEGT eg_le;
                   2028:
1.147     noro     2029: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
                   2030: {
1.157   ! noro     2031:     NODE tn;
        !          2032:     P p1;
1.147     noro     2033:
1.157   ! noro     2034:     for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
        !          2035:         substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
        !          2036:     }
        !          2037:     *r = p;
1.147     noro     2038: }
                   2039:
1.82      noro     2040: NODE nd_gb_trace(int m,int ishomo)
1.20      noro     2041: {
1.157   ! noro     2042:     int i,nh,sugar,stat;
        !          2043:     NODE r,g,t;
        !          2044:     ND_pairs d;
        !          2045:     ND_pairs l;
        !          2046:     ND h,nf,nfq,s,head;
        !          2047:     NDV nfv,nfqv;
        !          2048:     Q q,den,num;
        !          2049:     P hc;
        !          2050:     union oNDC dn;
        !          2051:     struct oEGT eg_monic,egm0,egm1;
        !          2052:     int diag_count = 0;
        !          2053:
        !          2054:     init_eg(&eg_monic);
        !          2055:     init_eg(&eg_invdalg);
        !          2056:     init_eg(&eg_le);
        !          2057:     g = 0; d = 0;
        !          2058:     for ( i = 0; i < nd_psn; i++ ) {
        !          2059:         d = update_pairs(d,g,i);
        !          2060:         g = update_base(g,i);
        !          2061:     }
        !          2062:     sugar = 0;
        !          2063:     while ( d ) {
1.20      noro     2064: again:
1.157   ! noro     2065:         l = nd_minp(d,&d);
        !          2066:         if ( SG(l) != sugar ) {
1.130     noro     2067: #if 1
1.157   ! noro     2068:             if ( ishomo ) {
        !          2069:                 if ( DP_Print > 2 ) fprintf(asir_out,"|");
        !          2070:                 stat = do_diagonalize_trace(sugar,m);
        !          2071:                 if ( DP_Print > 2 ) fprintf(asir_out,"|");
        !          2072:                 diag_count = 0;
        !          2073:                 if ( !stat ) {
        !          2074:                     NEXT(l) = d; d = l;
        !          2075:                     d = nd_reconstruct(1,d);
        !          2076:                     goto again;
        !          2077:                 }
        !          2078:             }
1.130     noro     2079: #endif
1.157   ! noro     2080:             sugar = SG(l);
        !          2081:             if ( DP_Print ) fprintf(asir_out,"%d",sugar);
        !          2082:         }
        !          2083:         stat = nd_sp(m,0,l,&h);
        !          2084:         if ( !stat ) {
        !          2085:             NEXT(l) = d; d = l;
        !          2086:             d = nd_reconstruct(1,d);
        !          2087:             goto again;
        !          2088:         }
1.41      noro     2089: #if USE_GEOBUCKET
1.157   ! noro     2090:         stat = nd_nf_pbucket(m,h,nd_ps,!Top,&nf);
1.41      noro     2091: #else
1.157   ! noro     2092:         stat = nd_nf(m,0,h,nd_ps,!Top,0,&nf);
1.41      noro     2093: #endif
1.157   ! noro     2094:         if ( !stat ) {
        !          2095:             NEXT(l) = d; d = l;
        !          2096:             d = nd_reconstruct(1,d);
        !          2097:             goto again;
        !          2098:         } else if ( nf ) {
        !          2099:             if ( nd_demand ) {
        !          2100:                 nfqv = ndv_load(nd_psn);
        !          2101:                 nfq = ndvtond(0,nfqv);
        !          2102:             } else
        !          2103:                 nfq = 0;
        !          2104:             if ( !nfq ) {
        !          2105:                 if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!Top,0,&nfq) ) {
        !          2106:                     NEXT(l) = d; d = l;
        !          2107:                     d = nd_reconstruct(1,d);
        !          2108:                     goto again;
        !          2109:                 }
        !          2110:             }
        !          2111:             if ( nfq ) {
        !          2112:                 /* m|HC(nfq) => failure */
        !          2113:                 if ( nd_vc ) {
        !          2114:                     nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Q)hc;
        !          2115:                 } else
        !          2116:                     q = HCQ(nfq);
        !          2117:                 if ( !rem(NM(q),m) ) return 0;
        !          2118:
        !          2119:                 if ( DP_Print ) { printf("+"); fflush(stdout); }
        !          2120:                 if ( nd_nalg ) {
        !          2121:                     /* m|DN(HC(nf)^(-1)) => failure */
        !          2122:                     get_eg(&egm0);
        !          2123:                     if ( !nd_monic(m,&nfq) ) return 0;
        !          2124:                     get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
        !          2125:                     nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
        !          2126:                     nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
        !          2127:                 } else {
        !          2128:                     nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
        !          2129:                     nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
        !          2130:                 }
        !          2131:                 nh = ndv_newps(0,nfv,nfqv);
        !          2132:                 if ( ishomo && ++diag_count == diag_period ) {
        !          2133:                     diag_count = 0;
        !          2134:                     if ( DP_Print > 2 ) fprintf(asir_out,"|");
        !          2135:                     stat = do_diagonalize_trace(sugar,m);
        !          2136:                     if ( DP_Print > 2 ) fprintf(asir_out,"|");
        !          2137:                     if ( !stat ) {
        !          2138:                         NEXT(l) = d; d = l;
        !          2139:                         d = nd_reconstruct(1,d);
        !          2140:                         goto again;
        !          2141:                     }
        !          2142:                 }
        !          2143:                 d = update_pairs(d,g,nh);
        !          2144:                 g = update_base(g,nh);
        !          2145:             } else {
        !          2146:                 if ( DP_Print ) { printf("*"); fflush(stdout); }
        !          2147:             }
        !          2148:         } else {
        !          2149:             if ( DP_Print ) { printf("."); fflush(stdout); }
        !          2150:         }
        !          2151:         FREENDP(l);
        !          2152:     }
        !          2153:     if ( nd_demand )
        !          2154:         for ( t = g; t; t = NEXT(t) )
        !          2155:             BDY(t) = (pointer)ndv_load((int)BDY(t));
        !          2156:     else
        !          2157:         for ( t = g; t; t = NEXT(t) )
        !          2158:             BDY(t) = (pointer)nd_ps_trace[(int)BDY(t)];
        !          2159:     if ( nd_nalg ) {
        !          2160:         print_eg("monic",&eg_monic);
        !          2161:         print_eg("invdalg",&eg_invdalg);
        !          2162:         print_eg("le",&eg_le);
        !          2163:     }
        !          2164:     if ( DP_Print ) { printf("nd_gb_trace done.\n"); fflush(stdout); }
        !          2165:     return g;
1.20      noro     2166: }
                   2167:
1.23      noro     2168: int ndv_compare(NDV *p1,NDV *p2)
                   2169: {
1.157   ! noro     2170:     return DL_COMPARE(HDL(*p1),HDL(*p2));
1.23      noro     2171: }
                   2172:
                   2173: int ndv_compare_rev(NDV *p1,NDV *p2)
                   2174: {
1.157   ! noro     2175:     return -DL_COMPARE(HDL(*p1),HDL(*p2));
1.23      noro     2176: }
                   2177:
1.61      noro     2178: NODE ndv_reduceall(int m,NODE f)
1.23      noro     2179: {
1.157   ! noro     2180:     int i,n,stat;
        !          2181:     ND nf,g,head;
        !          2182:     NODE t,a0,a;
        !          2183:     union oNDC dn;
        !          2184:     NDV *w;
        !          2185:     Q q,num,den;
1.23      noro     2186:
1.157   ! noro     2187:     n = length(f);
1.69      noro     2188: #if 0
1.157   ! noro     2189:     w = (NDV *)ALLOCA(n*sizeof(NDV));
        !          2190:     for ( i = 0, t = f; i < n; i++, t = NEXT(t) ) w[i] = (NDV)BDY(t);
        !          2191:     qsort(w,n,sizeof(NDV),
        !          2192:         (int (*)(const void *,const void *))ndv_compare);
        !          2193:     for ( t = f, i = 0; t; i++, t = NEXT(t) ) BDY(t) = (pointer)w[i];
1.69      noro     2194: #endif
1.157   ! noro     2195:     ndv_setup(m,0,f,0,1);
        !          2196:     for ( i = 0; i < n; ) {
        !          2197:         g = ndvtond(m,nd_ps[i]);
        !          2198:         g = nd_separate_head(g,&head);
        !          2199:         stat = nd_nf(m,head,g,nd_ps,1,0,&nf);
        !          2200:         if ( !stat )
        !          2201:             nd_reconstruct(0,0);
        !          2202:         else {
        !          2203:             if ( DP_Print ) { printf("."); fflush(stdout); }
        !          2204:             ndv_free(nd_ps[i]);
        !          2205:             nd_removecont(m,nf);
        !          2206:             nd_ps[i] = ndtondv(m,nf); nd_free(nf);
        !          2207:             nd_bound[i] = ndv_compute_bound(nd_ps[i]);
        !          2208:             i++;
        !          2209:         }
        !          2210:     }
        !          2211:     if ( DP_Print ) { printf("\n"); }
        !          2212:     for ( a0 = 0, i = 0; i < n; i++ ) {
        !          2213:         NEXTNODE(a0,a);
        !          2214:         BDY(a) = (pointer)nd_ps[i];
        !          2215:     }
        !          2216:     NEXT(a) = 0;
        !          2217:     return a0;
1.23      noro     2218: }
                   2219:
1.1       noro     2220: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t)
                   2221: {
1.157   ! noro     2222:     ND_pairs d1,nd,cur,head,prev,remove;
1.1       noro     2223:
1.157   ! noro     2224:     if ( !g ) return d;
        !          2225:     d = crit_B(d,t);
        !          2226:     d1 = nd_newpairs(g,t);
        !          2227:     d1 = crit_M(d1);
        !          2228:     d1 = crit_F(d1);
        !          2229:     if ( do_weyl )
        !          2230:         head = d1;
        !          2231:     else {
        !          2232:         prev = 0; cur = head = d1;
        !          2233:         while ( cur ) {
        !          2234:             if ( crit_2( cur->i1,cur->i2 ) ) {
        !          2235:                 remove = cur;
        !          2236:                 if ( !prev ) head = cur = NEXT(cur);
        !          2237:                 else cur = NEXT(prev) = NEXT(cur);
        !          2238:                 FREENDP(remove);
        !          2239:             } else {
        !          2240:                 prev = cur; cur = NEXT(cur);
        !          2241:             }
        !          2242:         }
        !          2243:     }
        !          2244:     if ( !d )
        !          2245:         return head;
        !          2246:     else {
        !          2247:         nd = d;
        !          2248:         while ( NEXT(nd) ) nd = NEXT(nd);
        !          2249:         NEXT(nd) = head;
        !          2250:         return d;
        !          2251:     }
1.1       noro     2252: }
                   2253:
1.157   ! noro     2254:
1.1       noro     2255: ND_pairs nd_newpairs( NODE g, int t )
                   2256: {
1.157   ! noro     2257:     NODE h;
        !          2258:     UINT *dl;
        !          2259:     int ts,s;
        !          2260:     ND_pairs r,r0;
        !          2261:
        !          2262:     dl = DL(nd_psh[t]);
        !          2263:     ts = SG(nd_psh[t]) - TD(dl);
        !          2264:     for ( r0 = 0, h = g; h; h = NEXT(h) ) {
        !          2265:         if ( nd_module && (MPOS(DL(nd_psh[(int)BDY(h)])) != MPOS(dl)) )
        !          2266:                 continue;
        !          2267:         NEXTND_pairs(r0,r);
        !          2268:         r->i1 = (int)BDY(h);
        !          2269:         r->i2 = t;
        !          2270:         ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
        !          2271:         s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
        !          2272:         SG(r) = MAX(s,ts) + TD(LCM(r));
        !          2273:     }
        !          2274:     if ( r0 ) NEXT(r) = 0;
        !          2275:     return r0;
1.1       noro     2276: }
                   2277:
1.157   ! noro     2278: /* kokokara */
        !          2279:
1.1       noro     2280: ND_pairs crit_B( ND_pairs d, int s )
                   2281: {
1.157   ! noro     2282:     ND_pairs cur,head,prev,remove;
        !          2283:     UINT *t,*tl,*lcm;
        !          2284:     int td,tdl;
        !          2285:
        !          2286:     if ( !d ) return 0;
        !          2287:     t = DL(nd_psh[s]);
        !          2288:     prev = 0;
        !          2289:     head = cur = d;
        !          2290:     lcm = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          2291:     while ( cur ) {
        !          2292:         tl = cur->lcm;
        !          2293:         if ( ndl_reducible(tl,t)
        !          2294:             && (ndl_lcm(DL(nd_psh[cur->i1]),t,lcm),!ndl_equal(lcm,tl))
        !          2295:             && (ndl_lcm(DL(nd_psh[cur->i2]),t,lcm),!ndl_equal(lcm,tl)) ) {
        !          2296:             remove = cur;
        !          2297:             if ( !prev ) {
        !          2298:                 head = cur = NEXT(cur);
        !          2299:             } else {
        !          2300:                 cur = NEXT(prev) = NEXT(cur);
        !          2301:             }
        !          2302:             FREENDP(remove);
        !          2303:         } else {
        !          2304:             prev = cur; cur = NEXT(cur);
        !          2305:         }
        !          2306:     }
        !          2307:     return head;
1.1       noro     2308: }
                   2309:
                   2310: ND_pairs crit_M( ND_pairs d1 )
                   2311: {
1.157   ! noro     2312:     ND_pairs e,d2,d3,dd,p;
        !          2313:     UINT *id,*jd;
1.1       noro     2314:
1.157   ! noro     2315:     if ( !d1 ) return d1;
        !          2316:     for ( dd = 0, e = d1; e; e = d3 ) {
        !          2317:         if ( !(d2 = NEXT(e)) ) {
        !          2318:             NEXT(e) = dd;
        !          2319:             return e;
        !          2320:         }
        !          2321:         id = LCM(e);
        !          2322:         for ( d3 = 0; d2; d2 = p ) {
        !          2323:             p = NEXT(d2);
        !          2324:             jd = LCM(d2);
        !          2325:             if ( ndl_equal(jd,id) )
        !          2326:                 ;
        !          2327:             else if ( TD(jd) > TD(id) )
        !          2328:                 if ( ndl_reducible(jd,id) ) continue;
        !          2329:                 else ;
        !          2330:             else if ( ndl_reducible(id,jd) ) goto delit;
        !          2331:             NEXT(d2) = d3;
        !          2332:             d3 = d2;
        !          2333:         }
        !          2334:         NEXT(e) = dd;
        !          2335:         dd = e;
        !          2336:         continue;
        !          2337:         /**/
        !          2338:     delit:    NEXT(d2) = d3;
        !          2339:         d3 = d2;
        !          2340:         for ( ; p; p = d2 ) {
        !          2341:             d2 = NEXT(p);
        !          2342:             NEXT(p) = d3;
        !          2343:             d3 = p;
        !          2344:         }
        !          2345:         FREENDP(e);
        !          2346:     }
        !          2347:     return dd;
1.1       noro     2348: }
                   2349:
                   2350: ND_pairs crit_F( ND_pairs d1 )
                   2351: {
1.157   ! noro     2352:     ND_pairs rest, head,remove;
        !          2353:     ND_pairs last, p, r, w;
        !          2354:     int s;
        !          2355:
        !          2356:     if ( !d1 ) return d1;
        !          2357:     for ( head = last = 0, p = d1; NEXT(p); ) {
        !          2358:         r = w = equivalent_pairs(p,&rest);
        !          2359:         s = SG(r);
        !          2360:         w = NEXT(w);
        !          2361:         while ( w ) {
        !          2362:             if ( crit_2(w->i1,w->i2) ) {
        !          2363:                 r = w;
        !          2364:                 w = NEXT(w);
        !          2365:                 while ( w ) {
        !          2366:                     remove = w;
        !          2367:                     w = NEXT(w);
        !          2368:                     FREENDP(remove);
        !          2369:                 }
        !          2370:                 break;
        !          2371:             } else if ( SG(w) < s ) {
        !          2372:                 FREENDP(r);
        !          2373:                 r = w;
        !          2374:                 s = SG(r);
        !          2375:                 w = NEXT(w);
        !          2376:             } else {
        !          2377:                 remove = w;
        !          2378:                 w = NEXT(w);
        !          2379:                 FREENDP(remove);
        !          2380:             }
        !          2381:         }
        !          2382:         if ( last ) NEXT(last) = r;
        !          2383:         else head = r;
        !          2384:         NEXT(last = r) = 0;
        !          2385:         p = rest;
        !          2386:         if ( !p ) return head;
        !          2387:     }
        !          2388:     if ( !last ) return p;
        !          2389:     NEXT(last) = p;
        !          2390:     return head;
1.1       noro     2391: }
                   2392:
                   2393: int crit_2( int dp1, int dp2 )
                   2394: {
1.157   ! noro     2395:     return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
1.1       noro     2396: }
                   2397:
1.40      noro     2398: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
1.1       noro     2399: {
1.157   ! noro     2400:     ND_pairs w,p,r,s;
        !          2401:     UINT *d;
1.1       noro     2402:
1.157   ! noro     2403:     w = d1;
        !          2404:     d = LCM(w);
        !          2405:     s = NEXT(w);
        !          2406:     NEXT(w) = 0;
        !          2407:     for ( r = 0; s; s = p ) {
        !          2408:         p = NEXT(s);
        !          2409:         if ( ndl_equal(d,LCM(s)) ) {
        !          2410:             NEXT(s) = w; w = s;
        !          2411:         } else {
        !          2412:             NEXT(s) = r; r = s;
        !          2413:         }
        !          2414:     }
        !          2415:     *prest = r;
        !          2416:     return w;
1.1       noro     2417: }
                   2418:
                   2419: NODE update_base(NODE nd,int ndp)
                   2420: {
1.157   ! noro     2421:     UINT *dl, *dln;
        !          2422:     NODE last, p, head;
1.1       noro     2423:
1.157   ! noro     2424:     dl = DL(nd_psh[ndp]);
        !          2425:     for ( head = last = 0, p = nd; p; ) {
        !          2426:         dln = DL(nd_psh[(int)BDY(p)]);
        !          2427:         if ( ndl_reducible( dln, dl ) ) {
        !          2428:             p = NEXT(p);
        !          2429:             if ( last ) NEXT(last) = p;
        !          2430:         } else {
        !          2431:             if ( !last ) head = p;
        !          2432:             p = NEXT(last = p);
        !          2433:         }
        !          2434:     }
        !          2435:     head = append_one(head,ndp);
        !          2436:     return head;
1.1       noro     2437: }
                   2438:
                   2439: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
                   2440: {
1.157   ! noro     2441:     ND_pairs m,ml,p,l;
        !          2442:     UINT *lcm;
        !          2443:     int s,td,len,tlen,c,c1;
        !          2444:
        !          2445:     if ( !(p = NEXT(m = d)) ) {
        !          2446:         *prest = p;
        !          2447:         NEXT(m) = 0;
        !          2448:         return m;
        !          2449:     }
        !          2450:     s = SG(m);
        !          2451:     if ( !NoSugar ) {
        !          2452:         for ( ml = 0, l = m; p; p = NEXT(l = p) )
        !          2453:             if ( (SG(p) < s)
        !          2454:                 || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
        !          2455:                 ml = l; m = p; s = SG(m);
        !          2456:             }
        !          2457:     } else {
        !          2458:         for ( ml = 0, l = m; p; p = NEXT(l = p) )
        !          2459:             if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
        !          2460:                 ml = l; m = p; s = SG(m);
        !          2461:             }
        !          2462:     }
        !          2463:     if ( !ml ) *prest = NEXT(m);
        !          2464:     else {
        !          2465:         NEXT(ml) = NEXT(m);
        !          2466:         *prest = d;
        !          2467:     }
        !          2468:     NEXT(m) = 0;
        !          2469:     return m;
1.1       noro     2470: }
                   2471:
1.63      noro     2472: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
                   2473: {
1.157   ! noro     2474:     int msugar,i;
        !          2475:     ND_pairs t,dm0,dm,dr0,dr;
1.63      noro     2476:
1.157   ! noro     2477:     for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
        !          2478:         if ( SG(t) < msugar ) msugar = SG(t);
        !          2479:     dm0 = 0; dr0 = 0;
        !          2480:     for ( i = 0, t = d; t; t = NEXT(t) )
        !          2481:         if ( i < nd_f4_nsp && SG(t) == msugar ) {
        !          2482:             if ( dm0 ) NEXT(dm) = t;
        !          2483:             else dm0 = t;
        !          2484:             dm = t;
        !          2485:             i++;
        !          2486:         } else {
        !          2487:             if ( dr0 ) NEXT(dr) = t;
        !          2488:             else dr0 = t;
        !          2489:             dr = t;
        !          2490:         }
        !          2491:     NEXT(dm) = 0;
        !          2492:     if ( dr0 ) NEXT(dr) = 0;
        !          2493:     *prest = dr0;
        !          2494:     return dm0;
1.63      noro     2495: }
                   2496:
1.77      noro     2497: int ndv_newps(int m,NDV a,NDV aq)
1.1       noro     2498: {
1.157   ! noro     2499:     int len;
        !          2500:     RHist r;
        !          2501:     NDV b;
        !          2502:
        !          2503:     if ( nd_psn == nd_pslen ) {
        !          2504:         nd_pslen *= 2;
        !          2505:         nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
        !          2506:         nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
        !          2507:         nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
        !          2508:         nd_bound = (UINT **)
        !          2509:             REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
        !          2510:     }
        !          2511:     NEWRHist(r); nd_psh[nd_psn] = r;
        !          2512:     nd_ps[nd_psn] = a;
        !          2513:     if ( aq ) {
        !          2514:         nd_ps_trace[nd_psn] = aq;
        !          2515:         register_hcf(aq);
        !          2516:         nd_bound[nd_psn] = ndv_compute_bound(aq);
        !          2517:         SG(r) = SG(aq); ndl_copy(HDL(aq),DL(r));
        !          2518:     } else {
        !          2519:         if ( !m ) register_hcf(a);
        !          2520:         nd_bound[nd_psn] = ndv_compute_bound(a);
        !          2521:         SG(r) = SG(a); ndl_copy(HDL(a),DL(r));
        !          2522:     }
        !          2523:     if ( nd_demand ) {
        !          2524:         if ( aq ) {
        !          2525:             ndv_save(nd_ps_trace[nd_psn],nd_psn);
        !          2526:             nd_ps_trace[nd_psn] = 0;
        !          2527:         } else {
        !          2528:             ndv_save(nd_ps[nd_psn],nd_psn);
        !          2529:             nd_ps[nd_psn] = 0;
        !          2530:         }
        !          2531:     }
        !          2532:     return nd_psn++;
1.1       noro     2533: }
                   2534:
1.151     noro     2535: void ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont)
1.1       noro     2536: {
1.157   ! noro     2537:     int i,j,td,len,max;
        !          2538:     NODE s,s0,f0;
        !          2539:     UINT *d;
        !          2540:     RHist r;
        !          2541:     NDV *w;
        !          2542:     NDV a,am;
        !          2543:
        !          2544:     nd_found = 0; nd_notfirst = 0; nd_create = 0;
        !          2545:
        !          2546:     for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
        !          2547:     w = (NDV *)ALLOCA(nd_psn*sizeof(NDV));
        !          2548:     for ( i = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) w[i++] = BDY(s);
        !          2549:     if ( !dont_sort ) {
        !          2550:         /* XXX heuristic */
        !          2551:         if ( !nd_ord->id && (nd_ord->ord.simple<2) )
        !          2552:             qsort(w,nd_psn,sizeof(NDV),
        !          2553:                 (int (*)(const void *,const void *))ndv_compare_rev);
        !          2554:         else
        !          2555:             qsort(w,nd_psn,sizeof(NDV),
        !          2556:                 (int (*)(const void *,const void *))ndv_compare);
        !          2557:     }
        !          2558:     nd_pslen = 2*nd_psn;
        !          2559:     nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
        !          2560:     nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
        !          2561:     nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
        !          2562:     nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
        !          2563:     nd_hcf = 0;
        !          2564:
        !          2565:     if ( trace && nd_vc )
        !          2566:         makesubst(nd_vc,&nd_subst);
        !          2567:     else
        !          2568:         nd_subst = 0;
        !          2569:
        !          2570:     if ( !nd_red )
        !          2571:         nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
        !          2572:     for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
        !          2573:     for ( i = 0; i < nd_psn; i++ ) {
        !          2574:         if ( trace ) {
        !          2575:             a = nd_ps_trace[i] = ndv_dup(0,w[i]);
        !          2576:             if ( !dont_removecont) ndv_removecont(0,a);
        !          2577:             register_hcf(a);
        !          2578:             am = nd_ps[i] = ndv_dup(mod,a);
        !          2579:             ndv_mod(mod,am);
        !          2580:             ndv_removecont(mod,am);
        !          2581:         } else {
        !          2582:             a = nd_ps[i] = ndv_dup(mod,w[i]);
        !          2583:             if ( mod || !dont_removecont ) ndv_removecont(mod,a);
        !          2584:             if ( !mod ) register_hcf(a);
        !          2585:         }
        !          2586:         NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
        !          2587:         nd_bound[i] = ndv_compute_bound(a);
        !          2588:         nd_psh[i] = r;
        !          2589:         if ( nd_demand ) {
        !          2590:             if ( trace ) {
        !          2591:                 ndv_save(nd_ps_trace[i],i);
        !          2592:                 nd_ps_trace[i] = 0;
        !          2593:             } else {
        !          2594:                 ndv_save(nd_ps[i],i);
        !          2595:                 nd_ps[i] = 0;
        !          2596:             }
        !          2597:         }
        !          2598:     }
1.20      noro     2599: }
                   2600:
1.119     noro     2601: struct order_spec *append_block(struct order_spec *spec,
                   2602:     int nv,int nalg,int ord);
                   2603:
1.121     noro     2604: extern VECT current_dl_weight_vector_obj;
                   2605: static VECT prev_weight_vector_obj;
                   2606:
1.120     noro     2607: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
1.157   ! noro     2608:     struct order_spec **ord1p,LIST *f1p,NODE *alistp)
1.120     noro     2609: {
1.157   ! noro     2610:     NODE alist,t,s,r0,r,arg;
        !          2611:     VL tv;
        !          2612:     P poly;
        !          2613:     DP d;
        !          2614:     Alg alpha,dp;
        !          2615:     DAlg inv,da,hc;
        !          2616:     MP m;
        !          2617:     int i,nvar,nalg,n;
        !          2618:     NumberField nf;
        !          2619:     LIST f1,f2;
        !          2620:     struct order_spec *current_spec;
        !          2621:     VECT obj,obj0;
        !          2622:     Obj tmp;
        !          2623:
        !          2624:     for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
        !          2625:     for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
        !          2626:
        !          2627:     for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
        !          2628:         NEXTNODE(alist,t); MKV(tv->v,poly);
        !          2629:         MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
        !          2630:         tv->v = tv->v->priv;
        !          2631:     }
        !          2632:     NEXT(t) = 0;
        !          2633:
        !          2634:     /* simplification, makeing polynomials monic */
        !          2635:     setfield_dalg(alist);
        !          2636:     obj_algtodalg(f,&f1);
        !          2637:     for ( t = BDY(f); t; t = NEXT(t) ) {
        !          2638:         initd(ord); ptod(vv,vv,(P)BDY(t),&d);
        !          2639:         hc = (DAlg)BDY(d)->c;
        !          2640:         if ( NID(hc) == N_DA ) {
        !          2641:             invdalg(hc,&inv);
        !          2642:             for ( m = BDY(d); m; m = NEXT(m) ) {
        !          2643:                 muldalg(inv,(DAlg)m->c,&da); m->c = (P)da;
        !          2644:             }
        !          2645:         }
        !          2646:         initd(ord); dtop(vv,vv,d,&poly); BDY(f) = (pointer)poly;
        !          2647:     }
        !          2648:     obj_dalgtoalg(f1,&f);
        !          2649:
        !          2650:     /* append alg vars to the var list */
        !          2651:     for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
        !          2652:     NEXT(tv) = av;
        !          2653:
        !          2654:     /* append a block to ord */
        !          2655:     *ord1p = append_block(ord,nvar,nalg,2);
        !          2656:
        !          2657:     /* create generator list */
        !          2658:     nf = get_numberfield();
        !          2659:     for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
        !          2660:         MKAlg(nf->defpoly[i],dp);
        !          2661:         MKNODE(s,dp,t); t = s;
        !          2662:     }
        !          2663:     MKLIST(f1,t);
        !          2664:     *alistp = alist;
        !          2665:     algobjtorat(f1,f1p);
        !          2666:
        !          2667:     /* creating a new weight vector */
        !          2668:     prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
        !          2669:     n = nvar+nalg+1;
        !          2670:     MKVECT(obj,n);
        !          2671:     if ( obj0 && obj0->len == nvar )
        !          2672:         for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
        !          2673:     else
        !          2674:         for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
        !          2675:     for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
        !          2676:     BDY(obj)[n-1] = (pointer)ONE;
        !          2677:     arg = mknode(1,obj);
        !          2678:     Pdp_set_weight(arg,&tmp);
1.121     noro     2679: }
                   2680:
                   2681: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
                   2682: {
1.157   ! noro     2683:     NODE s,t,u0,u;
        !          2684:     P p;
        !          2685:     VL tv;
        !          2686:     Obj obj,tmp;
        !          2687:     NODE arg;
        !          2688:
        !          2689:     u0 = 0;
        !          2690:     for ( t = r; t; t = NEXT(t) ) {
        !          2691:         p = (P)BDY(t);
        !          2692:         for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
        !          2693:             substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
        !          2694:         }
        !          2695:         if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
        !          2696:             NEXTNODE(u0,u);
        !          2697:             BDY(u) = (pointer)p;
        !          2698:         }
        !          2699:     }
        !          2700:     arg = mknode(1,prev_weight_vector_obj);
        !          2701:     Pdp_set_weight(arg,&tmp);
1.121     noro     2702:
1.157   ! noro     2703:     return u0;
1.120     noro     2704: }
                   2705:
1.63      noro     2706: void nd_gr(LIST f,LIST v,int m,int f4,struct order_spec *ord,LIST *rp)
1.1       noro     2707: {
1.157   ! noro     2708:     VL tv,fv,vv,vc,av;
        !          2709:     NODE fd,fd0,r,r0,t,x,s,xx,alist;
        !          2710:     int e,max,nvar,i;
        !          2711:     NDV b;
        !          2712:     int ishomo,nalg,mrank,trank;
        !          2713:     Alg alpha,dp;
        !          2714:     P p,zp;
        !          2715:     Q dmy;
        !          2716:     LIST f1,f2,zpl;
        !          2717:     Obj obj;
        !          2718:     NumberField nf;
        !          2719:     struct order_spec *ord1;
1.1       noro     2720:
1.157   ! noro     2721:     if ( !m && Demand ) nd_demand = 1;
        !          2722:     else nd_demand = 0;
1.78      noro     2723:
1.157   ! noro     2724:     if ( DP_Multiple )
        !          2725:         nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
1.103     noro     2726: #if 0
1.157   ! noro     2727:     ndv_alloc = 0;
1.103     noro     2728: #endif
1.157   ! noro     2729:     get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
        !          2730:     for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
        !          2731:     switch ( ord->id ) {
        !          2732:         case 1:
        !          2733:             if ( ord->nv != nvar )
        !          2734:                 error("nd_{gr,f4} : invalid order specification");
        !          2735:             break;
        !          2736:         default:
        !          2737:             break;
        !          2738:     }
        !          2739:     nd_nalg = 0;
        !          2740:     av = 0;
        !          2741:     if ( !m ) {
        !          2742:         get_algtree((Obj)f,&av);
        !          2743:         for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
        !          2744:         nd_ntrans = nvar;
        !          2745:         nd_nalg = nalg;
        !          2746:         /* #i -> t#i */
        !          2747:         if ( nalg ) {
        !          2748:             preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
        !          2749:             ord = ord1;
        !          2750:             f = f1;
        !          2751:         }
        !          2752:         nvar += nalg;
        !          2753:     }
        !          2754:     nd_init_ord(ord);
        !          2755:     mrank = 0;
        !          2756:     for ( t = BDY(f), max = 0; t; t = NEXT(t) )
        !          2757:         for ( tv = vv; tv; tv = NEXT(tv) ) {
        !          2758:             if ( nd_module ) {
        !          2759:                 s = BDY((LIST)BDY(t));
        !          2760:                 trank = length(s);
        !          2761:                 mrank = MAX(mrank,trank);
        !          2762:                 for ( ; s; s = NEXT(s) ) {
        !          2763:                     e = getdeg(tv->v,(P)BDY(s));
        !          2764:                     max = MAX(e,max);
        !          2765:                 }
        !          2766:             } else {
        !          2767:                 e = getdeg(tv->v,(P)BDY(t));
        !          2768:                 max = MAX(e,max);
        !          2769:             }
        !          2770:         }
        !          2771:     nd_setup_parameters(nvar,max);
        !          2772:     ishomo = 1;
        !          2773:     for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
        !          2774:        if ( nd_module ) {
        !          2775:            pltozpl((LIST)BDY(t),&dmy,&zpl);
        !          2776:             b = (pointer)pltondv(CO,vv,zpl);
        !          2777:         } else {
        !          2778:            ptozp((P)BDY(t),1,&dmy,&zp);
        !          2779:             b = (pointer)ptondv(CO,vv,zp);
        !          2780:        }
        !          2781:         if ( ishomo )
        !          2782:             ishomo = ishomo && ndv_ishomo(b);
        !          2783:         if ( m ) ndv_mod(m,b);
        !          2784:         if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
        !          2785:     }
        !          2786:     if ( fd0 ) NEXT(fd) = 0;
        !          2787:     ndv_setup(m,0,fd0,0,0);
        !          2788:     x = f4?nd_f4(m):nd_gb(m,ishomo,0);
        !          2789:     nd_demand = 0;
        !          2790:     x = ndv_reducebase(x);
        !          2791:     x = ndv_reduceall(m,x);
        !          2792:     for ( r0 = 0, t = x; t; t = NEXT(t) ) {
        !          2793:         NEXTNODE(r0,r);
        !          2794:        if ( nd_module ) BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
        !          2795:         else BDY(r) = ndvtop(m,CO,vv,BDY(t));
        !          2796:     }
        !          2797:     if ( r0 ) NEXT(r) = 0;
        !          2798:     if ( nalg )
        !          2799:         r0 = postprocess_algcoef(av,alist,r0);
        !          2800:     MKLIST(*rp,r0);
1.103     noro     2801: #if 0
1.157   ! noro     2802:     fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
1.103     noro     2803: #endif
1.127     noro     2804: }
                   2805:
                   2806: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
                   2807: {
1.157   ! noro     2808:     VL tv,fv,vv,vc,av;
        !          2809:     NODE fd,fd0,r,r0,t,x,s,xx,alist;
        !          2810:     int e,max,nvar,i;
        !          2811:     NDV b;
        !          2812:     int ishomo,nalg;
        !          2813:     Alg alpha,dp;
        !          2814:     P p,zp;
        !          2815:     Q dmy;
        !          2816:     LIST f1,f2;
        !          2817:     Obj obj;
        !          2818:     NumberField nf;
        !          2819:     struct order_spec *ord1;
        !          2820:
        !          2821:     get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
        !          2822:     for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
        !          2823:     switch ( ord->id ) {
        !          2824:         case 1:
        !          2825:             if ( ord->nv != nvar )
        !          2826:                 error("nd_check : invalid order specification");
        !          2827:             break;
        !          2828:         default:
        !          2829:             break;
        !          2830:     }
        !          2831:     nd_nalg = 0;
        !          2832:     av = 0;
        !          2833:     if ( !m ) {
        !          2834:         get_algtree((Obj)f,&av);
        !          2835:         for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
        !          2836:         nd_ntrans = nvar;
        !          2837:         nd_nalg = nalg;
        !          2838:         /* #i -> t#i */
        !          2839:         if ( nalg ) {
        !          2840:             preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
        !          2841:             ord = ord1;
        !          2842:             f = f1;
        !          2843:         }
        !          2844:         nvar += nalg;
        !          2845:     }
        !          2846:     nd_init_ord(ord);
        !          2847:     for ( t = BDY(f), max = 0; t; t = NEXT(t) )
        !          2848:         for ( tv = vv; tv; tv = NEXT(tv) ) {
        !          2849:             e = getdeg(tv->v,(P)BDY(t));
        !          2850:             max = MAX(e,max);
        !          2851:         }
        !          2852:     nd_setup_parameters(nvar,max);
        !          2853:     ishomo = 1;
        !          2854:     for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
        !          2855:         ptozp((P)BDY(t),1,&dmy,&zp);
        !          2856:         b = (pointer)ptondv(CO,vv,zp);
        !          2857:         if ( ishomo )
        !          2858:             ishomo = ishomo && ndv_ishomo(b);
        !          2859:         if ( m ) ndv_mod(m,b);
        !          2860:         if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
        !          2861:     }
        !          2862:     if ( fd0 ) NEXT(fd) = 0;
        !          2863:     ndv_setup(m,0,fd0,0,1);
        !          2864:     for ( x = 0, i = 0; i < nd_psn; i++ )
        !          2865:         x = update_base(x,i);
        !          2866:     if ( do_check ) {
        !          2867:         x = nd_gb(m,ishomo,1);
        !          2868:         if ( !x ) {
        !          2869:             *rp = 0;
        !          2870:             return;
        !          2871:         }
        !          2872:     } else {
        !          2873:         for ( t = x; t; t = NEXT(t) )
        !          2874:             BDY(t) = (pointer)nd_ps[(int)BDY(t)];
        !          2875:     }
        !          2876:     x = ndv_reducebase(x);
        !          2877:     x = ndv_reduceall(m,x);
        !          2878:     for ( r0 = 0, t = x; t; t = NEXT(t) ) {
        !          2879:         NEXTNODE(r0,r);
        !          2880:         BDY(r) = ndvtop(m,CO,vv,BDY(t));
        !          2881:     }
        !          2882:     if ( r0 ) NEXT(r) = 0;
        !          2883:     if ( nalg )
        !          2884:         r0 = postprocess_algcoef(av,alist,r0);
        !          2885:     MKLIST(*rp,r0);
1.20      noro     2886: }
                   2887:
1.133     noro     2888: void nd_gr_trace(LIST f,LIST v,int trace,int homo,int f4,struct order_spec *ord,LIST *rp)
1.20      noro     2889: {
1.157   ! noro     2890:     VL tv,fv,vv,vc,av;
        !          2891:     NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
        !          2892:     int m,nocheck,nvar,mindex,e,max;
        !          2893:     NDV c;
        !          2894:     NMV a;
        !          2895:     P p,zp;
        !          2896:     Q dmy;
        !          2897:     EPOS oepos;
        !          2898:     int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg;
        !          2899:     Alg alpha,dp;
        !          2900:     P poly;
        !          2901:     LIST f1,f2;
        !          2902:     Obj obj;
        !          2903:     NumberField nf;
        !          2904:     struct order_spec *ord1;
        !          2905:     struct oEGT eg_check,eg0,eg1;
        !          2906:
        !          2907:     if ( DP_Multiple )
        !          2908:         nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
        !          2909:
        !          2910:     get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
        !          2911:     for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
        !          2912:     switch ( ord->id ) {
        !          2913:         case 1:
        !          2914:             if ( ord->nv != nvar )
        !          2915:                 error("nd_gr_trace : invalid order specification");
        !          2916:             break;
        !          2917:         default:
        !          2918:             break;
        !          2919:     }
        !          2920:
        !          2921:     get_algtree((Obj)f,&av);
        !          2922:     for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
        !          2923:     nd_ntrans = nvar;
        !          2924:     nd_nalg = nalg;
        !          2925:     /* #i -> t#i */
        !          2926:     if ( nalg ) {
        !          2927:         preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
        !          2928:         ord = ord1;
        !          2929:         f = f1;
        !          2930:     }
        !          2931:     nvar += nalg;
        !          2932:
        !          2933:     nocheck = 0;
        !          2934:     mindex = 0;
        !          2935:
        !          2936:     if ( Demand ) nd_demand = 1;
        !          2937:     else nd_demand = 0;
        !          2938:
        !          2939:     /* setup modulus */
        !          2940:     if ( trace < 0 ) {
        !          2941:         trace = -trace;
        !          2942:         nocheck = 1;
        !          2943:     }
        !          2944:     m = trace > 1 ? trace : get_lprime(mindex);
        !          2945:     for ( t = BDY(f), max = 0; t; t = NEXT(t) )
        !          2946:         for ( tv = vv; tv; tv = NEXT(tv) ) {
        !          2947:             e = getdeg(tv->v,(P)BDY(t));
        !          2948:             max = MAX(e,max);
        !          2949:         }
        !          2950:     nd_init_ord(ord);
        !          2951:     nd_setup_parameters(nvar,max);
        !          2952:     obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos;
        !          2953:     ishomo = 1;
        !          2954:     for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
        !          2955:         ptozp((P)BDY(t),1,&dmy,&zp);
        !          2956:         c = (pointer)ptondv(CO,vv,zp);
        !          2957:         if ( ishomo )
        !          2958:             ishomo = ishomo && ndv_ishomo(c);
        !          2959:         if ( c ) {
        !          2960:             NEXTNODE(in0,in); BDY(in) = (pointer)c;
        !          2961:             NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
        !          2962:         }
        !          2963:     }
        !          2964:     if ( in0 ) NEXT(in) = 0;
        !          2965:     if ( fd0 ) NEXT(fd) = 0;
        !          2966:     if ( !ishomo && homo ) {
        !          2967:         for ( t = in0, wmax = max; t; t = NEXT(t) ) {
        !          2968:             c = (NDV)BDY(t); len = LEN(c);
        !          2969:             for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
        !          2970:                 wmax = MAX(TD(DL(a)),wmax);
        !          2971:         }
        !          2972:         homogenize_order(ord,nvar,&ord1);
        !          2973:         nd_init_ord(ord1);
        !          2974:         nd_setup_parameters(nvar+1,wmax);
        !          2975:         for ( t = fd0; t; t = NEXT(t) )
        !          2976:             ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos);
        !          2977:     }
        !          2978:     while ( 1 ) {
        !          2979:         if ( Demand )
        !          2980:             nd_demand = 1;
        !          2981:         ndv_setup(m,1,fd0,0,0);
        !          2982:         cand = f4?nd_f4_trace(m):nd_gb_trace(m,ishomo || homo);
        !          2983:         if ( !cand ) {
        !          2984:             /* failure */
        !          2985:             if ( trace > 1 ) { *rp = 0; return; }
        !          2986:             else m = get_lprime(++mindex);
        !          2987:             continue;
        !          2988:         }
        !          2989:         if ( !ishomo && homo ) {
        !          2990:             /* dehomogenization */
        !          2991:             for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
        !          2992:             nd_init_ord(ord);
        !          2993:             nd_setup_parameters(nvar,0);
        !          2994:         }
        !          2995:         nd_demand = 0;
        !          2996:         cand = ndv_reducebase(cand);
        !          2997:         cand = ndv_reduceall(0,cand);
        !          2998:         cbpe = nd_bpe;
        !          2999:         if ( nocheck )
        !          3000:             break;
        !          3001:         get_eg(&eg0);
        !          3002:         if ( ndv_check_candidate(in0,obpe,oadv,oepos,cand) )
        !          3003:             /* success */
        !          3004:             break;
        !          3005:         else if ( trace > 1 ) {
        !          3006:             /* failure */
        !          3007:             *rp = 0; return;
        !          3008:         } else {
        !          3009:             /* try the next modulus */
        !          3010:             m = get_lprime(++mindex);
        !          3011:             /* reset the parameters */
        !          3012:             if ( !ishomo && homo ) {
        !          3013:                 nd_init_ord(ord1);
        !          3014:                 nd_setup_parameters(nvar+1,wmax);
        !          3015:             } else {
        !          3016:                 nd_init_ord(ord);
        !          3017:                 nd_setup_parameters(nvar,max);
        !          3018:             }
        !          3019:         }
        !          3020:     }
        !          3021:     get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
        !          3022:     if ( DP_Print )
        !          3023:         fprintf(asir_out,"check=%fsec\n",eg_check.exectime+eg_check.gctime);
        !          3024:     /* dp->p */
        !          3025:     nd_bpe = cbpe;
        !          3026:     nd_setup_parameters(nd_nvar,0);
        !          3027:     for ( r = cand; r; r = NEXT(r) )
        !          3028:         BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
        !          3029:     if ( nalg )
        !          3030:         cand = postprocess_algcoef(av,alist,cand);
        !          3031:     MKLIST(*rp,cand);
        !          3032: }
1.52      noro     3033:
1.157   ! noro     3034: /* XXX : module element is not considered  */
1.1       noro     3035:
1.61      noro     3036: void dltondl(int n,DL dl,UINT *r)
1.1       noro     3037: {
1.157   ! noro     3038:     UINT *d;
        !          3039:     int i,j,l,s,ord_l;
        !          3040:     struct order_pair *op;
        !          3041:
        !          3042:     d = dl->d;
        !          3043:     for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
        !          3044:     if ( nd_blockmask ) {
        !          3045:         l = nd_blockmask->n;
        !          3046:         op = nd_blockmask->order_pair;
        !          3047:         for ( j = 0, s = 0; j < l; j++ ) {
        !          3048:             ord_l = op[j].length;
        !          3049:             for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
        !          3050:         }
        !          3051:         TD(r) = ndl_weight(r);
        !          3052:         ndl_weight_mask(r);
        !          3053:     } else {
        !          3054:         for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
        !          3055:         TD(r) = ndl_weight(r);
        !          3056:     }
1.1       noro     3057: }
                   3058:
1.61      noro     3059: DL ndltodl(int n,UINT *ndl)
1.1       noro     3060: {
1.157   ! noro     3061:     DL dl;
        !          3062:     int *d;
        !          3063:     int i,j,l,s,ord_l;
        !          3064:     struct order_pair *op;
        !          3065:
        !          3066:     NEWDL(dl,n);
        !          3067:     dl->td = TD(ndl);
        !          3068:     d = dl->d;
        !          3069:     if ( nd_blockmask ) {
        !          3070:         l = nd_blockmask->n;
        !          3071:         op = nd_blockmask->order_pair;
        !          3072:         for ( j = 0, s = 0; j < l; j++ ) {
        !          3073:             ord_l = op[j].length;
        !          3074:             for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
        !          3075:         }
        !          3076:     } else {
        !          3077:         for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
        !          3078:     }
        !          3079:     return dl;
1.1       noro     3080: }
                   3081:
1.61      noro     3082: void ndl_print(UINT *dl)
1.1       noro     3083: {
1.157   ! noro     3084:     int n;
        !          3085:     int i,j,l,ord_l,s,s0;
        !          3086:     struct order_pair *op;
        !          3087:
        !          3088:     n = nd_nvar;
        !          3089:     printf("<<");
        !          3090:     if ( nd_blockmask ) {
        !          3091:         l = nd_blockmask->n;
        !          3092:         op = nd_blockmask->order_pair;
        !          3093:         for ( j = 0, s = s0 = 0; j < l; j++ ) {
        !          3094:             ord_l = op[j].length;
        !          3095:             for ( i = 0; i < ord_l; i++, s++ )
        !          3096:                 printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
        !          3097:         }
        !          3098:     } else {
        !          3099:         for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
        !          3100:     }
        !          3101:     printf(">>");
        !          3102:     if ( MPOS(dl) )
        !          3103:         printf("*e%d",MPOS(dl));
1.1       noro     3104: }
                   3105:
                   3106: void nd_print(ND p)
                   3107: {
1.157   ! noro     3108:     NM m;
1.1       noro     3109:
1.157   ! noro     3110:     if ( !p )
        !          3111:         printf("0\n");
        !          3112:     else {
        !          3113:         for ( m = BDY(p); m; m = NEXT(m) ) {
        !          3114:             if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
        !          3115:             else printf("+%d*",CM(m));
        !          3116:             ndl_print(DL(m));
        !          3117:         }
        !          3118:         printf("\n");
        !          3119:     }
1.1       noro     3120: }
                   3121:
1.113     noro     3122: void nd_print_q(ND p)
1.16      noro     3123: {
1.157   ! noro     3124:     NM m;
1.16      noro     3125:
1.157   ! noro     3126:     if ( !p )
        !          3127:         printf("0\n");
        !          3128:     else {
        !          3129:         for ( m = BDY(p); m; m = NEXT(m) ) {
        !          3130:             printf("+");
        !          3131:             printexpr(CO,(Obj)CQ(m));
        !          3132:             printf("*");
        !          3133:             ndl_print(DL(m));
        !          3134:         }
        !          3135:         printf("\n");
        !          3136:     }
1.16      noro     3137: }
                   3138:
1.1       noro     3139: void ndp_print(ND_pairs d)
                   3140: {
1.157   ! noro     3141:     ND_pairs t;
1.1       noro     3142:
1.157   ! noro     3143:     for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
        !          3144:     printf("\n");
1.1       noro     3145: }
                   3146:
1.20      noro     3147: void nd_removecont(int mod,ND p)
1.16      noro     3148: {
1.157   ! noro     3149:     int i,n;
        !          3150:     Q *w;
        !          3151:     Q dvr,t;
        !          3152:     NM m;
        !          3153:     struct oVECT v;
        !          3154:     N q,r;
        !          3155:
        !          3156:     if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
        !          3157:     else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
        !          3158:     else {
        !          3159:         for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
        !          3160:         w = (Q *)ALLOCA(n*sizeof(Q));
        !          3161:         v.len = n;
        !          3162:         v.body = (pointer *)w;
        !          3163:         for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CQ(m);
        !          3164:         removecont_array((P *)w,n,1);
        !          3165:         for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CQ(m) = w[i];
        !          3166:     }
1.16      noro     3167: }
                   3168:
1.21      noro     3169: void nd_removecont2(ND p1,ND p2)
                   3170: {
1.157   ! noro     3171:     int i,n1,n2,n;
        !          3172:     Q *w;
        !          3173:     Q dvr,t;
        !          3174:     NM m;
        !          3175:     struct oVECT v;
        !          3176:     N q,r;
        !          3177:
        !          3178:     n1 = nd_length(p1);
        !          3179:     n2 = nd_length(p2);
        !          3180:     n = n1+n2;
        !          3181:     w = (Q *)ALLOCA(n*sizeof(Q));
        !          3182:     v.len = n;
        !          3183:     v.body = (pointer *)w;
        !          3184:     i = 0;
        !          3185:     if ( p1 )
        !          3186:         for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CQ(m);
        !          3187:     if ( p2 )
        !          3188:         for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CQ(m);
        !          3189:     removecont_array((P *)w,n,1);
        !          3190:     i = 0;
        !          3191:     if ( p1 )
        !          3192:         for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CQ(m) = w[i];
        !          3193:     if ( p2 )
        !          3194:         for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CQ(m) = w[i];
1.21      noro     3195: }
                   3196:
1.20      noro     3197: void ndv_removecont(int mod,NDV p)
1.16      noro     3198: {
1.157   ! noro     3199:     int i,len,all_p;
        !          3200:     Q *c;
        !          3201:     P *w;
        !          3202:     Q dvr,t;
        !          3203:     P g,cont,tp;
        !          3204:     NMV m;
        !          3205:
        !          3206:     if ( mod == -1 )
        !          3207:         ndv_mul_c(mod,p,_invsf(HCM(p)));
        !          3208:     else if ( mod )
        !          3209:         ndv_mul_c(mod,p,invm(HCM(p),mod));
        !          3210:     else {
        !          3211:         len = p->len;
        !          3212:         w = (P *)ALLOCA(len*sizeof(P));
        !          3213:         c = (Q *)ALLOCA(len*sizeof(Q));
        !          3214:         for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
        !          3215:             ptozp(CP(m),1,&c[i],&w[i]);
        !          3216:             all_p = all_p && !NUM(w[i]);
        !          3217:         }
        !          3218:         if ( all_p ) {
        !          3219:             qltozl(c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
        !          3220:             mulp(nd_vc,(P)dvr,g,&cont);
        !          3221:             for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
        !          3222:                 divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
        !          3223:             }
        !          3224:         } else {
        !          3225:             sortbynm((Q *)c,len);
        !          3226:             qltozl((Q *)c,len,&dvr);
        !          3227:             for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
        !          3228:                 divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
        !          3229:             }
        !          3230:         }
        !          3231:     }
1.21      noro     3232: }
                   3233:
1.157   ! noro     3234: /* koko */
        !          3235:
1.61      noro     3236: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos)
                   3237: {
1.157   ! noro     3238:     int len,i,max;
        !          3239:     NMV m,mr0,mr,t;
1.61      noro     3240:
1.157   ! noro     3241:     len = p->len;
        !          3242:     for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
        !          3243:         max = MAX(max,TD(DL(m)));
        !          3244:     mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
        !          3245:     m = (NMV)((char *)mr0+(len-1)*oadv);
        !          3246:     mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
        !          3247:     t = (NMV)ALLOCA(nmv_adv);
        !          3248:     for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
        !          3249:         ndl_homogenize(DL(m),DL(t),obpe,oepos,max);
        !          3250:         CQ(mr) = CQ(m);
        !          3251:         ndl_copy(DL(t),DL(mr));
        !          3252:     }
        !          3253:     NV(p)++;
        !          3254:     BDY(p) = mr0;
1.61      noro     3255: }
                   3256:
1.45      noro     3257: void ndv_dehomogenize(NDV p,struct order_spec *ord)
1.23      noro     3258: {
1.157   ! noro     3259:     int i,j,adj,len,newnvar,newwpd,newadv,newexporigin;
        !          3260:     Q *w;
        !          3261:     Q dvr,t;
        !          3262:     NMV m,r;
        !          3263:
        !          3264:     len = p->len;
        !          3265:     newnvar = nd_nvar-1;
        !          3266:     newexporigin = nd_get_exporigin(ord);
        !          3267:     newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
        !          3268:     for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
        !          3269:         ndl_dehomogenize(DL(m));
        !          3270:     if ( newwpd != nd_wpd ) {
        !          3271:         newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
        !          3272:         for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
        !          3273:             CQ(r) = CQ(m);
        !          3274:             for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
        !          3275:             adj = nd_exporigin-newexporigin;
        !          3276:             for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
        !          3277:         }
        !          3278:     }
        !          3279:     NV(p)--;
1.23      noro     3280: }
                   3281:
1.150     noro     3282: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
                   3283: {
1.157   ! noro     3284:     int i;
        !          3285:     P *tpl,*tpl1;
        !          3286:     NODE l;
        !          3287:     P h,gcd,t;
        !          3288:
        !          3289:     tpl = (P *)ALLOCA(m*sizeof(P));
        !          3290:     tpl1 = (P *)ALLOCA(m*sizeof(P));
        !          3291:     bcopy(pl,tpl,m*sizeof(P));
        !          3292:     gcd = (P)ONE;
        !          3293:     for ( l = nd_hcf; l; l = NEXT(l) ) {
        !          3294:         h = (P)BDY(l);
        !          3295:         while ( 1 ) {
        !          3296:             for ( i = 0; i < m; i++ )
        !          3297:                 if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
        !          3298:                     break;
        !          3299:             if ( i == m ) {
        !          3300:                 bcopy(tpl1,tpl,m*sizeof(P));
        !          3301:                 mulp(vl,gcd,h,&t); gcd = t;
        !          3302:             } else
        !          3303:                 break;
        !          3304:         }
        !          3305:     }
        !          3306:     if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
        !          3307:     if ( full ) {
        !          3308:         heu_nezgcdnpz(vl,tpl,m,&t);
        !          3309:         mulp(vl,gcd,t,pr);
        !          3310:     } else
        !          3311:         *pr = gcd;
1.150     noro     3312: }
                   3313:
                   3314: void removecont_array(P *p,int n,int full)
1.146     noro     3315: {
1.157   ! noro     3316:     int all_p,all_q,i;
        !          3317:     Q *c;
        !          3318:     P *w;
        !          3319:     P t,s;
        !          3320:
        !          3321:     for ( all_q = 1, i = 0; i < n; i++ )
        !          3322:         all_q = all_q && NUM(p[i]);
        !          3323:     if ( all_q ) {
        !          3324:         removecont_array_q((Q *)p,n);
        !          3325:     } else {
        !          3326:         c = (Q *)ALLOCA(n*sizeof(Q));
        !          3327:         w = (P *)ALLOCA(n*sizeof(P));
        !          3328:         for ( i = 0; i < n; i++ ) {
        !          3329:             ptozp(p[i],1,&c[i],&w[i]);
        !          3330:         }
        !          3331:         removecont_array_q(c,n);
        !          3332:         nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
        !          3333:         for ( i = 0; i < n; i++ ) {
        !          3334:             divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
        !          3335:         }
        !          3336:     }
1.146     noro     3337: }
                   3338:
                   3339: void removecont_array_q(Q *c,int n)
1.21      noro     3340: {
1.157   ! noro     3341:     struct oVECT v;
        !          3342:     Q d0,d1,a,u,u1,gcd;
        !          3343:     int i,j;
        !          3344:     N qn,rn,gn;
        !          3345:     Q *q,*r;
        !          3346:
        !          3347:     q = (Q *)ALLOCA(n*sizeof(Q));
        !          3348:     r = (Q *)ALLOCA(n*sizeof(Q));
        !          3349:     v.id = O_VECT; v.len = n; v.body = (pointer *)c;
        !          3350:     igcdv_estimate(&v,&d0);
        !          3351:     for ( i = 0; i < n; i++ ) {
        !          3352:         divn(NM(c[i]),NM(d0),&qn,&rn);
        !          3353:         NTOQ(qn,SGN(c[i])*SGN(d0),q[i]);
        !          3354:         NTOQ(rn,SGN(c[i]),r[i]);
        !          3355:     }
        !          3356:     for ( i = 0; i < n; i++ ) if ( r[i] ) break;
        !          3357:     if ( i < n ) {
        !          3358:         v.id = O_VECT; v.len = n; v.body = (pointer *)r;
        !          3359:         igcdv(&v,&d1);
        !          3360:         gcdn(NM(d0),NM(d1),&gn); NTOQ(gn,1,gcd);
        !          3361:         divsn(NM(d0),gn,&qn); NTOQ(qn,1,a);
        !          3362:         for ( i = 0; i < n; i++ ) {
        !          3363:             mulq(a,q[i],&u);
        !          3364:             if ( r[i] ) {
        !          3365:                 divsn(NM(r[i]),gn,&qn); NTOQ(qn,SGN(r[i]),u1);
        !          3366:                 addq(u,u1,&q[i]);
        !          3367:             } else
        !          3368:                 q[i] = u;
        !          3369:         }
        !          3370:     }
        !          3371:     for ( i = 0; i < n; i++ ) c[i] = q[i];
1.16      noro     3372: }
                   3373:
1.19      noro     3374: void nd_mul_c(int mod,ND p,int mul)
1.1       noro     3375: {
1.157   ! noro     3376:     NM m;
        !          3377:     int c,c1;
1.1       noro     3378:
1.157   ! noro     3379:     if ( !p ) return;
        !          3380:     if ( mul == 1 ) return;
        !          3381:     if ( mod == -1 )
        !          3382:         for ( m = BDY(p); m; m = NEXT(m) )
        !          3383:             CM(m) = _mulsf(CM(m),mul);
        !          3384:     else
        !          3385:         for ( m = BDY(p); m; m = NEXT(m) ) {
        !          3386:             c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
        !          3387:         }
1.1       noro     3388: }
                   3389:
1.146     noro     3390: void nd_mul_c_q(ND p,P mul)
1.16      noro     3391: {
1.157   ! noro     3392:     NM m;
        !          3393:     P c;
1.16      noro     3394:
1.157   ! noro     3395:     if ( !p ) return;
        !          3396:     if ( UNIQ(mul) ) return;
        !          3397:     for ( m = BDY(p); m; m = NEXT(m) ) {
        !          3398:         mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
        !          3399:     }
1.16      noro     3400: }
                   3401:
1.61      noro     3402: void nd_mul_c_p(VL vl,ND p,P mul)
                   3403: {
1.157   ! noro     3404:     NM m;
        !          3405:     P c;
1.61      noro     3406:
1.157   ! noro     3407:     if ( !p ) return;
        !          3408:     for ( m = BDY(p); m; m = NEXT(m) ) {
        !          3409:         mulp(vl,CP(m),mul,&c); CP(m) = c;
        !          3410:     }
1.61      noro     3411: }
                   3412:
1.1       noro     3413: void nd_free(ND p)
                   3414: {
1.157   ! noro     3415:     NM t,s;
1.1       noro     3416:
1.157   ! noro     3417:     if ( !p ) return;
        !          3418:     t = BDY(p);
        !          3419:     while ( t ) {
        !          3420:         s = NEXT(t);
        !          3421:         FREENM(t);
        !          3422:         t = s;
        !          3423:     }
        !          3424:     FREEND(p);
1.1       noro     3425: }
                   3426:
1.23      noro     3427: void ndv_free(NDV p)
                   3428: {
1.157   ! noro     3429:     GC_free(BDY(p));
1.23      noro     3430: }
                   3431:
1.61      noro     3432: void nd_append_red(UINT *d,int i)
1.1       noro     3433: {
1.157   ! noro     3434:     RHist m,m0;
        !          3435:     int h;
1.1       noro     3436:
1.157   ! noro     3437:     NEWRHist(m);
        !          3438:     h = ndl_hash_value(d);
        !          3439:     m->index = i;
        !          3440:     ndl_copy(d,DL(m));
        !          3441:     NEXT(m) = nd_red[h];
        !          3442:     nd_red[h] = m;
1.1       noro     3443: }
                   3444:
1.61      noro     3445: UINT *ndv_compute_bound(NDV p)
1.1       noro     3446: {
1.157   ! noro     3447:     UINT *d1,*d2,*t;
        !          3448:     UINT u;
        !          3449:     int i,j,k,l,len,ind;
        !          3450:     NMV m;
        !          3451:
        !          3452:     if ( !p )
        !          3453:         return 0;
        !          3454:     d1 = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          3455:     d2 = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          3456:     len = LEN(p);
        !          3457:     m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
        !          3458:     for ( i = 1; i < len; i++, NMV_ADV(m) ) {
        !          3459:         ndl_lcm_nocheck(DL(m),d1,d2);
        !          3460:         t = d1; d1 = d2; d2 = t;
        !          3461:     }
        !          3462:     l = nd_nvar+31;
        !          3463:     t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
        !          3464:     for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
        !          3465:         u = d1[i];
        !          3466:         k = (nd_epw-1)*nd_bpe;
        !          3467:         for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
        !          3468:             t[ind] = (u>>k)&nd_mask0;
        !          3469:     }
        !          3470:     for ( ; ind < l; ind++ ) t[ind] = 0;
        !          3471:     return t;
1.1       noro     3472: }
                   3473:
1.99      noro     3474: UINT *nd_compute_bound(ND p)
                   3475: {
1.157   ! noro     3476:     UINT *d1,*d2,*t;
        !          3477:     UINT u;
        !          3478:     int i,j,k,l,len,ind;
        !          3479:     NM m;
        !          3480:
        !          3481:     if ( !p )
        !          3482:         return 0;
        !          3483:     d1 = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          3484:     d2 = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          3485:     len = LEN(p);
        !          3486:     m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
        !          3487:     for ( m = NEXT(m); m; m = NEXT(m) ) {
        !          3488:         ndl_lcm(DL(m),d1,d2);
        !          3489:         t = d1; d1 = d2; d2 = t;
        !          3490:     }
        !          3491:     l = nd_nvar+31;
        !          3492:     t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
        !          3493:     for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
        !          3494:         u = d1[i];
        !          3495:         k = (nd_epw-1)*nd_bpe;
        !          3496:         for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
        !          3497:             t[ind] = (u>>k)&nd_mask0;
        !          3498:     }
        !          3499:     for ( ; ind < l; ind++ ) t[ind] = 0;
        !          3500:     return t;
1.99      noro     3501: }
                   3502:
1.157   ! noro     3503: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
        !          3504: /* of a term. In this case we need additional 1 word. */
        !          3505:
1.48      noro     3506: int nd_get_exporigin(struct order_spec *ord)
                   3507: {
1.157   ! noro     3508:     switch ( ord->id ) {
        !          3509:         case 0: case 2: case 256: case 258:
        !          3510:             return 1+nd_module;
        !          3511:         case 1: case 257:
        !          3512:             /* block order */
        !          3513:             /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
        !          3514:             /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
        !          3515:             return ord->ord.block.length+1+nd_module;
        !          3516:         case 3: case 259:
        !          3517:             error("nd_get_exporigin : composite order is not supported yet.");
        !          3518:     }
1.48      noro     3519: }
                   3520:
1.61      noro     3521: void nd_setup_parameters(int nvar,int max) {
1.157   ! noro     3522:     int i,j,n,elen,ord_o,ord_l,l,s,wpd;
        !          3523:     struct order_pair *op;
1.48      noro     3524:
1.157   ! noro     3525:     nd_nvar = nvar;
        !          3526:     if ( max ) {
        !          3527:         /* XXX */
        !          3528:         if ( do_weyl ) nd_bpe = 32;
        !          3529:         else if ( max < 2 ) nd_bpe = 1;
        !          3530:         else if ( max < 4 ) nd_bpe = 2;
        !          3531:         else if ( max < 8 ) nd_bpe = 3;
        !          3532:         else if ( max < 16 ) nd_bpe = 4;
        !          3533:         else if ( max < 32 ) nd_bpe = 5;
        !          3534:         else if ( max < 64 ) nd_bpe = 6;
        !          3535:         else if ( max < 256 ) nd_bpe = 8;
        !          3536:         else if ( max < 1024 ) nd_bpe = 10;
        !          3537:         else if ( max < 65536 ) nd_bpe = 16;
        !          3538:         else nd_bpe = 32;
        !          3539:     }
        !          3540:     nd_epw = (sizeof(UINT)*8)/nd_bpe;
        !          3541:     elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
        !          3542:     nd_exporigin = nd_get_exporigin(nd_ord);
        !          3543:     wpd = nd_exporigin+elen;
        !          3544:     if ( nd_module )
        !          3545:         nd_mpos = nd_exporigin-1;
        !          3546:     else
        !          3547:         nd_mpos = -1;
        !          3548:     if ( wpd != nd_wpd ) {
        !          3549:         nd_free_private_storage();
        !          3550:         nd_wpd = wpd;
        !          3551:     }
        !          3552:     if ( nd_bpe < 32 ) {
        !          3553:         nd_mask0 = (1<<nd_bpe)-1;
        !          3554:     } else {
        !          3555:         nd_mask0 = 0xffffffff;
        !          3556:     }
        !          3557:     bzero(nd_mask,sizeof(nd_mask));
        !          3558:     nd_mask1 = 0;
        !          3559:     for ( i = 0; i < nd_epw; i++ ) {
        !          3560:         nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
        !          3561:         nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
        !          3562:     }
        !          3563:     nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
        !          3564:     nd_epos = nd_create_epos(nd_ord);
        !          3565:     nd_blockmask = nd_create_blockmask(nd_ord);
        !          3566:     nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
1.1       noro     3567: }
                   3568:
1.103     noro     3569: ND_pairs nd_reconstruct(int trace,ND_pairs d)
1.1       noro     3570: {
1.157   ! noro     3571:     int i,obpe,oadv,h;
        !          3572:     static NM prev_nm_free_list;
        !          3573:     static ND_pairs prev_ndp_free_list;
        !          3574:     RHist mr0,mr;
        !          3575:     RHist r;
        !          3576:     RHist *old_red;
        !          3577:     ND_pairs s0,s,t;
        !          3578:     EPOS oepos;
        !          3579:
        !          3580:     obpe = nd_bpe;
        !          3581:     oadv = nmv_adv;
        !          3582:     oepos = nd_epos;
        !          3583:     if ( obpe < 2 ) nd_bpe = 2;
        !          3584:     else if ( obpe < 3 ) nd_bpe = 3;
        !          3585:     else if ( obpe < 4 ) nd_bpe = 4;
        !          3586:     else if ( obpe < 5 ) nd_bpe = 5;
        !          3587:     else if ( obpe < 6 ) nd_bpe = 6;
        !          3588:     else if ( obpe < 8 ) nd_bpe = 8;
        !          3589:     else if ( obpe < 10 ) nd_bpe = 10;
        !          3590:     else if ( obpe < 16 ) nd_bpe = 16;
        !          3591:     else if ( obpe < 32 ) nd_bpe = 32;
        !          3592:     else error("nd_reconstruct : exponent too large");
        !          3593:
        !          3594:     nd_setup_parameters(nd_nvar,0);
        !          3595:     prev_nm_free_list = _nm_free_list;
        !          3596:     prev_ndp_free_list = _ndp_free_list;
        !          3597:     _nm_free_list = 0;
        !          3598:     _ndp_free_list = 0;
        !          3599:     for ( i = nd_psn-1; i >= 0; i-- ) ndv_realloc(nd_ps[i],obpe,oadv,oepos);
        !          3600:     if ( trace )
        !          3601:         for ( i = nd_psn-1; i >= 0; i-- )
        !          3602:             ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
        !          3603:     s0 = 0;
        !          3604:     for ( t = d; t; t = NEXT(t) ) {
        !          3605:         NEXTND_pairs(s0,s);
        !          3606:         s->i1 = t->i1;
        !          3607:         s->i2 = t->i2;
        !          3608:         SG(s) = SG(t);
        !          3609:         ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
        !          3610:     }
        !          3611:
        !          3612:     old_red = (RHist *)ALLOCA(REDTAB_LEN*sizeof(RHist));
        !          3613:     for ( i = 0; i < REDTAB_LEN; i++ ) {
        !          3614:         old_red[i] = nd_red[i];
        !          3615:         nd_red[i] = 0;
        !          3616:     }
        !          3617:     for ( i = 0; i < REDTAB_LEN; i++ )
        !          3618:         for ( r = old_red[i]; r; r = NEXT(r) ) {
        !          3619:             NEWRHist(mr);
        !          3620:             mr->index = r->index;
        !          3621:             SG(mr) = SG(r);
        !          3622:             ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
        !          3623:             h = ndl_hash_value(DL(mr));
        !          3624:             NEXT(mr) = nd_red[h];
        !          3625:             nd_red[h] = mr;
        !          3626:         }
        !          3627:     for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
        !          3628:     old_red = 0;
        !          3629:     for ( i = 0; i < nd_psn; i++ ) {
        !          3630:         NEWRHist(r); SG(r) = SG(nd_psh[i]);
        !          3631:         ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
        !          3632:         nd_psh[i] = r;
        !          3633:     }
        !          3634:     if ( s0 ) NEXT(s) = 0;
        !          3635:     prev_nm_free_list = 0;
        !          3636:     prev_ndp_free_list = 0;
1.71      noro     3637: #if 0
1.157   ! noro     3638:     GC_gcollect();
1.71      noro     3639: #endif
1.157   ! noro     3640:     return s0;
1.1       noro     3641: }
                   3642:
1.61      noro     3643: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
1.1       noro     3644: {
1.157   ! noro     3645:     int n,i,ei,oepw,omask0,j,s,ord_l,l;
        !          3646:     struct order_pair *op;
1.1       noro     3647:
1.157   ! noro     3648:     n = nd_nvar;
        !          3649:     oepw = (sizeof(UINT)*8)/obpe;
        !          3650:     omask0 = (1<<obpe)-1;
        !          3651:     TD(r) = TD(d);
        !          3652:     for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
        !          3653:     if ( nd_blockmask ) {
        !          3654:         l = nd_blockmask->n;
        !          3655:         op = nd_blockmask->order_pair;
        !          3656:         for ( i = 1; i < nd_exporigin; i++ )
        !          3657:             r[i] = d[i];
        !          3658:         for ( j = 0, s = 0; j < l; j++ ) {
        !          3659:             ord_l = op[j].length;
        !          3660:             for ( i = 0; i < ord_l; i++, s++ ) {
        !          3661:                 ei =  GET_EXP_OLD(d,s);
        !          3662:                 PUT_EXP(r,s,ei);
        !          3663:             }
        !          3664:         }
        !          3665:     } else {
        !          3666:         for ( i = 0; i < n; i++ ) {
        !          3667:             ei = GET_EXP_OLD(d,i);
        !          3668:             PUT_EXP(r,i,ei);
        !          3669:         }
        !          3670:     }
        !          3671:     if ( nd_module ) MPOS(r) = MPOS(d);
1.1       noro     3672: }
1.3       noro     3673:
1.6       noro     3674: ND nd_copy(ND p)
                   3675: {
1.157   ! noro     3676:     NM m,mr,mr0;
        !          3677:     int c,n;
        !          3678:     ND r;
        !          3679:
        !          3680:     if ( !p )
        !          3681:         return 0;
        !          3682:     else {
        !          3683:         for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
        !          3684:             NEXTNM(mr0,mr);
        !          3685:             CM(mr) = CM(m);
        !          3686:             ndl_copy(DL(m),DL(mr));
        !          3687:         }
        !          3688:         NEXT(mr) = 0;
        !          3689:         MKND(NV(p),mr0,LEN(p),r);
        !          3690:         SG(r) = SG(p);
        !          3691:         return r;
        !          3692:     }
1.6       noro     3693: }
                   3694:
1.53      noro     3695: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
1.11      noro     3696: {
1.157   ! noro     3697:     NM m1,m2;
        !          3698:     NDV p1,p2;
        !          3699:     ND t1,t2;
        !          3700:     UINT *lcm;
        !          3701:     P gp,tp;
        !          3702:     Q g,t;
        !          3703:     int td;
        !          3704:
        !          3705:     if ( !mod && nd_demand ) {
        !          3706:         p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
        !          3707:     } else {
        !          3708:         if ( trace ) {
        !          3709:             p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
        !          3710:         } else {
        !          3711:             p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
        !          3712:         }
        !          3713:     }
        !          3714:     lcm = LCM(p);
        !          3715:     NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
        !          3716:     if ( ndl_check_bound2(p->i1,DL(m1)) ) {
        !          3717:         FREENM(m1); return 0;
        !          3718:     }
        !          3719:     NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
        !          3720:     if ( ndl_check_bound2(p->i2,DL(m2)) ) {
        !          3721:         FREENM(m1); FREENM(m2); return 0;
        !          3722:     }
        !          3723:
        !          3724:     if ( mod == -1 ) {
        !          3725:         CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
        !          3726:     } else if ( mod ) {
        !          3727:         CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
        !          3728:     } else if ( nd_vc ) {
        !          3729:         ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
        !          3730:         divsp(nd_vc,HCP(p2),gp,&CP(m1));
        !          3731:         divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
        !          3732:     } else {
        !          3733:         igcd_cofactor(HCQ(p1),HCQ(p2),&g,&t,&CQ(m1)); chsgnq(t,&CQ(m2));
        !          3734:     }
        !          3735:     t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
        !          3736:     *rp = nd_add(mod,t1,t2);
        !          3737:     FREENM(m1); FREENM(m2);
        !          3738:     return 1;
1.11      noro     3739: }
                   3740:
1.19      noro     3741: void ndv_mul_c(int mod,NDV p,int mul)
1.11      noro     3742: {
1.157   ! noro     3743:     NMV m;
        !          3744:     int c,c1,len,i;
1.11      noro     3745:
1.157   ! noro     3746:     if ( !p ) return;
        !          3747:     len = LEN(p);
        !          3748:     if ( mod == -1 )
        !          3749:         for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
        !          3750:             CM(m) = _mulsf(CM(m),mul);
        !          3751:     else
        !          3752:         for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3753:             c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
        !          3754:         }
1.11      noro     3755: }
                   3756:
1.113     noro     3757: void ndv_mul_c_q(NDV p,Q mul)
1.16      noro     3758: {
1.157   ! noro     3759:     NMV m;
        !          3760:     Q c;
        !          3761:     int len,i;
        !          3762:
        !          3763:     if ( !p ) return;
        !          3764:     len = LEN(p);
        !          3765:     for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3766:         mulq(CQ(m),mul,&c); CQ(m) = c;
        !          3767:     }
1.16      noro     3768: }
                   3769:
1.55      noro     3770: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
1.157   ! noro     3771:     int n2,i,j,l,n,tlen;
        !          3772:     UINT *d0;
        !          3773:     NM *tab,*psum;
        !          3774:     ND s,r;
        !          3775:     NM t;
        !          3776:     NMV m1;
        !          3777:
        !          3778:     if ( !p ) return 0;
        !          3779:     n = NV(p); n2 = n>>1;
        !          3780:     d0 = DL(m0);
        !          3781:     l = LEN(p);
        !          3782:     for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
        !          3783:     tab = (NM *)ALLOCA(tlen*sizeof(NM));
        !          3784:     psum = (NM *)ALLOCA(tlen*sizeof(NM));
        !          3785:     for ( i = 0; i < tlen; i++ ) psum[i] = 0;
        !          3786:     m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
        !          3787:     for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
        !          3788:         /* m0(NM) * m1(NMV) => tab(NM) */
        !          3789:         weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
        !          3790:         for ( j = 0; j < tlen; j++ ) {
        !          3791:             if ( tab[j] ) {
        !          3792:                 NEXT(tab[j]) = psum[j];    psum[j] = tab[j];
        !          3793:             }
        !          3794:         }
        !          3795:     }
        !          3796:     for ( i = tlen-1, r = 0; i >= 0; i-- )
        !          3797:         if ( psum[i] ) {
        !          3798:             for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
        !          3799:             MKND(n,psum[i],j,s);
        !          3800:             r = nd_add(mod,r,s);
        !          3801:         }
        !          3802:     if ( r ) SG(r) = SG(p)+TD(d0);
        !          3803:     return r;
1.55      noro     3804: }
                   3805:
1.56      noro     3806: /* product of monomials */
                   3807: /* XXX block order is not handled correctly */
                   3808:
1.55      noro     3809: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
                   3810: {
1.157   ! noro     3811:     int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
        !          3812:     UINT *d0,*d1,*d,*dt,*ctab;
        !          3813:     Q *ctab_q;
        !          3814:     Q q,q1;
        !          3815:     UINT c0,c1,c;
        !          3816:     NM *p;
        !          3817:     NM m,t;
        !          3818:     int mpos;
        !          3819:
        !          3820:     for ( i = 0; i < tlen; i++ ) tab[i] = 0;
        !          3821:     if ( !m0 || !m1 ) return;
        !          3822:     d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
        !          3823:     NEWNM(m); d = DL(m);
        !          3824:     if ( mod ) {
        !          3825:         c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
        !          3826:     } else
        !          3827:         mulq(CQ(m0),CQ(m1),&CQ(m));
        !          3828:     for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
        !          3829:     homo = n&1 ? 1 : 0;
        !          3830:     if ( homo ) {
        !          3831:         /* offset of h-degree */
        !          3832:         h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
        !          3833:         PUT_EXP(DL(m),n-1,h);
        !          3834:         TD(DL(m)) = h;
        !          3835:         if ( nd_blockmask ) ndl_weight_mask(DL(m));
        !          3836:     }
        !          3837:     if ( nd_module ) {
        !          3838:         mpos = MPOS(d1);
        !          3839:         if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
        !          3840:     }
        !          3841:     tab[0] = m;
        !          3842:     NEWNM(m); d = DL(m);
        !          3843:     for ( i = 0, curlen = 1; i < n2; i++ ) {
        !          3844:         a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
        !          3845:         k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
        !          3846:         /* xi^a*(Di^k*xi^l)*Di^b */
        !          3847:         a += l; b += k;
        !          3848:         s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
        !          3849:         if ( !k || !l ) {
        !          3850:             for ( j = 0; j < curlen; j++ )
        !          3851:                 if ( t = tab[j] ) {
        !          3852:                     dt = DL(t);
        !          3853:                     PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
        !          3854:                     if ( nd_blockmask ) ndl_weight_mask(dt);
        !          3855:                 }
        !          3856:             curlen *= k+1;
        !          3857:             continue;
        !          3858:         }
        !          3859:         min = MIN(k,l);
        !          3860:         if ( mod ) {
        !          3861:             ctab = (UINT *)ALLOCA((min+1)*sizeof(UINT));
        !          3862:             mkwcm(k,l,mod,ctab);
        !          3863:         } else {
        !          3864:             ctab_q = (Q *)ALLOCA((min+1)*sizeof(Q));
        !          3865:             mkwc(k,l,ctab_q);
        !          3866:         }
        !          3867:         for ( j = min; j >= 0; j-- ) {
        !          3868:             for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
        !          3869:             PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
        !          3870:             h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
        !          3871:             if ( homo ) {
        !          3872:                 TD(d) = s;
        !          3873:                 PUT_EXP(d,n-1,s-h);
        !          3874:             } else TD(d) = h;
        !          3875:             if ( nd_blockmask ) ndl_weight_mask(d);
        !          3876:             if ( nd_module ) MPOS(d) = mpos;
        !          3877:             if ( mod ) c = ctab[j];
        !          3878:             else q = ctab_q[j];
        !          3879:             p = tab+curlen*j;
        !          3880:             if ( j == 0 ) {
        !          3881:                 for ( u = 0; u < curlen; u++, p++ ) {
        !          3882:                     if ( tab[u] ) {
        !          3883:                         ndl_addto(DL(tab[u]),d);
        !          3884:                         if ( mod ) {
        !          3885:                             c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
        !          3886:                         } else {
        !          3887:                             mulq(CQ(tab[u]),q,&q1); CQ(tab[u]) = q1;
        !          3888:                         }
        !          3889:                     }
        !          3890:                 }
        !          3891:             } else {
        !          3892:                 for ( u = 0; u < curlen; u++, p++ ) {
        !          3893:                     if ( tab[u] ) {
        !          3894:                         NEWNM(t);
        !          3895:                         ndl_add(DL(tab[u]),d,DL(t));
        !          3896:                         if ( mod ) {
        !          3897:                             c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
        !          3898:                         } else
        !          3899:                             mulq(CQ(tab[u]),q,&CQ(t));
        !          3900:                         *p = t;
        !          3901:                     }
        !          3902:                 }
        !          3903:             }
        !          3904:         }
        !          3905:         curlen *= k+1;
        !          3906:     }
        !          3907:     FREENM(m);
1.55      noro     3908: }
                   3909:
1.63      noro     3910: ND ndv_mul_nm_symbolic(NM m0,NDV p)
                   3911: {
1.157   ! noro     3912:     NM mr,mr0;
        !          3913:     NMV m;
        !          3914:     UINT *d,*dt,*dm;
        !          3915:     int c,n,td,i,c1,c2,len;
        !          3916:     Q q;
        !          3917:     ND r;
        !          3918:
        !          3919:     if ( !p ) return 0;
        !          3920:     else {
        !          3921:         n = NV(p); m = BDY(p);
        !          3922:         d = DL(m0);
        !          3923:         len = LEN(p);
        !          3924:         mr0 = 0;
        !          3925:         td = TD(d);
        !          3926:         c = CM(m0);
        !          3927:         for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3928:             NEXTNM(mr0,mr);
        !          3929:             CM(mr) = 1;
        !          3930:             ndl_add(DL(m),d,DL(mr));
        !          3931:         }
        !          3932:         NEXT(mr) = 0;
        !          3933:         MKND(NV(p),mr0,len,r);
        !          3934:         SG(r) = SG(p) + TD(d);
        !          3935:         return r;
        !          3936:     }
1.63      noro     3937: }
                   3938:
1.55      noro     3939: ND ndv_mul_nm(int mod,NM m0,NDV p)
1.9       noro     3940: {
1.157   ! noro     3941:     NM mr,mr0;
        !          3942:     NMV m;
        !          3943:     UINT *d,*dt,*dm;
        !          3944:     int c,n,td,i,c1,c2,len;
        !          3945:     P q;
        !          3946:     ND r;
        !          3947:
        !          3948:     if ( !p ) return 0;
        !          3949:     else if ( do_weyl )
        !          3950:         if ( mod == -1 )
        !          3951:             error("ndv_mul_nm : not implemented (weyl)");
        !          3952:         else
        !          3953:             return weyl_ndv_mul_nm(mod,m0,p);
        !          3954:     else {
        !          3955:         n = NV(p); m = BDY(p);
        !          3956:         d = DL(m0);
        !          3957:         len = LEN(p);
        !          3958:         mr0 = 0;
        !          3959:         td = TD(d);
        !          3960:         if ( mod == -1 ) {
        !          3961:             c = CM(m0);
        !          3962:             for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3963:                 NEXTNM(mr0,mr);
        !          3964:                 CM(mr) = _mulsf(CM(m),c);
        !          3965:                 ndl_add(DL(m),d,DL(mr));
        !          3966:             }
        !          3967:         } else if ( mod ) {
        !          3968:             c = CM(m0);
        !          3969:             for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3970:                 NEXTNM(mr0,mr);
        !          3971:                 c1 = CM(m);
        !          3972:                 DMAR(c1,c,0,mod,c2);
        !          3973:                 CM(mr) = c2;
        !          3974:                 ndl_add(DL(m),d,DL(mr));
        !          3975:             }
        !          3976:         } else {
        !          3977:             q = CP(m0);
        !          3978:             for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          3979:                 NEXTNM(mr0,mr);
        !          3980:                 mulp(nd_vc,CP(m),q,&CP(mr));
        !          3981:                 ndl_add(DL(m),d,DL(mr));
        !          3982:             }
        !          3983:         }
        !          3984:         NEXT(mr) = 0;
        !          3985:         MKND(NV(p),mr0,len,r);
        !          3986:         SG(r) = SG(p) + TD(d);
        !          3987:         return r;
        !          3988:     }
1.4       noro     3989: }
                   3990:
1.104     noro     3991: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
1.99      noro     3992: {
1.157   ! noro     3993:     NM mq0,mq;
        !          3994:     NMV tm;
        !          3995:     Q q;
        !          3996:     int i,nv,sg,c,c1,c2,hindex;
        !          3997:     ND p,t,r;
        !          3998:     N tnm;
        !          3999:
        !          4000:     if ( bucket->m < 0 ) return 0;
        !          4001:     else {
        !          4002:         nv = NV(d);
        !          4003:         mq0 = 0;
        !          4004:         tm = (NMV)ALLOCA(nmv_adv);
        !          4005:         while ( 1 ) {
        !          4006:             hindex = mod?head_pbucket(mod,bucket):head_pbucket_q(bucket);
        !          4007:             if ( hindex < 0 ) break;
        !          4008:             p = bucket->body[hindex];
        !          4009:             NEXTNM(mq0,mq);
        !          4010:             ndl_sub(HDL(p),HDL(d),DL(mq));
        !          4011:             ndl_copy(DL(mq),DL(tm));
        !          4012:             if ( mod ) {
        !          4013:                 c1 = invm(HCM(d),mod); c2 = HCM(p);
        !          4014:                 DMAR(c1,c2,0,mod,c); CM(mq) = c;
        !          4015:                 CM(tm) = mod-c;
        !          4016:             } else {
        !          4017:                 divsn(NM(HCQ(p)),NM(HCQ(d)),&tnm);
        !          4018:                 NTOQ(tnm,SGN(HCQ(p))*SGN(HCQ(d)),CQ(mq));
        !          4019:                 chsgnq(CQ(mq),&CQ(tm));
        !          4020:             }
        !          4021:             t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
        !          4022:             bucket->body[hindex] = nd_remove_head(p);
        !          4023:             t = nd_remove_head(t);
        !          4024:             add_pbucket(mod,bucket,t);
        !          4025:         }
        !          4026:         if ( !mq0 )
        !          4027:             r = 0;
        !          4028:         else {
        !          4029:             NEXT(mq) = 0;
        !          4030:             for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
        !          4031:             MKND(nv,mq0,i,r);
        !          4032:             /* XXX */
        !          4033:             SG(r) = HTD(r);
        !          4034:         }
        !          4035:         return r;
        !          4036:     }
1.99      noro     4037: }
                   4038:
1.43      noro     4039: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
1.11      noro     4040: {
1.157   ! noro     4041:     NMV m,mr,mr0,t;
        !          4042:     int len,i,k;
1.11      noro     4043:
1.157   ! noro     4044:     if ( !p ) return;
        !          4045:     m = BDY(p); len = LEN(p);
        !          4046:     mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
        !          4047:     m = (NMV)((char *)mr0+(len-1)*oadv);
        !          4048:     mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
        !          4049:     t = (NMV)ALLOCA(nmv_adv);
        !          4050:     for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
        !          4051:         CQ(t) = CQ(m);
        !          4052:         for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
        !          4053:         ndl_reconstruct(DL(m),DL(t),obpe,oepos);
        !          4054:         CQ(mr) = CQ(t);
        !          4055:         ndl_copy(DL(t),DL(mr));
        !          4056:     }
        !          4057:     BDY(p) = mr0;
1.61      noro     4058: }
                   4059:
                   4060: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
                   4061: {
1.157   ! noro     4062:     NMV m,mr,mr0;
        !          4063:     int len,i;
        !          4064:     NDV r;
        !          4065:
        !          4066:     if ( !p ) return 0;
        !          4067:     m = BDY(p); len = LEN(p);
        !          4068:     mr0 = mr = (NMV)MALLOC(len*nmv_adv);
        !          4069:     for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
        !          4070:         ndl_zero(DL(mr));
        !          4071:         ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
        !          4072:         CQ(mr) = CQ(m);
        !          4073:     }
        !          4074:     MKNDV(NV(p),mr0,len,r);
        !          4075:     SG(r) = SG(p);
        !          4076:     return r;
1.11      noro     4077: }
                   4078:
1.61      noro     4079: /* duplicate p */
                   4080:
                   4081: NDV ndv_dup(int mod,NDV p)
1.3       noro     4082: {
1.157   ! noro     4083:     NDV d;
        !          4084:     NMV t,m,m0;
        !          4085:     int i,len;
        !          4086:
        !          4087:     if ( !p ) return 0;
        !          4088:     len = LEN(p);
        !          4089:     m0 = m = (NMV)(mod?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
        !          4090:     for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
        !          4091:         ndl_copy(DL(t),DL(m));
        !          4092:         CQ(m) = CQ(t);
        !          4093:     }
        !          4094:     MKNDV(NV(p),m0,len,d);
        !          4095:     SG(d) = SG(p);
        !          4096:     return d;
1.23      noro     4097: }
                   4098:
1.63      noro     4099: ND nd_dup(ND p)
                   4100: {
1.157   ! noro     4101:     ND d;
        !          4102:     NM t,m,m0;
1.63      noro     4103:
1.157   ! noro     4104:     if ( !p ) return 0;
        !          4105:     for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
        !          4106:         NEXTNM(m0,m);
        !          4107:         ndl_copy(DL(t),DL(m));
        !          4108:         CQ(m) = CQ(t);
        !          4109:     }
        !          4110:     if ( m0 ) NEXT(m) = 0;
        !          4111:     MKND(NV(p),m0,LEN(p),d);
        !          4112:     SG(d) = SG(p);
        !          4113:     return d;
1.63      noro     4114: }
                   4115:
1.61      noro     4116: /* XXX if p->len == 0 then it represents 0 */
                   4117:
                   4118: void ndv_mod(int mod,NDV p)
                   4119: {
1.157   ! noro     4120:     NMV t,d;
        !          4121:     int r,s,u;
        !          4122:     int i,len,dlen;
        !          4123:     P cp;
        !          4124:     Q c;
        !          4125:     Obj gfs;
        !          4126:
        !          4127:     if ( !p ) return;
        !          4128:     len = LEN(p);
        !          4129:     dlen = 0;
        !          4130:     if ( mod == -1 )
        !          4131:         for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
        !          4132:             simp_ff((Obj)CP(t),&gfs);
        !          4133:             r = FTOIF(CONT((GFS)gfs));
        !          4134:             CM(d) = r;
        !          4135:             ndl_copy(DL(t),DL(d));
        !          4136:             NMV_ADV(d);
        !          4137:             dlen++;
        !          4138:         }
        !          4139:     else
        !          4140:         for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
        !          4141:             if ( nd_vc ) {
        !          4142:                 nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
        !          4143:                 c = (Q)cp;
        !          4144:             } else
        !          4145:                 c = CQ(t);
        !          4146:             r = rem(NM(c),mod);
        !          4147:             if ( r ) {
        !          4148:                 if ( SGN(c) < 0 )
        !          4149:                     r = mod-r;
        !          4150:                 if ( DN(c) ) {
        !          4151:                     s = rem(DN(c),mod);
        !          4152:                     if ( !s )
        !          4153:                         error("ndv_mod : division by 0");
        !          4154:                     s = invm(s,mod);
        !          4155:                     DMAR(r,s,0,mod,u); r = u;
        !          4156:                 }
        !          4157:                 CM(d) = r;
        !          4158:                 ndl_copy(DL(t),DL(d));
        !          4159:                 NMV_ADV(d);
        !          4160:                 dlen++;
        !          4161:             }
        !          4162:         }
        !          4163:     LEN(p) = dlen;
1.61      noro     4164: }
                   4165:
                   4166: NDV ptondv(VL vl,VL dvl,P p)
                   4167: {
1.157   ! noro     4168:     ND nd;
        !          4169:
        !          4170:     nd = ptond(vl,dvl,p);
        !          4171:     return ndtondv(0,nd);
        !          4172: }
1.61      noro     4173:
1.157   ! noro     4174: void pltozpl(LIST l,Q *cont,LIST *pp)
        !          4175: {
        !          4176:     NODE nd,nd1;
        !          4177:     int n;
        !          4178:     P *pl;
        !          4179:     Q *cl;
        !          4180:     int i;
        !          4181:     P dmy;
        !          4182:     Q dvr;
        !          4183:     LIST r;
        !          4184:
        !          4185:     nd = BDY(l); n = length(nd);
        !          4186:     pl = (P *)ALLOCA(n*sizeof(P));
        !          4187:     cl = (Q *)ALLOCA(n*sizeof(P));
        !          4188:     for ( i = 0; i < n; i++, nd = NEXT(nd) )
        !          4189:         ptozp((P)BDY(nd),1,&cl[i],&dmy);
        !          4190:     qltozl(cl,n,&dvr);
        !          4191:     nd = BDY(l);
        !          4192:     for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
        !          4193:         divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
        !          4194:     }
        !          4195:     nd = 0;
        !          4196:     for ( i = n-1; i >= 0; i-- ) {
        !          4197:         MKNODE(nd1,pl[i],nd); nd = nd1;
        !          4198:     }
        !          4199:     MKLIST(r,nd);
        !          4200:     *pp = r;
        !          4201: }
        !          4202:
        !          4203: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
        !          4204:
        !          4205: NDV pltondv(VL vl,VL dvl,LIST p)
        !          4206: {
        !          4207:     int i;
        !          4208:     NODE t;
        !          4209:     ND r,ri;
        !          4210:     NM m;
        !          4211:
        !          4212:     if ( !nd_module ) error("pltond : module order must be set");
        !          4213:     r = 0;
        !          4214:     for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
        !          4215:         ri = ptond(vl,dvl,(P)BDY(t));
        !          4216:        if ( ri )
        !          4217:             for ( m = BDY(ri); m; m = NEXT(m) )
        !          4218:                 MPOS(DL(m)) = i;
        !          4219:         r = nd_add(0,r,ri);
        !          4220:     }
        !          4221:     return ndtondv(0,r);
1.61      noro     4222: }
                   4223:
                   4224: ND ptond(VL vl,VL dvl,P p)
1.23      noro     4225: {
1.157   ! noro     4226:     int n,i,j,k,e;
        !          4227:     VL tvl;
        !          4228:     V v;
        !          4229:     DCP dc;
        !          4230:     DCP *w;
        !          4231:     ND r,s,t,u;
        !          4232:     P x;
        !          4233:     int c;
        !          4234:     UINT *d;
        !          4235:     NM m,m0;
        !          4236:
        !          4237:     if ( !p )
        !          4238:         return 0;
        !          4239:     else if ( NUM(p) ) {
        !          4240:         NEWNM(m);
        !          4241:         ndl_zero(DL(m));
        !          4242:         CQ(m) = (Q)p;
        !          4243:         NEXT(m) = 0;
        !          4244:         MKND(nd_nvar,m,1,r);
        !          4245:         SG(r) = 0;
        !          4246:         return r;
        !          4247:     } else {
        !          4248:         for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
        !          4249:         w = (DCP *)ALLOCA(k*sizeof(DCP));
        !          4250:         for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
        !          4251:         for ( i = 0, tvl = dvl, v = VR(p);
        !          4252:             tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
        !          4253:         if ( !tvl ) {
        !          4254:             for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
        !          4255:                 t = ptond(vl,dvl,COEF(w[j]));
        !          4256:                 pwrp(vl,x,DEG(w[j]),&p);
        !          4257:                 nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
        !          4258:             }
        !          4259:             return s;
        !          4260:         } else {
        !          4261:             NEWNM(m0); d = DL(m0);
        !          4262:             for ( j = k-1, s = 0; j >= 0; j-- ) {
        !          4263:                 ndl_zero(d); e = QTOS(DEG(w[j])); PUT_EXP(d,i,e);
        !          4264:                 TD(d) = MUL_WEIGHT(e,i);
        !          4265:                 if ( nd_blockmask) ndl_weight_mask(d);
        !          4266:                 if ( nd_module ) MPOS(d) = 0;
        !          4267:                 t = ptond(vl,dvl,COEF(w[j]));
        !          4268:                 for ( m = BDY(t); m; m = NEXT(m) )
        !          4269:                     ndl_addto(DL(m),d);
        !          4270:                 SG(t) += TD(d);
        !          4271:                 s = nd_add(0,s,t);
        !          4272:             }
        !          4273:             FREENM(m0);
        !          4274:             return s;
        !          4275:         }
        !          4276:     }
1.61      noro     4277: }
                   4278:
                   4279: P ndvtop(int mod,VL vl,VL dvl,NDV p)
                   4280: {
1.157   ! noro     4281:     VL tvl;
        !          4282:     int len,n,j,i,e;
        !          4283:     NMV m;
        !          4284:     Q q;
        !          4285:     P c;
        !          4286:     UINT *d;
        !          4287:     P s,r,u,t,w;
        !          4288:     GFS gfs;
        !          4289:
        !          4290:     if ( !p ) return 0;
        !          4291:     else {
        !          4292:         len = LEN(p);
        !          4293:         n = NV(p);
        !          4294:         m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
        !          4295:         for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
        !          4296:             if ( mod == -1 ) {
        !          4297:                 e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
        !          4298:             } else if ( mod ) {
        !          4299:                 STOQ(CM(m),q); c = (P)q;
        !          4300:             } else
        !          4301:                 c = CP(m);
        !          4302:             d = DL(m);
        !          4303:             for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
        !          4304:                 MKV(tvl->v,r); e = GET_EXP(d,i); STOQ(e,q);
        !          4305:                 pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
        !          4306:             }
        !          4307:             addp(vl,s,t,&u); s = u;
        !          4308:         }
        !          4309:         return s;
        !          4310:     }
        !          4311: }
        !          4312:
        !          4313: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
        !          4314: {
        !          4315:     VL tvl;
        !          4316:     int len,n,j,i,e;
        !          4317:     NMV m;
        !          4318:     Q q;
        !          4319:     P c;
        !          4320:     UINT *d;
        !          4321:     P s,r,u,t,w;
        !          4322:     GFS gfs;
        !          4323:     P *a;
        !          4324:     LIST l;
        !          4325:     NODE nd,nd1;
        !          4326:
        !          4327:     if ( !p ) return 0;
        !          4328:     else {
        !          4329:         a = (P *)ALLOCA((rank+1)*sizeof(P));
        !          4330:         for ( i = 0; i <= rank; i++ ) a[i] = 0;
        !          4331:         len = LEN(p);
        !          4332:         n = NV(p);
        !          4333:         m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
        !          4334:         for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
        !          4335:             if ( mod == -1 ) {
        !          4336:                 e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
        !          4337:             } else if ( mod ) {
        !          4338:                 STOQ(CM(m),q); c = (P)q;
        !          4339:             } else
        !          4340:                 c = CP(m);
        !          4341:             d = DL(m);
        !          4342:             for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
        !          4343:                 MKV(tvl->v,r); e = GET_EXP(d,i); STOQ(e,q);
        !          4344:                 pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
        !          4345:             }
        !          4346:             addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
        !          4347:         }
        !          4348:         nd = 0;
        !          4349:         for ( i = rank; i > 0; i-- ) {
        !          4350:             MKNODE(nd1,a[i],nd); nd = nd1;
        !          4351:         }
        !          4352:         MKLIST(l,nd);
        !          4353:         return l;
        !          4354:     }
1.3       noro     4355: }
                   4356:
1.61      noro     4357: NDV ndtondv(int mod,ND p)
1.11      noro     4358: {
1.157   ! noro     4359:     NDV d;
        !          4360:     NMV m,m0;
        !          4361:     NM t;
        !          4362:     int i,len;
        !          4363:
        !          4364:     if ( !p ) return 0;
        !          4365:     len = LEN(p);
        !          4366:     if ( mod )
        !          4367:         m0 = m = (NMV)GC_malloc_atomic_ignore_off_page(len*nmv_adv);
        !          4368:     else
        !          4369:         m0 = m = MALLOC(len*nmv_adv);
1.103     noro     4370: #if 0
1.157   ! noro     4371:     ndv_alloc += nmv_adv*len;
1.103     noro     4372: #endif
1.157   ! noro     4373:     for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
        !          4374:         ndl_copy(DL(t),DL(m));
        !          4375:         CQ(m) = CQ(t);
        !          4376:     }
        !          4377:     MKNDV(NV(p),m0,len,d);
        !          4378:     SG(d) = SG(p);
        !          4379:     return d;
1.11      noro     4380: }
                   4381:
1.61      noro     4382: ND ndvtond(int mod,NDV p)
1.11      noro     4383: {
1.157   ! noro     4384:     ND d;
        !          4385:     NM m,m0;
        !          4386:     NMV t;
        !          4387:     int i,len;
        !          4388:
        !          4389:     if ( !p ) return 0;
        !          4390:     m0 = 0;
        !          4391:     len = p->len;
        !          4392:     for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
        !          4393:         NEXTNM(m0,m);
        !          4394:         ndl_copy(DL(t),DL(m));
        !          4395:         CQ(m) = CQ(t);
        !          4396:     }
        !          4397:     NEXT(m) = 0;
        !          4398:     MKND(NV(p),m0,len,d);
        !          4399:     SG(d) = SG(p);
        !          4400:     return d;
1.11      noro     4401: }
                   4402:
1.3       noro     4403: void ndv_print(NDV p)
                   4404: {
1.157   ! noro     4405:     NMV m;
        !          4406:     int i,len;
1.3       noro     4407:
1.157   ! noro     4408:     if ( !p ) printf("0\n");
        !          4409:     else {
        !          4410:         len = LEN(p);
        !          4411:         for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
        !          4412:             if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
        !          4413:             else printf("+%d*",CM(m));
        !          4414:             ndl_print(DL(m));
        !          4415:         }
        !          4416:         printf("\n");
        !          4417:     }
1.16      noro     4418: }
                   4419:
1.113     noro     4420: void ndv_print_q(NDV p)
1.16      noro     4421: {
1.157   ! noro     4422:     NMV m;
        !          4423:     int i,len;
1.16      noro     4424:
1.157   ! noro     4425:     if ( !p ) printf("0\n");
        !          4426:     else {
        !          4427:         len = LEN(p);
        !          4428:         for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
        !          4429:             printf("+");
        !          4430:             printexpr(CO,(Obj)CQ(m));
        !          4431:             printf("*");
        !          4432:             ndl_print(DL(m));
        !          4433:         }
        !          4434:         printf("\n");
        !          4435:     }
1.25      noro     4436: }
                   4437:
1.61      noro     4438: NODE ndv_reducebase(NODE x)
1.27      noro     4439: {
1.157   ! noro     4440:     int len,i,j;
        !          4441:     NDV *w;
        !          4442:     NODE t,t0;
        !          4443:
        !          4444:     len = length(x);
        !          4445:     w = (NDV *)ALLOCA(len*sizeof(NDV));
        !          4446:     for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) w[i] = BDY(t);
        !          4447:     for ( i = 0; i < len; i++ ) {
        !          4448:         for ( j = 0; j < i; j++ ) {
        !          4449:             if ( w[i] && w[j] )
        !          4450:                 if ( ndl_reducible(HDL(w[i]),HDL(w[j])) ) w[i] = 0;
        !          4451:                 else if ( ndl_reducible(HDL(w[j]),HDL(w[i])) ) w[j] = 0;
        !          4452:         }
        !          4453:     }
        !          4454:     for ( i = len-1, t0 = 0; i >= 0; i-- ) {
        !          4455:         if ( w[i] ) { NEXTNODE(t0,t); BDY(t) = (pointer)w[i]; }
        !          4456:     }
        !          4457:     NEXT(t) = 0; x = t0;
        !          4458:     return x;
1.11      noro     4459: }
1.32      noro     4460:
1.43      noro     4461: /* XXX incomplete */
                   4462:
1.32      noro     4463: void nd_init_ord(struct order_spec *ord)
                   4464: {
1.157   ! noro     4465:     nd_module = (ord->id >= 256);
        !          4466:     switch ( ord->id ) {
        !          4467:         case 0:
        !          4468:             switch ( ord->ord.simple ) {
        !          4469:                 case 0:
        !          4470:                     nd_dcomp = 1;
        !          4471:                     nd_isrlex = 1;
        !          4472:                     break;
        !          4473:                 case 1:
        !          4474:                     nd_dcomp = 1;
        !          4475:                     nd_isrlex = 0;
        !          4476:                     break;
        !          4477:                 case 2:
        !          4478:                     nd_dcomp = 0;
        !          4479:                     nd_isrlex = 0;
        !          4480:                     ndl_compare_function = ndl_lex_compare;
        !          4481:                     break;
        !          4482:                 case 11:
        !          4483:                     /* XXX */
        !          4484:                     nd_dcomp = 0;
        !          4485:                     nd_isrlex = 1;
        !          4486:                     ndl_compare_function = ndl_ww_lex_compare;
        !          4487:                     break;
        !          4488:                 default:
        !          4489:                     error("nd_gr : unsupported order");
        !          4490:             }
        !          4491:             break;
        !          4492:         case 1:
        !          4493:             /* block order */
        !          4494:             /* XXX */
        !          4495:             nd_dcomp = -1;
        !          4496:             nd_isrlex = 0;
        !          4497:             ndl_compare_function = ndl_block_compare;
        !          4498:             break;
        !          4499:         case 2:
        !          4500:             /* matrix order */
        !          4501:             /* XXX */
        !          4502:             nd_dcomp = -1;
        !          4503:             nd_isrlex = 0;
        !          4504:             nd_matrix_len = ord->ord.matrix.row;
        !          4505:             nd_matrix = ord->ord.matrix.matrix;
        !          4506:             ndl_compare_function = ndl_matrix_compare;
        !          4507:             break;
        !          4508:         case 3:
        !          4509:             /* composite order */
        !          4510:             nd_dcomp = -1;
        !          4511:             nd_isrlex = 0;
        !          4512:             nd_worb_len = ord->ord.composite.length;
        !          4513:             nd_worb = ord->ord.composite.w_or_b;
        !          4514:             ndl_compare_function = ndl_composite_compare;
        !          4515:             break;
        !          4516:
        !          4517:         /* module order */
        !          4518:         case 256:
        !          4519:             nd_istop = ord->istop;
        !          4520:             nd_dcomp = -1;
        !          4521:             nd_isrlex = 0;
        !          4522:             switch ( ord->ord.simple ) {
        !          4523:                 case 0:
        !          4524:                     ndl_compare_function = ndl_module_grlex_compare;
        !          4525:                     break;
        !          4526:                 case 1:
        !          4527:                     ndl_compare_function = ndl_module_glex_compare;
        !          4528:                     break;
        !          4529:                 case 2:
        !          4530:                     ndl_compare_function = ndl_module_lex_compare;
        !          4531:                     break;
        !          4532:                 default:
        !          4533:                     error("nd_gr : unsupported order");
        !          4534:             }
        !          4535:             break;
        !          4536:         case 257:
        !          4537:             /* block order */
        !          4538:             ndl_compare_function = ndl_module_block_compare;
        !          4539:             break;
        !          4540:         case 258:
        !          4541:             /* matrix order */
        !          4542:             nd_matrix_len = ord->ord.matrix.row;
        !          4543:             nd_matrix = ord->ord.matrix.matrix;
        !          4544:             ndl_compare_function = ndl_module_matrix_compare;
        !          4545:             break;
        !          4546:         case 259:
        !          4547:             /* composite order */
        !          4548:             nd_worb_len = ord->ord.composite.length;
        !          4549:             nd_worb = ord->ord.composite.w_or_b;
        !          4550:             ndl_compare_function = ndl_module_composite_compare;
        !          4551:             break;
        !          4552:     }
        !          4553:     nd_ord = ord;
1.32      noro     4554: }
                   4555:
1.43      noro     4556: BlockMask nd_create_blockmask(struct order_spec *ord)
                   4557: {
1.157   ! noro     4558:     int n,i,j,s,l;
        !          4559:     UINT *t;
        !          4560:     BlockMask bm;
        !          4561:
        !          4562:     /* we only create mask table for block order */
        !          4563:     if ( ord->id != 1 )
        !          4564:         return 0;
        !          4565:     n = ord->ord.block.length;
        !          4566:     bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
        !          4567:     bm->n = n;
        !          4568:     bm->order_pair = ord->ord.block.order_pair;
        !          4569:     bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
        !          4570:     for ( i = 0, s = 0; i < n; i++ ) {
        !          4571:         bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
        !          4572:         for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
        !          4573:         l = bm->order_pair[i].length;
        !          4574:         for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
        !          4575:     }
        !          4576:     return bm;
1.57      noro     4577: }
                   4578:
                   4579: EPOS nd_create_epos(struct order_spec *ord)
                   4580: {
1.157   ! noro     4581:     int i,j,l,s,ord_l,ord_o;
        !          4582:     EPOS epos;
        !          4583:     struct order_pair *op;
        !          4584:
        !          4585:     epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
        !          4586:     switch ( ord->id ) {
        !          4587:         case 0:
        !          4588:             if ( nd_isrlex ) {
        !          4589:                 for ( i = 0; i < nd_nvar; i++ ) {
        !          4590:                     epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
        !          4591:                     epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
        !          4592:                 }
        !          4593:             } else {
        !          4594:                 for ( i = 0; i < nd_nvar; i++ ) {
        !          4595:                     epos[i].i = nd_exporigin + i/nd_epw;
        !          4596:                     epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
        !          4597:                 }
        !          4598:             }
        !          4599:             break;
        !          4600:         case 1:
        !          4601:             /* block order */
        !          4602:             l = ord->ord.block.length;
        !          4603:             op = ord->ord.block.order_pair;
        !          4604:             for ( j = 0, s = 0; j < l; j++ ) {
        !          4605:                 ord_o = op[j].order;
        !          4606:                 ord_l = op[j].length;
        !          4607:                 if ( !ord_o )
        !          4608:                     for ( i = 0; i < ord_l; i++ ) {
        !          4609:                         epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
        !          4610:                         epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
        !          4611:                     }
        !          4612:                 else
        !          4613:                     for ( i = 0; i < ord_l; i++ ) {
        !          4614:                         epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
        !          4615:                         epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
        !          4616:                     }
        !          4617:                 s += ord_l;
        !          4618:             }
        !          4619:             break;
        !          4620:         case 2:
        !          4621:             /* matrix order */
        !          4622:         case 3:
        !          4623:             /* composite order */
        !          4624:        default:
        !          4625:             for ( i = 0; i < nd_nvar; i++ ) {
        !          4626:                 epos[i].i = nd_exporigin + i/nd_epw;
        !          4627:                 epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
        !          4628:             }
        !          4629:             break;
        !          4630:     }
        !          4631:     return epos;
1.43      noro     4632: }
1.59      noro     4633:
                   4634: /* external interface */
                   4635:
                   4636: void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec *ord,P *rp)
                   4637: {
1.157   ! noro     4638:     NODE t,in0,in;
        !          4639:     ND nd,nf;
        !          4640:     NDV ndv;
        !          4641:     VL vv,tv;
        !          4642:     int stat,nvar,max,e;
        !          4643:     union oNDC dn;
        !          4644:     Q cont;
        !          4645:     P pp;
        !          4646:
        !          4647:     if ( !f ) {
        !          4648:         *rp = 0;
        !          4649:         return;
        !          4650:     }
        !          4651:     pltovl(v,&vv);
        !          4652:     for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
        !          4653:
        !          4654:     /* get the degree bound */
        !          4655:     for ( t = BDY(g), max = 0; t; t = NEXT(t) )
        !          4656:         for ( tv = vv; tv; tv = NEXT(tv) ) {
        !          4657:             e = getdeg(tv->v,(P)BDY(t));
        !          4658:             max = MAX(e,max);
        !          4659:         }
        !          4660:     for ( tv = vv; tv; tv = NEXT(tv) ) {
        !          4661:         e = getdeg(tv->v,f);
        !          4662:         max = MAX(e,max);
        !          4663:     }
        !          4664:
        !          4665:     nd_init_ord(ord);
        !          4666:     nd_setup_parameters(nvar,max);
        !          4667:
        !          4668:     /* conversion to ndv */
        !          4669:     for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
        !          4670:         NEXTNODE(in0,in);
        !          4671:         ptozp((P)BDY(t),1,&cont,&pp);
        !          4672:         BDY(in) = (pointer)ptondv(CO,vv,pp);
        !          4673:         if ( m ) ndv_mod(m,(NDV)BDY(in));
        !          4674:     }
        !          4675:     NEXTNODE(in0,in);
        !          4676:     BDY(in) = (pointer)ptondv(CO,vv,f);
        !          4677:     if ( m ) ndv_mod(m,(NDV)BDY(in));
        !          4678:     NEXT(in) = 0;
        !          4679:
        !          4680:     /* dont sort, dont removecont */
        !          4681:     ndv_setup(m,0,in0,1,1);
        !          4682:     nd_psn--;
        !          4683:     nd_scale=2;
        !          4684:     while ( 1 ) {
        !          4685:         nd = (pointer)ndvtond(m,nd_ps[nd_psn]);
        !          4686:         stat = nd_nf(m,0,nd,nd_ps,1,0,&nf);
        !          4687:         if ( !stat ) {
        !          4688:             nd_psn++;
        !          4689:             nd_reconstruct(0,0);
        !          4690:             nd_psn--;
        !          4691:         } else
        !          4692:             break;
        !          4693:     }
        !          4694:     *rp = ndvtop(m,CO,vv,ndtondv(m,nf));
1.63      noro     4695: }
                   4696:
                   4697: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
                   4698: {
1.157   ! noro     4699:     NM m;
        !          4700:     UINT *t,*s;
        !          4701:     int i;
        !          4702:
        !          4703:     for ( i = 0; i < n; i++ ) r[i] = 0;
        !          4704:     for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
        !          4705:         t = DL(m);
        !          4706:         for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
        !          4707:         r[i] = CM(m);
        !          4708:     }
        !          4709:     for ( i = 0; !r[i]; i++ );
        !          4710:     return i;
1.63      noro     4711: }
                   4712:
1.113     noro     4713: int nd_to_vect_q(UINT *s0,int n,ND d,Q *r)
1.74      noro     4714: {
1.157   ! noro     4715:     NM m;
        !          4716:     UINT *t,*s;
        !          4717:     int i;
        !          4718:
        !          4719:     for ( i = 0; i < n; i++ ) r[i] = 0;
        !          4720:     for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
        !          4721:         t = DL(m);
        !          4722:         for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
        !          4723:         r[i] = CQ(m);
        !          4724:     }
        !          4725:     for ( i = 0; !r[i]; i++ );
        !          4726:     return i;
1.74      noro     4727: }
                   4728:
1.129     noro     4729: Q *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
                   4730: {
1.157   ! noro     4731:     NM m;
        !          4732:     NMV mr;
        !          4733:     UINT *d,*t,*s;
        !          4734:     NDV p;
        !          4735:     int i,j,len;
        !          4736:     Q *r;
        !          4737:
        !          4738:     m = pair->mul;
        !          4739:     d = DL(m);
        !          4740:     p = nd_ps[pair->index];
        !          4741:     len = LEN(p);
        !          4742:     r = (Q *)CALLOC(n,sizeof(Q));
        !          4743:     t = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          4744:     for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
        !          4745:         ndl_add(d,DL(mr),t);
        !          4746:         for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
        !          4747:         r[i] = CQ(mr);
        !          4748:     }
        !          4749:     return r;
1.129     noro     4750: }
                   4751:
1.67      noro     4752: IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0,int n,NM_ind_pair pair)
1.64      noro     4753: {
1.157   ! noro     4754:     NM m;
        !          4755:     NMV mr;
        !          4756:     UINT *d,*t,*s;
        !          4757:     NDV p;
        !          4758:     unsigned char *ivc;
        !          4759:     unsigned short *ivs;
        !          4760:     UINT *v,*ivi,*s0v;
        !          4761:     int i,j,len,prev,diff,cdiff;
        !          4762:     IndArray r;
        !          4763:
        !          4764:     m = pair->mul;
        !          4765:     d = DL(m);
        !          4766:     p = nd_ps[pair->index];
        !          4767:     len = LEN(p);
        !          4768:     t = (UINT *)ALLOCA(nd_wpd*sizeof(UINT));
        !          4769:     v = (unsigned int *)ALLOCA(len*sizeof(unsigned int));
        !          4770:     for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
        !          4771:         ndl_add(d,DL(mr),t);
        !          4772:         for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
        !          4773:         v[j] = i;
        !          4774:     }
        !          4775:     r = (IndArray)MALLOC(sizeof(struct oIndArray));
        !          4776:     r->head = v[0];
        !          4777:     diff = 0;
        !          4778:     for ( i = 1; i < len; i++ ) {
        !          4779:         cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
        !          4780:     }
        !          4781:     if ( diff < 256 ) {
        !          4782:         r->width = 1;
        !          4783:         ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
        !          4784:         r->index.c = ivc;
        !          4785:         for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
        !          4786:     } else if ( diff < 65536 ) {
        !          4787:         r->width = 2;
        !          4788:         ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
        !          4789:         r->index.s = ivs;
        !          4790:         for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
        !          4791:     } else {
        !          4792:         r->width = 4;
        !          4793:         ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
        !          4794:         r->index.i = ivi;
        !          4795:         for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
        !          4796:     }
        !          4797:     return r;
1.64      noro     4798: }
                   4799:
1.135     noro     4800: int compress_array(Q *svect,Q *cvect,int n)
                   4801: {
1.157   ! noro     4802:     int i,j;
1.135     noro     4803:
1.157   ! noro     4804:     for ( i = j = 0; i < n; i++ )
        !          4805:         if ( svect[i] ) cvect[j++] = svect[i];
        !          4806:     return j;
1.135     noro     4807: }
                   4808:
                   4809: void expand_array(Q *svect,Q *cvect,int n)
                   4810: {
1.157   ! noro     4811:     int i,j;
1.135     noro     4812:
1.157   ! noro     4813:     for ( i = j = 0; j < n;  i++  )
        !          4814:         if ( svect[i] ) svect[i] = cvect[j++];
1.135     noro     4815: }
                   4816:
1.133     noro     4817: int ndv_reduce_vect_q(Q *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
1.107     noro     4818: {
1.157   ! noro     4819:     int i,j,k,len,pos,prev,nz;
        !          4820:     Q cs,mcs,c1,c2,cr,gcd,t;
        !          4821:     IndArray ivect;
        !          4822:     unsigned char *ivc;
        !          4823:     unsigned short *ivs;
        !          4824:     unsigned int *ivi;
        !          4825:     NDV redv;
        !          4826:     NMV mr;
        !          4827:     NODE rp;
        !          4828:     int maxrs;
        !          4829:     double hmag;
        !          4830:     Q *cvect;
        !          4831:
        !          4832:     maxrs = 0;
        !          4833:     for ( i = 0; i < col && !svect[i]; i++ );
        !          4834:     if ( i == col ) return maxrs;
        !          4835:     hmag = p_mag((P)svect[i])*nd_scale;
        !          4836:     cvect = (Q *)ALLOCA(col*sizeof(Q));
        !          4837:     for ( i = 0; i < nred; i++ ) {
        !          4838:         ivect = imat[i];
        !          4839:         k = ivect->head;
        !          4840:         if ( svect[k] ) {
        !          4841:             maxrs = MAX(maxrs,rp0[i]->sugar);
        !          4842:             redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
        !          4843:             len = LEN(redv); mr = BDY(redv);
        !          4844:             igcd_cofactor(svect[k],CQ(mr),&gcd,&cs,&cr);
        !          4845:             chsgnq(cs,&mcs);
        !          4846:             if ( !UNIQ(cr) ) {
        !          4847:                 for ( j = 0; j < col; j++ ) {
        !          4848:                     mulq(svect[j],cr,&c1); svect[j] = c1;
        !          4849:                 }
        !          4850:             }
        !          4851:             svect[k] = 0; prev = k;
        !          4852:             switch ( ivect->width ) {
        !          4853:                 case 1:
        !          4854:                     ivc = ivect->index.c;
        !          4855:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4856:                         pos = prev+ivc[j]; prev = pos;
        !          4857:                         mulq(CQ(mr),mcs,&c2); addq(svect[pos],c2,&t); svect[pos] = t;
        !          4858:                     }
        !          4859:                     break;
        !          4860:                 case 2:
        !          4861:                     ivs = ivect->index.s;
        !          4862:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4863:                         pos = prev+ivs[j]; prev = pos;
        !          4864:                         mulq(CQ(mr),mcs,&c2); addq(svect[pos],c2,&t); svect[pos] = t;
        !          4865:                     }
        !          4866:                     break;
        !          4867:                 case 4:
        !          4868:                     ivi = ivect->index.i;
        !          4869:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4870:                         pos = prev+ivi[j]; prev = pos;
        !          4871:                         mulq(CQ(mr),mcs,&c2); addq(svect[pos],c2,&t); svect[pos] = t;
        !          4872:                     }
        !          4873:                     break;
        !          4874:             }
        !          4875:             for ( j = k+1; j < col && !svect[j]; j++ );
        !          4876:             if ( j == col ) break;
        !          4877:             if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
        !          4878:                 nz = compress_array(svect,cvect,col);
        !          4879:                 removecont_array((P *)cvect,nz,1);
        !          4880:                 expand_array(svect,cvect,nz);
        !          4881:                 hmag = ((double)p_mag((P)svect[j]))*nd_scale;
        !          4882:             }
        !          4883:         }
        !          4884:     }
        !          4885:     nz = compress_array(svect,cvect,col);
        !          4886:     removecont_array((P *)cvect,nz,1);
        !          4887:     expand_array(svect,cvect,nz);
        !          4888:     if ( DP_Print ) {
        !          4889:         fprintf(asir_out,"-"); fflush(asir_out);
        !          4890:     }
        !          4891:     return maxrs;
1.107     noro     4892: }
                   4893:
1.76      noro     4894: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
1.65      noro     4895: {
1.157   ! noro     4896:     int i,j,k,len,pos,prev;
        !          4897:     UINT c,c1,c2,c3,up,lo,dmy;
        !          4898:     IndArray ivect;
        !          4899:     unsigned char *ivc;
        !          4900:     unsigned short *ivs;
        !          4901:     unsigned int *ivi;
        !          4902:     NDV redv;
        !          4903:     NMV mr;
        !          4904:     NODE rp;
        !          4905:     int maxrs;
        !          4906:
        !          4907:     maxrs = 0;
        !          4908:     for ( i = 0; i < nred; i++ ) {
        !          4909:         ivect = imat[i];
        !          4910:         k = ivect->head; svect[k] %= m;
        !          4911:         if ( c = svect[k] ) {
        !          4912:             maxrs = MAX(maxrs,rp0[i]->sugar);
        !          4913:             c = m-c; redv = nd_ps[rp0[i]->index];
        !          4914:             len = LEN(redv); mr = BDY(redv);
        !          4915:             svect[k] = 0; prev = k;
        !          4916:             switch ( ivect->width ) {
        !          4917:                 case 1:
        !          4918:                     ivc = ivect->index.c;
        !          4919:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4920:                         pos = prev+ivc[j]; c1 = CM(mr); c2 = svect[pos];
        !          4921:                         prev = pos;
        !          4922:                         DMA(c1,c,c2,up,lo);
        !          4923:                         if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
        !          4924:                         } else svect[pos] = lo;
        !          4925:                     }
        !          4926:                     break;
        !          4927:                 case 2:
        !          4928:                     ivs = ivect->index.s;
        !          4929:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4930:                         pos = prev+ivs[j]; c1 = CM(mr); c2 = svect[pos];
        !          4931:                         prev = pos;
        !          4932:                         DMA(c1,c,c2,up,lo);
        !          4933:                         if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
        !          4934:                         } else svect[pos] = lo;
        !          4935:                     }
        !          4936:                     break;
        !          4937:                 case 4:
        !          4938:                     ivi = ivect->index.i;
        !          4939:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4940:                         pos = prev+ivi[j]; c1 = CM(mr); c2 = svect[pos];
        !          4941:                         prev = pos;
        !          4942:                         DMA(c1,c,c2,up,lo);
        !          4943:                         if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
        !          4944:                         } else svect[pos] = lo;
        !          4945:                     }
        !          4946:                     break;
        !          4947:             }
        !          4948:         }
        !          4949:     }
        !          4950:     for ( i = 0; i < col; i++ )
        !          4951:         if ( svect[i] >= (UINT)m ) svect[i] %= m;
        !          4952:     return maxrs;
1.65      noro     4953: }
                   4954:
1.76      noro     4955: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
1.72      noro     4956: {
1.157   ! noro     4957:     int i,j,k,len,pos,prev;
        !          4958:     UINT c,c1,c2,c3,up,lo,dmy;
        !          4959:     IndArray ivect;
        !          4960:     unsigned char *ivc;
        !          4961:     unsigned short *ivs;
        !          4962:     unsigned int *ivi;
        !          4963:     NDV redv;
        !          4964:     NMV mr;
        !          4965:     NODE rp;
        !          4966:     int maxrs;
        !          4967:
        !          4968:     maxrs = 0;
        !          4969:     for ( i = 0; i < nred; i++ ) {
        !          4970:         ivect = imat[i];
        !          4971:         k = ivect->head; svect[k] %= m;
        !          4972:         if ( c = svect[k] ) {
        !          4973:             maxrs = MAX(maxrs,rp0[i]->sugar);
        !          4974:             c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
        !          4975:             len = LEN(redv); mr = BDY(redv);
        !          4976:             svect[k] = 0; prev = k;
        !          4977:             switch ( ivect->width ) {
        !          4978:                 case 1:
        !          4979:                     ivc = ivect->index.c;
        !          4980:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4981:                         pos = prev+ivc[j]; prev = pos;
        !          4982:                         svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
        !          4983:                     }
        !          4984:                     break;
        !          4985:                 case 2:
        !          4986:                     ivs = ivect->index.s;
        !          4987:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4988:                         pos = prev+ivs[j]; prev = pos;
        !          4989:                         svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
        !          4990:                     }
        !          4991:                     break;
        !          4992:                 case 4:
        !          4993:                     ivi = ivect->index.i;
        !          4994:                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
        !          4995:                         pos = prev+ivi[j]; prev = pos;
        !          4996:                         svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
        !          4997:                     }
        !          4998:                     break;
        !          4999:             }
        !          5000:         }
        !          5001:     }
        !          5002:     return maxrs;
1.72      noro     5003: }
                   5004:
1.65      noro     5005: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
                   5006: {
1.157   ! noro     5007:     int j,k,len;
        !          5008:     UINT *p;
        !          5009:     UINT c;
        !          5010:     NDV r;
        !          5011:     NMV mr0,mr;
        !          5012:
        !          5013:     for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
        !          5014:     if ( !len ) return 0;
        !          5015:     else {
        !          5016:         mr0 = (NMV)GC_malloc_atomic_ignore_off_page(nmv_adv*len);
1.103     noro     5017: #if 0
1.157   ! noro     5018:         ndv_alloc += nmv_adv*len;
1.103     noro     5019: #endif
1.157   ! noro     5020:         mr = mr0;
        !          5021:         p = s0vect;
        !          5022:         for ( j = k = 0; j < col; j++, p += nd_wpd )
        !          5023:             if ( !rhead[j] ) {
        !          5024:                 if ( c = vect[k++] ) {
        !          5025:                     ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
        !          5026:                 }
        !          5027:             }
        !          5028:         MKNDV(nd_nvar,mr0,len,r);
        !          5029:         return r;
        !          5030:     }
1.65      noro     5031: }
                   5032:
1.129     noro     5033: /* for preprocessed vector */
                   5034:
1.113     noro     5035: NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead,UINT *s0vect)
1.107     noro     5036: {
1.157   ! noro     5037:     int j,k,len;
        !          5038:     UINT *p;
        !          5039:     Q c;
        !          5040:     NDV r;
        !          5041:     NMV mr0,mr;
        !          5042:
        !          5043:     for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
        !          5044:     if ( !len ) return 0;
        !          5045:     else {
        !          5046:         mr0 = (NMV)GC_malloc(nmv_adv*len);
1.107     noro     5047: #if 0
1.157   ! noro     5048:         ndv_alloc += nmv_adv*len;
1.107     noro     5049: #endif
1.157   ! noro     5050:         mr = mr0;
        !          5051:         p = s0vect;
        !          5052:         for ( j = k = 0; j < col; j++, p += nd_wpd )
        !          5053:             if ( !rhead[j] ) {
        !          5054:                 if ( c = vect[k++] ) {
        !          5055:                     if ( DN(c) )
        !          5056:                         error("afo");
        !          5057:                     ndl_copy(p,DL(mr)); CQ(mr) = c; NMV_ADV(mr);
        !          5058:                 }
        !          5059:             }
        !          5060:         MKNDV(nd_nvar,mr0,len,r);
        !          5061:         return r;
        !          5062:     }
1.107     noro     5063: }
                   5064:
1.129     noro     5065: /* for plain vector */
                   5066:
                   5067: NDV plain_vect_to_ndv_q(Q *vect,int col,UINT *s0vect)
                   5068: {
1.157   ! noro     5069:     int j,k,len;
        !          5070:     UINT *p;
        !          5071:     Q c;
        !          5072:     NDV r;
        !          5073:     NMV mr0,mr;
        !          5074:
        !          5075:     for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
        !          5076:     if ( !len ) return 0;
        !          5077:     else {
        !          5078:         mr0 = (NMV)GC_malloc(nmv_adv*len);
1.129     noro     5079: #if 0
1.157   ! noro     5080:         ndv_alloc += nmv_adv*len;
1.129     noro     5081: #endif
1.157   ! noro     5082:         mr = mr0;
        !          5083:         p = s0vect;
        !          5084:         for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
        !          5085:             if ( c = vect[k] ) {
        !          5086:                 if ( DN(c) )
        !          5087:                     error("afo");
        !          5088:                 ndl_copy(p,DL(mr)); CQ(mr) = c; NMV_ADV(mr);
        !          5089:             }
        !          5090:         MKNDV(nd_nvar,mr0,len,r);
        !          5091:         return r;
        !          5092:     }
1.129     noro     5093: }
                   5094:
1.133     noro     5095: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
1.65      noro     5096: {
1.157   ! noro     5097:     ND_pairs t;
        !          5098:     NODE sp0,sp;
        !          5099:     int stat;
        !          5100:     ND spol;
        !          5101:
        !          5102:     for ( t = l; t; t = NEXT(t) ) {
        !          5103:         stat = nd_sp(m,trace,t,&spol);
        !          5104:         if ( !stat ) return 0;
        !          5105:         if ( spol ) {
        !          5106:             add_pbucket_symbolic(bucket,spol);
        !          5107:         }
        !          5108:     }
        !          5109:     return 1;
1.65      noro     5110: }
                   5111:
1.133     noro     5112: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
1.65      noro     5113: {
1.157   ! noro     5114:     NODE rp0,rp;
        !          5115:     NM mul,head,s0,s;
        !          5116:     int index,col,i,sugar;
        !          5117:     RHist h;
        !          5118:     UINT *s0v,*p;
        !          5119:     NM_ind_pair pair;
        !          5120:     ND red;
        !          5121:     NDV *ps;
        !          5122:
        !          5123:     s0 = 0; rp0 = 0; col = 0;
        !          5124:     ps = trace?nd_ps_trace:nd_ps;
        !          5125:     while ( 1 ) {
        !          5126:         head = remove_head_pbucket_symbolic(bucket);
        !          5127:         if ( !head ) break;
        !          5128:         if ( !s0 ) s0 = head;
        !          5129:         else NEXT(s) = head;
        !          5130:         s = head;
        !          5131:         index = ndl_find_reducer(DL(head));
        !          5132:         if ( index >= 0 ) {
        !          5133:             h = nd_psh[index];
        !          5134:             NEWNM(mul);
        !          5135:             ndl_sub(DL(head),DL(h),DL(mul));
        !          5136:             if ( ndl_check_bound2(index,DL(mul)) ) return 0;
        !          5137:             sugar = TD(DL(mul))+SG(ps[index]);
        !          5138:             MKNM_ind_pair(pair,mul,index,sugar);
        !          5139:             red = ndv_mul_nm_symbolic(mul,ps[index]);
        !          5140:             add_pbucket_symbolic(bucket,nd_remove_head(red));
        !          5141:             NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
        !          5142:         }
        !          5143:         col++;
        !          5144:     }
        !          5145:     if ( rp0 ) NEXT(rp) = 0;
        !          5146:     NEXT(s) = 0;
        !          5147:     s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
        !          5148:     for ( i = 0, p = s0v, s = s0; i < col;
        !          5149:         i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
        !          5150:     *s0vect = s0v;
        !          5151:     *r = rp0;
        !          5152:     return col;
1.65      noro     5153: }
                   5154:
1.69      noro     5155: NODE nd_f4(int m)
                   5156: {
1.157   ! noro     5157:     int i,nh,stat,index;
        !          5158:     NODE r,g;
        !          5159:     ND_pairs d,l,t;
        !          5160:     ND spol,red;
        !          5161:     NDV nf,redv;
        !          5162:     NM s0,s;
        !          5163:     NODE rp0,srp0,nflist;
        !          5164:     int nsp,nred,col,rank,len,k,j,a;
        !          5165:     UINT c;
        !          5166:     UINT **spmat;
        !          5167:     UINT *s0vect,*svect,*p,*v;
        !          5168:     int *colstat;
        !          5169:     IndArray *imat;
        !          5170:     int *rhead;
        !          5171:     int spcol,sprow;
        !          5172:     int sugar;
        !          5173:     PGeoBucket bucket;
        !          5174:     struct oEGT eg0,eg1,eg_f4;
1.69      noro     5175:
1.103     noro     5176: #if 0
1.157   ! noro     5177:     ndv_alloc = 0;
1.103     noro     5178: #endif
1.157   ! noro     5179:     g = 0; d = 0;
        !          5180:     for ( i = 0; i < nd_psn; i++ ) {
        !          5181:         d = update_pairs(d,g,i);
        !          5182:         g = update_base(g,i);
        !          5183:     }
        !          5184:     while ( d ) {
        !          5185:         get_eg(&eg0);
        !          5186:         l = nd_minsugarp(d,&d);
        !          5187:         sugar = SG(l);
        !          5188:         bucket = create_pbucket();
        !          5189:         stat = nd_sp_f4(m,0,l,bucket);
        !          5190:         if ( !stat ) {
        !          5191:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5192:             NEXT(t) = d; d = l;
        !          5193:             d = nd_reconstruct(0,d);
        !          5194:             continue;
        !          5195:         }
        !          5196:         if ( bucket->m < 0 ) continue;
        !          5197:         col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
        !          5198:         if ( !col ) {
        !          5199:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5200:             NEXT(t) = d; d = l;
        !          5201:             d = nd_reconstruct(0,d);
        !          5202:             continue;
        !          5203:         }
        !          5204:         get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
        !          5205:         if ( DP_Print )
        !          5206:             fprintf(asir_out,"sugar=%d,symb=%fsec,",
        !          5207:                 sugar,eg_f4.exectime+eg_f4.gctime);
        !          5208:         if ( 1 )
        !          5209:             nflist = nd_f4_red(m,l,0,s0vect,col,rp0,0);
        !          5210:         else
        !          5211:             nflist = nd_f4_red_dist(m,l,s0vect,col,rp0,0);
        !          5212:         /* adding new bases */
        !          5213:         for ( r = nflist; r; r = NEXT(r) ) {
        !          5214:             nf = (NDV)BDY(r);
        !          5215:             ndv_removecont(m,nf);
        !          5216:             if ( !m && nd_nalg ) {
        !          5217:                 ND nf1;
        !          5218:
        !          5219:                 nf1 = ndvtond(m,nf);
        !          5220:                 nd_monic(0,&nf1);
        !          5221:                 nd_removecont(m,nf1);
        !          5222:                 nf = ndtondv(m,nf1);
        !          5223:             }
        !          5224:             nh = ndv_newps(m,nf,0);
        !          5225:             d = update_pairs(d,g,nh);
        !          5226:             g = update_base(g,nh);
        !          5227:         }
        !          5228:     }
        !          5229:     for ( r = g; r; r = NEXT(r) ) BDY(r) = (pointer)nd_ps[(int)BDY(r)];
1.103     noro     5230: #if 0
1.157   ! noro     5231:     fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
1.103     noro     5232: #endif
1.157   ! noro     5233:     return g;
1.69      noro     5234: }
1.74      noro     5235:
1.133     noro     5236: NODE nd_f4_trace(int m)
                   5237: {
1.157   ! noro     5238:     int i,nh,stat,index;
        !          5239:     NODE r,g;
        !          5240:     ND_pairs d,l,l0,t;
        !          5241:     ND spol,red;
        !          5242:     NDV nf,redv,nfqv,nfv;
        !          5243:     NM s0,s;
        !          5244:     NODE rp0,srp0,nflist;
        !          5245:     int nsp,nred,col,rank,len,k,j,a;
        !          5246:     UINT c;
        !          5247:     UINT **spmat;
        !          5248:     UINT *s0vect,*svect,*p,*v;
        !          5249:     int *colstat;
        !          5250:     IndArray *imat;
        !          5251:     int *rhead;
        !          5252:     int spcol,sprow;
        !          5253:     int sugar;
        !          5254:     PGeoBucket bucket;
        !          5255:     struct oEGT eg0,eg1,eg_f4;
        !          5256:
        !          5257:     g = 0; d = 0;
        !          5258:     for ( i = 0; i < nd_psn; i++ ) {
        !          5259:         d = update_pairs(d,g,i);
        !          5260:         g = update_base(g,i);
        !          5261:     }
        !          5262:     while ( d ) {
        !          5263:         get_eg(&eg0);
        !          5264:         l = nd_minsugarp(d,&d);
        !          5265:         sugar = SG(l);
        !          5266:         bucket = create_pbucket();
        !          5267:         stat = nd_sp_f4(m,0,l,bucket);
        !          5268:         if ( !stat ) {
        !          5269:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5270:             NEXT(t) = d; d = l;
        !          5271:             d = nd_reconstruct(1,d);
        !          5272:             continue;
        !          5273:         }
        !          5274:         if ( bucket->m < 0 ) continue;
        !          5275:         col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
        !          5276:         if ( !col ) {
        !          5277:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5278:             NEXT(t) = d; d = l;
        !          5279:             d = nd_reconstruct(1,d);
        !          5280:             continue;
        !          5281:         }
        !          5282:         get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
        !          5283:         if ( DP_Print )
        !          5284:             fprintf(asir_out,"sugar=%d,symb=%fsec,",
        !          5285:                 sugar,eg_f4.exectime+eg_f4.gctime);
        !          5286:         nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
        !          5287:         if ( !l0 ) continue;
        !          5288:         l = l0;
        !          5289:
        !          5290:         /* over Q */
        !          5291:         bucket = create_pbucket();
        !          5292:         stat = nd_sp_f4(0,1,l,bucket);
        !          5293:         if ( !stat ) {
        !          5294:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5295:             NEXT(t) = d; d = l;
        !          5296:             d = nd_reconstruct(1,d);
        !          5297:             continue;
        !          5298:         }
        !          5299:         if ( bucket->m < 0 ) continue;
        !          5300:         col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
        !          5301:         if ( !col ) {
        !          5302:             for ( t = l; NEXT(t); t = NEXT(t) );
        !          5303:             NEXT(t) = d; d = l;
        !          5304:             d = nd_reconstruct(1,d);
        !          5305:             continue;
        !          5306:         }
        !          5307:         nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
        !          5308:         /* adding new bases */
        !          5309:         for ( r = nflist; r; r = NEXT(r) ) {
        !          5310:             nfqv = (NDV)BDY(r);
        !          5311:             ndv_removecont(0,nfqv);
        !          5312:             if ( !rem(NM(HCQ(nfqv)),m) ) return 0;
        !          5313:             if ( nd_nalg ) {
        !          5314:                 ND nf1;
        !          5315:
        !          5316:                 nf1 = ndvtond(m,nfqv);
        !          5317:                 nd_monic(0,&nf1);
        !          5318:                 nd_removecont(0,nf1);
        !          5319:                 nfqv = ndtondv(0,nf1); nd_free(nf1);
        !          5320:             }
        !          5321:             nfv = ndv_dup(0,nfqv);
        !          5322:             ndv_mod(m,nfv);
        !          5323:             ndv_removecont(m,nfv);
        !          5324:             nh = ndv_newps(0,nfv,nfqv);
        !          5325:             d = update_pairs(d,g,nh);
        !          5326:             g = update_base(g,nh);
        !          5327:         }
        !          5328:     }
        !          5329:     for ( r = g; r; r = NEXT(r) ) BDY(r) = (pointer)nd_ps_trace[(int)BDY(r)];
1.133     noro     5330: #if 0
1.157   ! noro     5331:     fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
1.133     noro     5332: #endif
1.157   ! noro     5333:     return g;
1.133     noro     5334: }
                   5335:
                   5336: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
1.63      noro     5337: {
1.157   ! noro     5338:     IndArray *imat;
        !          5339:     int nsp,nred,i;
        !          5340:     int *rhead;
        !          5341:     NODE r0,rp;
        !          5342:     ND_pairs sp;
        !          5343:     NM_ind_pair *rvect;
        !          5344:
        !          5345:     for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
        !          5346:     nred = length(rp0);
        !          5347:     imat = (IndArray *)ALLOCA(nred*sizeof(IndArray));
        !          5348:     rhead = (int *)ALLOCA(col*sizeof(int));
        !          5349:     for ( i = 0; i < col; i++ ) rhead[i] = 0;
        !          5350:
        !          5351:     /* construction of index arrays */
        !          5352:     rvect = (NM_ind_pair *)ALLOCA(nred*sizeof(NM_ind_pair));
        !          5353:     for ( rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
        !          5354:         rvect[i] = (NM_ind_pair)BDY(rp);
        !          5355:         imat[i] = nm_ind_pair_to_vect_compress(m,s0vect,col,rvect[i]);
        !          5356:         rhead[imat[i]->head] = 1;
        !          5357:     }
        !          5358:     if ( m )
        !          5359:         r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
        !          5360:     else
        !          5361:         r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
        !          5362:     return r0;
1.106     noro     5363: }
1.74      noro     5364:
1.106     noro     5365: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
1.133     noro     5366:         NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
1.106     noro     5367: {
1.157   ! noro     5368:     int spcol,sprow,a;
        !          5369:     int i,j,k,l,rank;
        !          5370:     NODE r0,r;
        !          5371:     ND_pairs sp;
        !          5372:     ND spol;
        !          5373:     int **spmat;
        !          5374:     UINT *svect,*v;
        !          5375:     int *colstat;
        !          5376:     struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
        !          5377:     int maxrs;
        !          5378:     int *spsugar;
        !          5379:     ND_pairs *spactive;
        !          5380:
        !          5381:     spcol = col-nred;
        !          5382:     get_eg(&eg0);
        !          5383:     /* elimination (1st step) */
        !          5384:     spmat = (int **)ALLOCA(nsp*sizeof(UINT *));
        !          5385:     svect = (UINT *)ALLOCA(col*sizeof(UINT));
        !          5386:     spsugar = (int *)ALLOCA(nsp*sizeof(UINT));
        !          5387:     spactive = !nz?0:(ND_pairs *)ALLOCA(nsp*sizeof(ND_pairs));
        !          5388:     for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
        !          5389:         nd_sp(m,0,sp,&spol);
        !          5390:         if ( !spol ) continue;
        !          5391:         nd_to_vect(m,s0vect,col,spol,svect);
        !          5392:         if ( m == -1 )
        !          5393:             maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
        !          5394:         else
        !          5395:             maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred);
        !          5396:         for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
        !          5397:         if ( i < col ) {
        !          5398:             spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
        !          5399:             for ( j = k = 0; j < col; j++ )
        !          5400:                 if ( !rhead[j] ) v[k++] = svect[j];
        !          5401:             spsugar[sprow] = MAX(maxrs,SG(spol));
        !          5402:             if ( nz )
        !          5403:             spactive[sprow] = sp;
        !          5404:             sprow++;
        !          5405:         }
        !          5406:         nd_free(spol);
        !          5407:     }
        !          5408:     get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
        !          5409:     if ( DP_Print ) {
        !          5410:         fprintf(asir_out,"elim1=%fsec,",eg_f4_1.exectime+eg_f4_1.gctime);
        !          5411:         fflush(asir_out);
        !          5412:     }
        !          5413:     /* free index arrays */
        !          5414:     for ( i = 0; i < nred; i++ ) GC_free(imat[i]->index.c);
        !          5415:
        !          5416:     /* elimination (2nd step) */
        !          5417:     colstat = (int *)ALLOCA(spcol*sizeof(int));
        !          5418:     if ( m == -1 )
        !          5419:         rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
        !          5420:     else
        !          5421:         rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
        !          5422:     r0 = 0;
        !          5423:     for ( i = 0; i < rank; i++ ) {
        !          5424:         NEXTNODE(r0,r); BDY(r) =
        !          5425:             (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
        !          5426:         SG((NDV)BDY(r)) = spsugar[i];
        !          5427:         GC_free(spmat[i]);
        !          5428:     }
        !          5429:     if ( r0 ) NEXT(r) = 0;
        !          5430:
        !          5431:     for ( ; i < sprow; i++ ) GC_free(spmat[i]);
        !          5432:     get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
        !          5433:     init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
        !          5434:     if ( DP_Print ) {
        !          5435:         fprintf(asir_out,"elim2=%fsec\n",eg_f4_2.exectime+eg_f4_2.gctime);
        !          5436:         fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d  ",
        !          5437:             nsp,nred,sprow,spcol,rank);
        !          5438:         fprintf(asir_out,"%fsec\n",eg_f4.exectime+eg_f4.gctime);
        !          5439:     }
        !          5440:     if ( nz ) {
        !          5441:         for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
        !          5442:         if ( rank > 0 ) {
        !          5443:             NEXT(spactive[rank-1]) = 0;
        !          5444:             *nz = spactive[0];
        !          5445:         } else
        !          5446:             *nz = 0;
        !          5447:     }
        !          5448:     return r0;
1.74      noro     5449: }
                   5450:
1.133     noro     5451: #if 1
                   5452: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
1.107     noro     5453:         NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
                   5454: {
1.157   ! noro     5455:     int spcol,sprow,a;
        !          5456:     int i,j,k,l,rank;
        !          5457:     NODE r0,r;
        !          5458:     ND_pairs sp;
        !          5459:     ND spol;
        !          5460:     Q **spmat;
        !          5461:     Q *svect,*v;
        !          5462:     int *colstat;
        !          5463:     struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
        !          5464:     int maxrs;
        !          5465:     int *spsugar;
        !          5466:     pointer *w;
        !          5467:
        !          5468:     spcol = col-nred;
        !          5469:     get_eg(&eg0);
        !          5470:     /* elimination (1st step) */
        !          5471:     spmat = (Q **)ALLOCA(nsp*sizeof(Q *));
        !          5472:     svect = (Q *)ALLOCA(col*sizeof(Q));
        !          5473:     spsugar = (int *)ALLOCA(nsp*sizeof(Q));
        !          5474:     for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
        !          5475:         nd_sp(0,trace,sp,&spol);
        !          5476:         if ( !spol ) continue;
        !          5477:         nd_to_vect_q(s0vect,col,spol,svect);
        !          5478:         maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
        !          5479:         for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
        !          5480:         if ( i < col ) {
        !          5481:             spmat[sprow] = v = (Q *)MALLOC(spcol*sizeof(Q));
        !          5482:             for ( j = k = 0; j < col; j++ )
        !          5483:                 if ( !rhead[j] ) v[k++] = svect[j];
        !          5484:             spsugar[sprow] = MAX(maxrs,SG(spol));
        !          5485:             sprow++;
        !          5486:         }
        !          5487: /*        nd_free(spol); */
        !          5488:     }
        !          5489:     get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
        !          5490:     if ( DP_Print ) {
        !          5491:         fprintf(asir_out,"elim1=%fsec,",eg_f4_1.exectime+eg_f4_1.gctime);
        !          5492:         fflush(asir_out);
        !          5493:     }
        !          5494:     /* free index arrays */
        !          5495: /*    for ( i = 0; i < nred; i++ ) GC_free(imat[i]->index.c); */
        !          5496:
        !          5497:     /* elimination (2nd step) */
        !          5498:     colstat = (int *)ALLOCA(spcol*sizeof(int));
        !          5499:     rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
        !          5500:     w = (pointer *)ALLOCA(rank*sizeof(pointer));
        !          5501:     for ( i = 0; i < rank; i++ ) {
        !          5502:         w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
        !          5503:         SG((NDV)w[rank-i-1]) = spsugar[i];
        !          5504: /*        GC_free(spmat[i]); */
        !          5505:     }
1.138     noro     5506: #if 0
1.157   ! noro     5507:     qsort(w,rank,sizeof(NDV),
        !          5508:         (int (*)(const void *,const void *))ndv_compare);
1.137     noro     5509: #endif
1.157   ! noro     5510:     r0 = 0;
        !          5511:     for ( i = 0; i < rank; i++ ) {
        !          5512:         NEXTNODE(r0,r); BDY(r) = w[i];
        !          5513:     }
        !          5514:     if ( r0 ) NEXT(r) = 0;
        !          5515:
        !          5516: /*    for ( ; i < sprow; i++ ) GC_free(spmat[i]); */
        !          5517:     get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
        !          5518:     init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
        !          5519:     if ( DP_Print ) {
        !          5520:         fprintf(asir_out,"elim2=%fsec\n",eg_f4_2.exectime+eg_f4_2.gctime);
        !          5521:         fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d  ",
        !          5522:             nsp,nred,sprow,spcol,rank);
        !          5523:         fprintf(asir_out,"%fsec\n",eg_f4.exectime+eg_f4.gctime);
        !          5524:     }
        !          5525:     return r0;
1.107     noro     5526: }
1.129     noro     5527: #else
                   5528: void printm(Q **mat,int row,int col)
                   5529: {
1.157   ! noro     5530:     int i,j;
        !          5531:     printf("[");
        !          5532:     for ( i = 0; i < row; i++ ) {
        !          5533:         for ( j = 0; j < col; j++ ) {
        !          5534:             printexpr(CO,mat[i][j]); printf(" ");
        !          5535:         }
        !          5536:         printf("]\n");
        !          5537:     }
1.129     noro     5538: }
                   5539:
                   5540: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vect,int col,
                   5541:         NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
                   5542: {
1.157   ! noro     5543:     int row,a;
        !          5544:     int i,j,rank;
        !          5545:     NODE r0,r;
        !          5546:     ND_pairs sp;
        !          5547:     ND spol;
        !          5548:     Q **mat;
        !          5549:     int *colstat;
        !          5550:     int *sugar;
        !          5551:
        !          5552:     row = nsp+nred;
        !          5553:     /* make the matrix */
        !          5554:     mat = (Q **)ALLOCA(row*sizeof(Q *));
        !          5555:     sugar = (int *)ALLOCA(row*sizeof(int));
        !          5556:     for ( row = a = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
        !          5557:         nd_sp(0,0,sp,&spol);
        !          5558:         if ( !spol ) continue;
        !          5559:         mat[row] = (Q *)MALLOC(col*sizeof(Q));
        !          5560:         nd_to_vect_q(s0vect,col,spol,mat[row]);
        !          5561:         sugar[row] = SG(spol);
        !          5562:         row++;
        !          5563:     }
        !          5564:     for ( i = 0; i < nred; i++, row++ ) {
        !          5565:         mat[row] = nm_ind_pair_to_vect(0,s0vect,col,rvect[i]);
        !          5566:         sugar[row] = rvect[i]->sugar;
        !          5567:     }
        !          5568:     /* elimination */
        !          5569:     colstat = (int *)ALLOCA(col*sizeof(int));
        !          5570:     rank = nd_gauss_elim_q(mat,sugar,row,col,colstat);
        !          5571:     r0 = 0;
        !          5572:     for ( i = 0; i < rank; i++ ) {
        !          5573:         for ( j = 0; j < col; j++ ) if ( mat[i][j] ) break;
        !          5574:         if ( j == col ) error("nd_f4_red_q_main : cannot happen");
        !          5575:         if ( rhead[j] ) continue;
        !          5576:         NEXTNODE(r0,r); BDY(r) =
        !          5577:             (pointer)plain_vect_to_ndv_q(mat[i],col,s0vect);
        !          5578:         SG((NDV)BDY(r)) = sugar[i];
        !          5579:     }
        !          5580:     if ( r0 ) NEXT(r) = 0;
        !          5581:     printf("\n");
        !          5582:     return r0;
1.129     noro     5583: }
                   5584: #endif
1.107     noro     5585:
1.74      noro     5586: FILE *nd_write,*nd_read;
                   5587:
                   5588: void nd_send_int(int a) {
1.157   ! noro     5589:     write_int(nd_write,&a);
1.74      noro     5590: }
                   5591:
                   5592: void nd_send_intarray(int *p,int len) {
1.157   ! noro     5593:     write_intarray(nd_write,p,len);
1.74      noro     5594: }
                   5595:
                   5596: int nd_recv_int() {
1.157   ! noro     5597:     int a;
1.74      noro     5598:
1.157   ! noro     5599:     read_int(nd_read,&a);
        !          5600:     return a;
1.74      noro     5601: }
                   5602:
                   5603: void nd_recv_intarray(int *p,int len) {
1.157   ! noro     5604:     read_intarray(nd_read,p,len);
1.74      noro     5605: }
                   5606:
                   5607: void nd_send_ndv(NDV p) {
1.157   ! noro     5608:     int len,i;
        !          5609:     NMV m;
1.74      noro     5610:
1.157   ! noro     5611:     if ( !p ) nd_send_int(0);
        !          5612:     else {
        !          5613:         len = LEN(p);
        !          5614:         nd_send_int(len);
        !          5615:         m = BDY(p);
        !          5616:         for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          5617:             nd_send_int(CM(m));
        !          5618:             nd_send_intarray(DL(m),nd_wpd);
        !          5619:         }
        !          5620:     }
1.74      noro     5621: }
                   5622:
                   5623: void nd_send_nd(ND p) {
1.157   ! noro     5624:     int len,i;
        !          5625:     NM m;
1.74      noro     5626:
1.157   ! noro     5627:     if ( !p ) nd_send_int(0);
        !          5628:     else {
        !          5629:         len = LEN(p);
        !          5630:         nd_send_int(len);
        !          5631:         m = BDY(p);
        !          5632:         for ( i = 0; i < len; i++, m = NEXT(m) ) {
        !          5633:             nd_send_int(CM(m));
        !          5634:             nd_send_intarray(DL(m),nd_wpd);
        !          5635:         }
        !          5636:     }
1.74      noro     5637: }
1.65      noro     5638:
1.74      noro     5639: NDV nd_recv_ndv()
                   5640: {
1.157   ! noro     5641:     int len,i;
        !          5642:     NMV m,m0;
        !          5643:     NDV r;
        !          5644:
        !          5645:     len = nd_recv_int();
        !          5646:     if ( !len ) return 0;
        !          5647:     else {
        !          5648:         m0 = m = (NMV)GC_malloc_atomic_ignore_off_page(nmv_adv*len);
1.103     noro     5649: #if 0
1.157   ! noro     5650:         ndv_alloc += len*nmv_adv;
1.103     noro     5651: #endif
1.157   ! noro     5652:         for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          5653:             CM(m) = nd_recv_int();
        !          5654:             nd_recv_intarray(DL(m),nd_wpd);
        !          5655:         }
        !          5656:         MKNDV(nd_nvar,m0,len,r);
        !          5657:         return r;
        !          5658:     }
1.74      noro     5659: }
1.65      noro     5660:
1.74      noro     5661: int ox_exec_f4_red(Q proc)
                   5662: {
1.157   ! noro     5663:     Obj obj;
        !          5664:     STRING fname;
        !          5665:     NODE arg;
        !          5666:     int s;
        !          5667:     extern int ox_need_conv,ox_file_io;
        !          5668:
        !          5669:     MKSTR(fname,"nd_exec_f4_red");
        !          5670:     arg = mknode(2,proc,fname);
        !          5671:     Pox_cmo_rpc(arg,&obj);
        !          5672:     s = get_ox_server_id(QTOS(proc));
        !          5673:     nd_write = iofp[s].out;
        !          5674:     nd_read = iofp[s].in;
        !          5675:     ox_need_conv = ox_file_io = 0;
        !          5676:     return s;
1.74      noro     5677: }
                   5678:
1.133     noro     5679: NODE nd_f4_red_dist(int m,ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
1.74      noro     5680: {
1.157   ! noro     5681:     int nsp,nred;
        !          5682:     int i,rank,s;
        !          5683:     NODE rp,r0,r;
        !          5684:     ND_pairs sp;
        !          5685:     NM_ind_pair pair;
        !          5686:     NMV nmv;
        !          5687:     NM nm;
        !          5688:     NDV nf;
        !          5689:     Obj proc,dmy;
        !          5690:
        !          5691:     ox_launch_main(0,0,&proc);
        !          5692:     s = ox_exec_f4_red((Q)proc);
        !          5693:
        !          5694:     nd_send_int(m);
        !          5695:     nd_send_int(nd_nvar);
        !          5696:     nd_send_int(nd_bpe);
        !          5697:     nd_send_int(nd_wpd);
        !          5698:     nd_send_int(nmv_adv);
        !          5699:
        !          5700:     saveobj(nd_write,dp_current_spec->obj); fflush(nd_write);
        !          5701:
        !          5702:     nd_send_int(nd_psn);
        !          5703:     for ( i = 0; i < nd_psn; i++ ) nd_send_ndv(nd_ps[i]);
        !          5704:
        !          5705:     for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
        !          5706:     nd_send_int(nsp);
        !          5707:     for ( i = 0, sp = sp0; i < nsp; i++, sp = NEXT(sp) ) {
        !          5708:         nd_send_int(sp->i1); nd_send_int(sp->i2);
        !          5709:     }
        !          5710:
        !          5711:     nd_send_int(col); nd_send_intarray(s0vect,col*nd_wpd);
        !          5712:
        !          5713:     nred = length(rp0); nd_send_int(nred);
        !          5714:     for ( i = 0, rp = rp0; i < nred; i++, rp = NEXT(rp) ) {
        !          5715:         pair = (NM_ind_pair)BDY(rp);
        !          5716:         nd_send_int(pair->index);
        !          5717:         nd_send_intarray(pair->mul->dl,nd_wpd);
        !          5718:     }
        !          5719:     fflush(nd_write);
        !          5720:     rank = nd_recv_int();
        !          5721:     fprintf(asir_out,"rank=%d\n",rank);
        !          5722:     r0 = 0;
        !          5723:     for ( i = 0; i < rank; i++ ) {
        !          5724:         nf = nd_recv_ndv();
        !          5725:         NEXTNODE(r0,r); BDY(r) = (pointer)nf;
        !          5726:     }
        !          5727:     Pox_shutdown(mknode(1,proc),&dmy);
        !          5728:     return r0;
1.74      noro     5729: }
                   5730:
                   5731: /* server side */
                   5732:
                   5733: void nd_exec_f4_red_dist()
                   5734: {
1.157   ! noro     5735:     int m,i,nsp,col,s0size,nred,spcol,j,k;
        !          5736:     NM_ind_pair *rp0;
        !          5737:     NDV nf;
        !          5738:     UINT *s0vect;
        !          5739:     IndArray *imat;
        !          5740:     int *rhead;
        !          5741:     int **spmat;
        !          5742:     UINT *svect,*v;
        !          5743:     ND_pairs *sp0;
        !          5744:     int *colstat;
        !          5745:     int a,sprow,rank;
        !          5746:     struct order_spec *ord;
        !          5747:     Obj ordspec;
        !          5748:     ND spol;
        !          5749:     int maxrs;
        !          5750:     int *spsugar;
        !          5751:
        !          5752:     nd_read = iofp[0].in;
        !          5753:     nd_write = iofp[0].out;
        !          5754:     m = nd_recv_int();
        !          5755:     nd_nvar = nd_recv_int();
        !          5756:     nd_bpe = nd_recv_int();
        !          5757:     nd_wpd = nd_recv_int();
        !          5758:     nmv_adv = nd_recv_int();
        !          5759:
        !          5760:     loadobj(nd_read,&ordspec);
        !          5761:     create_order_spec(0,ordspec,&ord);
        !          5762:     nd_init_ord(ord);
        !          5763:     nd_setup_parameters(nd_nvar,0);
        !          5764:
        !          5765:     nd_psn = nd_recv_int();
        !          5766:     nd_ps = (NDV *)MALLOC(nd_psn*sizeof(NDV));
        !          5767:     nd_bound = (UINT **)MALLOC(nd_psn*sizeof(UINT *));
        !          5768:     for ( i = 0; i < nd_psn; i++ ) {
        !          5769:         nd_ps[i] = nd_recv_ndv();
        !          5770:         nd_bound[i] = ndv_compute_bound(nd_ps[i]);
        !          5771:     }
        !          5772:
        !          5773:     nsp = nd_recv_int();
        !          5774:     sp0 = (ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
        !          5775:     for ( i = 0; i < nsp; i++ ) {
        !          5776:         NEWND_pairs(sp0[i]);
        !          5777:         sp0[i]->i1 = nd_recv_int(); sp0[i]->i2 = nd_recv_int();
        !          5778:         ndl_lcm(HDL(nd_ps[sp0[i]->i1]),HDL(nd_ps[sp0[i]->i2]),LCM(sp0[i]));
        !          5779:     }
        !          5780:
        !          5781:     col = nd_recv_int();
        !          5782:     s0size = col*nd_wpd;
        !          5783:     s0vect = (UINT *)MALLOC(s0size*sizeof(UINT));
        !          5784:     nd_recv_intarray(s0vect,s0size);
        !          5785:
        !          5786:     nred = nd_recv_int();
        !          5787:     rp0 = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
        !          5788:     for ( i = 0; i < nred; i++ ) {
        !          5789:         rp0[i] = (NM_ind_pair)MALLOC(sizeof(struct oNM_ind_pair));
        !          5790:         rp0[i]->index = nd_recv_int();
        !          5791:         rp0[i]->mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
        !          5792:         nd_recv_intarray(rp0[i]->mul->dl,nd_wpd);
        !          5793:     }
        !          5794:
        !          5795:     spcol = col-nred;
        !          5796:     imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
        !          5797:     rhead = (int *)MALLOC(col*sizeof(int));
        !          5798:     for ( i = 0; i < col; i++ ) rhead[i] = 0;
        !          5799:
        !          5800:     /* construction of index arrays */
        !          5801:     for ( i = 0; i < nred; i++ ) {
        !          5802:         imat[i] = nm_ind_pair_to_vect_compress(m,s0vect,col,rp0[i]);
        !          5803:         rhead[imat[i]->head] = 1;
        !          5804:     }
        !          5805:
        !          5806:     /* elimination (1st step) */
        !          5807:     spmat = (int **)MALLOC(nsp*sizeof(UINT *));
        !          5808:     svect = (UINT *)MALLOC(col*sizeof(UINT));
        !          5809:     spsugar = (int *)ALLOCA(nsp*sizeof(UINT));
        !          5810:     for ( a = sprow = 0; a < nsp; a++ ) {
        !          5811:         nd_sp(m,0,sp0[a],&spol);
        !          5812:         if ( !spol ) continue;
        !          5813:         nd_to_vect(m,s0vect,col,spol,svect);
        !          5814:         if ( m == -1 )
        !          5815:             maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rp0,nred);
        !          5816:         else
        !          5817:             maxrs = ndv_reduce_vect(m,svect,col,imat,rp0,nred);
        !          5818:         for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
        !          5819:         if ( i < col ) {
        !          5820:             spmat[sprow] = v = (UINT *)MALLOC(spcol*sizeof(UINT));
        !          5821:             for ( j = k = 0; j < col; j++ )
        !          5822:                 if ( !rhead[j] ) v[k++] = svect[j];
        !          5823:             spsugar[sprow] = MAX(maxrs,SG(spol));
        !          5824:             sprow++;
        !          5825:         }
        !          5826:         nd_free(spol);
        !          5827:     }
        !          5828:     /* elimination (2nd step) */
        !          5829:     colstat = (int *)ALLOCA(spcol*sizeof(int));
        !          5830:     if ( m == -1 )
        !          5831:         rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
        !          5832:     else
        !          5833:         rank = nd_gauss_elim_mod(spmat,spsugar,0,sprow,spcol,m,colstat);
        !          5834:     nd_send_int(rank);
        !          5835:     for ( i = 0; i < rank; i++ ) {
        !          5836:         nf = vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
        !          5837:         nd_send_ndv(nf);
        !          5838:     }
        !          5839:     fflush(nd_write);
1.107     noro     5840: }
                   5841:
1.113     noro     5842: int nd_gauss_elim_q(Q **mat0,int *sugar,int row,int col,int *colstat)
1.107     noro     5843: {
1.157   ! noro     5844:     int mod,i,j,t,c,rank,rank0,inv;
        !          5845:     int *ci,*ri;
        !          5846:     Q dn;
        !          5847:     MAT m,nm;
        !          5848:     int **wmat;
        !          5849:
        !          5850:     /* XXX */
        !          5851:     mod = 99999989;
        !          5852:     wmat = (int **)ALLOCA(row*sizeof(int *));
        !          5853:     for ( i = 0; i < row; i++ ) {
        !          5854:         wmat[i] = (int *)ALLOCA(col*sizeof(int));
        !          5855:         for ( j = 0; j < col; j++ ) {
        !          5856:             if ( mat0[i][j] ) {
        !          5857:                 t = rem(NM(mat0[i][j]),mod);
        !          5858:                 if ( SGN(mat0[i][j]) < 0 ) t = mod-t;
        !          5859:                 wmat[i][j] = t;
        !          5860:             } else
        !          5861:                 wmat[i][j] = 0;
        !          5862:         }
        !          5863:     }
        !          5864:     rank0 = nd_gauss_elim_mod(wmat,sugar,0,row,col,mod,colstat);
        !          5865:     NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
        !          5866:     rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
        !          5867:     if ( rank != rank0 )
        !          5868:         error("afo");
        !          5869:     for ( i = 0; i < row; i++ )
        !          5870:         for ( j = 0; j < col; j++ )
        !          5871:             mat0[i][j] = 0;
        !          5872:     c = col-rank;
        !          5873:     for ( i = 0; i < rank; i++ ) {
        !          5874:         mat0[i][ri[i]] = dn;
        !          5875:         for ( j = 0; j < c; j++ )
        !          5876:             mat0[i][ci[j]] = (Q)BDY(nm)[i][j];
        !          5877:     }
        !          5878:     inv = invm(rem(NM(dn),mod),mod);
        !          5879:     if ( SGN(dn) < 0 ) inv = mod-inv;
        !          5880:     for ( i = 0; i < row; i++ )
        !          5881:         for ( j = 0; j < col; j++ ) {
        !          5882:             if ( mat0[i][j] ) {
        !          5883:                 t = rem(NM(mat0[i][j]),mod);
        !          5884:                 if ( SGN(mat0[i][j]) < 0 ) t = mod-t;
        !          5885:             } else
        !          5886:                 t = 0;
        !          5887:             c = dmar(t,inv,0,mod);
        !          5888:             if ( wmat[i][j] != c )
        !          5889:                 error("afo");
        !          5890:         }
        !          5891:     return rank;
1.76      noro     5892: }
                   5893:
1.133     noro     5894: int nd_gauss_elim_mod(int **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
1.76      noro     5895: {
1.157   ! noro     5896:     int i,j,k,l,inv,a,rank,s;
        !          5897:     unsigned int *t,*pivot,*pk;
        !          5898:     unsigned int **mat;
        !          5899:     ND_pairs pair;
        !          5900:
        !          5901:     mat = (unsigned int **)mat0;
        !          5902:     for ( rank = 0, j = 0; j < col; j++ ) {
        !          5903:         for ( i = rank; i < row; i++ )
        !          5904:             mat[i][j] %= md;
        !          5905:         for ( i = rank; i < row; i++ )
        !          5906:             if ( mat[i][j] )
        !          5907:                 break;
        !          5908:         if ( i == row ) {
        !          5909:             colstat[j] = 0;
        !          5910:             continue;
        !          5911:         } else
        !          5912:             colstat[j] = 1;
        !          5913:         if ( i != rank ) {
        !          5914:             t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
        !          5915:             s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
        !          5916:             if ( spactive ) {
        !          5917:                 pair = spactive[i]; spactive[i] = spactive[rank];
        !          5918:                 spactive[rank] = pair;
        !          5919:             }
        !          5920:         }
        !          5921:         pivot = mat[rank];
        !          5922:         s = sugar[rank];
        !          5923:         inv = invm(pivot[j],md);
        !          5924:         for ( k = j, pk = pivot+k; k < col; k++, pk++ )
        !          5925:             if ( *pk ) {
        !          5926:                 if ( *pk >= (unsigned int)md )
        !          5927:                     *pk %= md;
        !          5928:                 DMAR(*pk,inv,0,md,*pk)
        !          5929:             }
        !          5930:         for ( i = rank+1; i < row; i++ ) {
        !          5931:             t = mat[i];
        !          5932:             if ( a = t[j] ) {
        !          5933:                 sugar[i] = MAX(sugar[i],s);
        !          5934:                 red_by_vect(md,t+j,pivot+j,md-a,col-j);
        !          5935:             }
        !          5936:         }
        !          5937:         rank++;
        !          5938:     }
        !          5939:     for ( j = col-1, l = rank-1; j >= 0; j-- )
        !          5940:         if ( colstat[j] ) {
        !          5941:             pivot = mat[l];
        !          5942:             s = sugar[l];
        !          5943:             for ( i = 0; i < l; i++ ) {
        !          5944:                 t = mat[i];
        !          5945:                 t[j] %= md;
        !          5946:                 if ( a = t[j] ) {
        !          5947:                     sugar[i] = MAX(sugar[i],s);
        !          5948:                     red_by_vect(md,t+j,pivot+j,md-a,col-j);
        !          5949:                 }
        !          5950:             }
        !          5951:             l--;
        !          5952:         }
        !          5953:     for ( j = 0, l = 0; l < rank; j++ )
        !          5954:         if ( colstat[j] ) {
        !          5955:             t = mat[l];
        !          5956:             for ( k = j; k < col; k++ )
        !          5957:                 if ( t[k] >= (unsigned int)md )
        !          5958:                     t[k] %= md;
        !          5959:             l++;
        !          5960:         }
        !          5961:     return rank;
1.76      noro     5962: }
                   5963:
                   5964: int nd_gauss_elim_sf(int **mat0,int *sugar,int row,int col,int md,int *colstat)
                   5965: {
1.157   ! noro     5966:     int i,j,k,l,inv,a,rank,s;
        !          5967:     unsigned int *t,*pivot,*pk;
        !          5968:     unsigned int **mat;
        !          5969:
        !          5970:     mat = (unsigned int **)mat0;
        !          5971:     for ( rank = 0, j = 0; j < col; j++ ) {
        !          5972:         for ( i = rank; i < row; i++ )
        !          5973:             if ( mat[i][j] )
        !          5974:                 break;
        !          5975:         if ( i == row ) {
        !          5976:             colstat[j] = 0;
        !          5977:             continue;
        !          5978:         } else
        !          5979:             colstat[j] = 1;
        !          5980:         if ( i != rank ) {
        !          5981:             t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
        !          5982:             s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
        !          5983:         }
        !          5984:         pivot = mat[rank];
        !          5985:         s = sugar[rank];
        !          5986:         inv = _invsf(pivot[j]);
        !          5987:         for ( k = j, pk = pivot+k; k < col; k++, pk++ )
        !          5988:             if ( *pk )
        !          5989:                 *pk = _mulsf(*pk,inv);
        !          5990:         for ( i = rank+1; i < row; i++ ) {
        !          5991:             t = mat[i];
        !          5992:             if ( a = t[j] ) {
        !          5993:                 sugar[i] = MAX(sugar[i],s);
        !          5994:                 red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
        !          5995:             }
        !          5996:         }
        !          5997:         rank++;
        !          5998:     }
        !          5999:     for ( j = col-1, l = rank-1; j >= 0; j-- )
        !          6000:         if ( colstat[j] ) {
        !          6001:             pivot = mat[l];
        !          6002:             s = sugar[l];
        !          6003:             for ( i = 0; i < l; i++ ) {
        !          6004:                 t = mat[i];
        !          6005:                 if ( a = t[j] ) {
        !          6006:                     sugar[i] = MAX(sugar[i],s);
        !          6007:                     red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
        !          6008:                 }
        !          6009:             }
        !          6010:             l--;
        !          6011:         }
        !          6012:     return rank;
1.77      noro     6013: }
                   6014:
                   6015: int ndv_ishomo(NDV p)
                   6016: {
1.157   ! noro     6017:     NMV m;
        !          6018:     int len,h;
1.77      noro     6019:
1.157   ! noro     6020:     if ( !p ) return 1;
        !          6021:     len = LEN(p);
        !          6022:     m = BDY(p);
        !          6023:     h = TD(DL(m));
        !          6024:     NMV_ADV(m);
        !          6025:     for ( len--; len; len--, NMV_ADV(m) )
        !          6026:         if ( TD(DL(m)) != h ) return 0;
        !          6027:     return 1;
1.77      noro     6028: }
                   6029:
                   6030: void ndv_save(NDV p,int index)
                   6031: {
1.157   ! noro     6032:     FILE *s;
        !          6033:     char name[BUFSIZ];
        !          6034:     short id;
        !          6035:     int nv,sugar,len,n,i,td,e,j;
        !          6036:     NMV m;
        !          6037:     unsigned int *dl;
        !          6038:     int mpos;
        !          6039:
        !          6040:     sprintf(name,"%s/%d",Demand,index);
        !          6041:     s = fopen(name,"w");
        !          6042:     savevl(s,0);
        !          6043:     if ( !p ) {
        !          6044:         saveobj(s,0);
        !          6045:         return;
        !          6046:     }
        !          6047:     id = O_DP;
        !          6048:     nv = NV(p);
        !          6049:     sugar = SG(p);
        !          6050:     len = LEN(p);
        !          6051:     write_short(s,&id); write_int(s,&nv); write_int(s,&sugar);
        !          6052:     write_int(s,&len);
        !          6053:
        !          6054:     for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
        !          6055:         saveobj(s,(Obj)CQ(m));
        !          6056:         dl = DL(m);
        !          6057:         td = TD(dl);
        !          6058:         write_int(s,&td);
        !          6059:         for ( j = 0; j < nv; j++ ) {
        !          6060:             e = GET_EXP(dl,j);
        !          6061:             write_int(s,&e);
        !          6062:         }
        !          6063:         if ( nd_module ) {
        !          6064:             mpos = MPOS(dl); write_int(s,&mpos);
        !          6065:         }
        !          6066:     }
        !          6067:     fclose(s);
1.77      noro     6068: }
                   6069:
                   6070: NDV ndv_load(int index)
                   6071: {
1.157   ! noro     6072:     FILE *s;
        !          6073:     char name[BUFSIZ];
        !          6074:     short id;
        !          6075:     int nv,sugar,len,n,i,td,e,j;
        !          6076:     NDV d;
        !          6077:     NMV m0,m;
        !          6078:     unsigned int *dl;
        !          6079:     Obj obj;
        !          6080:     int mpos;
        !          6081:
        !          6082:     sprintf(name,"%s/%d",Demand,index);
        !          6083:     s = fopen(name,"r");
        !          6084:     if ( !s ) return 0;
        !          6085:
        !          6086:     skipvl(s);
        !          6087:     read_short(s,&id);
        !          6088:     if ( !id ) return 0;
        !          6089:     read_int(s,&nv);
        !          6090:     read_int(s,&sugar);
        !          6091:     read_int(s,&len);
        !          6092:
        !          6093:     m0 = m = MALLOC(len*nmv_adv);
        !          6094:     for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          6095:         loadobj(s,&obj); CQ(m) = (Q)obj;
        !          6096:         dl = DL(m);
        !          6097:         ndl_zero(dl);
        !          6098:         read_int(s,&td); TD(dl) = td;
        !          6099:         for ( j = 0; j < nv; j++ ) {
        !          6100:             read_int(s,&e);
        !          6101:             PUT_EXP(dl,j,e);
        !          6102:         }
        !          6103:         if ( nd_module ) {
        !          6104:             read_int(s,&mpos); MPOS(dl) = mpos;
        !          6105:         }
        !          6106:         if ( nd_blockmask ) ndl_weight_mask(dl);
        !          6107:     }
        !          6108:     fclose(s);
        !          6109:     MKNDV(nv,m0,len,d);
        !          6110:     SG(d) = sugar;
        !          6111:     return d;
1.99      noro     6112: }
                   6113:
1.102     noro     6114: void nd_det(int mod,MAT f,P *rp)
1.99      noro     6115: {
1.157   ! noro     6116:     VL fv,tv;
        !          6117:     int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
        !          6118:     pointer **m;
        !          6119:     Q mone;
        !          6120:     P **w;
        !          6121:     P mp,r;
        !          6122:     NDV **dm;
        !          6123:     NDV *t,*mi,*mj;
        !          6124:     NDV d,s,mij,mjj;
        !          6125:     ND u;
        !          6126:     NMV nmv;
        !          6127:     UINT *bound;
        !          6128:     PGeoBucket bucket;
        !          6129:     struct order_spec *ord;
        !          6130:     Q dq,dt,ds;
        !          6131:     N gn,qn,dn0,nm,dn;
        !          6132:
        !          6133:     create_order_spec(0,0,&ord);
        !          6134:     nd_init_ord(ord);
        !          6135:     get_vars((Obj)f,&fv);
        !          6136:     if ( f->row != f->col )
        !          6137:         error("nd_det : non-square matrix");
        !          6138:     n = f->row;
        !          6139:     m = f->body;
        !          6140:     for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
        !          6141:
        !          6142:     if ( !nvar ) {
        !          6143:         if ( !mod )
        !          6144:             detp(CO,(P **)m,n,rp);
        !          6145:         else {
        !          6146:             w = (P **)almat_pointer(n,n);
        !          6147:             for ( i = 0; i < n; i++ )
        !          6148:                 for ( j = 0; j < n; j++ )
        !          6149:                     ptomp(mod,(P)m[i][j],&w[i][j]);
        !          6150:             detmp(CO,mod,w,n,&mp);
        !          6151:             mptop(mp,rp);
        !          6152:         }
        !          6153:         return;
        !          6154:     }
        !          6155:
        !          6156:     if ( !mod ) {
        !          6157:         w = (P **)almat_pointer(n,n);
        !          6158:         dq = ONE;
        !          6159:         for ( i = 0; i < n; i++ ) {
        !          6160:             dn0 = ONEN;
        !          6161:             for ( j = 0; j < n; j++ ) {
        !          6162:                 if ( !m[i][j] ) continue;
        !          6163:                 lgp(m[i][j],&nm,&dn);
        !          6164:                 gcdn(dn0,dn,&gn); divsn(dn0,gn,&qn); muln(qn,dn,&dn0);
        !          6165:             }
        !          6166:             if ( !UNIN(dn0) ) {
        !          6167:                 NTOQ(dn0,1,ds);
        !          6168:                 for ( j = 0; j < n; j++ )
        !          6169:                     mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
        !          6170:                 mulq(dq,ds,&dt); dq = dt;
        !          6171:             } else
        !          6172:                 for ( j = 0; j < n; j++ )
        !          6173:                     w[i][j] = (P)m[i][j];
        !          6174:         }
        !          6175:         m = (pointer **)w;
        !          6176:     }
        !          6177:
        !          6178:     for ( i = 0, max = 0; i < n; i++ )
        !          6179:         for ( j = 0; j < n; j++ )
        !          6180:             for ( tv = fv; tv; tv = NEXT(tv) ) {
        !          6181:                 e = getdeg(tv->v,(P)m[i][j]);
        !          6182:                 max = MAX(e,max);
        !          6183:             }
        !          6184:     nd_setup_parameters(nvar,max);
        !          6185:     dm = (NDV **)almat_pointer(n,n);
        !          6186:     for ( i = 0, max = 0; i < n; i++ )
        !          6187:         for ( j = 0; j < n; j++ ) {
        !          6188:             dm[i][j] = ptondv(CO,fv,m[i][j]);
        !          6189:             if ( mod ) ndv_mod(mod,dm[i][j]);
        !          6190:             if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
        !          6191:         }
        !          6192:     d = ptondv(CO,fv,(P)ONE);
        !          6193:     if ( mod ) ndv_mod(mod,d);
        !          6194:     chsgnq(ONE,&mone);
        !          6195:     for ( j = 0, sgn = 1; j < n; j++ ) {
        !          6196:         if ( DP_Print ) fprintf(stderr,".",j);
        !          6197:         for ( i = j; i < n && !dm[i][j]; i++ );
        !          6198:         if ( i == n ) {
        !          6199:             *rp = 0;
        !          6200:             return;
        !          6201:         }
        !          6202:         k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
        !          6203:         for ( k = j; k < n; k++ )
        !          6204:             for ( l = j; l < n; l++ )
        !          6205:                 if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
        !          6206:                     k0 = k; l0 = l; len0 = LEN(dm[k][l]);
        !          6207:                 }
        !          6208:         if ( k0 != j ) {
        !          6209:             t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
        !          6210:             sgn = -sgn;
        !          6211:         }
        !          6212:         if ( l0 != j ) {
        !          6213:             for ( k = j; k < n; k++ ) {
        !          6214:                 s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
        !          6215:             }
        !          6216:             sgn = -sgn;
        !          6217:         }
        !          6218:         bound = nd_det_compute_bound(dm,n,j);
        !          6219:         for ( k = 0; k < nd_nvar; k++ )
        !          6220:             if ( bound[k]*2 > nd_mask0 ) break;
        !          6221:         if ( k < nd_nvar )
        !          6222:             nd_det_reconstruct(dm,n,j,d);
        !          6223:
        !          6224:         for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
        !          6225: /*            if ( DP_Print ) fprintf(stderr,"    i=%d\n        ",i); */
        !          6226:             mi = dm[i]; mij = mi[j];
        !          6227:             if ( mod )
        !          6228:                 ndv_mul_c(mod,mij,mod-1);
        !          6229:             else
        !          6230:                 ndv_mul_c_q(mij,mone);
        !          6231:             for ( k = j+1; k < n; k++ ) {
        !          6232: /*                if ( DP_Print ) fprintf(stderr,"k=%d ",k); */
        !          6233:                 bucket = create_pbucket();
        !          6234:                 if ( mi[k] ) {
        !          6235:                     nmv = BDY(mjj); len = LEN(mjj);
        !          6236:                     for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
        !          6237:                         u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
        !          6238:                         add_pbucket(mod,bucket,u);
        !          6239:                     }
        !          6240:                 }
        !          6241:                 if ( mj[k] && mij ) {
        !          6242:                     nmv = BDY(mij); len = LEN(mij);
        !          6243:                     for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
        !          6244:                         u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
        !          6245:                         add_pbucket(mod,bucket,u);
        !          6246:                     }
        !          6247:                 }
        !          6248:                 u = nd_quo(mod,bucket,d);
        !          6249:                 mi[k] = ndtondv(mod,u);
        !          6250:             }
        !          6251: /*            if ( DP_Print ) fprintf(stderr,"\n",k); */
        !          6252:         }
        !          6253:         d = mjj;
        !          6254:     }
        !          6255:     if ( DP_Print ) fprintf(stderr,"\n",k);
        !          6256:     if ( sgn < 0 )
        !          6257:         if ( mod )
        !          6258:             ndv_mul_c(mod,d,mod-1);
        !          6259:         else
        !          6260:             ndv_mul_c_q(d,mone);
        !          6261:     r = ndvtop(mod,CO,fv,d);
        !          6262:     if ( !mod && !UNIQ(dq) )
        !          6263:         divsp(CO,r,(P)dq,rp);
        !          6264:     else
        !          6265:         *rp = r;
1.99      noro     6266: }
                   6267:
1.102     noro     6268: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
1.99      noro     6269: {
1.157   ! noro     6270:     NM mr,mr0;
        !          6271:     NM tnm;
        !          6272:     NMV m;
        !          6273:     UINT *d0,*dt,*dm;
        !          6274:     int c,n,td,i,c1,c2,len;
        !          6275:     Q q;
        !          6276:     ND r;
        !          6277:
        !          6278:     if ( !p ) return 0;
        !          6279:     else {
        !          6280:         n = NV(p); m = BDY(p); len = LEN(p);
        !          6281:         d0 = DL(m0);
        !          6282:         td = TD(d);
        !          6283:         mr0 = 0;
        !          6284:         NEWNM(tnm);
        !          6285:         if ( mod ) {
        !          6286:             c = CM(m0);
        !          6287:             for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          6288:                 ndl_add(DL(m),d0,DL(tnm));
        !          6289:                 if ( ndl_reducible(DL(tnm),d) ) {
        !          6290:                     NEXTNM(mr0,mr);
        !          6291:                     c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
        !          6292:                     ndl_copy(DL(tnm),DL(mr));
        !          6293:                 }
        !          6294:             }
        !          6295:         } else {
        !          6296:             q = CQ(m0);
        !          6297:             for ( i = 0; i < len; i++, NMV_ADV(m) ) {
        !          6298:                 ndl_add(DL(m),d0,DL(tnm));
        !          6299:                 if ( ndl_reducible(DL(tnm),d) ) {
        !          6300:                     NEXTNM(mr0,mr);
        !          6301:                     mulq(CQ(m),q,&CQ(mr));
        !          6302:                     ndl_copy(DL(tnm),DL(mr));
        !          6303:                 }
        !          6304:             }
        !          6305:         }
        !          6306:         if ( !mr0 )
        !          6307:             return 0;
        !          6308:         else {
        !          6309:             NEXT(mr) = 0;
        !          6310:             for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
        !          6311:             MKND(NV(p),mr0,len,r);
        !          6312:             SG(r) = SG(p) + TD(d0);
        !          6313:             return r;
        !          6314:         }
        !          6315:     }
1.114     noro     6316: }
                   6317:
                   6318: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
                   6319: {
1.157   ! noro     6320:     int i,obpe,oadv,h,k,l;
        !          6321:     static NM prev_nm_free_list;
        !          6322:     EPOS oepos;
        !          6323:
        !          6324:     obpe = nd_bpe;
        !          6325:     oadv = nmv_adv;
        !          6326:     oepos = nd_epos;
        !          6327:     if ( obpe < 2 ) nd_bpe = 2;
        !          6328:     else if ( obpe < 3 ) nd_bpe = 3;
        !          6329:     else if ( obpe < 4 ) nd_bpe = 4;
        !          6330:     else if ( obpe < 5 ) nd_bpe = 5;
        !          6331:     else if ( obpe < 6 ) nd_bpe = 6;
        !          6332:     else if ( obpe < 8 ) nd_bpe = 8;
        !          6333:     else if ( obpe < 10 ) nd_bpe = 10;
        !          6334:     else if ( obpe < 16 ) nd_bpe = 16;
        !          6335:     else if ( obpe < 32 ) nd_bpe = 32;
        !          6336:     else error("nd_det_reconstruct : exponent too large");
        !          6337:
        !          6338:     nd_setup_parameters(nd_nvar,0);
        !          6339:     prev_nm_free_list = _nm_free_list;
        !          6340:     _nm_free_list = 0;
        !          6341:     for ( k = j; k < n; k++ )
        !          6342:         for (l = j; l < n; l++ )
        !          6343:             ndv_realloc(dm[k][l],obpe,oadv,oepos);
        !          6344:     ndv_realloc(d,obpe,oadv,oepos);
        !          6345:     prev_nm_free_list = 0;
1.114     noro     6346: #if 0
1.157   ! noro     6347:     GC_gcollect();
1.114     noro     6348: #endif
                   6349: }
                   6350:
1.153     noro     6351: /* returns a UINT array containing degree bounds */
                   6352:
1.114     noro     6353: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
                   6354: {
1.157   ! noro     6355:     UINT *d0,*d1,*d,*t,*r;
        !          6356:     int k,l,i;
1.114     noro     6357:
1.157   ! noro     6358:     d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
        !          6359:     for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
        !          6360:     for ( k = j; k < n; k++ )
        !          6361:         for ( l = j; l < n; l++ )
        !          6362:             if ( dm[k][l] ) {
        !          6363:                 d = ndv_compute_bound(dm[k][l]);
        !          6364:                 for ( i = 0; i < nd_nvar; i++ )
        !          6365:                     d0[i] = MAX(d0[i],d[i]);
        !          6366:             }
        !          6367:     return d0;
1.117     noro     6368: }
                   6369:
                   6370: DL nd_separate_d(UINT *d,UINT *trans)
                   6371: {
1.157   ! noro     6372:     int n,td,i,e,j;
        !          6373:     DL a;
1.117     noro     6374:
1.157   ! noro     6375:     ndl_zero(trans);
        !          6376:     td = 0;
        !          6377:     for ( i = 0; i < nd_ntrans; i++ ) {
        !          6378:         e = GET_EXP(d,i);
        !          6379:         PUT_EXP(trans,i,e);
        !          6380:         td += MUL_WEIGHT(e,i);
        !          6381:     }
        !          6382:     if ( nd_ntrans+nd_nalg < nd_nvar ) {
        !          6383:         /* homogenized */
        !          6384:         i = nd_nvar-1;
        !          6385:         e = GET_EXP(d,i);
        !          6386:         PUT_EXP(trans,i,e);
        !          6387:         td += MUL_WEIGHT(e,i);
        !          6388:     }
        !          6389:     TD(trans) = td;
        !          6390:     if ( nd_blockmask) ndl_weight_mask(trans);
        !          6391:     NEWDL(a,nd_nalg);
        !          6392:     td = 0;
        !          6393:     for ( i = 0; i < nd_nalg; i++ ) {
        !          6394:         j = nd_ntrans+i;
        !          6395:         e = GET_EXP(d,j);
        !          6396:         a->d[i] = e;
        !          6397:         td += e;
        !          6398:     }
        !          6399:     a->td = td;
        !          6400:     return a;
1.117     noro     6401: }
                   6402:
1.118     noro     6403: int nd_monic(int mod,ND *p)
1.117     noro     6404: {
1.157   ! noro     6405:     UINT *trans,*t;
        !          6406:     DL alg;
        !          6407:     MP mp0,mp;
        !          6408:     NM m,m0,m1,ma0,ma,mb,mr0,mr;
        !          6409:     ND r;
        !          6410:     DL dl;
        !          6411:     DP nm;
        !          6412:     NDV ndv;
        !          6413:     DAlg inv,cd;
        !          6414:     ND s,c;
        !          6415:     Q l,mul;
        !          6416:     N ln;
        !          6417:     int n,ntrans,i,e,td,is_lc,len;
        !          6418:     NumberField nf;
        !          6419:     struct oEGT eg0,eg1;
        !          6420:
        !          6421:     if ( !(nf = get_numberfield()) )
        !          6422:         error("nd_monic : current_numberfield is not set");
        !          6423:
        !          6424:     /* Q coef -> DAlg coef */
        !          6425:     NEWNM(ma0); ma = ma0;
        !          6426:     m = BDY(*p);
        !          6427:     is_lc = 1;
        !          6428:     while ( 1 ) {
        !          6429:         NEWMP(mp0); mp = mp0;
        !          6430:         mp->c = (P)CQ(m);
        !          6431:         mp->dl = nd_separate_d(DL(m),DL(ma));
        !          6432:         NEWNM(mb);
        !          6433:         for ( m = NEXT(m); m; m = NEXT(m) ) {
        !          6434:             alg = nd_separate_d(DL(m),DL(mb));
        !          6435:             if ( !ndl_equal(DL(ma),DL(mb)) )
        !          6436:                 break;
        !          6437:             NEXTMP(mp0,mp); mp->c = (P)CQ(m); mp->dl = alg;
        !          6438:         }
        !          6439:         NEXT(mp) = 0;
        !          6440:         MKDP(nd_nalg,mp0,nm);
        !          6441:         MKDAlg(nm,ONE,cd);
        !          6442:         if ( is_lc == 1 ) {
        !          6443:             /* if the lc is a rational number, we have nothing to do */
        !          6444:             if ( !mp0->dl->td )
        !          6445:                 return 1;
        !          6446:
        !          6447:             get_eg(&eg0);
        !          6448:             invdalg(cd,&inv);
        !          6449:             get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
        !          6450:             /* check the validity of inv */
        !          6451:             if ( mod && !rem(NM(inv->dn),mod) )
        !          6452:                 return 0;
        !          6453:             CA(ma) = nf->one;
        !          6454:             is_lc = 0;
        !          6455:             ln = ONEN;
        !          6456:         } else {
        !          6457:             muldalg(cd,inv,&CA(ma));
        !          6458:             lcmn(ln,NM(CA(ma)->dn),&ln);
        !          6459:         }
        !          6460:         if ( m ) {
        !          6461:             NEXT(ma) = mb; ma = mb;
        !          6462:         } else {
        !          6463:             NEXT(ma) = 0;
        !          6464:             break;
        !          6465:         }
        !          6466:     }
        !          6467:     /* l = lcm(denoms) */
        !          6468:     NTOQ(ln,1,l);
        !          6469:     for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
        !          6470:         divq(l,CA(m)->dn,&mul);
        !          6471:         for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
        !          6472:             NEXTNM(mr0,mr);
        !          6473:             mulq((Q)mp->c,mul,&CQ(mr));
        !          6474:             dl = mp->dl;
        !          6475:             td = TD(DL(m));
        !          6476:             ndl_copy(DL(m),DL(mr));
        !          6477:             for ( i = 0; i < nd_nalg; i++ ) {
        !          6478:                 e = dl->d[i];
        !          6479:                 PUT_EXP(DL(mr),i+nd_ntrans,e);
        !          6480:                 td += MUL_WEIGHT(e,i+nd_ntrans);
        !          6481:             }
        !          6482:             TD(DL(mr)) = td;
        !          6483:             if ( nd_blockmask) ndl_weight_mask(DL(mr));
        !          6484:             if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
        !          6485:         }
        !          6486:     }
        !          6487:     NEXT(mr) = 0;
        !          6488:     for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
        !          6489:     MKND(NV(*p),mr0,len,r);
        !          6490:     /* XXX */
        !          6491:     SG(r) = SG(*p);
        !          6492:     nd_free(*p);
        !          6493:     *p = r;
        !          6494:     return 1;
1.59      noro     6495: }

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