=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/engine/nd.c,v retrieving revision 1.187 retrieving revision 1.231 diff -u -p -r1.187 -r1.231 --- OpenXM_contrib2/asir2000/engine/nd.c 2010/04/26 01:06:22 1.187 +++ OpenXM_contrib2/asir2000/engine/nd.c 2016/12/05 10:29:14 1.231 @@ -1,15 +1,21 @@ -/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.186 2010/04/23 07:35:44 noro Exp $ */ +/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.230 2016/12/02 02:12:00 noro Exp $ */ #include "nd.h" +struct oEGT eg_search; + int diag_period = 6; +int weight_check = 1; int (*ndl_compare_function)(UINT *a1,UINT *a2); int nd_dcomp; +int nd_rref2; NM _nm_free_list; ND _nd_free_list; ND_pairs _ndp_free_list; NODE nd_hcf; +Obj nd_top_weight; + static NODE nd_subst; static VL nd_vc; static int nd_ntrans; @@ -34,7 +40,10 @@ static UINT nd_mask[32]; static UINT nd_mask0,nd_mask1; static NDV *nd_ps; +static NDV *nd_ps_gz; static NDV *nd_ps_trace; +static NDV *nd_ps_sym; +static NDV *nd_ps_trace_sym; static RHist *nd_psh; static int nd_psn,nd_pslen; static RHist *nd_red; @@ -47,10 +56,15 @@ static int nd_found,nd_create,nd_notfirst; static int nmv_adv; static int nd_demand; static int nd_module,nd_ispot,nd_mpos,nd_pot_nelim; +static int nd_module_rank,nd_poly_weight_len; +static int *nd_poly_weight,*nd_module_weight; static NODE nd_tracelist; static NODE nd_alltracelist; -static int nd_gentrace,nd_gensyz,nd_nora; +static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect; static int *nd_gbblock; +static NODE nd_nzlist,nd_check_splist; +static int nd_splist; +static int *nd_sugarweight; NumberField get_numberfield(); UINT *nd_det_compute_bound(NDV **dm,int n,int j); @@ -62,7 +76,6 @@ LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank); NDV pltondv(VL vl,VL dvl,LIST p); void pltozpl(LIST l,Q *cont,LIST *pp); void ndl_max(UINT *d1,unsigned *d2,UINT *d); -pointer GC_malloc_atomic_ignore_off_page(int); void nmtodp(int mod,NM m,DP *r); NODE reverse_node(NODE n); P ndc_div(int mod,union oNDC a,union oNDC b); @@ -70,9 +83,27 @@ P ndctop(int mod,union oNDC c); void finalize_tracelist(int i,P cont); void conv_ilist(int demand,int trace,NODE g,int **indp); void parse_nd_option(NODE opt); +void dltondl(int n,DL dl,UINT *r); +DP ndvtodp(int mod,NDV p); +DP ndtodp(int mod,ND p); +NDV ndvtondvgz(NDV p); +NDV ndvgztondv(NDV p); +ND ndtondgz(ND p); +ND ndgztond(ND p); -extern int Denominator,DP_Multiple; +void Pdp_set_weight(NODE,VECT *); +void Pox_cmo_rpc(NODE,Obj *); +extern int Denominator,DP_Multiple,MaxDeg; + +#define BLEN (8*sizeof(unsigned long)) + +typedef struct matrix { + int row,col; + unsigned long **a; +} *matrix; + + void nd_free_private_storage() { _nm_free_list = 0; @@ -88,18 +119,32 @@ void _NM_alloc() int i; for ( i = 0; i < 1024; i++ ) { - p = (NM)GC_malloc(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT)); + p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT)); p->next = _nm_free_list; _nm_free_list = p; } } +matrix alloc_matrix(int row,int col) +{ + unsigned long **a; + int i,len,blen; + matrix mat; + + mat = (matrix)MALLOC(sizeof(struct matrix)); + mat->row = row; + mat->col = col; + mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *)); + return mat; +} + + void _ND_alloc() { ND p; int i; for ( i = 0; i < 1024; i++ ) { - p = (ND)GC_malloc(sizeof(struct oND)); + p = (ND)MALLOC(sizeof(struct oND)); p->body = (NM)_nd_free_list; _nd_free_list = p; } } @@ -110,7 +155,7 @@ void _NDP_alloc() int i; for ( i = 0; i < 1024; i++ ) { - p = (ND_pairs)GC_malloc(sizeof(struct oND_pairs) + p = (ND_pairs)MALLOC(sizeof(struct oND_pairs) +(nd_wpd-1)*sizeof(UINT)); p->next = _ndp_free_list; _ndp_free_list = p; } @@ -129,6 +174,8 @@ INLINE int nd_length(ND p) } } +extern int dp_negative_weight; + INLINE int ndl_reducible(UINT *d1,UINT *d2) { UINT u1,u2; @@ -136,7 +183,7 @@ INLINE int ndl_reducible(UINT *d1,UINT *d2) if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0; - if ( TD(d1) < TD(d2) ) return 0; + if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0; #if USE_UNROLL switch ( nd_bpe ) { case 3: @@ -415,6 +462,22 @@ int ndl_weight(UINT *d) return t; } +/* for sugarweight */ + +int ndl_weight2(UINT *d) +{ + int t,u; + int i,j; + + for ( i = 0, t = 0; i < nd_nvar; i++ ) { + u = GET_EXP(d,i); + t += nd_sugarweight[i]*u; + } + if ( nd_module && current_module_weight_vector && MPOS(d) ) + t += current_module_weight_vector[MPOS(d)]; + return t; +} + void ndl_weight_mask(UINT *d) { UINT t,u; @@ -483,11 +546,37 @@ int ndl_block_compare(UINT *d1,UINT *d2) int ndl_matrix_compare(UINT *d1,UINT *d2) { - int i,j,s; + int i,j,s,row; int *v; + Q **mat; + Q *w; + Q t,t1,t2; for ( j = 0; j < nd_nvar; j++ ) nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j); + if ( nd_top_weight ) { + if ( OID(nd_top_weight) == O_VECT ) { + mat = (Q **)&BDY((VECT)nd_top_weight); + row = 1; + } else { + mat = (Q **)BDY((MAT)nd_top_weight); + row = ((MAT)nd_top_weight)->row; + } + for ( i = 0; i < row; i++ ) { + w = (Q *)mat[i]; + for ( j = 0, t = 0; j < nd_nvar; j++ ) { + STOQ(nd_work_vector[j],t1); + mulq(w[j],t1,&t2); + addq(t,t2,&t1); + t = t1; + } + if ( t ) { + s = SGN(t); + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + } + } + } for ( i = 0; i < nd_matrix_len; i++ ) { v = nd_matrix[i]; for ( j = 0, s = 0; j < nd_nvar; j++ ) @@ -495,6 +584,8 @@ int ndl_matrix_compare(UINT *d1,UINT *d2) if ( s > 0 ) return 1; else if ( s < 0 ) return -1; } + if ( !ndl_equal(d1,d2) ) + error("afo"); return 0; } @@ -577,10 +668,28 @@ int ndl_ww_lex_compare(UINT *d1,UINT *d2) return ndl_lex_compare(d1,d2); } +int ndl_module_weight_compare(UINT *d1,UINT *d2) +{ + int s,j; + + if ( nd_nvar != nd_poly_weight_len ) + error("invalid module weight : the length of polynomial weight != the number of variables"); + s = 0; + for ( j = 0; j < nd_nvar; j++ ) + s += (GET_EXP(d1,j)-GET_EXP(d2,j))*nd_poly_weight[j]; + if ( MPOS(d1) >= 1 && MPOS(d2) >= 1 ) { + s += nd_module_weight[MPOS(d1)-1]-nd_module_weight[MPOS(d2)-1]; + } + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + else return 0; +} + int ndl_module_grlex_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) { if ( TD(d1) > TD(d2) ) return 1; @@ -607,6 +716,7 @@ int ndl_module_glex_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( MPOS(d1) < MPOS(d2) ) return 1; else if ( MPOS(d1) > MPOS(d2) ) return -1; @@ -625,6 +735,7 @@ int ndl_module_lex_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( MPOS(d1) < MPOS(d2) ) return 1; else if ( MPOS(d1) > MPOS(d2) ) return -1; @@ -641,6 +752,7 @@ int ndl_module_block_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( MPOS(d1) < MPOS(d2) ) return 1; else if ( MPOS(d1) > MPOS(d2) ) return -1; @@ -657,6 +769,7 @@ int ndl_module_matrix_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( MPOS(d1) < MPOS(d2) ) return 1; else if ( MPOS(d1) > MPOS(d2) ) return -1; @@ -673,6 +786,7 @@ int ndl_module_composite_compare(UINT *d1,UINT *d2) { int i,c; + if ( nd_module_rank && (c = ndl_module_weight_compare(d1,d2)) ) return c; if ( nd_ispot ) { if ( MPOS(d1) > MPOS(d2) ) return 1; else if ( MPOS(d1) < MPOS(d2) ) return -1; @@ -1343,7 +1457,7 @@ int nd_nf(int mod,ND d,ND g,NDV *ps,int full,NDC dn,ND node = mknode(4,div,iq,dmul,ONE); } sugar = MAX(sugar,SG(p)+TD(DL(mul))); - if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) { + if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) { hg = HCU(g); nd_removecont2(d,g); if ( dn || nd_gentrace ) { @@ -1577,7 +1691,7 @@ void free_pbucket(PGeoBucket b) { nd_free(b->body[i]); b->body[i] = 0; } - GC_free(b); + GCFREE(b); } void add_pbucket_symbolic(PGeoBucket g,ND d) @@ -1862,6 +1976,29 @@ int do_diagonalize(int sugar,int m) return 1; } +LIST compute_splist() +{ + NODE g,tn0,tn,node; + LIST l0; + ND_pairs d,t; + int i; + Q i1,i2; + + g = 0; d = 0; + for ( i = 0; i < nd_psn; i++ ) { + d = update_pairs(d,g,i,0); + g = update_base(g,i); + } + for ( t = d, tn0 = 0; t; t = NEXT(t) ) { + NEXTNODE(tn0,tn); + STOQ(t->i1,i1); STOQ(t->i2,i2); + node = mknode(2,i1,i2); MKLIST(l0,node); + BDY(tn) = l0; + } + if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0); + return l0; +} + /* return value = 0 => input is not a GB */ NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp) @@ -1887,6 +2024,7 @@ NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,i while ( d ) { again: l = nd_minp(d,&d); + if ( MaxDeg > 0 && SG(l) > MaxDeg ) break; if ( SG(l) != sugar ) { if ( ishomo ) { diag_count = 0; @@ -1918,6 +2056,11 @@ again: goto again; } else if ( nf ) { if ( checkonly || gensyz ) return 0; + if ( nd_newelim ) { + if ( nd_module ) { + if ( MPOS(HDL(nf)) > 1 ) return 0; + } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0; + } if ( DP_Print ) { printf("+"); fflush(stdout); } hc = HCU(nf); nd_removecont(m,nf); @@ -1928,13 +2071,13 @@ again: if ( nd_gentrace ) { cont = ndc_div(m,hc,HCU(nf)); if ( m || !UNIQ(cont) ) { - t = mknode(4,0,0,0,cont); + t = mknode(4,NULLP,NULLP,NULLP,cont); MKLIST(list,t); MKNODE(t,list,nd_tracelist); nd_tracelist = t; } } nfv = ndtondv(m,nf); nd_free(nf); - nh = ndv_newps(m,nfv,0); + nh = ndv_newps(m,nfv,0,0); if ( !m && (ishomo && ++diag_count == diag_period) ) { diag_count = 0; stat = do_diagonalize(sugar,m); @@ -1964,6 +2107,85 @@ again: return g; } +/* splist = [[i1,i2],...] */ + +int check_splist(int m,NODE splist) +{ + NODE t,p; + ND_pairs d,r,l; + int stat; + ND h,nf; + + for ( d = 0, t = splist; t; t = NEXT(t) ) { + p = BDY((LIST)BDY(t)); + NEXTND_pairs(d,r); + r->i1 = QTOS((Q)ARG0(p)); r->i2 = QTOS((Q)ARG1(p)); + ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm); + SG(r) = TD(LCM(r)); /* XXX */ + } + if ( d ) NEXT(r) = 0; + + while ( d ) { +again: + l = nd_minp(d,&d); + stat = nd_sp(m,0,l,&h); + if ( !stat ) { + NEXT(l) = d; d = l; + d = nd_reconstruct(0,d); + goto again; + } + stat = nd_nf(m,0,h,nd_ps,!Top,0,&nf); + if ( !stat ) { + NEXT(l) = d; d = l; + d = nd_reconstruct(0,d); + goto again; + } else if ( nf ) return 0; + if ( DP_Print) { printf("."); fflush(stdout); } + } + if ( DP_Print) { printf("done.\n"); fflush(stdout); } + return 1; +} + +int check_splist_f4(int m,NODE splist) +{ + UINT *s0vect; + PGeoBucket bucket; + NODE p,rp0,t; + ND_pairs d,r,l,ll; + int col,stat; + + for ( d = 0, t = splist; t; t = NEXT(t) ) { + p = BDY((LIST)BDY(t)); + NEXTND_pairs(d,r); + r->i1 = QTOS((Q)ARG0(p)); r->i2 = QTOS((Q)ARG1(p)); + ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm); + SG(r) = TD(LCM(r)); /* XXX */ + } + if ( d ) NEXT(r) = 0; + + while ( d ) { + l = nd_minsugarp(d,&d); + bucket = create_pbucket(); + stat = nd_sp_f4(m,0,l,bucket); + if ( !stat ) { + for ( ll = l; NEXT(ll); ll = NEXT(ll) ); + NEXT(ll) = d; d = l; + d = nd_reconstruct(0,d); + continue; + } + if ( bucket->m < 0 ) continue; + col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0); + if ( !col ) { + for ( ll = l; NEXT(ll); ll = NEXT(ll) ); + NEXT(ll) = d; d = l; + d = nd_reconstruct(0,d); + continue; + } + if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0; + } + return 1; +} + int do_diagonalize_trace(int sugar,int m) { int i,nh,stat; @@ -2061,6 +2283,7 @@ NODE nd_gb_trace(int m,int ishomo,int **indp) while ( d ) { again: l = nd_minp(d,&d); + if ( MaxDeg > 0 && SG(l) > MaxDeg ) break; if ( SG(l) != sugar ) { #if 1 if ( ishomo ) { @@ -2130,12 +2353,12 @@ again: if ( nd_gentrace ) { cont = ndc_div(0,hnfq,HCU(nfqv)); if ( !UNIQ(cont) ) { - t = mknode(4,0,0,0,cont); + t = mknode(4,NULLP,NULLP,NULLP,cont); MKLIST(list,t); MKNODE(t,list,nd_tracelist); nd_tracelist = t; } } - nh = ndv_newps(0,nfv,nfqv); + nh = ndv_newps(0,nfv,nfqv,0); if ( ishomo && ++diag_count == diag_period ) { diag_count = 0; if ( DP_Print > 2 ) fprintf(asir_out,"|"); @@ -2158,9 +2381,11 @@ again: FREENDP(l); } if ( nd_nalg ) { - print_eg("monic",&eg_monic); - print_eg("invdalg",&eg_invdalg); - print_eg("le",&eg_le); + if ( DP_Print ) { + print_eg("monic",&eg_monic); + print_eg("invdalg",&eg_invdalg); + print_eg("le",&eg_le); + } } conv_ilist(nd_demand,1,g,indp); if ( DP_Print ) { printf("nd_gb_trace done.\n"); fflush(stdout); } @@ -2306,6 +2531,7 @@ ND_pairs nd_newpairs( NODE g, int t ) dl = DL(nd_psh[t]); ts = SG(nd_psh[t]) - TD(dl); + if ( nd_module && nd_intersect && (MPOS(dl) > 1) ) return 0; for ( r0 = 0, h = g; h; h = NEXT(h) ) { if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) ) continue; @@ -2316,10 +2542,8 @@ ND_pairs nd_newpairs( NODE g, int t ) if ( t0 >= min && t0 <= max && t >= min && t <= max ) break; } - if ( nd_gbblock[i] >= 0 ) { - fprintf(stderr,"(%d,%d)",t0,t); + if ( nd_gbblock[i] >= 0 ) continue; - } } NEXTND_pairs(r0,r); r->i1 = (long)BDY(h); @@ -2327,11 +2551,38 @@ ND_pairs nd_newpairs( NODE g, int t ) ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm); s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1])); SG(r) = MAX(s,ts) + TD(LCM(r)); + /* experimental */ + if ( nd_sugarweight ) + r->sugar2 = ndl_weight2(r->lcm); } if ( r0 ) NEXT(r) = 0; return r0; } +/* ipair = [i1,i2],[i1,i2],... */ +ND_pairs nd_ipairtospair(NODE ipair) +{ + int s1,s2; + NODE tn,t; + ND_pairs r,r0; + + for ( r0 = 0, t = ipair; t; t = NEXT(t) ) { + NEXTND_pairs(r0,r); + tn = BDY((LIST)BDY(t)); + r->i1 = QTOS((Q)ARG0(tn)); + r->i2 = QTOS((Q)ARG1(tn)); + ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm); + s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1])); + s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2])); + SG(r) = MAX(s1,s2) + TD(LCM(r)); + /* experimental */ + if ( nd_sugarweight ) + r->sugar2 = ndl_weight2(r->lcm); + } + if ( r0 ) NEXT(r) = 0; + return r0; +} + /* kokokara */ ND_pairs crit_B( ND_pairs d, int s ) @@ -2512,13 +2763,22 @@ ND_pairs nd_minp( ND_pairs d, ND_pairs *prest ) NEXT(m) = 0; return m; } - s = SG(m); if ( !NoSugar ) { - for ( ml = 0, l = m; p; p = NEXT(l = p) ) - if ( (SG(p) < s) - || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) { - ml = l; m = p; s = SG(m); - } + if ( nd_sugarweight ) { + s = m->sugar2; + for ( ml = 0, l = m; p; p = NEXT(l = p) ) + if ( (p->sugar2 < s) + || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) { + ml = l; m = p; s = m->sugar2; + } + } else { + s = SG(m); + for ( ml = 0, l = m; p; p = NEXT(l = p) ) + if ( (SG(p) < s) + || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) { + ml = l; m = p; s = SG(m); + } + } } else { for ( ml = 0, l = m; p; p = NEXT(l = p) ) if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) { @@ -2539,27 +2799,44 @@ ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest ) int msugar,i; ND_pairs t,dm0,dm,dr0,dr; - for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) ) - if ( SG(t) < msugar ) msugar = SG(t); - dm0 = 0; dr0 = 0; - for ( i = 0, t = d; t; t = NEXT(t) ) - if ( i < nd_f4_nsp && SG(t) == msugar ) { - if ( dm0 ) NEXT(dm) = t; - else dm0 = t; - dm = t; - i++; - } else { - if ( dr0 ) NEXT(dr) = t; - else dr0 = t; - dr = t; - } + if ( nd_sugarweight ) { + for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) ) + if ( t->sugar2 < msugar ) msugar = t->sugar2; + dm0 = 0; dr0 = 0; + for ( i = 0, t = d; t; t = NEXT(t) ) + if ( i < nd_f4_nsp && t->sugar2 == msugar ) { + if ( dm0 ) NEXT(dm) = t; + else dm0 = t; + dm = t; + i++; + } else { + if ( dr0 ) NEXT(dr) = t; + else dr0 = t; + dr = t; + } + } else { + for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) ) + if ( SG(t) < msugar ) msugar = SG(t); + dm0 = 0; dr0 = 0; + for ( i = 0, t = d; t; t = NEXT(t) ) + if ( i < nd_f4_nsp && SG(t) == msugar ) { + if ( dm0 ) NEXT(dm) = t; + else dm0 = t; + dm = t; + i++; + } else { + if ( dr0 ) NEXT(dr) = t; + else dr0 = t; + dr = t; + } + } NEXT(dm) = 0; if ( dr0 ) NEXT(dr) = 0; *prest = dr0; return dm0; } -int ndv_newps(int m,NDV a,NDV aq) +int ndv_newps(int m,NDV a,NDV aq,int f4) { int len; RHist r; @@ -2571,15 +2848,19 @@ int ndv_newps(int m,NDV a,NDV aq) if ( nd_psn == nd_pslen ) { nd_pslen *= 2; nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV)); + nd_ps_gz = (NDV *)REALLOC((char *)nd_ps_gz,nd_pslen*sizeof(NDV)); nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV)); nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist)); nd_bound = (UINT **) REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *)); + nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV)); + nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV)); } NEWRHist(r); nd_psh[nd_psn] = r; nd_ps[nd_psn] = a; if ( aq ) { nd_ps_trace[nd_psn] = aq; + if ( !nd_vc ) nd_ps_gz[nd_psn] = ndvtondvgz(aq); register_hcf(aq); nd_bound[nd_psn] = ndv_compute_bound(aq); SG(r) = SG(aq); ndl_copy(HDL(aq),DL(r)); @@ -2587,13 +2868,16 @@ int ndv_newps(int m,NDV a,NDV aq) if ( !m ) register_hcf(a); nd_bound[nd_psn] = ndv_compute_bound(a); SG(r) = SG(a); ndl_copy(HDL(a),DL(r)); + if ( !m && !nd_vc ) nd_ps_gz[nd_psn] = ndvtondvgz(a); } if ( nd_demand ) { if ( aq ) { ndv_save(nd_ps_trace[nd_psn],nd_psn); + nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]); nd_ps_trace[nd_psn] = 0; } else { ndv_save(nd_ps[nd_psn],nd_psn); + nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]); nd_ps[nd_psn] = 0; } } @@ -2642,7 +2926,10 @@ int ndv_setup(int mod,int trace,NODE f,int dont_sort,i } nd_pslen = 2*nd_psn; nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); + nd_ps_gz = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); + nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); + nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist)); nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *)); nd_hcf = 0; @@ -2659,15 +2946,17 @@ int ndv_setup(int mod,int trace,NODE f,int dont_sort,i hc = HCU(w[i].p); if ( trace ) { a = nd_ps_trace[i] = ndv_dup(0,w[i].p); + if ( !nd_vc ) nd_ps_gz[i] = ndvtondvgz(a); if ( !dont_removecont) ndv_removecont(0,a); register_hcf(a); am = nd_ps[i] = ndv_dup(mod,a); ndv_mod(mod,am); - if ( DL_COMPARE(HDL(am),HDL(a)) ) - return 0; + if ( DL_COMPARE(HDL(am),HDL(a)) ) + return 0; ndv_removecont(mod,am); } else { a = nd_ps[i] = ndv_dup(mod,w[i].p); + if ( !mod && !nd_vc ) nd_ps_gz[i] = ndvtondvgz(a); if ( mod || !dont_removecont ) ndv_removecont(mod,a); if ( !mod ) register_hcf(a); } @@ -2683,9 +2972,11 @@ int ndv_setup(int mod,int trace,NODE f,int dont_sort,i if ( nd_demand ) { if ( trace ) { ndv_save(nd_ps_trace[i],i); + nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]); nd_ps_trace[i] = 0; } else { ndv_save(nd_ps[i],i); + nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]); nd_ps[i] = 0; } } @@ -2799,7 +3090,7 @@ NODE postprocess_algcoef(VL av,NODE alist,NODE r) return u0; } -void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct order_spec *ord,LIST *rp) +void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp) { VL tv,fv,vv,vc,av; NODE fd,fd0,r,r0,t,x,s,xx,alist; @@ -2814,13 +3105,13 @@ void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct Obj obj; NumberField nf; struct order_spec *ord1; - NODE tr,tl1,tl2,tl3,tl4; + NODE tr,tl1,tl2,tl3,tl4,nzlist; LIST l1,l2,l3,l4,l5; int j; - Q jq; + Q jq,bpe; int *perm; EPOS oepos; - int obpe,oadv,ompos; + int obpe,oadv,ompos,cbpe; nd_module = 0; if ( !m && Demand ) nd_demand = 1; @@ -2833,6 +3124,8 @@ void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct ndv_alloc = 0; #endif get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc); + if ( m && nd_vc ) + error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main()."); for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); switch ( ord->id ) { case 1: @@ -2874,7 +3167,7 @@ void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct max = MAX(e,max); } } - nd_setup_parameters(nvar,max); + nd_setup_parameters(nvar,nd_nzlist?0:max); obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos; ishomo = 1; for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) { @@ -2907,11 +3200,28 @@ void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos); } - ndv_setup(m,0,fd0,nd_gbblock?1:0,0); + ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0); if ( nd_gentrace ) { MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0); } + if ( nd_splist ) { + *rp = compute_splist(); + return; + } + if ( nd_check_splist ) { + if ( f4 ) { + if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE; + else *rp = 0; + } else { + if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE; + else *rp = 0; + } + return; + } x = f4?nd_f4(m,&perm):nd_gb(m,ishomo || homo,0,0,&perm); + if ( !x ) { + *rp = 0; return; + } if ( !ishomo && homo ) { /* dehomogenization */ for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord); @@ -2919,48 +3229,66 @@ void nd_gr(LIST f,LIST v,int m,int homo,int f4,struct nd_setup_parameters(nvar,0); } nd_demand = 0; + if ( nd_module && nd_intersect ) { + for ( j = nd_psn-1, x = 0; j >= 0; j-- ) + if ( MPOS(DL(nd_psh[j])) > 1 ) { + MKNODE(xx,(pointer)j,x); x = xx; + } + conv_ilist(nd_demand,0,x,0); + goto FINAL; + } + if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; } x = ndv_reducebase(x,perm); - if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; } + if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; } x = ndv_reduceall(m,x); - if ( nd_gentrace ) { + cbpe = nd_bpe; + if ( nd_gentrace && !f4 ) { tl2 = nd_alltracelist; nd_alltracelist = 0; ndv_check_membership(m,fd0,obpe,oadv,oepos,x); - if ( nd_gentrace ) { - tl3 = nd_alltracelist; nd_alltracelist = 0; - } else tl3 = 0; - nd_gb(m,0,1,nd_gensyz?1:0,0)!=0; - if ( nd_gentrace && nd_gensyz ) { + tl3 = nd_alltracelist; nd_alltracelist = 0; + if ( nd_gensyz ) { + nd_gb(m,0,1,1,0); tl4 = nd_alltracelist; nd_alltracelist = 0; } else tl4 = 0; } + nd_bpe = cbpe; + nd_setup_parameters(nd_nvar,0); +FINAL: for ( r0 = 0, t = x; t; t = NEXT(t) ) { NEXTNODE(r0,r); - if ( nd_module ) BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank); - else BDY(r) = ndvtop(m,CO,vv,BDY(t)); + if ( nd_module ) BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank); + else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t)); + else BDY(r) = ndvtop(m,CO,vv,BDY(t)); } if ( r0 ) NEXT(r) = 0; - if ( nalg ) + if ( !m && nd_nalg ) r0 = postprocess_algcoef(av,alist,r0); MKLIST(*rp,r0); if ( nd_gentrace ) { - tl1 = reverse_node(tl1); tl2 = reverse_node(tl2); - tl3 = reverse_node(tl3); - /* tl2 = [[i,[[*,j,*,*],...]],...] */ - for ( t = tl2; t; t = NEXT(t) ) { - /* s = [i,[*,j,*,*],...] */ - s = BDY((LIST)BDY(t)); - j = perm[QTOS((Q)ARG0(s))]; STOQ(j,jq); ARG0(s) = (pointer)jq; - for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) { - j = perm[QTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOQ(j,jq); - ARG1(BDY((LIST)BDY(s))) = (pointer)jq; + if ( f4 ) { + STOQ(16,bpe); + tr = mknode(4,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe); MKLIST(*rp,tr); + } else { + tl1 = reverse_node(tl1); tl2 = reverse_node(tl2); + tl3 = reverse_node(tl3); + /* tl2 = [[i,[[*,j,*,*],...]],...] */ + for ( t = tl2; t; t = NEXT(t) ) { + /* s = [i,[*,j,*,*],...] */ + s = BDY((LIST)BDY(t)); + j = perm[QTOS((Q)ARG0(s))]; STOQ(j,jq); ARG0(s) = (pointer)jq; + for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) { + j = perm[QTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOQ(j,jq); + ARG1(BDY((LIST)BDY(s))) = (pointer)jq; + } } - } - for ( j = length(x)-1, t = 0; j >= 0; j-- ) { - STOQ(perm[j],jq); MKNODE(s,jq,t); t = s; - } - MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3); - MKLIST(l5,tl4); - tr = mknode(7,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5); MKLIST(*rp,tr); + for ( j = length(x)-1, t = 0; j >= 0; j-- ) { + STOQ(perm[j],jq); MKNODE(s,jq,t); t = s; + } + MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3); + MKLIST(l5,tl4); + STOQ(nd_bpe,bpe); + tr = mknode(8,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe); MKLIST(*rp,tr); + } } #if 0 fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); @@ -2983,6 +3311,7 @@ void nd_gr_postproc(LIST f,LIST v,int m,struct order_s struct order_spec *ord1; int *perm; + parse_nd_option(current_option); get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc); for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); switch ( ord->id ) { @@ -3050,11 +3379,152 @@ void nd_gr_postproc(LIST f,LIST v,int m,struct order_s BDY(r) = ndvtop(m,CO,vv,BDY(t)); } if ( r0 ) NEXT(r) = 0; - if ( nalg ) + if ( !m && nd_nalg ) r0 = postprocess_algcoef(av,alist,r0); MKLIST(*rp,r0); } +NDV recompute_trace(NODE trace,NDV *p,int m); +void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp); + +NDV recompute_trace(NODE ti,NDV *p,int mod) +{ + int c,c1,c2,i; + NM mul,m,tail; + ND d,r,rm; + NODE sj; + NDV red; + Obj mj; + static int afo=0; + + afo++; + mul = (NM)ALLOCA(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT)); + CM(mul) = 1; + tail = 0; + for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) { + sj = BDY((LIST)BDY(ti)); + if ( ARG0(sj) ) { + red = p[QTOS((Q)ARG1(sj))]; + mj = (Obj)ARG2(sj); + if ( OID(mj) != O_DP ) ndl_zero(DL(mul)); + else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul)); + rm = ndv_mul_nm(mod,mul,red); + if ( !r ) r = rm; + else { + for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) { + if ( d ) { + NEXT(tail) = m; tail = m; LEN(d)++; + } else { + MKND(nd_nvar,m,1,d); tail = BDY(d); + } + } + if ( !m ) return 0; /* failure */ + else { + BDY(r) = m; + c1 = invm(HCM(rm),mod); c2 = mod-HCM(r); + DMAR(c1,c2,0,mod,c); + nd_mul_c(mod,rm,c); + r = nd_add(mod,r,rm); + } + } + } + } + if ( tail ) NEXT(tail) = 0; + d = nd_add(mod,d,r); + nd_mul_c(mod,d,invm(HCM(d),mod)); + return ndtondv(mod,d); +} + +void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp) +{ + VL tv,fv,vv,vc,av; + NODE fd,fd0,r,r0,t,x,s,xx,alist; + int e,max,nvar,i; + NDV b; + int ishomo,nalg; + Alg alpha,dp; + P p,zp; + Q dmy; + LIST f1,f2; + Obj obj; + NumberField nf; + struct order_spec *ord1; + NODE permtrace,intred,ind,perm,trace,ti; + int len,n,j; + NDV *db,*pb; + + parse_nd_option(current_option); + get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc); + for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); + switch ( ord->id ) { + case 1: + if ( ord->nv != nvar ) + error("nd_check : invalid order specification"); + break; + default: + break; + } + nd_init_ord(ord); + nd_bpe = QTOS((Q)ARG7(BDY(tlist))); + nd_setup_parameters(nvar,0); + + len = length(BDY(f)); + db = (NDV *)MALLOC(len*sizeof(NDV *)); + for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) { + ptozp((P)BDY(t),1,&dmy,&zp); + b = ptondv(CO,vv,zp); + ndv_mod(m,b); + ndv_mul_c(m,b,invm(HCM(b),m)); + db[i] = b; + } + + permtrace = BDY((LIST)ARG2(BDY(tlist))); + intred = BDY((LIST)ARG3(BDY(tlist))); + ind = BDY((LIST)ARG4(BDY(tlist))); + perm = BDY((LIST)ARG0(permtrace)); + trace = NEXT(permtrace); + + for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) { + j = QTOS((Q)ARG0(BDY((LIST)BDY(t)))); + if ( j > i ) i = j; + } + n = i+1; + pb = (NDV *)MALLOC(n*sizeof(NDV *)); + for ( t = perm, i = 0; t; t = NEXT(t), i++ ) { + ti = BDY((LIST)BDY(t)); + pb[QTOS((Q)ARG0(ti))] = db[QTOS((Q)ARG1(ti))]; + } + for ( t = trace; t; t = NEXT(t) ) { + ti = BDY((LIST)BDY(t)); + pb[QTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m); + if ( !pb[QTOS((Q)ARG0(ti))] ) { *rp = 0; return; } + if ( DP_Print ) { + fprintf(asir_out,"."); fflush(asir_out); + } + } + for ( t = intred; t; t = NEXT(t) ) { + ti = BDY((LIST)BDY(t)); + pb[QTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m); + if ( !pb[QTOS((Q)ARG0(ti))] ) { *rp = 0; return; } + if ( DP_Print ) { + fprintf(asir_out,"*"); fflush(asir_out); + } + } + for ( r0 = 0, t = ind; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + b = pb[QTOS((Q)BDY(t))]; + ndv_mul_c(m,b,invm(HCM(b),m)); +#if 0 + BDY(r) = ndvtop(m,CO,vv,pb[QTOS((Q)BDY(t))]); +#else + BDY(r) = ndvtodp(m,pb[QTOS((Q)BDY(t))]); +#endif + } + if ( r0 ) NEXT(r) = 0; + MKLIST(*rp,r0); + if ( DP_Print ) fprintf(asir_out,"\n"); +} + void nd_gr_trace(LIST f,LIST v,int trace,int homo,int f4,struct order_spec *ord,LIST *rp) { VL tv,fv,vv,vc,av; @@ -3077,7 +3547,7 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,int LIST l1,l2,l3,l4,l5; int *perm; int j,ret; - Q jq; + Q jq,bpe; nd_module = 0; parse_nd_option(current_option); @@ -3170,6 +3640,7 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,int for ( t = fd0; t; t = NEXT(t) ) ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos); } + if ( MaxDeg > 0 ) nocheck = 1; while ( 1 ) { tl1 = tl2 = tl3 = tl4 = 0; if ( Demand ) @@ -3238,7 +3709,7 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,int if ( nd_module ) BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank); else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r)); } - if ( nalg ) + if ( nd_nalg ) cand = postprocess_algcoef(av,alist,cand); MKLIST(*rp,cand); if ( nd_gentrace ) { @@ -3259,7 +3730,8 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,int } MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3); MKLIST(l5,tl4); - tr = mknode(7,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5); MKLIST(*rp,tr); + STOQ(nd_bpe,bpe); + tr = mknode(8,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe); MKLIST(*rp,tr); } } @@ -3676,7 +4148,7 @@ void nd_free(ND p) void ndv_free(NDV p) { - GC_free(BDY(p)); + GCFREE(BDY(p)); } void nd_append_red(UINT *d,int i) @@ -3787,6 +4259,31 @@ void nd_setup_parameters(int nvar,int max) { else if ( max < 65536 ) nd_bpe = 16; else nd_bpe = 32; } + if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) { + UINT t; + int st; + int *v; + /* t = max(weights) */ + t = 0; + if ( current_dl_weight_vector ) + for ( i = 0, t = 0; i < nd_nvar; i++ ) { + if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st; + if ( t < st ) t = st; + } + if ( nd_matrix ) + for ( i = 0; i < nd_matrix_len; i++ ) + for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) { + if ( (st=v[j]) < 0 ) st = -st; + if ( t < st ) t = st; + } + /* i = bitsize of t */ + for ( i = 0; t; t >>=1, i++ ); + /* i += bitsize of nd_nvar */ + for ( t = nd_nvar; t; t >>=1, i++); + /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */ + if ( (nd_bpe+i) >= 31 ) + error("nd_setup_parameters : too large weight"); + } nd_epw = (sizeof(UINT)*8)/nd_bpe; elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0); nd_exporigin = nd_get_exporigin(nd_ord); @@ -3846,10 +4343,16 @@ ND_pairs nd_reconstruct(int trace,ND_pairs d) prev_ndp_free_list = _ndp_free_list; _nm_free_list = 0; _ndp_free_list = 0; - for ( i = nd_psn-1; i >= 0; i-- ) ndv_realloc(nd_ps[i],obpe,oadv,oepos); + for ( i = nd_psn-1; i >= 0; i-- ) { + ndv_realloc(nd_ps[i],obpe,oadv,oepos); + ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos); + ndv_realloc(nd_ps_gz[i],obpe,oadv,oepos); + } if ( trace ) - for ( i = nd_psn-1; i >= 0; i-- ) + for ( i = nd_psn-1; i >= 0; i-- ) { ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos); + ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos); + } s0 = 0; for ( t = d; t; t = NEXT(t) ) { NEXTND_pairs(s0,s); @@ -4370,6 +4873,48 @@ NDV ndv_dup(int mod,NDV p) return d; } +NDV ndvtondvgz(NDV p) +{ + NDV r; + int len,i; + NMV t; + + r = ndv_dup(0,p); + len = LEN(p); + for ( t = BDY(r), i = 0; i < len; i++, NMV_ADV(t) ) CZ(t) = ztogz(CQ(t)); + return r; +} + +NDV ndvgztondv(NDV p) +{ + NDV r; + int len,i; + NMV t; + + r = ndv_dup(0,p); + len = LEN(p); + for ( t = BDY(r), i = 0; i < len; i++, NMV_ADV(t) ) CQ(t) = gztoz(CZ(t)); + return r; +} + +NDV ndv_symbolic(int mod,NDV p) +{ + NDV d; + NMV t,m,m0; + int i,len; + + if ( !p ) return 0; + len = LEN(p); + m0 = m = (NMV)(mod?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv)); + for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) { + ndl_copy(DL(t),DL(m)); + CQ(m) = ONE; + } + MKNDV(NV(p),m0,len,d); + SG(d) = SG(p); + return d; +} + ND nd_dup(ND p) { ND d; @@ -4387,6 +4932,28 @@ ND nd_dup(ND p) return d; } +ND ndtondgz(ND p) +{ + ND r; + NM t; + + r = nd_dup(p); + for ( t = BDY(r); t; t = NEXT(t) ) CZ(t) = ztogz(CQ(t)); + return r; +} + + +ND ndgztond(ND p) +{ + ND r; + NM t; + + r = nd_dup(p); + for ( t = BDY(r); t; t = NEXT(t) ) CQ(t) = gztoz(CZ(t)); + return r; +} + + /* XXX if p->len == 0 then it represents 0 */ void ndv_mod(int mod,NDV p) @@ -4641,7 +5208,7 @@ NDV ndtondv(int mod,ND p) if ( !p ) return 0; len = LEN(p); if ( mod ) - m0 = m = (NMV)GC_malloc_atomic_ignore_off_page(len*nmv_adv); + m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv); else m0 = m = MALLOC(len*nmv_adv); #if 0 @@ -4677,6 +5244,48 @@ ND ndvtond(int mod,NDV p) return d; } +DP ndvtodp(int mod,NDV p) +{ + MP m,m0; + DP d; + NMV t; + int i,len; + + if ( !p ) return 0; + m0 = 0; + len = p->len; + for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) { + NEXTMP(m0,m); + m->dl = ndltodl(nd_nvar,DL(t)); + m->c = ndctop(mod,t->c); + } + NEXT(m) = 0; + MKDP(nd_nvar,m0,d); + SG(d) = SG(p); + return d; +} + +DP ndtodp(int mod,ND p) +{ + MP m,m0; + DP d; + NM t; + int i,len; + + if ( !p ) return 0; + m0 = 0; + len = p->len; + for ( t = BDY(p); t; t = NEXT(t) ) { + NEXTMP(m0,m); + m->dl = ndltodl(nd_nvar,DL(t)); + m->c = ndctop(mod,t->c); + } + NEXT(m) = 0; + MKDP(nd_nvar,m0,d); + SG(d) = SG(p); + return d; +} + void ndv_print(NDV p) { NMV m; @@ -4744,7 +5353,18 @@ NODE ndv_reducebase(NODE x,int *perm) void nd_init_ord(struct order_spec *ord) { - nd_module = (ord->id >= 256); + nd_module = (ord->id >= 256); + if ( nd_module ) { + nd_dcomp = -1; + nd_ispot = ord->ispot; + nd_pot_nelim = ord->pot_nelim; + nd_poly_weight_len = ord->nv; + nd_poly_weight = ord->top_weight; + nd_module_rank = ord->module_rank; + nd_module_weight = ord->module_top_weight; + } + nd_matrix = 0; + nd_matrix_len = 0; switch ( ord->id ) { case 0: switch ( ord->ord.simple ) { @@ -4798,9 +5418,6 @@ void nd_init_ord(struct order_spec *ord) /* module order */ case 256: - nd_ispot = ord->ispot; - nd_pot_nelim = ord->pot_nelim; - nd_dcomp = -1; switch ( ord->ord.simple ) { case 0: nd_isrlex = 1; @@ -4820,17 +5437,11 @@ void nd_init_ord(struct order_spec *ord) break; case 257: /* block order */ - nd_ispot = ord->ispot; - nd_pot_nelim = ord->pot_nelim; - nd_dcomp = -1; nd_isrlex = 0; ndl_compare_function = ndl_module_block_compare; break; case 258: /* matrix order */ - nd_ispot = ord->ispot; - nd_pot_nelim = ord->pot_nelim; - nd_dcomp = -1; nd_isrlex = 0; nd_matrix_len = ord->ord.matrix.row; nd_matrix = ord->ord.matrix.matrix; @@ -4838,9 +5449,6 @@ void nd_init_ord(struct order_spec *ord) break; case 259: /* composite order */ - nd_ispot = ord->ispot; - nd_pot_nelim = ord->pot_nelim; - nd_dcomp = -1; nd_isrlex = 0; nd_worb_len = ord->ord.composite.length; nd_worb = ord->ord.composite.w_or_b; @@ -4930,16 +5538,17 @@ EPOS nd_create_epos(struct order_spec *ord) /* external interface */ -void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec *ord,P *rp) +void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp) { NODE t,in0,in; - ND nd,nf; - NDV ndv; + ND ndf,nf; + NDV ndvf; VL vv,tv; - int stat,nvar,max,e; + int stat,nvar,max,mrank; union oNDC dn; Q cont; P pp; + LIST ppl; if ( !f ) { *rp = 0; @@ -4948,47 +5557,48 @@ void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec pltovl(v,&vv); for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); - /* get the degree bound */ - for ( t = BDY(g), max = 1; t; t = NEXT(t) ) - for ( tv = vv; tv; tv = NEXT(tv) ) { - e = getdeg(tv->v,(P)BDY(t)); - max = MAX(e,max); - } - for ( tv = vv; tv; tv = NEXT(tv) ) { - e = getdeg(tv->v,f); - max = MAX(e,max); - } + /* max=65536 implies nd_bpe=32 */ + max = 65536; + nd_module = 0; + /* nd_module will be set if ord is a module ordering */ nd_init_ord(ord); nd_setup_parameters(nvar,max); - + if ( nd_module && OID(f) != O_LIST ) + error("nd_nf_p : the first argument must be a list"); + if ( nd_module ) mrank = length(BDY((LIST)f)); /* conversion to ndv */ for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) { NEXTNODE(in0,in); - ptozp((P)BDY(t),1,&cont,&pp); - BDY(in) = (pointer)ptondv(CO,vv,pp); + if ( nd_module ) { + if ( !BDY(t) || OID(BDY(t)) != O_LIST + || length(BDY((LIST)BDY(t))) != mrank ) + error("nd_nf_p : inconsistent basis element"); + if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl); + else ppl = (LIST)BDY(t); + BDY(in) = (pointer)pltondv(CO,vv,ppl); + } else { + if ( !m ) ptozp((P)BDY(t),1,&cont,&pp); + else pp = (P)BDY(t); + BDY(in) = (pointer)ptondv(CO,vv,pp); + } if ( m ) ndv_mod(m,(NDV)BDY(in)); } - NEXTNODE(in0,in); - BDY(in) = (pointer)ptondv(CO,vv,f); - if ( m ) ndv_mod(m,(NDV)BDY(in)); - NEXT(in) = 0; + if ( in0 ) NEXT(in) = 0; + if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f); + else ndvf = ptondv(CO,vv,(P)f); + if ( m ) ndv_mod(m,ndvf); + ndf = (pointer)ndvtond(m,ndvf); + /* dont sort, dont removecont */ ndv_setup(m,0,in0,1,1); - nd_psn--; nd_scale=2; - while ( 1 ) { - nd = (pointer)ndvtond(m,nd_ps[nd_psn]); - stat = nd_nf(m,0,nd,nd_ps,1,0,&nf); - if ( !stat ) { - nd_psn++; - nd_reconstruct(0,0); - nd_psn--; - } else - break; - } - *rp = ndvtop(m,CO,vv,ndtondv(m,nf)); + stat = nd_nf(m,0,ndf,nd_ps,1,0,&nf); + if ( !stat ) + error("nd_nf_p : exponent too large"); + if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank); + else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf)); } int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r) @@ -5023,6 +5633,44 @@ int nd_to_vect_q(UINT *s0,int n,ND d,Q *r) return i; } +unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p) +{ + NM m; + unsigned long *v; + int i,j,h,size; + UINT *s,*t; + + size = sizeof(unsigned long)*(n+BLEN-1)/BLEN; + v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size); + bzero(v,size); + for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) { + t = DL(m); + h = ndl_hash_value(t); + for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ ); + v[i/BLEN] |= 1L <<(i%BLEN); + } + return v; +} + +int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v) +{ + NMV mr; + UINT *d,*t,*s; + int i,j,len,h,head; + + d = DL(m); + len = LEN(p); + t = (UINT *)ALLOCA(nd_wpd*sizeof(UINT)); + for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) { + ndl_add(d,DL(mr),t); + h = ndl_hash_value(t); + for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ ); + if ( j == 0 ) head = i; + v[i/BLEN] |= 1L <<(i%BLEN); + } + return head; +} + Q *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair) { NM m; @@ -5046,7 +5694,7 @@ Q *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_p return r; } -IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0,int n,NM_ind_pair pair) +IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0,int n,int *s0hash,NM_ind_pair pair) { NM m; NMV mr; @@ -5055,20 +5703,24 @@ IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0 unsigned char *ivc; unsigned short *ivs; UINT *v,*ivi,*s0v; - int i,j,len,prev,diff,cdiff; + int i,j,len,prev,diff,cdiff,h; IndArray r; +struct oEGT eg0,eg1; m = pair->mul; d = DL(m); - p = nd_ps[pair->index]; + p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index]; len = LEN(p); t = (UINT *)ALLOCA(nd_wpd*sizeof(UINT)); v = (unsigned int *)ALLOCA(len*sizeof(unsigned int)); +get_eg(&eg0); for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) { ndl_add(d,DL(mr),t); - for ( ; !ndl_equal(t,s); s += nd_wpd, i++ ); + h = ndl_hash_value(t); + for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ ); v[j] = i; } +get_eg(&eg1); add_eg(&eg_search,&eg0,&eg1); r = (IndArray)MALLOC(sizeof(struct oIndArray)); r->head = v[0]; diff = 0; @@ -5136,7 +5788,8 @@ int ndv_reduce_vect_q(Q *svect,int trace,int col,IndAr k = ivect->head; if ( svect[k] ) { maxrs = MAX(maxrs,rp0[i]->sugar); - redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]; + redv = nd_demand?ndv_load(rp0[i]->index) + :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]); len = LEN(redv); mr = BDY(redv); igcd_cofactor(svect[k],CQ(mr),&gcd,&cs,&cr); chsgnq(cs,&mcs); @@ -5188,6 +5841,88 @@ int ndv_reduce_vect_q(Q *svect,int trace,int col,IndAr return maxrs; } +int ndv_reduce_vect_gz(GZ *gvect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) +{ + int i,j,k,l,len,pos,prev,nz; + GZ cs,mcs,c1,c2,cr,gcd,t; + IndArray ivect; + unsigned char *ivc; + unsigned short *ivs; + unsigned int *ivi; + NDV redv; + NMV mr; + NODE rp; + int maxrs; + double hmag; + struct oVECT v; + + maxrs = 0; + for ( i = 0; i < col && !gvect[i]; i++ ); + if ( i == col ) return maxrs; + hmag = (double)n_bits_gz(gvect[i])*nd_scale; + for ( i = 0; i < nred; i++ ) { + ivect = imat[i]; + k = ivect->head; + if ( gvect[k] ) { + maxrs = MAX(maxrs,rp0[i]->sugar); + redv = nd_ps_gz[rp0[i]->index]; + len = LEN(redv); mr = BDY(redv); + gcdgz(gvect[k],CZ(mr),&gcd); + divsgz(gvect[k],gcd,&cs); + divsgz(CZ(mr),gcd,&cr); + chsgngz(cs,&mcs); + if ( !UNIGZ(cr) ) { + for ( j = 0; j < col; j++ ) { + mulgz(gvect[j],cr,&c1); gvect[j] = c1; + } + } + gvect[k] = 0; prev = k; + switch ( ivect->width ) { + case 1: + ivc = ivect->index.c; + for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { + pos = prev+ivc[j]; prev = pos; + mulgz(CZ(mr),mcs,&c2); addgz(gvect[pos],c2,&t); gvect[pos] = t; + } + break; + case 2: + ivs = ivect->index.s; + for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { + pos = prev+ivs[j]; prev = pos; + mulgz(CZ(mr),mcs,&c2); addgz(gvect[pos],c2,&t); gvect[pos] = t; + } + break; + case 4: + ivi = ivect->index.i; + for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { + pos = prev+ivi[j]; prev = pos; + mulgz(CZ(mr),mcs,&c2); addgz(gvect[pos],c2,&t); gvect[pos] = t; + } + break; + } + for ( j = k+1; j < col && !gvect[j]; j++ ); + if ( j == col ) break; + if ( hmag && ((double)n_bits_gz(gvect[j]) > hmag) ) { + v.len = col; v.body = (pointer)gvect; gcdvgz(&v,&gcd); +#if 1 + for ( l = 0; l < col; l++ ) { divsgz(gvect[l],gcd,&t); gvect[l] = t; } +#endif + hmag = (double)n_bits_gz(gvect[j])*nd_scale; + } + } + } + for ( j = 0; j < col && !gvect[j]; j++ ); + if ( j < col ) { + v.len = col; v.body = (pointer)gvect; gcdvgz(&v,&gcd); + for ( l = 0; l < col; l++ ) { divsgz(gvect[l],gcd,&t); gvect[l] = t; } + } + if ( DP_Print ) { + fprintf(asir_out,"-"); fflush(asir_out); + } + return maxrs; +} + + int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) { int i,j,k,len,pos,prev; @@ -5214,31 +5949,39 @@ int ndv_reduce_vect(int m,UINT *svect,int col,IndArray case 1: ivc = ivect->index.c; for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { - pos = prev+ivc[j]; c1 = CM(mr); c2 = svect[pos]; - prev = pos; - DMA(c1,c,c2,up,lo); - if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; - } else svect[pos] = lo; + pos = prev+ivc[j]; c1 = CM(mr); prev = pos; + if ( c1 ) { + c2 = svect[pos]; + DMA(c1,c,c2,up,lo); + if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; + } else svect[pos] = lo; + } } break; case 2: ivs = ivect->index.s; for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { - pos = prev+ivs[j]; c1 = CM(mr); c2 = svect[pos]; + pos = prev+ivs[j]; c1 = CM(mr); prev = pos; - DMA(c1,c,c2,up,lo); - if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; - } else svect[pos] = lo; + if ( c1 ) { + c2 = svect[pos]; + DMA(c1,c,c2,up,lo); + if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; + } else svect[pos] = lo; + } } break; case 4: ivi = ivect->index.i; for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { - pos = prev+ivi[j]; c1 = CM(mr); c2 = svect[pos]; + pos = prev+ivi[j]; c1 = CM(mr); prev = pos; - DMA(c1,c,c2,up,lo); - if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; - } else svect[pos] = lo; + if ( c1 ) { + c2 = svect[pos]; + DMA(c1,c,c2,up,lo); + if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3; + } else svect[pos] = lo; + } } break; } @@ -5310,7 +6053,7 @@ NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhea for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++; if ( !len ) return 0; else { - mr0 = (NMV)GC_malloc_atomic_ignore_off_page(nmv_adv*len); + mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len); #if 0 ndv_alloc += nmv_adv*len; #endif @@ -5327,6 +6070,28 @@ NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhea } } +NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect) +{ + int j,k,len; + UINT *p; + NDV r; + NMV mr0,mr; + + for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++; + if ( !len ) return 0; + else { + mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len); + mr = mr0; + p = s0vect; + for ( j = 0; j < col; j++, p += nd_wpd ) + if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) { + ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr); + } + MKNDV(nd_nvar,mr0,len,r); + return r; + } +} + /* for preprocessed vector */ NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead,UINT *s0vect) @@ -5340,7 +6105,7 @@ NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++; if ( !len ) return 0; else { - mr0 = (NMV)GC_malloc(nmv_adv*len); + mr0 = (NMV)MALLOC(nmv_adv*len); #if 0 ndv_alloc += nmv_adv*len; #endif @@ -5359,6 +6124,34 @@ NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead } } +NDV vect_to_ndv_gz(GZ *vect,int spcol,int col,int *rhead,UINT *s0vect) +{ + int j,k,len; + UINT *p; + Q c; + NDV r; + NMV mr0,mr; + + for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++; + if ( !len ) return 0; + else { + mr0 = (NMV)MALLOC(nmv_adv*len); +#if 0 + ndv_alloc += nmv_adv*len; +#endif + mr = mr0; + p = s0vect; + for ( j = k = 0; j < col; j++, p += nd_wpd ) + if ( !rhead[j] ) { + if ( c = vect[k++] ) { + ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr); + } + } + MKNDV(nd_nvar,mr0,len,r); + return r; + } +} + /* for plain vector */ NDV plain_vect_to_ndv_q(Q *vect,int col,UINT *s0vect) @@ -5372,7 +6165,7 @@ NDV plain_vect_to_ndv_q(Q *vect,int col,UINT *s0vect) for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++; if ( !len ) return 0; else { - mr0 = (NMV)GC_malloc(nmv_adv*len); + mr0 = (NMV)MALLOC(nmv_adv*len); #if 0 ndv_alloc += nmv_adv*len; #endif @@ -5418,7 +6211,10 @@ int nd_symbolic_preproc(PGeoBucket bucket,int trace,UI NDV *ps; s0 = 0; rp0 = 0; col = 0; - ps = trace?nd_ps_trace:nd_ps; + if ( nd_demand ) + ps = trace?nd_ps_trace_sym:nd_ps_sym; + else + ps = trace?nd_ps_trace:nd_ps; while ( 1 ) { head = remove_head_pbucket_symbolic(bucket); if ( !head ) break; @@ -5452,13 +6248,14 @@ int nd_symbolic_preproc(PGeoBucket bucket,int trace,UI NODE nd_f4(int m,int **indp) { int i,nh,stat,index; - NODE r,g; - ND_pairs d,l,t; + NODE r,g,tn0,tn,node; + ND_pairs d,l,t,ll0,ll; + LIST l0,l1; ND spol,red; NDV nf,redv; NM s0,s; - NODE rp0,srp0,nflist; - int nsp,nred,col,rank,len,k,j,a; + NODE rp0,srp0,nflist,nzlist,nzlist_t; + int nsp,nred,col,rank,len,k,j,a,i1s,i2s; UINT c; UINT **spmat; UINT *s0vect,*svect,*p,*v; @@ -5469,25 +6266,42 @@ NODE nd_f4(int m,int **indp) int sugar; PGeoBucket bucket; struct oEGT eg0,eg1,eg_f4; - + Q i1,i2,sugarq; #if 0 ndv_alloc = 0; #endif g = 0; d = 0; for ( i = 0; i < nd_psn; i++ ) { - d = update_pairs(d,g,i,0); + if ( !nd_nzlist ) d = update_pairs(d,g,i,0); g = update_base(g,i); } - while ( d ) { + nzlist = 0; + nzlist_t = nd_nzlist; + while ( d || nzlist_t ) { get_eg(&eg0); - l = nd_minsugarp(d,&d); - sugar = SG(l); + if ( nd_nzlist ) { + node = BDY((LIST)BDY(nzlist_t)); + sugar = ARG0(node); + tn = BDY((LIST)ARG1(node)); + if ( !tn ) { + nzlist_t = NEXT(nzlist_t); + continue; + } + /* tn = [[i1,i2],...] */ + l = nd_ipairtospair(tn); + } else { + l = nd_minsugarp(d,&d); + sugar = nd_sugarweight?l->sugar2:SG(l); + if ( MaxDeg > 0 && sugar > MaxDeg ) break; + } bucket = create_pbucket(); stat = nd_sp_f4(m,0,l,bucket); if ( !stat ) { - for ( t = l; NEXT(t); t = NEXT(t) ); - NEXT(t) = d; d = l; - d = nd_reconstruct(0,d); + if ( !nd_nzlist ) { + for ( t = l; NEXT(t); t = NEXT(t) ); + NEXT(t) = d; d = l; + d = nd_reconstruct(0,d); + } continue; } if ( bucket->m < 0 ) continue; @@ -5502,10 +6316,7 @@ NODE nd_f4(int m,int **indp) if ( DP_Print ) fprintf(asir_out,"sugar=%d,symb=%fsec,", sugar,eg_f4.exectime+eg_f4.gctime); - if ( 1 ) - nflist = nd_f4_red(m,l,0,s0vect,col,rp0,0); - else - nflist = nd_f4_red_dist(m,l,s0vect,col,rp0,0); + nflist = nd_f4_red(m,l,0,s0vect,col,rp0,nd_gentrace?&ll:0); /* adding new bases */ for ( r = nflist; r; r = NEXT(r) ) { nf = (NDV)BDY(r); @@ -5518,15 +6329,31 @@ NODE nd_f4(int m,int **indp) nd_removecont(m,nf1); nf = ndtondv(m,nf1); } - nh = ndv_newps(m,nf,0); - d = update_pairs(d,g,nh,0); + nh = ndv_newps(m,nf,0,1); + if ( !nd_nzlist ) d = update_pairs(d,g,nh,0); g = update_base(g,nh); } + if ( nd_gentrace ) { + for ( t = ll, tn0 = 0; t; t = NEXT(t) ) { + NEXTNODE(tn0,tn); + STOQ(t->i1,i1); STOQ(t->i2,i2); + node = mknode(2,i1,i2); MKLIST(l0,node); + BDY(tn) = l0; + } + if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0); + STOQ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node); + MKNODE(node,l1,nzlist); nzlist = node; + } + if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t); } + if ( nd_gentrace ) { + MKLIST(l0,reverse_node(nzlist)); + MKNODE(nd_alltracelist,l0,0); + } #if 0 fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); #endif - conv_ilist(0,0,g,indp); + conv_ilist(nd_demand,0,g,indp); return g; } @@ -5560,6 +6387,7 @@ NODE nd_f4_trace(int m,int **indp) get_eg(&eg0); l = nd_minsugarp(d,&d); sugar = SG(l); + if ( MaxDeg > 0 && sugar > MaxDeg ) break; bucket = create_pbucket(); stat = nd_sp_f4(m,0,l,bucket); if ( !stat ) { @@ -5618,7 +6446,7 @@ NODE nd_f4_trace(int m,int **indp) nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); ndv_removecont(m,nfv); - nh = ndv_newps(0,nfv,nfqv); + nh = ndv_newps(0,nfv,nfqv,1); d = update_pairs(d,g,nh,0); g = update_base(g,nh); } @@ -5626,7 +6454,7 @@ NODE nd_f4_trace(int m,int **indp) #if 0 fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); #endif - conv_ilist(0,1,g,indp); + conv_ilist(nd_demand,1,g,indp); return g; } @@ -5721,7 +6549,7 @@ NODE nd_f4_pseudo_trace(int m,int **indp) nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); ndv_removecont(m,nfv); - nh = ndv_newps(0,nfv,nfqv); + nh = ndv_newps(0,nfv,nfqv,1); d = update_pairs(d,g,nh,0); g = update_base(g,nh); } @@ -5733,6 +6561,176 @@ NODE nd_f4_pseudo_trace(int m,int **indp) return g; } +int rref(matrix mat,int *sugar) +{ + int row,col,i,j,k,l,s,wcol,wj; + unsigned long bj; + unsigned long **a; + unsigned long *ai,*ak,*as,*t; + int *pivot; + + row = mat->row; + col = mat->col; + a = mat->a; + wcol = (col+BLEN-1)/BLEN; + pivot = (int *)MALLOC_ATOMIC(row*sizeof(int)); + i = 0; + for ( j = 0; j < col; j++ ) { + wj = j/BLEN; bj = 1L<<(j%BLEN); + for ( k = i; k < row; k++ ) + if ( a[k][wj] & bj ) break; + if ( k == row ) continue; + pivot[i] = j; + if ( k != i ) { + t = a[i]; a[i] = a[k]; a[k] = t; + s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s; + } + ai = a[i]; + for ( k = i+1; k < row; k++ ) { + ak = a[k]; + if ( ak[wj] & bj ) { + for ( l = wj; l < wcol; l++ ) + ak[l] ^= ai[l]; + sugar[k] = MAX(sugar[k],sugar[i]); + } + } + i++; + } + for ( k = i-1; k >= 0; k-- ) { + j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN); + ak = a[k]; + for ( s = 0; s < k; s++ ) { + as = a[s]; + if ( as[wj] & bj ) { + for ( l = wj; l < wcol; l++ ) + as[l] ^= ak[l]; + sugar[s] = MAX(sugar[s],sugar[k]); + } + } + } + return i; +} + +void print_matrix(matrix mat) +{ + int row,col,i,j; + unsigned long *ai; + + row = mat->row; + col = mat->col; + printf("%d x %d\n",row,col); + for ( i = 0; i < row; i++ ) { + ai = mat->a[i]; + for ( j = 0; j < col; j++ ) { + if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1'); + else putchar('0'); + } + putchar('\n'); + } +} + +NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect); + +void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar) +{ + int row,col,wcol,wj,i,j; + unsigned long bj; + unsigned long *ai; + unsigned long **a; + int len; + int *pos; + + row = mat->row; + col = mat->col; + wcol = (col+BLEN-1)/BLEN; + pos = (int *)ALLOCA(wcol*sizeof(int)); + bzero(pos,wcol*sizeof(int)); + for ( i = j = 0; i < wcol; i++ ) + if ( v[i] ) pos[j++] = i;; + len = j; + wj = rhead/BLEN; + bj = 1L<a; + for ( i = 0; i < row; i++ ) { + ai = a[i]; + if ( ai[wj]&bj ) { + for ( j = 0; j < len; j++ ) + ai[pos[j]] ^= v[pos[j]]; + sugar[i] = MAX(sugar[i],rsugar); + } + } +} + +NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) +{ + int nsp,nred,i,i0,k,rank,row; + NODE r0,rp; + ND_pairs sp; + ND spol; + NM_ind_pair rt; + int *s0hash; + UINT *s; + int *pivot,*sugar,*head; + matrix mat; + NM m; + NODE r; + struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2; + int rhead,rsugar,size; + unsigned long *v; + + get_eg(&eg0); +init_eg(&eg_search); + for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); + nred = length(rp0); + mat = alloc_matrix(nsp,col); + s0hash = (int *)ALLOCA(col*sizeof(int)); + for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd ) + s0hash[i] = ndl_hash_value(s); + + sugar = (int *)ALLOCA(nsp*sizeof(int)); + for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) { + nd_sp(2,0,sp,&spol); + if ( spol ) { + mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol); + sugar[i] = SG(spol); + i++; + } + } + mat->row = i; + if ( DP_Print ) { + fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out); + } + size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long); + v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long)); + for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) { + rt = (NM_ind_pair)BDY(rp); + bzero(v,size); + rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v); + rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul)); + red_by_vect_2(mat,sugar,v,rhead,rsugar); + } + + get_eg(&eg1); + init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1); + rank = rref(mat,sugar); + + for ( i = 0, r0 = 0; i < rank; i++ ) { + NEXTNODE(r0,r); + BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect); + SG((NDV)BDY(r)) = sugar[i]; + } + if ( r0 ) NEXT(r) = 0; + get_eg(&eg2); + init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2); + if ( DP_Print ) { + fprintf(asir_out,"elim1=%fsec,elim2=%fsec\n", + eg_elim1.exectime+eg_elim1.gctime,eg_elim2.exectime+eg_elim2.gctime); + fflush(asir_out); + } + return r0; +} + + NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) { IndArray *imat; @@ -5741,7 +6739,13 @@ NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0ve NODE r0,rp; ND_pairs sp; NM_ind_pair *rvect; + UINT *s; + int *s0hash; + if ( m == 2 && nd_rref2 ) + return nd_f4_red_2(sp0,s0vect,col,rp0,nz); + +init_eg(&eg_search); for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); nred = length(rp0); imat = (IndArray *)ALLOCA(nred*sizeof(IndArray)); @@ -5749,16 +6753,23 @@ NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0ve for ( i = 0; i < col; i++ ) rhead[i] = 0; /* construction of index arrays */ + if ( DP_Print ) { + fprintf(stderr,"%dx%d,",nsp+nred,col); + } rvect = (NM_ind_pair *)ALLOCA(nred*sizeof(NM_ind_pair)); + s0hash = (int *)ALLOCA(col*sizeof(int)); + for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd ) + s0hash[i] = ndl_hash_value(s); for ( rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) { rvect[i] = (NM_ind_pair)BDY(rp); - imat[i] = nm_ind_pair_to_vect_compress(m,s0vect,col,rvect[i]); + imat[i] = nm_ind_pair_to_vect_compress(m,s0vect,col,s0hash,rvect[i]); rhead[imat[i]->head] = 1; } if ( m ) r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); else - r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); + r0 = nd_f4_red_gz_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); + if ( DP_Print ) print_eg("search",&eg_search); return r0; } @@ -5811,7 +6822,7 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s fflush(asir_out); } /* free index arrays */ - for ( i = 0; i < nred; i++ ) GC_free(imat[i]->index.c); + for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); /* elimination (2nd step) */ colstat = (int *)ALLOCA(spcol*sizeof(int)); @@ -5824,11 +6835,11 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s NEXTNODE(r0,r); BDY(r) = (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect); SG((NDV)BDY(r)) = spsugar[i]; - GC_free(spmat[i]); + GCFREE(spmat[i]); } if ( r0 ) NEXT(r) = 0; - for ( ; i < sprow; i++ ) GC_free(spmat[i]); + for ( ; i < sprow; i++ ) GCFREE(spmat[i]); get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2); if ( DP_Print ) { @@ -5892,16 +6903,21 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,U fflush(asir_out); } /* free index arrays */ -/* for ( i = 0; i < nred; i++ ) GC_free(imat[i]->index.c); */ +/* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */ /* elimination (2nd step) */ colstat = (int *)ALLOCA(spcol*sizeof(int)); rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat); w = (pointer *)ALLOCA(rank*sizeof(pointer)); for ( i = 0; i < rank; i++ ) { +#if 0 w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect); SG((NDV)w[rank-i-1]) = spsugar[i]; -/* GC_free(spmat[i]); */ +#else + w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect); + SG((NDV)w[i]) = spsugar[i]; +#endif +/* GCFREE(spmat[i]); */ } #if 0 qsort(w,rank,sizeof(NDV), @@ -5913,7 +6929,7 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,U } if ( r0 ) NEXT(r) = 0; -/* for ( ; i < sprow; i++ ) GC_free(spmat[i]); */ +/* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */ get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2); if ( DP_Print ) { @@ -5924,7 +6940,92 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,U } return r0; } + +NODE nd_f4_red_gz_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col, + NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred) +{ + int spcol,sprow,a; + int i,j,k,l,rank; + NODE r0,r; + ND_pairs sp; + ND spol; + GZ **spmat; + GZ *svect,*v; + int *colstat; + struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2; + int maxrs; + int *spsugar; + pointer *w; + + spcol = col-nred; + get_eg(&eg0); + /* elimination (1st step) */ + spmat = (GZ **)ALLOCA(nsp*sizeof(GZ *)); + svect = (GZ *)ALLOCA(col*sizeof(GZ)); + spsugar = (int *)ALLOCA(nsp*sizeof(Q)); + for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { + nd_sp(0,trace,sp,&spol); + if ( !spol ) continue; + spol = ndtondgz(spol); + nd_to_vect_q(s0vect,col,spol,(Q *)svect); + maxrs = ndv_reduce_vect_gz(svect,trace,col,imat,rvect,nred); + for ( i = 0; i < col; i++ ) if ( svect[i] ) break; + if ( i < col ) { + spmat[sprow] = v = (GZ *)MALLOC(spcol*sizeof(GZ)); + for ( j = k = 0; j < col; j++ ) + if ( !rhead[j] ) v[k++] = svect[j]; + spsugar[sprow] = MAX(maxrs,SG(spol)); + sprow++; + } +/* nd_free(spol); */ + } + get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); + if ( DP_Print ) { + fprintf(asir_out,"elim1=%fsec,",eg_f4_1.exectime+eg_f4_1.gctime); + fflush(asir_out); + } + /* free index arrays */ +/* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */ + + /* elimination (2nd step) */ + colstat = (int *)ALLOCA(spcol*sizeof(int)); + rank = nd_gauss_elim_gz(spmat,spsugar,sprow,spcol,colstat); + w = (pointer *)ALLOCA(rank*sizeof(pointer)); + for ( i = 0; i < rank; i++ ) { +#if 0 + w[rank-i-1] = (pointer)vect_to_ndv_gz(spmat[i],spcol,col,rhead,s0vect); + w[rank-i-1] = ndvgztondv(w[rank-i-1]); + SG((NDV)w[rank-i-1]) = spsugar[i]; #else + w[i] = (pointer)vect_to_ndv_gz((Q *)spmat[i],spcol,col,rhead,s0vect); + w[i] = ndvgztondv(w[i]); + SG((NDV)w[i]) = spsugar[i]; +#endif +/* GCFREE(spmat[i]); */ + + } +#if 0 + qsort(w,rank,sizeof(NDV), + (int (*)(const void *,const void *))ndv_compare); +#endif + r0 = 0; + for ( i = 0; i < rank; i++ ) { + NEXTNODE(r0,r); BDY(r) = w[i]; + } + if ( r0 ) NEXT(r) = 0; + +/* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */ + get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); + init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2); + if ( DP_Print ) { + fprintf(asir_out,"elim2=%fsec\n",eg_f4_2.exectime+eg_f4_2.gctime); + fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ", + nsp,nred,sprow,spcol,rank); + fprintf(asir_out,"%fsec\n",eg_f4.exectime+eg_f4.gctime); + } + return r0; +} +#else void printm(Q **mat,int row,int col) { int i,j; @@ -6045,7 +7146,7 @@ NDV nd_recv_ndv() len = nd_recv_int(); if ( !len ) return 0; else { - m0 = m = (NMV)GC_malloc_atomic_ignore_off_page(nmv_adv*len); + m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len); #if 0 ndv_alloc += len*nmv_adv; #endif @@ -6076,6 +7177,7 @@ int ox_exec_f4_red(Q proc) return s; } +#if 0 NODE nd_f4_red_dist(int m,ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) { int nsp,nred; @@ -6238,6 +7340,7 @@ void nd_exec_f4_red_dist() } fflush(nd_write); } +#endif int nd_gauss_elim_q(Q **mat0,int *sugar,int row,int col,int *colstat) { @@ -6260,6 +7363,27 @@ int nd_gauss_elim_q(Q **mat0,int *sugar,int row,int co return rank; } +int nd_gauss_elim_gz(GZ **mat0,int *sugar,int row,int col,int *colstat) +{ + int i,j,t,c,rank,inv; + int *ci,*ri; + GZ dn; + MAT m,nm; + + NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0; + rank = gz_generic_gauss_elim(m,&nm,&dn,&ri,&ci); + for ( i = 0; i < row; i++ ) + for ( j = 0; j < col; j++ ) + mat0[i][j] = 0; + c = col-rank; + for ( i = 0; i < rank; i++ ) { + mat0[i][ri[i]] = dn; + for ( j = 0; j < c; j++ ) + mat0[i][ci[j]] = (GZ)BDY(nm)[i][j]; + } + return rank; +} + int nd_gauss_elim_mod(int **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat) { int i,j,k,l,inv,a,rank,s; @@ -6436,6 +7560,32 @@ void ndv_save(NDV p,int index) fclose(s); } +void nd_save_mod(ND p,int index) +{ + FILE *s; + char name[BUFSIZ]; + int nv,sugar,len,c; + NM m; + + sprintf(name,"%s/%d",Demand,index); + s = fopen(name,"w"); + if ( !p ) { + len = 0; + write_int(s,&len); + fclose(s); + return; + } + nv = NV(p); + sugar = SG(p); + len = LEN(p); + write_int(s,&nv); write_int(s,&sugar); write_int(s,&len); + for ( m = BDY(p); m; m = NEXT(m) ) { + c = CM(m); write_int(s,&c); + write_intarray(s,DL(m),nd_wpd); + } + fclose(s); +} + NDV ndv_load(int index) { FILE *s; @@ -6480,6 +7630,36 @@ NDV ndv_load(int index) return d; } +ND nd_load_mod(int index) +{ + FILE *s; + char name[BUFSIZ]; + int nv,sugar,len,i,c; + ND d; + NM m0,m; + + sprintf(name,"%s/%d",Demand,index); + s = fopen(name,"r"); + /* if the file does not exist, it means p[index]=0 */ + if ( !s ) return 0; + + read_int(s,&nv); + if ( !nv ) { fclose(s); return 0; } + + read_int(s,&sugar); + read_int(s,&len); + for ( m0 = 0, i = 0; i < len; i++ ) { + NEXTNM(m0,m); + read_int(s,&c); CM(m) = c; + read_intarray(s,DL(m),nd_wpd); + } + NEXT(m) = 0; + MKND(nv,m0,len,d); + SG(d) = sugar; + fclose(s); + return d; +} + void nd_det(int mod,MAT f,P *rp) { VL fv,tv; @@ -6562,7 +7742,9 @@ void nd_det(int mod,MAT f,P *rp) if ( mod ) ndv_mod(mod,d); chsgnq(ONE,&mone); for ( j = 0, sgn = 1; j < n; j++ ) { - if ( DP_Print ) fprintf(stderr,".",j); + if ( DP_Print ) { + fprintf(stderr,".",j); + } for ( i = j; i < n && !dm[i][j]; i++ ); if ( i == n ) { *rp = 0; @@ -6602,24 +7784,16 @@ void nd_det(int mod,MAT f,P *rp) bucket = create_pbucket(); if ( mi[k] ) { nmv = BDY(mjj); len = LEN(mjj); - fprintf(stderr,"len=%d\n",len); for ( a = 0; a < len; a++, NMV_ADV(nmv) ) { - fprintf(stderr,"."); u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d))); add_pbucket(mod,bucket,u); - if ( !(a%1000) ) - fprintf(stderr,"%d\n",a); } } if ( mj[k] && mij ) { nmv = BDY(mij); len = LEN(mij); - fprintf(stderr,"len=%d\n",len); for ( a = 0; a < len; a++, NMV_ADV(nmv) ) { - fprintf(stderr,"."); u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d))); add_pbucket(mod,bucket,u); - if ( !(a%1000) ) - fprintf(stderr,"%d\n",a); } } u = nd_quo(mod,bucket,d); @@ -6629,7 +7803,9 @@ void nd_det(int mod,MAT f,P *rp) } d = mjj; } - if ( DP_Print ) fprintf(stderr,"\n",k); + if ( DP_Print ) { + fprintf(stderr,"\n",k); + } if ( sgn < 0 ) if ( mod ) ndv_mul_c(mod,d,mod-1); @@ -6920,7 +8096,7 @@ void finalize_tracelist(int i,P cont) Q iq; if ( !UNIQ(cont) ) { - node = mknode(4,0,0,0,cont); + node = mknode(4,NULLP,NULLP,NULLP,cont); MKLIST(l,node); MKNODE(node,l,nd_tracelist); nd_tracelist = node; } @@ -6950,11 +8126,15 @@ void conv_ilist(int demand,int trace,NODE g,int **indp void parse_nd_option(NODE opt) { NODE t,p,u; - int i,s; + int i,s,n; char *key; Obj value; nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_gbblock = 0; + nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0; + nd_splist = 0; nd_check_splist = 0; + nd_sugarweight = 0; + for ( t = opt; t; t = NEXT(t) ) { p = BDY((LIST)BDY(t)); key = BDY((STRING)BDY(p)); @@ -6969,13 +8149,311 @@ void parse_nd_option(NODE opt) if ( !value || OID(value) != O_LIST ) error("nd_* : invalid value for gbblock option"); u = BDY((LIST)value); - nd_gbblock = MALLOC(2*length(t)+1); + nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int)); for ( i = 0; u; u = NEXT(u) ) { p = BDY((LIST)BDY(u)); s = nd_gbblock[i++] = QTOS((Q)BDY(p)); nd_gbblock[i++] = s+QTOS((Q)BDY(NEXT(p)))-1; } nd_gbblock[i] = -1; + } else if ( !strcmp(key,"newelim") ) + nd_newelim = value?1:0; + else if ( !strcmp(key,"intersect") ) + nd_intersect = value?1:0; + else if ( !strcmp(key,"trace") ) { + u = BDY((LIST)value); + nd_nzlist = BDY((LIST)ARG2(u)); + nd_bpe = QTOS((Q)ARG3(u)); + } else if ( !strcmp(key,"splist") ) + nd_splist = value?1:0; + else if ( !strcmp(key,"check_splist") ) { + nd_check_splist = BDY((LIST)value); + } else if ( !strcmp(key,"sugarweight") ) { + nd_sugarweight = BDY((LIST)value); + u = BDY((LIST)value); + n = length(u); + nd_sugarweight = MALLOC(n*sizeof(int)); + for ( i = 0; i < n; i++, u = NEXT(u) ) + nd_sugarweight[i] = QTOS((Q)BDY(u)); } } +} + +ND mdptond(DP d); +ND nd_mul_nm(int mod,NM m0,ND p); +ND *btog(NODE ti,ND **p,int nb,int mod); +ND btog_one(NODE ti,ND *p,int nb,int mod); +MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp); +VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp); + +/* d:monomial */ +ND mdptond(DP d) +{ + NM m; + ND r; + + if ( OID(d) == 1 ) + r = ptond(CO,CO,(P)d); + else { + NEWNM(m); + dltondl(NV(d),BDY(d)->dl,DL(m)); + CQ(m) = (Q)BDY(d)->c; + NEXT(m) = 0; + MKND(NV(d),m,1,r); + } + return r; +} + +ND nd_mul_nm(int mod,NM m0,ND p) +{ + UINT *d0; + int c0,c1,c; + NM tm,mr,mr0; + ND r; + + if ( !p ) return 0; + d0 = DL(m0); + c0 = CM(m0); + mr0 = 0; + for ( tm = BDY(p); tm; tm = NEXT(tm) ) { + NEXTNM(mr0,mr); + c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1; + ndl_add(d0,DL(tm),DL(mr)); + } + NEXT(mr) = 0; + MKND(NV(p),mr0,LEN(p),r); + return r; +} + +ND *btog(NODE ti,ND **p,int nb,int mod) +{ + PGeoBucket *r; + int i,ci; + NODE t,s; + ND m,tp; + ND *pi,*rd; + P c; + + r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket)); + for ( i = 0; i < nb; i++ ) + r[i] = create_pbucket(); + for ( t = ti; t; t = NEXT(t) ) { + s = BDY((LIST)BDY(t)); + if ( ARG0(s) ) { + m = mdptond((DP)ARG2(s)); + ptomp(mod,(P)HCQ(m),&c); + if ( ci = ((MQ)c)->cont ) { + HCM(m) = ci; + pi = p[QTOS((Q)ARG1(s))]; + for ( i = 0; i < nb; i++ ) { + tp = nd_mul_nm(mod,BDY(m),pi[i]); + add_pbucket(mod,r[i],tp); + } + } + ci = 1; + } else { + ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont; + ci = invm(ci,mod); + } + } + rd = (ND *)MALLOC(nb*sizeof(ND)); + for ( i = 0; i < nb; i++ ) + rd[i] = normalize_pbucket(mod,r[i]); + if ( ci != 1 ) + for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci); + return rd; +} + +ND btog_one(NODE ti,ND *p,int nb,int mod) +{ + PGeoBucket r; + int i,ci,j; + NODE t,s; + ND m,tp; + ND pi,rd; + P c; + + r = create_pbucket(); + for ( t = ti; t; t = NEXT(t) ) { + s = BDY((LIST)BDY(t)); + if ( ARG0(s) ) { + m = mdptond((DP)ARG2(s)); + ptomp(mod,(P)HCQ(m),&c); + if ( ci = ((MQ)c)->cont ) { + HCM(m) = ci; + pi = p[j=QTOS((Q)ARG1(s))]; + if ( !pi ) { + pi = nd_load_mod(j); + tp = nd_mul_nm(mod,BDY(m),pi); + nd_free(pi); + add_pbucket(mod,r,tp); + } else { + tp = nd_mul_nm(mod,BDY(m),pi); + add_pbucket(mod,r,tp); + } + } + ci = 1; + } else { + ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont; + ci = invm(ci,mod); + } + } + rd = normalize_pbucket(mod,r); + free_pbucket(r); + if ( ci != 1 ) nd_mul_c(mod,rd,ci); + return rd; +} + +MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp) +{ + int i,j,n,m,nb,pi0,pi1,nvar; + VL fv,tv,vv; + NODE permtrace,perm,trace,intred,ind,t,pi,ti; + ND **p; + ND *c; + ND u; + P inv; + MAT mat; + + parse_nd_option(current_option); + get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc); + for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); + switch ( ord->id ) { + case 1: + if ( ord->nv != nvar ) + error("nd_check : invalid order specification"); + break; + default: + break; + } + nd_init_ord(ord); +#if 0 + nd_bpe = QTOS((Q)ARG7(BDY(tlist))); +#else + nd_bpe = 32; +#endif + nd_setup_parameters(nvar,0); + permtrace = BDY((LIST)ARG2(BDY(tlist))); + intred = BDY((LIST)ARG3(BDY(tlist))); + ind = BDY((LIST)ARG4(BDY(tlist))); + perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace); + for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) { + j = QTOS((Q)BDY(BDY((LIST)BDY(t)))); + if ( j > i ) i = j; + } + n = i+1; + nb = length(BDY(f)); + p = (ND **)MALLOC(n*sizeof(ND *)); + for ( t = perm, i = 0; t; t = NEXT(t), i++ ) { + pi = BDY((LIST)BDY(t)); + pi0 = QTOS((Q)ARG0(pi)); pi1 = QTOS((Q)ARG1(pi)); + p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND)); + ptomp(mod,(P)ARG2(pi),&inv); + ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod); + u = ptond(CO,vv,(P)ONE); + HCM(u) = ((MQ)inv)->cont; + c[pi1] = u; + } + for ( t = trace,i=0; t; t = NEXT(t), i++ ) { + printf("%d ",i); fflush(stdout); + ti = BDY((LIST)BDY(t)); + p[j=QTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod); + if ( j == 441 ) + printf("afo"); + } + for ( t = intred, i=0; t; t = NEXT(t), i++ ) { + printf("%d ",i); fflush(stdout); + ti = BDY((LIST)BDY(t)); + p[j=QTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod); + if ( j == 441 ) + printf("afo"); + } + m = length(ind); + MKMAT(mat,nb,m); + for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) + for ( i = 0, c = p[QTOS((Q)BDY(t))]; i < nb; i++ ) + BDY(mat)[i][j] = ndtodp(mod,c[i]); + return mat; +} + +VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord, + LIST tlist,int pos,MAT *rp) +{ + int i,j,n,m,nb,pi0,pi1,nvar; + VL fv,tv,vv; + NODE permtrace,perm,trace,intred,ind,t,pi,ti; + ND *p; + ND *c; + ND u; + P inv; + VECT vect; + + parse_nd_option(current_option); + get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc); + for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ ); + switch ( ord->id ) { + case 1: + if ( ord->nv != nvar ) + error("nd_check : invalid order specification"); + break; + default: + break; + } + nd_init_ord(ord); +#if 0 + nd_bpe = QTOS((Q)ARG7(BDY(tlist))); +#else + nd_bpe = 32; +#endif + nd_setup_parameters(nvar,0); + permtrace = BDY((LIST)ARG2(BDY(tlist))); + intred = BDY((LIST)ARG3(BDY(tlist))); + ind = BDY((LIST)ARG4(BDY(tlist))); + perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace); + for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) { + j = QTOS((Q)BDY(BDY((LIST)BDY(t)))); + if ( j > i ) i = j; + } + n = i+1; + nb = length(BDY(f)); + p = (ND *)MALLOC(n*sizeof(ND *)); + for ( t = perm, i = 0; t; t = NEXT(t), i++ ) { + pi = BDY((LIST)BDY(t)); + pi0 = QTOS((Q)ARG0(pi)); pi1 = QTOS((Q)ARG1(pi)); + if ( pi1 == pos ) { + ptomp(mod,(P)ARG2(pi),&inv); + ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod); + u = ptond(CO,vv,(P)ONE); + HCM(u) = ((MQ)inv)->cont; + p[pi0] = u; + } + } + for ( t = trace,i=0; t; t = NEXT(t), i++ ) { + printf("%d ",i); fflush(stdout); + ti = BDY((LIST)BDY(t)); + p[j=QTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod); + if ( Demand ) { + nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0; + } + } + for ( t = intred, i=0; t; t = NEXT(t), i++ ) { + printf("%d ",i); fflush(stdout); + ti = BDY((LIST)BDY(t)); + p[j=QTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod); + if ( Demand ) { + nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0; + } + } + m = length(ind); + MKVECT(vect,m); + for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) { + u = p[QTOS((Q)BDY(t))]; + if ( !u ) { + u = nd_load_mod(QTOS((Q)BDY(t))); + BDY(vect)[j] = ndtodp(mod,u); + nd_free(u); + } else + BDY(vect)[j] = ndtodp(mod,u); + } + return vect; }