=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/engine/nd.c,v retrieving revision 1.131 retrieving revision 1.152 diff -u -p -r1.131 -r1.152 --- OpenXM_contrib2/asir2000/engine/nd.c 2006/06/05 01:01:41 1.131 +++ OpenXM_contrib2/asir2000/engine/nd.c 2006/12/21 07:45:02 1.152 @@ -1,4 +1,4 @@ -/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.130 2006/05/30 07:35:31 noro Exp $ */ +/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.151 2006/12/14 02:49:59 noro Exp $ */ #include "nd.h" @@ -8,7 +8,10 @@ int nd_dcomp; NM _nm_free_list; ND _nd_free_list; ND_pairs _ndp_free_list; +NODE nd_hcf; +static NODE nd_subst; +static VL nd_vc; static int nd_ntrans; static int nd_nalg; #if 0 @@ -47,9 +50,12 @@ static int nd_demand; NumberField get_numberfield(); UINT *nd_det_compute_bound(NDV **dm,int n,int j); void nd_det_reconstruct(NDV **dm,int n,int j,NDV d); +void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr); int nd_monic(int m,ND *p); NDV plain_vect_to_ndv_q(Q *mat,int col,UINT *s0vect); +extern int Denominator,DP_Multiple; + void nd_free_private_storage() { _nm_free_list = 0; @@ -976,13 +982,13 @@ ND nd_add(int mod,ND p1,ND p2) int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr) { NM s; - Q t; + P t; int can; - addq(CQ(*m1),CQ(*m2),&t); + addp(nd_vc,CP(*m1),CP(*m2),&t); s = *m1; *m1 = NEXT(*m1); if ( t ) { - can = 1; NEXTNM2(*mr0,*mr,s); CQ(*mr) = (t); + can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t); } else { can = 2; FREENM(s); } @@ -995,7 +1001,7 @@ ND nd_add_q(ND p1,ND p2) int n,c,can; ND r; NM m1,m2,mr0,mr,s; - Q t; + P t; if ( !p1 ) return p2; else if ( !p2 ) return p1; @@ -1008,10 +1014,10 @@ ND nd_add_q(ND p1,ND p2) #if defined(__x86_64__) can += nm_destructive_add_q(&m1,&m2,&mr0,&mr); #else - addq(CQ(m1),CQ(m2),&t); + addp(nd_vc,CP(m1),CP(m2),&t); s = m1; m1 = NEXT(m1); if ( t ) { - can++; NEXTNM2(mr0,mr,s); CQ(mr) = (t); + can++; NEXTNM2(mr0,mr,s); CP(mr) = (t); } else { can += 2; FREENM(s); } @@ -1088,10 +1094,41 @@ ND nd_add_sf(ND p1,ND p2) } } +ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn) +{ + int c,c1,c2; + Q cg,cred,gcd,tq; + P cgp,credp,gcdp; + Obj tr,tr1; + + if ( mod == -1 ) + CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g))); + else if ( mod ) { + c1 = invm(HCM(p),mod); c2 = mod-HCM(g); + DMAR(c1,c2,0,mod,c); CM(mul) = c; + } else if ( nd_vc ) { + ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp); + divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp); + chsgnp(cgp,&CP(mul)); + nd_mul_c_q(d,credp); nd_mul_c_q(g,credp); + if ( dn ) { + mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr); + reductr(nd_vc,tr,&tr1); dn->r = (R)tr1; + } + } else { + igcd_cofactor(HCQ(g),HCQ(p),&gcd,&cg,&cred); + chsgnq(cg,&CQ(mul)); + nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred); + if ( dn ) { + mulq(dn->z,cred,&tq); dn->z = tq; + } + } + return nd_add(mod,g,ndv_mul_nm(mod,mul,p)); +} + /* ret=1 : success, ret=0 : overflow */ -int nd_nf(int mod,ND g,NDV *ps,int full,NDC dn,ND *rp) +int nd_nf(int mod,ND d,ND g,NDV *ps,int full,NDC dn,ND *rp) { - ND d; NM m,mrd,tail; NM mul; int n,sugar,psugar,sugar0,stat,index; @@ -1100,23 +1137,29 @@ int nd_nf(int mod,ND g,NDV *ps,int full,NDC dn,ND *rp) NDV p,red; Q cg,cred,gcd,tq,qq; double hmag; + P tp,tp1; + Obj tr,tr1; if ( dn ) { if ( mod ) dn->m = 1; + else if ( nd_vc ) + dn->r = (R)ONE; else dn->z = ONE; } if ( !g ) { - *rp = 0; + *rp = d; return 1; } - if ( !mod ) hmag = ((double)p_mag((P)HCQ(g)))*nd_scale; + if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale; sugar0 = sugar = SG(g); n = NV(g); mul = (NM)ALLOCA(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT)); - for ( d = 0; g; ) { + if ( d ) + for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) ); + for ( ; g; ) { index = ndl_find_reducer(HDL(g)); if ( index >= 0 ) { h = nd_psh[index]; @@ -1125,32 +1168,23 @@ int nd_nf(int mod,ND g,NDV *ps,int full,NDC dn,ND *rp) nd_free(g); nd_free(d); return 0; } - if ( nd_demand ) - p = ndv_load(index); - else - p = ps[index]; - if ( mod == -1 ) - CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g))); - else if ( mod ) { - c1 = invm(HCM(p),mod); c2 = mod-HCM(g); - DMAR(c1,c2,0,mod,c); CM(mul) = c; - } else { - igcd_cofactor(HCQ(g),HCQ(p),&gcd,&cg,&cred); - chsgnq(cg,&CQ(mul)); - nd_mul_c_q(d,cred); nd_mul_c_q(g,cred); - if ( dn ) { - mulq(dn->z,cred,&tq); dn->z = tq; - } - } - g = nd_add(mod,g,ndv_mul_nm(mod,mul,p)); + p = nd_demand ? ndv_load(index) : ps[index]; + g = nd_reduce2(mod,d,g,p,mul,dn); sugar = MAX(sugar,SG(p)+TD(DL(mul))); - if ( !mod && hmag && g && ((double)(p_mag((P)HCQ(g))) > hmag) ) { - tq = HCQ(g); + if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) { + tp = HCP(g); nd_removecont2(d,g); if ( dn ) { - divq(tq,HCQ(g),&qq); divq(dn->z,qq,&tq); dn->z = tq; + if ( nd_vc ) { + divsp(nd_vc,tp,HCP(g),&tp1); + divr(nd_vc,(Obj)dn->r,(Obj)tp1,&tr); + reductr(nd_vc,(Obj)tr,&tr1); dn->r = (R)tr1; + } else { + divq((Q)tp,HCQ(g),&qq); + divq(dn->z,qq,&tq); dn->z = tq; + } } - hmag = ((double)p_mag((P)HCQ(g)))*nd_scale; + hmag = ((double)p_mag(HCP(g)))*nd_scale; } } else if ( !full ) { *rp = g; @@ -1231,7 +1265,7 @@ int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp } else { igcd_cofactor(HCQ(g),HCQ(p),&gcd,&cg,&cred); chsgnq(cg,&CQ(mul)); - nd_mul_c_q(d,cred); + nd_mul_c_q(d,(P)cred); mulq_pbucket(bucket,cred); g = bucket->body[hindex]; gmag = (double)p_mag((P)HCQ(g)); @@ -1286,7 +1320,7 @@ int ndv_check_candidate(NODE input,int obpe,int oadv,E NODE t,s; union oNDC dn; - ndv_setup(0,0,cand,0); + ndv_setup(0,0,cand,0,1); n = length(cand); /* membercheck : list is a subset of Id(cand) ? */ @@ -1297,7 +1331,7 @@ again: else r = (NDV)BDY(t); d = ndvtond(0,r); - stat = nd_nf(0,d,nd_ps,0,0,&nf); + stat = nd_nf(0,0,d,nd_ps,0,0,&nf); if ( !stat ) { nd_reconstruct(0,0); goto again; @@ -1404,7 +1438,7 @@ void mulq_pbucket(PGeoBucket g,Q c) int k; for ( k = 0; k <= g->m; k++ ) - nd_mul_c_q(g->body[k],c); + nd_mul_c_q(g->body[k],(P)c); } NM remove_head_pbucket_symbolic(PGeoBucket g) @@ -1539,6 +1573,68 @@ ND normalize_pbucket(int mod,PGeoBucket g) return r; } +#if 0 +void register_hcf(NDV p) +{ + DCP dc,t; + P hc,h; + int c; + NODE l,l1,prev; + + hc = p->body->c.p; + if ( !nd_vc || NUM(hc) ) return; + fctrp(nd_vc,hc,&dc); + for ( t = dc; t; t = NEXT(t) ) { + h = t->c; + if ( NUM(h) ) continue; + for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) { + c = compp(nd_vc,h,(P)BDY(l)); + if ( c >= 0 ) break; + } + if ( !l || c > 0 ) { + MKNODE(l1,h,l); + if ( !prev ) + nd_hcf = l1; + else + NEXT(prev) = l1; + } + } +} +#else +void register_hcf(NDV p) +{ + DCP dc,t; + P hc,h,q; + Q dmy; + int c; + NODE l,l1,prev; + + hc = p->body->c.p; + if ( NUM(hc) ) return; + ptozp(hc,1,&dmy,&h); +#if 1 + for ( l = nd_hcf; l; l = NEXT(l) ) { + while ( 1 ) { + if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q; + else break; + } + } + if ( NUM(h) ) return; +#endif + for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) { + c = compp(nd_vc,h,(P)BDY(l)); + if ( c >= 0 ) break; + } + if ( !l || c > 0 ) { + MKNODE(l1,h,l); + if ( !prev ) + nd_hcf = l1; + else + NEXT(prev) = l1; + } +} +#endif + int do_diagonalize(int sugar,int m) { int i,nh,stat; @@ -1546,7 +1642,7 @@ int do_diagonalize(int sugar,int m) ND h,nf,s,head; NDV nfv; Q q,num,den; - union oNDC dn; + P nm,nmp,dn,mnp,dnp; for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) { if ( nd_demand ) @@ -1555,22 +1651,14 @@ int do_diagonalize(int sugar,int m) nfv = nd_ps[i]; s = ndvtond(m,nfv); s = nd_separate_head(s,&head); - stat = nd_nf(m,s,nd_ps,1,&dn,&nf); + stat = nd_nf(m,head,s,nd_ps,1,0,&nf); if ( !stat ) return 0; - if ( !m ) { - NTOQ(NM(dn.z),SGN(dn.z),num); - mulq(HCQ(head),num,&q); HCQ(head) = q; - if ( DN(dn.z) ) { - NTOQ(DN(dn.z),1,den); - nd_mul_c_q(nf,den); - } - } - nf = nd_add(m,head,nf); ndv_free(nfv); nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf); nd_bound[i] = ndv_compute_bound(nfv); + if ( !m ) register_hcf(nfv); if ( nd_demand ) { ndv_save(nfv,i); ndv_free(nfv); @@ -1605,6 +1693,7 @@ again: l = nd_minp(d,&d); if ( SG(l) != sugar ) { if ( ishomo ) { + diag_count = 0; stat = do_diagonalize(sugar,m); if ( !stat ) { NEXT(l) = d; d = l; @@ -1622,9 +1711,9 @@ again: goto again; } #if USE_GEOBUCKET - stat = m?nd_nf_pbucket(m,h,nd_ps,!Top,&nf):nd_nf(m,h,nd_ps,!Top,0,&nf); + stat = m?nd_nf_pbucket(m,h,nd_ps,!Top,&nf):nd_nf(m,0,h,nd_ps,!Top,0,&nf); #else - stat = nd_nf(m,h,nd_ps,!Top,0,&nf); + stat = nd_nf(m,0,h,nd_ps,!Top,0,&nf); #endif if ( !stat ) { NEXT(l) = d; d = l; @@ -1640,12 +1729,12 @@ again: } nfv = ndtondv(m,nf); nd_free(nf); nh = ndv_newps(m,nfv,0); - if ( ishomo && ++diag_count == diag_period ) { + if ( !m && (ishomo && ++diag_count == diag_period) ) { diag_count = 0; stat = do_diagonalize(sugar,m); if ( !stat ) { NEXT(l) = d; d = l; - d = nd_reconstruct(0,d); + d = nd_reconstruct(1,d); goto again; } } @@ -1663,6 +1752,7 @@ again: else for ( t = g; t; t = NEXT(t) ) BDY(t) = (pointer)nd_ps[(int)BDY(t)]; + if ( !checkonly && DP_Print ) { printf("nd_gb done.\n"); fflush(stdout); } return g; } @@ -1673,7 +1763,6 @@ int do_diagonalize_trace(int sugar,int m) ND h,nf,nfq,s,head; NDV nfv,nfqv; Q q,den,num; - union oNDC dn; for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) { /* for nd_ps */ @@ -1693,20 +1782,14 @@ int do_diagonalize_trace(int sugar,int m) nfv = nd_ps_trace[i]; s = ndvtond(0,nfv); s = nd_separate_head(s,&head); - stat = nd_nf(0,s,nd_ps_trace,1,&dn,&nf); + stat = nd_nf(0,head,s,nd_ps_trace,1,0,&nf); if ( !stat ) return 0; - NTOQ(NM(dn.z),SGN(dn.z),num); - mulq(HCQ(head),num,&q); HCQ(head) = q; - if ( DN(dn.z) ) { - NTOQ(DN(dn.z),1,den); - nd_mul_c_q(nf,den); - } - nf = nd_add(0,head,nf); ndv_free(nfv); nd_removecont(0,nf); nfv = ndtondv(0,nf); nd_free(nf); nd_bound[i] = ndv_compute_bound(nfv); + register_hcf(nfv); if ( nd_demand ) { ndv_save(nfv,i); ndv_free(nfv); @@ -1719,6 +1802,17 @@ int do_diagonalize_trace(int sugar,int m) static struct oEGT eg_invdalg; struct oEGT eg_le; +void nd_subst_vector(VL vl,P p,NODE subst,P *r) +{ + NODE tn; + P p1; + + for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) { + substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1; + } + *r = p; +} + NODE nd_gb_trace(int m,int ishomo) { int i,nh,sugar,stat; @@ -1728,6 +1822,7 @@ NODE nd_gb_trace(int m,int ishomo) ND h,nf,nfq,s,head; NDV nfv,nfqv; Q q,den,num; + P hc; union oNDC dn; struct oEGT eg_monic,egm0,egm1; int diag_count = 0; @@ -1747,7 +1842,9 @@ again: if ( SG(l) != sugar ) { #if 1 if ( ishomo ) { + if ( DP_Print > 2 ) fprintf(asir_out,"|"); stat = do_diagonalize_trace(sugar,m); + if ( DP_Print > 2 ) fprintf(asir_out,"|"); diag_count = 0; if ( !stat ) { NEXT(l) = d; d = l; @@ -1768,7 +1865,7 @@ again: #if USE_GEOBUCKET stat = nd_nf_pbucket(m,h,nd_ps,!Top,&nf); #else - stat = nd_nf(m,h,nd_ps,!Top,0,&nf); + stat = nd_nf(m,0,h,nd_ps,!Top,0,&nf); #endif if ( !stat ) { NEXT(l) = d; d = l; @@ -1781,7 +1878,7 @@ again: } else nfq = 0; if ( !nfq ) { - if ( !nd_sp(0,1,l,&h) || !nd_nf(0,h,nd_ps_trace,!Top,0,&nfq) ) { + if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!Top,0,&nfq) ) { NEXT(l) = d; d = l; d = nd_reconstruct(1,d); goto again; @@ -1789,7 +1886,11 @@ again: } if ( nfq ) { /* m|HC(nfq) => failure */ - if ( !rem(NM(HCQ(nfq)),m) ) return 0; + if ( nd_vc ) { + nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Q)hc; + } else + q = HCQ(nfq); + if ( !rem(NM(q),m) ) return 0; if ( DP_Print ) { printf("+"); fflush(stdout); } if ( nd_nalg ) { @@ -1806,7 +1907,9 @@ again: nh = ndv_newps(0,nfv,nfqv); if ( ishomo && ++diag_count == diag_period ) { diag_count = 0; + if ( DP_Print > 2 ) fprintf(asir_out,"|"); stat = do_diagonalize_trace(sugar,m); + if ( DP_Print > 2 ) fprintf(asir_out,"|"); if ( !stat ) { NEXT(l) = d; d = l; d = nd_reconstruct(1,d); @@ -1834,6 +1937,7 @@ again: print_eg("invdalg",&eg_invdalg); print_eg("le",&eg_le); } + if ( DP_Print ) { printf("nd_gb_trace done.\n"); fflush(stdout); } return g; } @@ -1864,24 +1968,15 @@ NODE ndv_reduceall(int m,NODE f) (int (*)(const void *,const void *))ndv_compare); for ( t = f, i = 0; t; i++, t = NEXT(t) ) BDY(t) = (pointer)w[i]; #endif - ndv_setup(m,0,f,0); + ndv_setup(m,0,f,0,1); for ( i = 0; i < n; ) { g = ndvtond(m,nd_ps[i]); g = nd_separate_head(g,&head); - stat = nd_nf(m,g,nd_ps,1,&dn,&nf); + stat = nd_nf(m,head,g,nd_ps,1,0,&nf); if ( !stat ) nd_reconstruct(0,0); else { if ( DP_Print ) { printf("."); fflush(stdout); } - if ( !m ) { - NTOQ(NM(dn.z),SGN(dn.z),num); - mulq(HCQ(head),num,&q); HCQ(head) = q; - if ( DN(dn.z) ) { - NTOQ(DN(dn.z),1,den); - nd_mul_c_q(nf,den); - } - } - nf = nd_add(m,head,nf); ndv_free(nd_ps[i]); nd_removecont(m,nf); nd_ps[i] = ndtondv(m,nf); nd_free(nf); @@ -2186,9 +2281,11 @@ int ndv_newps(int m,NDV a,NDV aq) nd_ps[nd_psn] = a; if ( aq ) { nd_ps_trace[nd_psn] = aq; + register_hcf(aq); nd_bound[nd_psn] = ndv_compute_bound(aq); SG(r) = SG(aq); ndl_copy(HDL(aq),DL(r)); } else { + if ( !m ) register_hcf(a); nd_bound[nd_psn] = ndv_compute_bound(a); SG(r) = SG(a); ndl_copy(HDL(a),DL(r)); } @@ -2204,7 +2301,7 @@ int ndv_newps(int m,NDV a,NDV aq) return nd_psn++; } -void ndv_setup(int mod,int trace,NODE f,int dont_sort) +void ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont) { int i,j,td,len,max; NODE s,s0,f0; @@ -2218,28 +2315,42 @@ void ndv_setup(int mod,int trace,NODE f,int dont_sort) for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++; w = (NDV *)ALLOCA(nd_psn*sizeof(NDV)); for ( i = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) w[i++] = BDY(s); - if ( !dont_sort ) - qsort(w,nd_psn,sizeof(NDV), - (int (*)(const void *,const void *))ndv_compare); + if ( !dont_sort ) { + /* XXX heuristic */ + if ( !nd_ord->id && (nd_ord->ord.simple<2) ) + qsort(w,nd_psn,sizeof(NDV), + (int (*)(const void *,const void *))ndv_compare_rev); + else + qsort(w,nd_psn,sizeof(NDV), + (int (*)(const void *,const void *))ndv_compare); + } nd_pslen = 2*nd_psn; nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV)); nd_ps_trace = (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; + if ( trace && nd_vc ) + makesubst(nd_vc,&nd_subst); + else + nd_subst = 0; + if ( !nd_red ) nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist)); for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0; for ( i = 0; i < nd_psn; i++ ) { if ( trace ) { a = nd_ps_trace[i] = ndv_dup(0,w[i]); - ndv_removecont(0,a); + if ( !dont_removecont) ndv_removecont(0,a); + register_hcf(a); am = nd_ps[i] = ndv_dup(mod,a); ndv_mod(mod,am); ndv_removecont(mod,am); } else { a = nd_ps[i] = ndv_dup(mod,w[i]); - ndv_removecont(mod,a); + if ( mod || !dont_removecont ) ndv_removecont(mod,a); + if ( !mod ) register_hcf(a); } NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r)); nd_bound[i] = ndv_compute_bound(a); @@ -2369,7 +2480,8 @@ void nd_gr(LIST f,LIST v,int m,int f4,struct order_spe NDV b; int ishomo,nalg; Alg alpha,dp; - P p; + P p,zp; + Q dmy; LIST f1,f2; Obj obj; NumberField nf; @@ -2378,10 +2490,12 @@ void nd_gr(LIST f,LIST v,int m,int f4,struct order_spe if ( !m && Demand ) nd_demand = 1; else nd_demand = 0; + if ( DP_Multiple ) + nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1); #if 0 ndv_alloc = 0; #endif - get_vars((Obj)f,&fv); pltovl(v,&vv); + 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: @@ -2415,14 +2529,15 @@ void nd_gr(LIST f,LIST v,int m,int f4,struct order_spe nd_setup_parameters(nvar,max); ishomo = 1; for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) { - b = (pointer)ptondv(CO,vv,(P)BDY(t)); + ptozp((P)BDY(t),1,&dmy,&zp); + b = (pointer)ptondv(CO,vv,zp); if ( ishomo ) ishomo = ishomo && ndv_ishomo(b); if ( m ) ndv_mod(m,b); if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; } } if ( fd0 ) NEXT(fd) = 0; - ndv_setup(m,0,fd0,0); + ndv_setup(m,0,fd0,0,0); x = f4?nd_f4(m):nd_gb(m,ishomo,0); nd_demand = 0; x = ndv_reducebase(x); @@ -2448,13 +2563,14 @@ void nd_gr_postproc(LIST f,LIST v,int m,struct order_s NDV b; int ishomo,nalg; Alg alpha,dp; - P p; + P p,zp; + Q dmy; LIST f1,f2; Obj obj; NumberField nf; struct order_spec *ord1; - get_vars((Obj)f,&fv); pltovl(v,&vv); + 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: @@ -2488,14 +2604,15 @@ void nd_gr_postproc(LIST f,LIST v,int m,struct order_s nd_setup_parameters(nvar,max); ishomo = 1; for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) { - b = (pointer)ptondv(CO,vv,(P)BDY(t)); + ptozp((P)BDY(t),1,&dmy,&zp); + b = (pointer)ptondv(CO,vv,zp); if ( ishomo ) ishomo = ishomo && ndv_ishomo(b); if ( m ) ndv_mod(m,b); if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; } } if ( fd0 ) NEXT(fd) = 0; - ndv_setup(m,0,fd0,0); + ndv_setup(m,0,fd0,0,1); for ( x = 0, i = 0; i < nd_psn; i++ ) x = update_base(x,i); if ( do_check ) { @@ -2520,14 +2637,15 @@ void nd_gr_postproc(LIST f,LIST v,int m,struct order_s MKLIST(*rp,r0); } -void nd_gr_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp) +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; NODE fd,fd0,in0,in,r,r0,t,s,cand,alist; int m,nocheck,nvar,mindex,e,max; NDV c; NMV a; - P p; + P p,zp; + Q dmy; EPOS oepos; int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg; Alg alpha,dp; @@ -2536,8 +2654,12 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,stru Obj obj; NumberField nf; struct order_spec *ord1; + struct oEGT eg_check,eg0,eg1; - get_vars((Obj)f,&fv); pltovl(v,&vv); + if ( DP_Multiple ) + nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1); + + 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: @@ -2582,7 +2704,8 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,stru obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ishomo = 1; for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) { - c = ptondv(CO,vv,(P)BDY(t)); + ptozp((P)BDY(t),1,&dmy,&zp); + c = (pointer)ptondv(CO,vv,zp); if ( ishomo ) ishomo = ishomo && ndv_ishomo(c); if ( c ) { @@ -2607,8 +2730,8 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,stru while ( 1 ) { if ( Demand ) nd_demand = 1; - ndv_setup(m,1,fd0,0); - cand = nd_gb_trace(m,ishomo || homo); + ndv_setup(m,1,fd0,0,0); + cand = f4?nd_f4_trace(m):nd_gb_trace(m,ishomo || homo); if ( !cand ) { /* failure */ if ( trace > 1 ) { *rp = 0; return; } @@ -2627,6 +2750,7 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,stru cbpe = nd_bpe; if ( nocheck ) break; + get_eg(&eg0); if ( ndv_check_candidate(in0,obpe,oadv,oepos,cand) ) /* success */ break; @@ -2646,6 +2770,9 @@ void nd_gr_trace(LIST f,LIST v,int trace,int homo,stru } } } + get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1); + if ( DP_Print ) + fprintf(asir_out,"check=%fsec\n",eg_check.exectime+eg_check.gctime); /* dp->p */ nd_bpe = cbpe; nd_setup_parameters(nd_nvar,0); @@ -2782,7 +2909,7 @@ void nd_removecont(int mod,ND p) v.len = n; v.body = (pointer *)w; for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CQ(m); - removecont_array(w,n); + removecont_array((P *)w,n,1); for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CQ(m) = w[i]; } } @@ -2796,29 +2923,32 @@ void nd_removecont2(ND p1,ND p2) struct oVECT v; N q,r; - if ( !p1 ) { - nd_removecont(0,p2); return; - } else if ( !p2 ) { - nd_removecont(0,p1); return; - } n1 = nd_length(p1); n2 = nd_length(p2); n = n1+n2; w = (Q *)ALLOCA(n*sizeof(Q)); v.len = n; v.body = (pointer *)w; - for ( m = BDY(p1), i = 0; i < n1; m = NEXT(m), i++ ) w[i] = CQ(m); - for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CQ(m); - removecont_array(w,n); - for ( m = BDY(p1), i = 0; i < n1; m = NEXT(m), i++ ) CQ(m) = w[i]; - for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CQ(m) = w[i]; + i = 0; + if ( p1 ) + for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CQ(m); + if ( p2 ) + for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CQ(m); + removecont_array((P *)w,n,1); + i = 0; + if ( p1 ) + for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CQ(m) = w[i]; + if ( p2 ) + for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CQ(m) = w[i]; } void ndv_removecont(int mod,NDV p) { - int i,len; - Q *w; + int i,len,all_p; + Q *c; + P *w; Q dvr,t; + P g,cont,tp; NMV m; if ( mod == -1 ) @@ -2827,13 +2957,25 @@ void ndv_removecont(int mod,NDV p) ndv_mul_c(mod,p,invm(HCM(p),mod)); else { len = p->len; - w = (Q *)ALLOCA(len*sizeof(Q)); - for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) w[i] = CQ(m); - sortbynm(w,len); - qltozl(w,len,&dvr); - for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) { - divq(CQ(m),dvr,&t); CQ(m) = t; + w = (P *)ALLOCA(len*sizeof(P)); + c = (Q *)ALLOCA(len*sizeof(Q)); + for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) { + ptozp(CP(m),1,&c[i],&w[i]); + all_p = all_p && !NUM(w[i]); } + if ( all_p ) { + qltozl(c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g); + mulp(nd_vc,(P)dvr,g,&cont); + for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) { + divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp; + } + } else { + sortbynm((Q *)c,len); + qltozl((Q *)c,len,&dvr); + for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) { + divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp; + } + } } } @@ -2883,8 +3025,65 @@ void ndv_dehomogenize(NDV p,struct order_spec *ord) NV(p)--; } -void removecont_array(Q *c,int n) +void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr) { + int i; + P *tpl,*tpl1; + NODE l; + P h,gcd,t; + + tpl = (P *)ALLOCA(m*sizeof(P)); + tpl1 = (P *)ALLOCA(m*sizeof(P)); + bcopy(pl,tpl,m*sizeof(P)); + gcd = (P)ONE; + for ( l = nd_hcf; l; l = NEXT(l) ) { + h = (P)BDY(l); + while ( 1 ) { + for ( i = 0; i < m; i++ ) + if ( !divtpz(vl,tpl[i],h,&tpl1[i]) ) + break; + if ( i == m ) { + bcopy(tpl1,tpl,m*sizeof(P)); + mulp(vl,gcd,h,&t); gcd = t; + } else + break; + } + } + if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);} + if ( full ) { + heu_nezgcdnpz(vl,tpl,m,&t); + mulp(vl,gcd,t,pr); + } else + *pr = gcd; +} + +void removecont_array(P *p,int n,int full) +{ + int all_p,all_q,i; + Q *c; + P *w; + P t,s; + + for ( all_q = 1, i = 0; i < n; i++ ) + all_q = all_q && NUM(p[i]); + if ( all_q ) { + removecont_array_q((Q *)p,n); + } else { + c = (Q *)ALLOCA(n*sizeof(Q)); + w = (P *)ALLOCA(n*sizeof(P)); + for ( i = 0; i < n; i++ ) { + ptozp(p[i],1,&c[i],&w[i]); + } + removecont_array_q(c,n); + nd_heu_nezgcdnpz(nd_vc,w,n,full,&t); + for ( i = 0; i < n; i++ ) { + divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]); + } + } +} + +void removecont_array_q(Q *c,int n) +{ struct oVECT v; Q d0,d1,a,u,u1,gcd; int i,j; @@ -2934,15 +3133,15 @@ void nd_mul_c(int mod,ND p,int mul) } } -void nd_mul_c_q(ND p,Q mul) +void nd_mul_c_q(ND p,P mul) { NM m; - Q c; + P c; if ( !p ) return; if ( UNIQ(mul) ) return; for ( m = BDY(p); m; m = NEXT(m) ) { - mulq(CQ(m),mul,&c); CQ(m) = c; + mulp(nd_vc,CP(m),mul,&c); CP(m) = c; } } @@ -3232,10 +3431,12 @@ ND nd_copy(ND p) int nd_sp(int mod,int trace,ND_pairs p,ND *rp) { - NM m; + NM m1,m2; NDV p1,p2; ND t1,t2; UINT *lcm; + P gp,tp; + Q g,t; int td; if ( !mod && nd_demand ) { @@ -3248,23 +3449,29 @@ int nd_sp(int mod,int trace,ND_pairs p,ND *rp) } } lcm = LCM(p); - NEWNM(m); - CQ(m) = HCQ(p2); - ndl_sub(lcm,HDL(p1),DL(m)); - if ( ndl_check_bound2(p->i1,DL(m)) ) - return 0; - t1 = ndv_mul_nm(mod,m,p1); - if ( mod == -1 ) CM(m) = _chsgnsf(HCM(p1)); - else if ( mod ) CM(m) = mod-HCM(p1); - else chsgnq(HCQ(p1),&CQ(m)); - ndl_sub(lcm,HDL(p2),DL(m)); - if ( ndl_check_bound2(p->i2,DL(m)) ) { - nd_free(t1); - return 0; + NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1)); + if ( ndl_check_bound2(p->i1,DL(m1)) ) { + FREENM(m1); return 0; } - t2 = ndv_mul_nm(mod,m,p2); + NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2)); + if ( ndl_check_bound2(p->i2,DL(m2)) ) { + FREENM(m1); FREENM(m2); return 0; + } + + if ( mod == -1 ) { + CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1)); + } else if ( mod ) { + CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1); + } else if ( nd_vc ) { + ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp); + divsp(nd_vc,HCP(p2),gp,&CP(m1)); + divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2)); + } else { + igcd_cofactor(HCQ(p1),HCQ(p2),&g,&t,&CQ(m1)); chsgnq(t,&CQ(m2)); + } + t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2); *rp = nd_add(mod,t1,t2); - FREENM(m); + FREENM(m1); FREENM(m2); return 1; } @@ -3466,7 +3673,7 @@ ND ndv_mul_nm(int mod,NM m0,NDV p) NMV m; UINT *d,*dt,*dm; int c,n,td,i,c1,c2,len; - Q q; + P q; ND r; if ( !p ) return 0; @@ -3498,10 +3705,10 @@ ND ndv_mul_nm(int mod,NM m0,NDV p) ndl_add(DL(m),d,DL(mr)); } } else { - q = CQ(m0); + q = CP(m0); for ( i = 0; i < len; i++, NMV_ADV(m) ) { NEXTNM(mr0,mr); - mulq(CQ(m),q,&CQ(mr)); + mulp(nd_vc,CP(m),q,&CP(mr)); ndl_add(DL(m),d,DL(mr)); } } @@ -3644,6 +3851,8 @@ void ndv_mod(int mod,NDV p) NMV t,d; int r,s,u; int i,len,dlen; + P cp; + Q c; Obj gfs; if ( !p ) return; @@ -3660,12 +3869,17 @@ void ndv_mod(int mod,NDV p) } else for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) { - r = rem(NM(CQ(t)),mod); + if ( nd_vc ) { + nd_subst_vector(nd_vc,CP(t),nd_subst,&cp); + c = (Q)cp; + } else + c = CQ(t); + r = rem(NM(c),mod); if ( r ) { - if ( SGN(CQ(t)) < 0 ) + if ( SGN(c) < 0 ) r = mod-r; - if ( DN(CQ(t)) ) { - s = rem(DN(CQ(t)),mod); + if ( DN(c) ) { + s = rem(DN(c),mod); if ( !s ) error("ndv_mod : division by 0"); s = invm(s,mod); @@ -4025,6 +4239,8 @@ void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec VL vv,tv; int stat,nvar,max,e; union oNDC dn; + Q cont; + P pp; if ( !f ) { *rp = 0; @@ -4050,7 +4266,8 @@ void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec /* conversion to ndv */ for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) { NEXTNODE(in0,in); - BDY(in) = (pointer)ptondv(CO,vv,(P)BDY(t)); + ptozp((P)BDY(t),1,&cont,&pp); + BDY(in) = (pointer)ptondv(CO,vv,pp); if ( m ) ndv_mod(m,(NDV)BDY(in)); } NEXTNODE(in0,in); @@ -4058,13 +4275,13 @@ void nd_nf_p(P f,LIST g,LIST v,int m,struct order_spec if ( m ) ndv_mod(m,(NDV)BDY(in)); NEXT(in) = 0; - /* dont sort */ - ndv_setup(m,0,in0,1); + /* 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,nd,nd_ps,1,0,&nf); + stat = nd_nf(m,0,nd,nd_ps,1,0,&nf); if ( !stat ) { nd_psn++; nd_reconstruct(0,0); @@ -4178,10 +4395,26 @@ IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0 return r; } +int compress_array(Q *svect,Q *cvect,int n) +{ + int i,j; -int ndv_reduce_vect_q(Q *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) + for ( i = j = 0; i < n; i++ ) + if ( svect[i] ) cvect[j++] = svect[i]; + return j; +} + +void expand_array(Q *svect,Q *cvect,int n) { - int i,j,k,len,pos,prev; + int i,j; + + for ( i = j = 0; j < n; i++ ) + if ( svect[i] ) svect[i] = cvect[j++]; +} + +int ndv_reduce_vect_q(Q *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) +{ + int i,j,k,len,pos,prev,nz; Q cs,mcs,c1,c2,cr,gcd,t; IndArray ivect; unsigned char *ivc; @@ -4191,14 +4424,20 @@ int ndv_reduce_vect_q(Q *svect,int col,IndArray *imat, NMV mr; NODE rp; int maxrs; + double hmag; + Q *cvect; maxrs = 0; + for ( i = 0; i < col && !svect[i]; i++ ); + if ( i == col ) return maxrs; + hmag = p_mag((P)svect[i])*nd_scale; + cvect = (Q *)ALLOCA(col*sizeof(Q)); for ( i = 0; i < nred; i++ ) { ivect = imat[i]; k = ivect->head; if ( svect[k] ) { maxrs = MAX(maxrs,rp0[i]->sugar); - redv = nd_ps[rp0[i]->index]; + redv = 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); @@ -4231,8 +4470,22 @@ int ndv_reduce_vect_q(Q *svect,int col,IndArray *imat, } break; } + for ( j = k+1; j < col && !svect[j]; j++ ); + if ( j == col ) break; + if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) { + nz = compress_array(svect,cvect,col); + removecont_array((P *)cvect,nz,1); + expand_array(svect,cvect,nz); + hmag = ((double)p_mag((P)svect[j]))*nd_scale; + } } } + nz = compress_array(svect,cvect,col); + removecont_array((P *)cvect,nz,1); + expand_array(svect,cvect,nz); + if ( DP_Print ) { + fprintf(asir_out,"-"); fflush(asir_out); + } return maxrs; } @@ -4437,7 +4690,7 @@ NDV plain_vect_to_ndv_q(Q *vect,int col,UINT *s0vect) } } -int nd_sp_f4(int m,ND_pairs l,PGeoBucket bucket) +int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket) { ND_pairs t; NODE sp0,sp; @@ -4445,7 +4698,7 @@ int nd_sp_f4(int m,ND_pairs l,PGeoBucket bucket) ND spol; for ( t = l; t; t = NEXT(t) ) { - stat = nd_sp(m,0,t,&spol); + stat = nd_sp(m,trace,t,&spol); if ( !stat ) return 0; if ( spol ) { add_pbucket_symbolic(bucket,spol); @@ -4454,7 +4707,7 @@ int nd_sp_f4(int m,ND_pairs l,PGeoBucket bucket) return 1; } -int nd_symbolic_preproc(PGeoBucket bucket,UINT **s0vect,NODE *r) +int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r) { NODE rp0,rp; NM mul,head,s0,s; @@ -4463,8 +4716,10 @@ int nd_symbolic_preproc(PGeoBucket bucket,UINT **s0vec UINT *s0v,*p; NM_ind_pair pair; ND red; + NDV *ps; s0 = 0; rp0 = 0; col = 0; + ps = trace?nd_ps_trace:nd_ps; while ( 1 ) { head = remove_head_pbucket_symbolic(bucket); if ( !head ) break; @@ -4477,9 +4732,9 @@ int nd_symbolic_preproc(PGeoBucket bucket,UINT **s0vec NEWNM(mul); ndl_sub(DL(head),DL(h),DL(mul)); if ( ndl_check_bound2(index,DL(mul)) ) return 0; - sugar = TD(DL(mul))+SG(nd_ps[index]); + sugar = TD(DL(mul))+SG(ps[index]); MKNM_ind_pair(pair,mul,index,sugar); - red = ndv_mul_nm_symbolic(mul,nd_ps[index]); + red = ndv_mul_nm_symbolic(mul,ps[index]); add_pbucket_symbolic(bucket,nd_remove_head(red)); NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair; } @@ -4529,7 +4784,7 @@ NODE nd_f4(int m) l = nd_minsugarp(d,&d); sugar = SG(l); bucket = create_pbucket(); - stat = nd_sp_f4(m,l,bucket); + stat = nd_sp_f4(m,0,l,bucket); if ( !stat ) { for ( t = l; NEXT(t); t = NEXT(t) ); NEXT(t) = d; d = l; @@ -4537,7 +4792,7 @@ NODE nd_f4(int m) continue; } if ( bucket->m < 0 ) continue; - col = nd_symbolic_preproc(bucket,&s0vect,&rp0); + col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0); if ( !col ) { for ( t = l; NEXT(t); t = NEXT(t) ); NEXT(t) = d; d = l; @@ -4549,9 +4804,9 @@ NODE nd_f4(int m) fprintf(asir_out,"sugar=%d,symb=%fsec,", sugar,eg_f4.exectime+eg_f4.gctime); if ( 1 ) - nflist = nd_f4_red(m,l,s0vect,col,rp0); + nflist = nd_f4_red(m,l,0,s0vect,col,rp0,0); else - nflist = nd_f4_red_dist(m,l,s0vect,col,rp0); + nflist = nd_f4_red_dist(m,l,s0vect,col,rp0,0); /* adding new bases */ for ( r = nflist; r; r = NEXT(r) ) { nf = (NDV)BDY(r); @@ -4576,9 +4831,109 @@ NODE nd_f4(int m) return g; } -NODE nd_f4_red(int m,ND_pairs sp0,UINT *s0vect,int col,NODE rp0) +NODE nd_f4_trace(int m) { + int i,nh,stat,index; + NODE r,g; + ND_pairs d,l,l0,t; + ND spol,red; + NDV nf,redv,nfqv,nfv; + NM s0,s; + NODE rp0,srp0,nflist; + int nsp,nred,col,rank,len,k,j,a; + UINT c; + UINT **spmat; + UINT *s0vect,*svect,*p,*v; + int *colstat; IndArray *imat; + int *rhead; + int spcol,sprow; + int sugar; + PGeoBucket bucket; + struct oEGT eg0,eg1,eg_f4; + + g = 0; d = 0; + for ( i = 0; i < nd_psn; i++ ) { + d = update_pairs(d,g,i); + g = update_base(g,i); + } + while ( d ) { + get_eg(&eg0); + l = nd_minsugarp(d,&d); + sugar = SG(l); + 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(1,d); + continue; + } + if ( bucket->m < 0 ) continue; + col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0); + if ( !col ) { + for ( t = l; NEXT(t); t = NEXT(t) ); + NEXT(t) = d; d = l; + d = nd_reconstruct(1,d); + continue; + } + get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); + if ( DP_Print ) + fprintf(asir_out,"sugar=%d,symb=%fsec,", + sugar,eg_f4.exectime+eg_f4.gctime); + nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0); + if ( !l0 ) continue; + l = l0; + + /* over Q */ + bucket = create_pbucket(); + stat = nd_sp_f4(0,1,l,bucket); + if ( !stat ) { + for ( t = l; NEXT(t); t = NEXT(t) ); + NEXT(t) = d; d = l; + d = nd_reconstruct(1,d); + continue; + } + if ( bucket->m < 0 ) continue; + col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0); + if ( !col ) { + for ( t = l; NEXT(t); t = NEXT(t) ); + NEXT(t) = d; d = l; + d = nd_reconstruct(1,d); + continue; + } + nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0); + /* adding new bases */ + for ( r = nflist; r; r = NEXT(r) ) { + nfqv = (NDV)BDY(r); + ndv_removecont(0,nfqv); + if ( !rem(NM(HCQ(nfqv)),m) ) return 0; + if ( nd_nalg ) { + ND nf1; + + nf1 = ndvtond(m,nfqv); + nd_monic(0,&nf1); + nd_removecont(0,nf1); + nfqv = ndtondv(0,nf1); nd_free(nf1); + } + nfv = ndv_dup(0,nfqv); + ndv_mod(m,nfv); + ndv_removecont(m,nfv); + nh = ndv_newps(0,nfv,nfqv); + d = update_pairs(d,g,nh); + g = update_base(g,nh); + } + } + for ( r = g; r; r = NEXT(r) ) BDY(r) = (pointer)nd_ps_trace[(int)BDY(r)]; +#if 0 + fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); +#endif + return g; +} + +NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) +{ + IndArray *imat; int nsp,nred,i; int *rhead; NODE r0,rp; @@ -4599,14 +4954,14 @@ NODE nd_f4_red(int m,ND_pairs sp0,UINT *s0vect,int col rhead[imat[i]->head] = 1; } if ( m ) - r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred); + r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); else - r0 = nd_f4_red_q_main(sp0,nsp,s0vect,col,rvect,rhead,imat,nred); + r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); return r0; } NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col, - NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred) + NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz) { int spcol,sprow,a; int i,j,k,l,rank; @@ -4619,6 +4974,7 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2; int maxrs; int *spsugar; + ND_pairs *spactive; spcol = col-nred; get_eg(&eg0); @@ -4626,6 +4982,7 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s spmat = (int **)ALLOCA(nsp*sizeof(UINT *)); svect = (UINT *)ALLOCA(col*sizeof(UINT)); spsugar = (int *)ALLOCA(nsp*sizeof(UINT)); + spactive = !nz?0:(ND_pairs *)ALLOCA(nsp*sizeof(ND_pairs)); for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { nd_sp(m,0,sp,&spol); if ( !spol ) continue; @@ -4640,6 +4997,8 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s for ( j = k = 0; j < col; j++ ) if ( !rhead[j] ) v[k++] = svect[j]; spsugar[sprow] = MAX(maxrs,SG(spol)); + if ( nz ) + spactive[sprow] = sp; sprow++; } nd_free(spol); @@ -4657,7 +5016,7 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s if ( m == -1 ) rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat); else - rank = nd_gauss_elim_mod(spmat,spsugar,sprow,spcol,m,colstat); + rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat); r0 = 0; for ( i = 0; i < rank; i++ ) { NEXTNODE(r0,r); BDY(r) = @@ -4666,6 +5025,7 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s GC_free(spmat[i]); } if ( r0 ) NEXT(r) = 0; + for ( ; i < sprow; i++ ) GC_free(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); @@ -4675,11 +5035,19 @@ NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s nsp,nred,sprow,spcol,rank); fprintf(asir_out,"%fsec\n",eg_f4.exectime+eg_f4.gctime); } + if ( nz ) { + for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1]; + if ( rank > 0 ) { + NEXT(spactive[rank-1]) = 0; + *nz = spactive[0]; + } else + *nz = 0; + } return r0; } -#if 0 -NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vect,int col, +#if 1 +NODE nd_f4_red_q_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; @@ -4693,6 +5061,7 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vec 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); @@ -4701,10 +5070,10 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vec svect = (Q *)ALLOCA(col*sizeof(Q)); spsugar = (int *)ALLOCA(nsp*sizeof(Q)); for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { - nd_sp(0,0,sp,&spol); + nd_sp(0,trace,sp,&spol); if ( !spol ) continue; nd_to_vect_q(s0vect,col,spol,svect); - maxrs = ndv_reduce_vect_q(svect,col,imat,rvect,nred); + maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred); for ( i = 0; i < col; i++ ) if ( svect[i] ) break; if ( i < col ) { spmat[sprow] = v = (Q *)MALLOC(spcol*sizeof(Q)); @@ -4726,13 +5095,20 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vec /* elimination (2nd step) */ colstat = (int *)ALLOCA(spcol*sizeof(int)); rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat); - r0 = 0; + w = (pointer *)ALLOCA(rank*sizeof(pointer)); for ( i = 0; i < rank; i++ ) { - NEXTNODE(r0,r); BDY(r) = - (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect); - SG((NDV)BDY(r)) = spsugar[i]; + 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]); */ } +#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++ ) GC_free(spmat[i]); */ @@ -4898,7 +5274,7 @@ int ox_exec_f4_red(Q proc) return s; } -NODE nd_f4_red_dist(int m,ND_pairs sp0,UINT *s0vect,int col,NODE rp0) +NODE nd_f4_red_dist(int m,ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) { int nsp,nred; int i,rank,s; @@ -5052,7 +5428,7 @@ void nd_exec_f4_red_dist() if ( m == -1 ) rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat); else - rank = nd_gauss_elim_mod(spmat,spsugar,sprow,spcol,m,colstat); + rank = nd_gauss_elim_mod(spmat,spsugar,0,sprow,spcol,m,colstat); nd_send_int(rank); for ( i = 0; i < rank; i++ ) { nf = vect_to_ndv(spmat[i],spcol,col,rhead,s0vect); @@ -5083,7 +5459,7 @@ int nd_gauss_elim_q(Q **mat0,int *sugar,int row,int co wmat[i][j] = 0; } } - rank0 = nd_gauss_elim_mod(wmat,sugar,row,col,mod,colstat); + rank0 = nd_gauss_elim_mod(wmat,sugar,0,row,col,mod,colstat); NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0; rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci); if ( rank != rank0 ) @@ -5113,11 +5489,12 @@ int nd_gauss_elim_q(Q **mat0,int *sugar,int row,int co return rank; } -int nd_gauss_elim_mod(int **mat0,int *sugar,int row,int col,int md,int *colstat) +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; unsigned int *t,*pivot,*pk; unsigned int **mat; + ND_pairs pair; mat = (unsigned int **)mat0; for ( rank = 0, j = 0; j < col; j++ ) { @@ -5134,6 +5511,10 @@ int nd_gauss_elim_mod(int **mat0,int *sugar,int row,in if ( i != rank ) { t = mat[i]; mat[i] = mat[rank]; mat[rank] = t; s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s; + if ( spactive ) { + pair = spactive[i]; spactive[i] = spactive[rank]; + spactive[rank] = pair; + } } pivot = mat[rank]; s = sugar[rank];