=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/engine/nd.c,v retrieving revision 1.123 retrieving revision 1.144 diff -u -p -r1.123 -r1.144 --- OpenXM_contrib2/asir2000/engine/nd.c 2005/01/23 14:03:48 1.123 +++ OpenXM_contrib2/asir2000/engine/nd.c 2006/08/26 03:09:55 1.144 @@ -1,7 +1,8 @@ -/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.122 2004/12/09 13:20:33 noro Exp $ */ +/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.143 2006/08/09 02:48:49 noro Exp $ */ #include "nd.h" +int diag_period = 6; int (*ndl_compare_function)(UINT *a1,UINT *a2); int nd_dcomp; NM _nm_free_list; @@ -47,6 +48,7 @@ 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); int nd_monic(int m,ND *p); +NDV plain_vect_to_ndv_q(Q *mat,int col,UINT *s0vect); void nd_free_private_storage() { @@ -1284,7 +1286,7 @@ int ndv_check_candidate(NODE input,int obpe,int oadv,E NODE t,s; union oNDC dn; - ndv_setup(0,0,cand); + ndv_setup(0,0,cand,0); n = length(cand); /* membercheck : list is a subset of Id(cand) ? */ @@ -1590,6 +1592,7 @@ NODE nd_gb(int m,int ishomo,int checkonly) NDV nfv; Q q,num,den; union oNDC dn; + int diag_count = 0; g = 0; d = 0; for ( i = 0; i < nd_psn; i++ ) { @@ -1602,6 +1605,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; @@ -1637,6 +1641,15 @@ again: } nfv = ndtondv(m,nf); nd_free(nf); nh = ndv_newps(m,nfv,0); + 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(1,d); + goto again; + } + } d = update_pairs(d,g,nh); g = update_base(g,nh); FREENDP(l); @@ -1718,6 +1731,7 @@ NODE nd_gb_trace(int m,int ishomo) Q q,den,num; union oNDC dn; struct oEGT eg_monic,egm0,egm1; + int diag_count = 0; init_eg(&eg_monic); init_eg(&eg_invdalg); @@ -1732,14 +1746,17 @@ NODE nd_gb_trace(int m,int ishomo) again: l = nd_minp(d,&d); if ( SG(l) != sugar ) { +#if 1 if ( ishomo ) { stat = do_diagonalize_trace(sugar,m); + diag_count = 0; if ( !stat ) { NEXT(l) = d; d = l; d = nd_reconstruct(1,d); goto again; } } +#endif sugar = SG(l); if ( DP_Print ) fprintf(asir_out,"%d",sugar); } @@ -1788,6 +1805,15 @@ again: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf); } nh = ndv_newps(0,nfv,nfqv); + if ( ishomo && ++diag_count == diag_period ) { + diag_count = 0; + stat = do_diagonalize_trace(sugar,m); + if ( !stat ) { + NEXT(l) = d; d = l; + d = nd_reconstruct(1,d); + goto again; + } + } d = update_pairs(d,g,nh); g = update_base(g,nh); } else { @@ -1839,7 +1865,7 @@ 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); + ndv_setup(m,0,f,0); for ( i = 0; i < n; ) { g = ndvtond(m,nd_ps[i]); g = nd_separate_head(g,&head); @@ -2179,7 +2205,7 @@ int ndv_newps(int m,NDV a,NDV aq) return nd_psn++; } -void ndv_setup(int mod,int trace,NODE f) +void ndv_setup(int mod,int trace,NODE f,int dont_sort) { int i,j,td,len,max; NODE s,s0,f0; @@ -2193,8 +2219,15 @@ void ndv_setup(int mod,int trace,NODE f) 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); - 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)); @@ -2343,7 +2376,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; @@ -2389,14 +2423,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); + ndv_setup(m,0,fd0,0); x = f4?nd_f4(m):nd_gb(m,ishomo,0); nd_demand = 0; x = ndv_reducebase(x); @@ -2414,14 +2449,97 @@ void nd_gr(LIST f,LIST v,int m,int f4,struct order_spe #endif } -void nd_gr_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp) +void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,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; + + get_vars((Obj)f,&fv); pltovl(v,&vv); + 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_nalg = 0; + av = 0; + if ( !m ) { + get_algtree((Obj)f,&av); + for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ ); + nd_ntrans = nvar; + nd_nalg = nalg; + /* #i -> t#i */ + if ( nalg ) { + preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist); + ord = ord1; + f = f1; + } + nvar += nalg; + } + nd_init_ord(ord); + for ( t = BDY(f), max = 0; t; t = NEXT(t) ) + for ( tv = vv; tv; tv = NEXT(tv) ) { + e = getdeg(tv->v,(P)BDY(t)); + max = MAX(e,max); + } + nd_setup_parameters(nvar,max); + ishomo = 1; + for ( fd0 = 0, t = BDY(f); t; t = NEXT(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); + for ( x = 0, i = 0; i < nd_psn; i++ ) + x = update_base(x,i); + if ( do_check ) { + x = nd_gb(m,ishomo,1); + if ( !x ) { + *rp = 0; + return; + } + } else { + for ( t = x; t; t = NEXT(t) ) + BDY(t) = (pointer)nd_ps[(int)BDY(t)]; + } + x = ndv_reducebase(x); + x = ndv_reduceall(m,x); + for ( r0 = 0, t = x; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + BDY(r) = ndvtop(m,CO,vv,BDY(t)); + } + if ( r0 ) NEXT(r) = 0; + if ( nalg ) + r0 = postprocess_algcoef(av,alist,r0); + MKLIST(*rp,r0); +} + +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; @@ -2476,7 +2594,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 ) { @@ -2501,8 +2620,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); - cand = nd_gb_trace(m,ishomo || homo); + ndv_setup(m,1,fd0,0); + cand = f4?nd_f4_trace(m):nd_gb_trace(m,ishomo || homo); if ( !cand ) { /* failure */ if ( trace > 1 ) { *rp = 0; return; } @@ -3415,7 +3534,7 @@ ND nd_quo(int mod,PGeoBucket bucket,NDV d) ND p,t,r; N tnm; - if ( !p ) return 0; + if ( bucket->m < 0 ) return 0; else { nv = NV(d); mq0 = 0; @@ -3536,7 +3655,7 @@ ND nd_dup(ND p) void ndv_mod(int mod,NDV p) { NMV t,d; - int r; + int r,s,u; int i,len,dlen; Obj gfs; @@ -3558,6 +3677,13 @@ void ndv_mod(int mod,NDV p) if ( r ) { if ( SGN(CQ(t)) < 0 ) r = mod-r; + if ( DN(CQ(t)) ) { + s = rem(DN(CQ(t)),mod); + if ( !s ) + error("ndv_mod : division by 0"); + s = invm(s,mod); + DMAR(r,s,0,mod,u); r = u; + } CM(d) = r; ndl_copy(DL(t),DL(d)); NMV_ADV(d); @@ -3945,7 +4071,8 @@ 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; - ndv_setup(m,0,in0); + /* dont sort */ + ndv_setup(m,0,in0,1); nd_psn--; nd_scale=2; while ( 1 ) { @@ -3993,6 +4120,29 @@ int nd_to_vect_q(UINT *s0,int n,ND d,Q *r) return i; } +Q *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair) +{ + NM m; + NMV mr; + UINT *d,*t,*s; + NDV p; + int i,j,len; + Q *r; + + m = pair->mul; + d = DL(m); + p = nd_ps[pair->index]; + len = LEN(p); + r = (Q *)CALLOC(n,sizeof(Q)); + 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); + for ( ; !ndl_equal(t,s); s += nd_wpd, i++ ); + r[i] = CQ(mr); + } + return r; +} + IndArray nm_ind_pair_to_vect_compress(int mod,UINT *s0,int n,NM_ind_pair pair) { NM m; @@ -4041,10 +4191,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; @@ -4054,14 +4220,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); @@ -4094,8 +4266,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(cvect,nz); + expand_array(svect,cvect,nz); + hmag = ((double)p_mag((P)svect[j]))*nd_scale; + } } } + nz = compress_array(svect,cvect,col); + removecont_array(cvect,nz); + expand_array(svect,cvect,nz); + if ( DP_Print ) { + fprintf(asir_out,"-"); fflush(asir_out); + } return maxrs; } @@ -4238,6 +4424,8 @@ NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhea } } +/* for preprocessed vector */ + NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead,UINT *s0vect) { int j,k,len; @@ -4268,15 +4456,45 @@ NDV vect_to_ndv_q(Q *vect,int spcol,int col,int *rhead } } -int nd_sp_f4(int m,ND_pairs l,PGeoBucket bucket) +/* for plain vector */ + +NDV plain_vect_to_ndv_q(Q *vect,int col,UINT *s0vect) { + int j,k,len; + UINT *p; + Q c; + NDV r; + NMV mr0,mr; + + for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++; + if ( !len ) return 0; + else { + mr0 = (NMV)GC_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, k++ ) + if ( c = vect[k] ) { + if ( DN(c) ) + error("afo"); + ndl_copy(p,DL(mr)); CQ(mr) = c; NMV_ADV(mr); + } + MKNDV(nd_nvar,mr0,len,r); + return r; + } +} + +int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket) +{ ND_pairs t; NODE sp0,sp; int stat; 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); @@ -4285,7 +4503,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; @@ -4294,8 +4512,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; @@ -4308,9 +4528,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; } @@ -4360,7 +4580,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; @@ -4368,7 +4588,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; @@ -4380,13 +4600,21 @@ 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); ndv_removecont(m,nf); + if ( !m && nd_nalg ) { + ND nf1; + + nf1 = ndvtond(m,nf); + nd_monic(0,&nf1); + nd_removecont(m,nf1); + nf = ndtondv(m,nf1); + } nh = ndv_newps(m,nf,0); d = update_pairs(d,g,nh); g = update_base(g,nh); @@ -4399,9 +4627,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; @@ -4422,14 +4750,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; @@ -4442,6 +4770,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); @@ -4449,6 +4778,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; @@ -4463,6 +4793,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); @@ -4480,7 +4812,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) = @@ -4489,6 +4821,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); @@ -4498,10 +4831,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; } -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; @@ -4515,6 +4857,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); @@ -4523,10 +4866,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)); @@ -4548,13 +4891,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]); */ @@ -4568,7 +4918,65 @@ NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vec } return r0; } +#else +void printm(Q **mat,int row,int col) +{ + int i,j; + printf("["); + for ( i = 0; i < row; i++ ) { + for ( j = 0; j < col; j++ ) { + printexpr(CO,mat[i][j]); printf(" "); + } + printf("]\n"); + } +} +NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,UINT *s0vect,int col, + NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred) +{ + int row,a; + int i,j,rank; + NODE r0,r; + ND_pairs sp; + ND spol; + Q **mat; + int *colstat; + int *sugar; + + row = nsp+nred; + /* make the matrix */ + mat = (Q **)ALLOCA(row*sizeof(Q *)); + sugar = (int *)ALLOCA(row*sizeof(int)); + for ( row = a = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { + nd_sp(0,0,sp,&spol); + if ( !spol ) continue; + mat[row] = (Q *)MALLOC(col*sizeof(Q)); + nd_to_vect_q(s0vect,col,spol,mat[row]); + sugar[row] = SG(spol); + row++; + } + for ( i = 0; i < nred; i++, row++ ) { + mat[row] = nm_ind_pair_to_vect(0,s0vect,col,rvect[i]); + sugar[row] = rvect[i]->sugar; + } + /* elimination */ + colstat = (int *)ALLOCA(col*sizeof(int)); + rank = nd_gauss_elim_q(mat,sugar,row,col,colstat); + r0 = 0; + for ( i = 0; i < rank; i++ ) { + for ( j = 0; j < col; j++ ) if ( mat[i][j] ) break; + if ( j == col ) error("nd_f4_red_q_main : cannot happen"); + if ( rhead[j] ) continue; + NEXTNODE(r0,r); BDY(r) = + (pointer)plain_vect_to_ndv_q(mat[i],col,s0vect); + SG((NDV)BDY(r)) = sugar[i]; + } + if ( r0 ) NEXT(r) = 0; + printf("\n"); + return r0; +} +#endif + FILE *nd_write,*nd_read; void nd_send_int(int a) { @@ -4662,7 +5070,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; @@ -4816,7 +5224,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); @@ -4847,7 +5255,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 ) @@ -4877,11 +5285,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++ ) { @@ -4898,6 +5307,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]; @@ -5090,6 +5503,8 @@ void nd_det(int mod,MAT f,P *rp) int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a; pointer **m; Q mone; + P **w; + P mp,r; NDV **dm; NDV *t,*mi,*mj; NDV d,s,mij,mjj; @@ -5098,6 +5513,8 @@ void nd_det(int mod,MAT f,P *rp) UINT *bound; PGeoBucket bucket; struct order_spec *ord; + Q dq,dt,ds; + N gn,qn,dn0,nm,dn; create_order_spec(0,0,&ord); nd_init_ord(ord); @@ -5105,8 +5522,45 @@ void nd_det(int mod,MAT f,P *rp) if ( f->row != f->col ) error("nd_det : non-square matrix"); n = f->row; - for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ ); m = f->body; + for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ ); + + if ( !nvar ) { + if ( !mod ) + detp(CO,(P **)m,n,rp); + else { + w = (P **)almat_pointer(n,n); + for ( i = 0; i < n; i++ ) + for ( j = 0; j < n; j++ ) + ptomp(mod,(P)m[i][j],&w[i][j]); + detmp(CO,mod,w,n,&mp); + mptop(mp,rp); + } + return; + } + + if ( !mod ) { + w = (P **)almat_pointer(n,n); + dq = ONE; + for ( i = 0; i < n; i++ ) { + dn0 = ONEN; + for ( j = 0; j < n; j++ ) { + if ( !m[i][j] ) continue; + lgp(m[i][j],&nm,&dn); + gcdn(dn0,dn,&gn); divsn(dn0,gn,&qn); muln(qn,dn,&dn0); + } + if ( !UNIN(dn0) ) { + NTOQ(dn0,1,ds); + for ( j = 0; j < n; j++ ) + mulp(CO,(P)m[i][j],(P)ds,&w[i][j]); + mulq(dq,ds,&dt); dq = dt; + } else + for ( j = 0; j < n; j++ ) + w[i][j] = (P)m[i][j]; + } + m = (pointer **)w; + } + for ( i = 0, max = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) for ( tv = fv; tv; tv = NEXT(tv) ) { @@ -5125,7 +5579,7 @@ 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=%d\n",j); + if ( DP_Print ) fprintf(stderr,".",j); for ( i = j; i < n && !dm[i][j]; i++ ); if ( i == n ) { *rp = 0; @@ -5182,12 +5636,17 @@ void nd_det(int mod,MAT f,P *rp) } d = mjj; } + if ( DP_Print ) fprintf(stderr,"\n",k); if ( sgn < 0 ) if ( mod ) ndv_mul_c(mod,d,mod-1); else ndv_mul_c_q(d,mone); - *rp = ndvtop(mod,CO,fv,d); + r = ndvtop(mod,CO,fv,d); + if ( !mod && !UNIQ(dq) ) + divsp(CO,r,(P)dq,rp); + else + *rp = r; } ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)