Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.57
1.57 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.56 2021/12/05 22:41:04 noro Exp $ */
1.1 noro 2:
3: #include "nd.h"
4:
1.45 noro 5: void print_siglist(NODE l);
6:
1.49 noro 7: NODE nd_hpdata;
1.47 noro 8: int Nnd_add,Nf4_red,NcriB,NcriMF,Ncri2,Npairs,Nnewpair;
1.12 noro 9: struct oEGT eg_search,f4_symb,f4_conv,f4_elim1,f4_elim2;
1.1 noro 10:
11: int diag_period = 6;
12: int weight_check = 1;
13: int (*ndl_compare_function)(UINT *a1,UINT *a2);
1.21 noro 14: /* for general module order */
1.19 noro 15: int (*ndl_base_compare_function)(UINT *a1,UINT *a2);
1.21 noro 16: int (*dl_base_compare_function)(int nv,DL a,DL b);
17: int nd_base_ordtype;
1.1 noro 18: int nd_dcomp;
19: int nd_rref2;
20: NM _nm_free_list;
21: ND _nd_free_list;
22: ND_pairs _ndp_free_list;
23: NODE nd_hcf;
1.35 noro 24: int Nsyz,Nsamesig;
1.1 noro 25:
26: Obj nd_top_weight;
27:
28: static NODE nd_subst;
29: static VL nd_vc;
30: static int nd_ntrans;
31: static int nd_nalg;
32: #if 0
33: static int ndv_alloc;
34: #endif
35: #if 1
36: static int nd_f4_nsp=0x7fffffff;
37: #else
38: static int nd_f4_nsp=50;
39: #endif
40: static double nd_scale=2;
41: static UINT **nd_bound;
42: static struct order_spec *nd_ord;
43: static EPOS nd_epos;
44: static BlockMask nd_blockmask;
45: static int nd_nvar;
46: static int nd_isrlex;
47: static int nd_epw,nd_bpe,nd_wpd,nd_exporigin;
48: static UINT nd_mask[32];
49: static UINT nd_mask0,nd_mask1;
50:
51: static NDV *nd_ps;
52: static NDV *nd_ps_trace;
53: static NDV *nd_ps_sym;
54: static NDV *nd_ps_trace_sym;
55: static RHist *nd_psh;
1.30 noro 56: static int nd_psn,nd_pslen,nd_nbase;
1.1 noro 57: static RHist *nd_red;
58: static int *nd_work_vector;
59: static int **nd_matrix;
60: static int nd_matrix_len;
61: static struct weight_or_block *nd_worb;
62: static int nd_worb_len;
63: static int nd_found,nd_create,nd_notfirst;
64: static int nmv_adv;
65: static int nd_demand;
1.21 noro 66: static int nd_module,nd_module_ordtype,nd_mpos,nd_pot_nelim;
1.1 noro 67: static int nd_module_rank,nd_poly_weight_len;
68: static int *nd_poly_weight,*nd_module_weight;
69: static NODE nd_tracelist;
70: static NODE nd_alltracelist;
1.41 noro 71: static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect,nd_lf,nd_norb;
72: static int nd_f4_td,nd_sba_f4step,nd_sba_pot,nd_sba_largelcm,nd_sba_dontsort,nd_sba_redundant_check;
1.46 noro 73: static int nd_top,nd_sba_syz,nd_sba_inputisgb;
1.1 noro 74: static int *nd_gbblock;
75: static NODE nd_nzlist,nd_check_splist;
76: static int nd_splist;
77: static int *nd_sugarweight;
78: static int nd_f4red,nd_rank0,nd_last_nonzero;
1.27 noro 79: static DL *nd_sba_hm;
1.29 noro 80: static NODE *nd_sba_pos;
1.1 noro 81:
1.46 noro 82: struct comp_sig_spec {
83: int n;
84: // current_i <-> oldv[i]
85: int *oldv;
86: int *weight;
87: struct order_pair *order_pair;
88: int block_length;
89: int **matrix;
90: int row;
91: int (*cmpdl)(int n,DL d1,DL d2);
92: };
93:
94: struct comp_sig_spec *nd_sba_modord;
95:
1.49 noro 96: DL ndltodl(int n,UINT *ndl);
1.1 noro 97: NumberField get_numberfield();
98: UINT *nd_det_compute_bound(NDV **dm,int n,int j);
99: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d);
100: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr);
101: int nd_monic(int m,ND *p);
102: NDV plain_vect_to_ndv_q(Z *mat,int col,UINT *s0vect);
103: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank);
104: NDV pltondv(VL vl,VL dvl,LIST p);
105: void pltozpl(LIST l,Q *cont,LIST *pp);
106: void ndl_max(UINT *d1,unsigned *d2,UINT *d);
107: void nmtodp(int mod,NM m,DP *r);
1.15 noro 108: void ndltodp(UINT *d,DP *r);
1.1 noro 109: NODE reverse_node(NODE n);
110: P ndc_div(int mod,union oNDC a,union oNDC b);
111: P ndctop(int mod,union oNDC c);
112: void finalize_tracelist(int i,P cont);
113: void conv_ilist(int demand,int trace,NODE g,int **indp);
1.46 noro 114: void parse_nd_option(VL vl,NODE opt);
1.1 noro 115: void dltondl(int n,DL dl,UINT *r);
116: DP ndvtodp(int mod,NDV p);
117: DP ndtodp(int mod,ND p);
1.16 noro 118: DPM ndvtodpm(int mod,NDV p);
1.43 noro 119: NDV dptondv(int mod,DP p);
1.16 noro 120: NDV dpmtondv(int mod,DPM p);
1.43 noro 121: int dp_getdeg(DP p);
1.16 noro 122: int dpm_getdeg(DPM p,int *rank);
123: void dpm_ptozp(DPM p,Z *cont,DPM *r);
124: int compdmm(int nv,DMM a,DMM b);
1.44 noro 125: DPM sigtodpm(SIG s);
126: SIG dup_sig(SIG sig);
1.1 noro 127:
128: void Pdp_set_weight(NODE,VECT *);
129: void Pox_cmo_rpc(NODE,Obj *);
130:
131: ND nd_add_lf(ND p1,ND p2);
132: void nd_mul_c_lf(ND p,Z mul);
133: void ndv_mul_c_lf(NDV p,Z mul);
134: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
135: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
136: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
137: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
138: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
139: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred);
140: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat);
1.40 noro 141: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig);
1.1 noro 142: NODE nd_f4_lf_trace_main(int m,int **indp);
143: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp);
144:
145: extern int lf_lazy;
146: extern Z current_mod_lf;
147:
148: extern int Denominator,DP_Multiple,MaxDeg;
149:
150: #define BLEN (8*sizeof(unsigned long))
151:
152: typedef struct matrix {
153: int row,col;
154: unsigned long **a;
155: } *matrix;
156:
157:
158: void nd_free_private_storage()
159: {
160: _nm_free_list = 0;
161: _ndp_free_list = 0;
162: #if 0
163: GC_gcollect();
164: #endif
165: }
166:
167: void _NM_alloc()
168: {
169: NM p;
170: int i;
171:
172: for ( i = 0; i < 1024; i++ ) {
173: p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
174: p->next = _nm_free_list; _nm_free_list = p;
175: }
176: }
177:
178: matrix alloc_matrix(int row,int col)
179: {
180: unsigned long **a;
181: int i,len,blen;
182: matrix mat;
183:
184: mat = (matrix)MALLOC(sizeof(struct matrix));
185: mat->row = row;
186: mat->col = col;
187: mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *));
188: return mat;
189: }
190:
191:
192: void _ND_alloc()
193: {
194: ND p;
195: int i;
196:
197: for ( i = 0; i < 1024; i++ ) {
198: p = (ND)MALLOC(sizeof(struct oND));
199: p->body = (NM)_nd_free_list; _nd_free_list = p;
200: }
201: }
202:
203: void _NDP_alloc()
204: {
205: ND_pairs p;
206: int i;
207:
208: for ( i = 0; i < 1024; i++ ) {
209: p = (ND_pairs)MALLOC(sizeof(struct oND_pairs)
210: +(nd_wpd-1)*sizeof(UINT));
211: p->next = _ndp_free_list; _ndp_free_list = p;
212: }
213: }
214:
215: INLINE int nd_length(ND p)
216: {
217: NM m;
218: int i;
219:
220: if ( !p )
221: return 0;
222: else {
223: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
224: return i;
225: }
226: }
227:
228: extern int dp_negative_weight;
229:
230: INLINE int ndl_reducible(UINT *d1,UINT *d2)
231: {
232: UINT u1,u2;
233: int i,j;
234:
235: if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
236:
237: if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0;
238: #if USE_UNROLL
239: switch ( nd_bpe ) {
240: case 3:
241: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
242: u1 = d1[i]; u2 = d2[i];
243: if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
244: if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
245: if ( (u1& 0xe00000) < (u2& 0xe00000) ) return 0;
246: if ( (u1& 0x1c0000) < (u2& 0x1c0000) ) return 0;
247: if ( (u1& 0x38000) < (u2& 0x38000) ) return 0;
248: if ( (u1& 0x7000) < (u2& 0x7000) ) return 0;
249: if ( (u1& 0xe00) < (u2& 0xe00) ) return 0;
250: if ( (u1& 0x1c0) < (u2& 0x1c0) ) return 0;
251: if ( (u1& 0x38) < (u2& 0x38) ) return 0;
252: if ( (u1& 0x7) < (u2& 0x7) ) return 0;
253: }
254: return 1;
255: break;
256: case 4:
257: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
258: u1 = d1[i]; u2 = d2[i];
259: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
260: if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
261: if ( (u1& 0xf00000) < (u2& 0xf00000) ) return 0;
262: if ( (u1& 0xf0000) < (u2& 0xf0000) ) return 0;
263: if ( (u1& 0xf000) < (u2& 0xf000) ) return 0;
264: if ( (u1& 0xf00) < (u2& 0xf00) ) return 0;
265: if ( (u1& 0xf0) < (u2& 0xf0) ) return 0;
266: if ( (u1& 0xf) < (u2& 0xf) ) return 0;
267: }
268: return 1;
269: break;
270: case 6:
271: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
272: u1 = d1[i]; u2 = d2[i];
273: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
274: if ( (u1& 0xfc0000) < (u2& 0xfc0000) ) return 0;
275: if ( (u1& 0x3f000) < (u2& 0x3f000) ) return 0;
276: if ( (u1& 0xfc0) < (u2& 0xfc0) ) return 0;
277: if ( (u1& 0x3f) < (u2& 0x3f) ) return 0;
278: }
279: return 1;
280: break;
281: case 8:
282: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
283: u1 = d1[i]; u2 = d2[i];
284: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
285: if ( (u1& 0xff0000) < (u2& 0xff0000) ) return 0;
286: if ( (u1& 0xff00) < (u2& 0xff00) ) return 0;
287: if ( (u1& 0xff) < (u2& 0xff) ) return 0;
288: }
289: return 1;
290: break;
291: case 16:
292: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
293: u1 = d1[i]; u2 = d2[i];
294: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
295: if ( (u1& 0xffff) < (u2& 0xffff) ) return 0;
296: }
297: return 1;
298: break;
299: case 32:
300: for ( i = nd_exporigin; i < nd_wpd; i++ )
301: if ( d1[i] < d2[i] ) return 0;
302: return 1;
303: break;
304: default:
305: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
306: u1 = d1[i]; u2 = d2[i];
307: for ( j = 0; j < nd_epw; j++ )
308: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
309: }
310: return 1;
311: }
312: #else
313: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
314: u1 = d1[i]; u2 = d2[i];
315: for ( j = 0; j < nd_epw; j++ )
316: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
317: }
318: return 1;
319: #endif
320: }
321:
322: /*
323: * If the current order is a block order,
324: * then the last block is length 1 and contains
325: * the homo variable. Otherwise, the original
326: * order is either 0 or 2.
327: */
328:
329: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int ompos,int weight)
330: {
331: int w,i,e,n,omask0;
332:
333: omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
334: n = nd_nvar-1;
335: ndl_zero(r);
336: for ( i = 0; i < n; i++ ) {
337: e = GET_EXP_OLD(d,i);
338: PUT_EXP(r,i,e);
339: }
340: w = TD(d);
341: PUT_EXP(r,nd_nvar-1,weight-w);
342: if ( nd_module ) MPOS(r) = d[ompos];
343: TD(r) = weight;
344: if ( nd_blockmask ) ndl_weight_mask(r);
345: }
346:
347: void ndl_dehomogenize(UINT *d)
348: {
349: UINT mask;
350: UINT h;
351: int i,bits;
352:
353: if ( nd_blockmask ) {
354: h = GET_EXP(d,nd_nvar-1);
355: XOR_EXP(d,nd_nvar-1,h);
356: TD(d) -= h;
357: ndl_weight_mask(d);
358: } else {
359: if ( nd_isrlex ) {
360: if ( nd_bpe == 32 ) {
361: h = d[nd_exporigin];
362: for ( i = nd_exporigin+1; i < nd_wpd; i++ )
363: d[i-1] = d[i];
364: d[i-1] = 0;
365: TD(d) -= h;
366: } else {
367: bits = nd_epw*nd_bpe;
368: mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
369: h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
370: for ( i = nd_exporigin; i < nd_wpd; i++ )
371: d[i] = ((d[i]<<nd_bpe)&mask)
372: |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
373: TD(d) -= h;
374: }
375: } else {
376: h = GET_EXP(d,nd_nvar-1);
377: XOR_EXP(d,nd_nvar-1,h);
378: TD(d) -= h;
379: }
380: }
381: }
382:
383: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
384: {
385: UINT t1,t2,u,u1,u2;
386: int i,j,l;
387:
388: if ( nd_module && (MPOS(d1) != MPOS(d2)) )
389: error("ndl_lcm : inconsistent monomials");
390: #if USE_UNROLL
391: switch ( nd_bpe ) {
392: case 3:
393: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
394: u1 = d1[i]; u2 = d2[i];
395: t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
396: t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
397: t1 = (u1& 0xe00000); t2 = (u2& 0xe00000); u |= t1>t2?t1:t2;
398: t1 = (u1& 0x1c0000); t2 = (u2& 0x1c0000); u |= t1>t2?t1:t2;
399: t1 = (u1& 0x38000); t2 = (u2& 0x38000); u |= t1>t2?t1:t2;
400: t1 = (u1& 0x7000); t2 = (u2& 0x7000); u |= t1>t2?t1:t2;
401: t1 = (u1& 0xe00); t2 = (u2& 0xe00); u |= t1>t2?t1:t2;
402: t1 = (u1& 0x1c0); t2 = (u2& 0x1c0); u |= t1>t2?t1:t2;
403: t1 = (u1& 0x38); t2 = (u2& 0x38); u |= t1>t2?t1:t2;
404: t1 = (u1& 0x7); t2 = (u2& 0x7); u |= t1>t2?t1:t2;
405: d[i] = u;
406: }
407: break;
408: case 4:
409: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
410: u1 = d1[i]; u2 = d2[i];
411: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
412: t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
413: t1 = (u1& 0xf00000); t2 = (u2& 0xf00000); u |= t1>t2?t1:t2;
414: t1 = (u1& 0xf0000); t2 = (u2& 0xf0000); u |= t1>t2?t1:t2;
415: t1 = (u1& 0xf000); t2 = (u2& 0xf000); u |= t1>t2?t1:t2;
416: t1 = (u1& 0xf00); t2 = (u2& 0xf00); u |= t1>t2?t1:t2;
417: t1 = (u1& 0xf0); t2 = (u2& 0xf0); u |= t1>t2?t1:t2;
418: t1 = (u1& 0xf); t2 = (u2& 0xf); u |= t1>t2?t1:t2;
419: d[i] = u;
420: }
421: break;
422: case 6:
423: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
424: u1 = d1[i]; u2 = d2[i];
425: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
426: t1 = (u1& 0xfc0000); t2 = (u2& 0xfc0000); u |= t1>t2?t1:t2;
427: t1 = (u1& 0x3f000); t2 = (u2& 0x3f000); u |= t1>t2?t1:t2;
428: t1 = (u1& 0xfc0); t2 = (u2& 0xfc0); u |= t1>t2?t1:t2;
429: t1 = (u1& 0x3f); t2 = (u2& 0x3f); u |= t1>t2?t1:t2;
430: d[i] = u;
431: }
432: break;
433: case 8:
434: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
435: u1 = d1[i]; u2 = d2[i];
436: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
437: t1 = (u1& 0xff0000); t2 = (u2& 0xff0000); u |= t1>t2?t1:t2;
438: t1 = (u1& 0xff00); t2 = (u2& 0xff00); u |= t1>t2?t1:t2;
439: t1 = (u1& 0xff); t2 = (u2& 0xff); u |= t1>t2?t1:t2;
440: d[i] = u;
441: }
442: break;
443: case 16:
444: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
445: u1 = d1[i]; u2 = d2[i];
446: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
447: t1 = (u1& 0xffff); t2 = (u2& 0xffff); u |= t1>t2?t1:t2;
448: d[i] = u;
449: }
450: break;
451: case 32:
452: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
453: u1 = d1[i]; u2 = d2[i];
454: d[i] = u1>u2?u1:u2;
455: }
456: break;
457: default:
458: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
459: u1 = d1[i]; u2 = d2[i];
460: for ( j = 0, u = 0; j < nd_epw; j++ ) {
461: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
462: }
463: d[i] = u;
464: }
465: break;
466: }
467: #else
468: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
469: u1 = d1[i]; u2 = d2[i];
470: for ( j = 0, u = 0; j < nd_epw; j++ ) {
471: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
472: }
473: d[i] = u;
474: }
475: #endif
476: if ( nd_module ) MPOS(d) = MPOS(d1);
477: TD(d) = ndl_weight(d);
478: if ( nd_blockmask ) ndl_weight_mask(d);
479: }
480:
481: void ndl_max(UINT *d1,unsigned *d2,UINT *d)
482: {
483: UINT t1,t2,u,u1,u2;
484: int i,j,l;
485:
486: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
487: u1 = d1[i]; u2 = d2[i];
488: for ( j = 0, u = 0; j < nd_epw; j++ ) {
489: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
490: }
491: d[i] = u;
492: }
493: }
494:
495: int ndl_weight(UINT *d)
496: {
497: UINT t,u;
498: int i,j;
499:
500: if ( current_dl_weight_vector )
501: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
502: u = GET_EXP(d,i);
503: t += MUL_WEIGHT(u,i);
504: }
505: else
506: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
507: u = d[i];
508: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
509: t += (u&nd_mask0);
510: }
1.20 noro 511: if ( nd_module && nd_module_rank && MPOS(d) )
512: t += nd_module_weight[MPOS(d)-1];
513: for ( i = nd_exporigin; i < nd_wpd; i++ )
514: if ( d[i] && !t )
515: printf("afo\n");
1.1 noro 516: return t;
517: }
518:
519: /* for sugarweight */
520:
521: int ndl_weight2(UINT *d)
522: {
523: int t,u;
524: int i,j;
525:
526: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
527: u = GET_EXP(d,i);
528: t += nd_sugarweight[i]*u;
529: }
1.20 noro 530: if ( nd_module && nd_module_rank && MPOS(d) )
531: t += nd_module_weight[MPOS(d)-1];
1.1 noro 532: return t;
533: }
534:
535: void ndl_weight_mask(UINT *d)
536: {
537: UINT t,u;
538: UINT *mask;
539: int i,j,k,l;
540:
541: l = nd_blockmask->n;
542: for ( k = 0; k < l; k++ ) {
543: mask = nd_blockmask->mask[k];
544: if ( current_dl_weight_vector )
545: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
546: u = GET_EXP_MASK(d,i,mask);
547: t += MUL_WEIGHT(u,i);
548: }
549: else
550: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
551: u = d[i]&mask[i];
552: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
553: t += (u&nd_mask0);
554: }
555: d[k+1] = t;
556: }
557: }
558:
1.21 noro 559: int ndl_glex_compare(UINT *d1,UINT *d2)
560: {
561: if ( TD(d1) > TD(d2) ) return 1;
562: else if ( TD(d1) < TD(d2) ) return -1;
563: else return ndl_lex_compare(d1,d2);
564: }
565:
1.1 noro 566: int ndl_lex_compare(UINT *d1,UINT *d2)
567: {
568: int i;
569:
570: d1 += nd_exporigin;
571: d2 += nd_exporigin;
572: for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
573: if ( *d1 > *d2 )
574: return nd_isrlex ? -1 : 1;
575: else if ( *d1 < *d2 )
576: return nd_isrlex ? 1 : -1;
577: return 0;
578: }
579:
580: int ndl_block_compare(UINT *d1,UINT *d2)
581: {
582: int i,l,j,ord_o,ord_l;
583: struct order_pair *op;
584: UINT t1,t2,m;
585: UINT *mask;
586:
587: l = nd_blockmask->n;
588: op = nd_blockmask->order_pair;
589: for ( j = 0; j < l; j++ ) {
590: mask = nd_blockmask->mask[j];
591: ord_o = op[j].order;
592: if ( ord_o < 2 ) {
593: if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
594: else if ( t1 < t2 ) return -1;
595: }
596: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
597: m = mask[i];
598: t1 = d1[i]&m;
599: t2 = d2[i]&m;
600: if ( t1 > t2 )
601: return !ord_o ? -1 : 1;
602: else if ( t1 < t2 )
603: return !ord_o ? 1 : -1;
604: }
605: }
606: return 0;
607: }
608:
609: int ndl_matrix_compare(UINT *d1,UINT *d2)
610: {
611: int i,j,s,row;
612: int *v;
613: Z **mat;
614: Z *w;
615: Z t1;
616: Z t,t2;
617:
1.6 noro 618: for ( j = 0; j < nd_nvar; j++ )
619: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
1.1 noro 620: if ( nd_top_weight ) {
621: if ( OID(nd_top_weight) == O_VECT ) {
1.6 noro 622: mat = (Z **)&BDY((VECT)nd_top_weight);
623: row = 1;
1.1 noro 624: } else {
625: mat = (Z **)BDY((MAT)nd_top_weight);
1.6 noro 626: row = ((MAT)nd_top_weight)->row;
1.1 noro 627: }
628: for ( i = 0; i < row; i++ ) {
1.6 noro 629: w = mat[i];
1.1 noro 630: for ( j = 0, t = 0; j < nd_nvar; j++ ) {
1.6 noro 631: STOZ(nd_work_vector[j],t1);
1.1 noro 632: mulz(w[j],t1,&t2);
633: addz(t,t2,&t1);
634: t = t1;
635: }
1.6 noro 636: if ( t ) {
637: s = sgnz(t);
1.1 noro 638: if ( s > 0 ) return 1;
639: else if ( s < 0 ) return -1;
1.6 noro 640: }
1.1 noro 641: }
1.6 noro 642: }
643: for ( i = 0; i < nd_matrix_len; i++ ) {
644: v = nd_matrix[i];
645: for ( j = 0, s = 0; j < nd_nvar; j++ )
646: s += v[j]*nd_work_vector[j];
647: if ( s > 0 ) return 1;
648: else if ( s < 0 ) return -1;
649: }
1.1 noro 650: if ( !ndl_equal(d1,d2) )
1.6 noro 651: error("ndl_matrix_compare : invalid matrix");
652: return 0;
1.1 noro 653: }
654:
655: int ndl_composite_compare(UINT *d1,UINT *d2)
656: {
657: int i,j,s,start,end,len,o;
658: int *v;
659: struct sparse_weight *sw;
660:
661: for ( j = 0; j < nd_nvar; j++ )
662: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
663: for ( i = 0; i < nd_worb_len; i++ ) {
664: len = nd_worb[i].length;
665: switch ( nd_worb[i].type ) {
666: case IS_DENSE_WEIGHT:
667: v = nd_worb[i].body.dense_weight;
668: for ( j = 0, s = 0; j < len; j++ )
669: s += v[j]*nd_work_vector[j];
670: if ( s > 0 ) return 1;
671: else if ( s < 0 ) return -1;
672: break;
673: case IS_SPARSE_WEIGHT:
674: sw = nd_worb[i].body.sparse_weight;
675: for ( j = 0, s = 0; j < len; j++ )
676: s += sw[j].value*nd_work_vector[sw[j].pos];
677: if ( s > 0 ) return 1;
678: else if ( s < 0 ) return -1;
679: break;
680: case IS_BLOCK:
681: o = nd_worb[i].body.block.order;
682: start = nd_worb[i].body.block.start;
683: switch ( o ) {
684: case 0:
685: end = start+len;
686: for ( j = start, s = 0; j < end; j++ )
687: s += MUL_WEIGHT(nd_work_vector[j],j);
688: if ( s > 0 ) return 1;
689: else if ( s < 0 ) return -1;
690: for ( j = end-1; j >= start; j-- )
691: if ( nd_work_vector[j] < 0 ) return 1;
692: else if ( nd_work_vector[j] > 0 ) return -1;
693: break;
694: case 1:
695: end = start+len;
696: for ( j = start, s = 0; j < end; j++ )
697: s += MUL_WEIGHT(nd_work_vector[j],j);
698: if ( s > 0 ) return 1;
699: else if ( s < 0 ) return -1;
700: for ( j = start; j < end; j++ )
701: if ( nd_work_vector[j] > 0 ) return 1;
702: else if ( nd_work_vector[j] < 0 ) return -1;
703: break;
704: case 2:
705: end = start+len;
706: for ( j = start; j < end; j++ )
707: if ( nd_work_vector[j] > 0 ) return 1;
708: else if ( nd_work_vector[j] < 0 ) return -1;
709: break;
710: }
711: break;
712: }
713: }
714: return 0;
715: }
716:
717: /* TDH -> WW -> TD-> RL */
718:
719: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
720: {
721: int i,m,e1,e2;
722:
723: if ( TD(d1) > TD(d2) ) return 1;
724: else if ( TD(d1) < TD(d2) ) return -1;
725: m = nd_nvar>>1;
726: for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
727: e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
728: e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
729: }
730: if ( e1 > e2 ) return 1;
731: else if ( e1 < e2 ) return -1;
732: return ndl_lex_compare(d1,d2);
733: }
734:
1.21 noro 735: // common function for module glex and grlex comparison
736: int ndl_module_glex_compare(UINT *d1,UINT *d2)
1.1 noro 737: {
1.21 noro 738: int c;
1.1 noro 739:
1.21 noro 740: switch ( nd_module_ordtype ) {
741: case 0:
742: if ( TD(d1) > TD(d2) ) return 1;
743: else if ( TD(d1) < TD(d2) ) return -1;
744: else if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
745: else if ( MPOS(d1) < MPOS(d2) ) return 1;
746: else if ( MPOS(d1) > MPOS(d2) ) return -1;
747: else return 0;
748: break;
1.1 noro 749:
1.21 noro 750: case 1:
1.19 noro 751: if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) {
752: if ( TD(d1) > TD(d2) ) return 1;
753: else if ( TD(d1) < TD(d2) ) return -1;
754: if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
755: if ( MPOS(d1) < MPOS(d2) ) return 1;
756: else if ( MPOS(d1) > MPOS(d2) ) return -1;
757: }
758: if ( MPOS(d1) < MPOS(d2) ) return 1;
759: else if ( MPOS(d1) > MPOS(d2) ) return -1;
1.21 noro 760: else if ( TD(d1) > TD(d2) ) return 1;
761: else if ( TD(d1) < TD(d2) ) return -1;
762: else return ndl_lex_compare(d1,d2);
763: break;
1.1 noro 764:
1.21 noro 765: case 2: // weight -> POT
766: if ( TD(d1) > TD(d2) ) return 1;
767: else if ( TD(d1) < TD(d2) ) return -1;
768: else if ( MPOS(d1) < MPOS(d2) ) return 1;
769: else if ( MPOS(d1) > MPOS(d2) ) return -1;
770: else return ndl_lex_compare(d1,d2);
771: break;
1.1 noro 772:
1.21 noro 773: default:
774: error("ndl_module_glex_compare : invalid module_ordtype");
1.28 noro 775: return 0;
1.21 noro 776: }
1.1 noro 777: }
778:
1.21 noro 779: // common for module comparison
780: int ndl_module_compare(UINT *d1,UINT *d2)
1.1 noro 781: {
1.21 noro 782: int c;
1.1 noro 783:
1.21 noro 784: switch ( nd_module_ordtype ) {
785: case 0:
1.23 noro 786: if ( (c = (*ndl_base_compare_function)(d1,d2)) != 0 ) return c;
1.21 noro 787: else if ( MPOS(d1) > MPOS(d2) ) return -1;
788: else if ( MPOS(d1) < MPOS(d2) ) return 1;
789: else return 0;
790: break;
1.1 noro 791:
1.21 noro 792: case 1:
793: if ( MPOS(d1) < MPOS(d2) ) return 1;
794: else if ( MPOS(d1) > MPOS(d2) ) return -1;
795: else return (*ndl_base_compare_function)(d1,d2);
796: break;
1.1 noro 797:
1.21 noro 798: case 2: // weight -> POT
799: if ( TD(d1) > TD(d2) ) return 1;
800: else if ( TD(d1) < TD(d2) ) return -1;
801: else if ( MPOS(d1) < MPOS(d2) ) return 1;
802: else if ( MPOS(d1) > MPOS(d2) ) return -1;
803: else return (*ndl_base_compare_function)(d1,d2);
804: break;
1.1 noro 805:
1.21 noro 806: default:
807: error("ndl_module_compare : invalid module_ordtype");
1.28 noro 808: return 0;
1.21 noro 809: }
1.1 noro 810: }
811:
1.21 noro 812: extern DMMstack dmm_stack;
813: void _addtodl(int n,DL d1,DL d2);
1.31 noro 814: void _adddl(int n,DL d1,DL d2,DL d3);
1.21 noro 815: int _eqdl(int n,DL d1,DL d2);
816:
817: int ndl_module_schreyer_compare(UINT *m1,UINT *m2)
818: {
1.44 noro 819: int pos1,pos2,t,j,retpot;
1.21 noro 820: DMM *in;
821: DMMstack s;
822: static DL d1=0;
823: static DL d2=0;
824: static int dlen=0;
1.44 noro 825: extern int ReversePOT;
1.21 noro 826:
1.44 noro 827: if ( ReversePOT ) retpot = -1;
828: else retpot = 1;
1.21 noro 829: pos1 = MPOS(m1); pos2 = MPOS(m2);
830: if ( pos1 == pos2 ) return (*ndl_base_compare_function)(m1,m2);
831: if ( nd_nvar > dlen ) {
832: NEWDL(d1,nd_nvar);
833: NEWDL(d2,nd_nvar);
834: dlen = nd_nvar;
835: }
836: d1->td = TD(m1);
837: for ( j = 0; j < nd_nvar; j++ ) d1->d[j] = GET_EXP(m1,j);
838: d2->td = TD(m2);
839: for ( j = 0; j < nd_nvar; j++ ) d2->d[j] = GET_EXP(m2,j);
840: for ( s = dmm_stack; s; s = NEXT(s) ) {
841: in = s->in;
842: _addtodl(nd_nvar,in[pos1]->dl,d1);
843: _addtodl(nd_nvar,in[pos2]->dl,d2);
844: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(nd_nvar,d1,d2)) {
1.44 noro 845: if ( pos1 < pos2 ) return retpot;
846: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 847: else return 0;
848: }
849: pos1 = in[pos1]->pos;
850: pos2 = in[pos2]->pos;
851: if ( pos1 == pos2 ) return (*dl_base_compare_function)(nd_nvar,d1,d2);
852: }
853: // comparison by the bottom order
854: LAST:
855: switch ( nd_base_ordtype ) {
856: case 0:
857: t = (*dl_base_compare_function)(nd_nvar,d1,d2);
858: if ( t ) return t;
1.44 noro 859: else if ( pos1 < pos2 ) return retpot;
860: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 861: else return 0;
862: break;
863: case 1:
1.44 noro 864: if ( pos1 < pos2 ) return retpot;
865: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 866: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
867: break;
868: case 2:
869: if ( d1->td > d2->td ) return 1;
870: else if ( d1->td < d2->td ) return -1;
1.44 noro 871: else if ( pos1 < pos2 ) return retpot;
872: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 873: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
874: break;
875: default:
876: error("ndl_schreyer_compare : invalid base ordtype");
1.28 noro 877: return 0;
1.21 noro 878: }
1.1 noro 879: }
880:
881: INLINE int ndl_equal(UINT *d1,UINT *d2)
882: {
883: int i;
884:
885: switch ( nd_wpd ) {
886: case 2:
887: if ( TD(d2) != TD(d1) ) return 0;
888: if ( d2[1] != d1[1] ) return 0;
889: return 1;
890: break;
891: case 3:
892: if ( TD(d2) != TD(d1) ) return 0;
893: if ( d2[1] != d1[1] ) return 0;
894: if ( d2[2] != d1[2] ) return 0;
895: return 1;
896: break;
897: default:
898: for ( i = 0; i < nd_wpd; i++ )
899: if ( *d1++ != *d2++ ) return 0;
900: return 1;
901: break;
902: }
903: }
904:
905: INLINE void ndl_copy(UINT *d1,UINT *d2)
906: {
907: int i;
908:
909: switch ( nd_wpd ) {
910: case 2:
911: TD(d2) = TD(d1);
912: d2[1] = d1[1];
913: break;
914: case 3:
915: TD(d2) = TD(d1);
916: d2[1] = d1[1];
917: d2[2] = d1[2];
918: break;
919: default:
920: for ( i = 0; i < nd_wpd; i++ )
921: d2[i] = d1[i];
922: break;
923: }
924: }
925:
926: INLINE void ndl_zero(UINT *d)
927: {
928: int i;
929: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
930: }
931:
932: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
933: {
934: int i;
935:
936: if ( nd_module ) {
937: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
938: error("ndl_add : invalid operation");
939: }
940: #if 1
941: switch ( nd_wpd ) {
942: case 2:
943: TD(d) = TD(d1)+TD(d2);
944: d[1] = d1[1]+d2[1];
945: break;
946: case 3:
947: TD(d) = TD(d1)+TD(d2);
948: d[1] = d1[1]+d2[1];
949: d[2] = d1[2]+d2[2];
950: break;
951: default:
952: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
953: break;
954: }
955: #else
956: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
957: #endif
958: }
959:
960: /* d1 += d2 */
961: INLINE void ndl_addto(UINT *d1,UINT *d2)
962: {
963: int i;
964:
965: if ( nd_module ) {
966: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
967: error("ndl_addto : invalid operation");
968: }
969: #if 1
970: switch ( nd_wpd ) {
971: case 2:
972: TD(d1) += TD(d2);
973: d1[1] += d2[1];
974: break;
975: case 3:
976: TD(d1) += TD(d2);
977: d1[1] += d2[1];
978: d1[2] += d2[2];
979: break;
980: default:
981: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
982: break;
983: }
984: #else
985: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
986: #endif
987: }
988:
989: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
990: {
991: int i;
992:
993: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
994: }
995:
996: int ndl_disjoint(UINT *d1,UINT *d2)
997: {
998: UINT t1,t2,u,u1,u2;
999: int i,j;
1000:
1001: if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
1002: #if USE_UNROLL
1003: switch ( nd_bpe ) {
1004: case 3:
1005: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1006: u1 = d1[i]; u2 = d2[i];
1007: t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
1008: t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
1009: t1 = u1& 0xe00000; t2 = u2& 0xe00000; if ( t1&&t2 ) return 0;
1010: t1 = u1& 0x1c0000; t2 = u2& 0x1c0000; if ( t1&&t2 ) return 0;
1011: t1 = u1& 0x38000; t2 = u2& 0x38000; if ( t1&&t2 ) return 0;
1012: t1 = u1& 0x7000; t2 = u2& 0x7000; if ( t1&&t2 ) return 0;
1013: t1 = u1& 0xe00; t2 = u2& 0xe00; if ( t1&&t2 ) return 0;
1014: t1 = u1& 0x1c0; t2 = u2& 0x1c0; if ( t1&&t2 ) return 0;
1015: t1 = u1& 0x38; t2 = u2& 0x38; if ( t1&&t2 ) return 0;
1016: t1 = u1& 0x7; t2 = u2& 0x7; if ( t1&&t2 ) return 0;
1017: }
1018: return 1;
1019: break;
1020: case 4:
1021: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1022: u1 = d1[i]; u2 = d2[i];
1023: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
1024: t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
1025: t1 = u1& 0xf00000; t2 = u2& 0xf00000; if ( t1&&t2 ) return 0;
1026: t1 = u1& 0xf0000; t2 = u2& 0xf0000; if ( t1&&t2 ) return 0;
1027: t1 = u1& 0xf000; t2 = u2& 0xf000; if ( t1&&t2 ) return 0;
1028: t1 = u1& 0xf00; t2 = u2& 0xf00; if ( t1&&t2 ) return 0;
1029: t1 = u1& 0xf0; t2 = u2& 0xf0; if ( t1&&t2 ) return 0;
1030: t1 = u1& 0xf; t2 = u2& 0xf; if ( t1&&t2 ) return 0;
1031: }
1032: return 1;
1033: break;
1034: case 6:
1035: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1036: u1 = d1[i]; u2 = d2[i];
1037: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1038: t1 = u1& 0xfc0000; t2 = u2& 0xfc0000; if ( t1&&t2 ) return 0;
1039: t1 = u1& 0x3f000; t2 = u2& 0x3f000; if ( t1&&t2 ) return 0;
1040: t1 = u1& 0xfc0; t2 = u2& 0xfc0; if ( t1&&t2 ) return 0;
1041: t1 = u1& 0x3f; t2 = u2& 0x3f; if ( t1&&t2 ) return 0;
1042: }
1043: return 1;
1044: break;
1045: case 8:
1046: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1047: u1 = d1[i]; u2 = d2[i];
1048: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1049: t1 = u1& 0xff0000; t2 = u2& 0xff0000; if ( t1&&t2 ) return 0;
1050: t1 = u1& 0xff00; t2 = u2& 0xff00; if ( t1&&t2 ) return 0;
1051: t1 = u1& 0xff; t2 = u2& 0xff; if ( t1&&t2 ) return 0;
1052: }
1053: return 1;
1054: break;
1055: case 16:
1056: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1057: u1 = d1[i]; u2 = d2[i];
1058: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1059: t1 = u1& 0xffff; t2 = u2& 0xffff; if ( t1&&t2 ) return 0;
1060: }
1061: return 1;
1062: break;
1063: case 32:
1064: for ( i = nd_exporigin; i < nd_wpd; i++ )
1065: if ( d1[i] && d2[i] ) return 0;
1066: return 1;
1067: break;
1068: default:
1069: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1070: u1 = d1[i]; u2 = d2[i];
1071: for ( j = 0; j < nd_epw; j++ ) {
1072: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1073: u1 >>= nd_bpe; u2 >>= nd_bpe;
1074: }
1075: }
1076: return 1;
1077: break;
1078: }
1079: #else
1080: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1081: u1 = d1[i]; u2 = d2[i];
1082: for ( j = 0; j < nd_epw; j++ ) {
1083: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1084: u1 >>= nd_bpe; u2 >>= nd_bpe;
1085: }
1086: }
1087: return 1;
1088: #endif
1089: }
1090:
1091: int ndl_check_bound(UINT *d1,UINT *d2)
1092: {
1093: UINT u2;
1094: int i,j,ind,k;
1095:
1096: ind = 0;
1097: #if USE_UNROLL
1098: switch ( nd_bpe ) {
1099: case 3:
1100: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1101: u2 = d2[i];
1102: if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
1103: if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
1104: if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
1105: if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
1106: if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
1107: if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
1108: if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
1109: if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
1110: if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
1111: if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
1112: }
1113: return 0;
1114: break;
1115: case 4:
1116: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1117: u2 = d2[i];
1118: if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
1119: if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
1120: if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
1121: if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
1122: if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
1123: if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
1124: if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
1125: if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
1126: }
1127: return 0;
1128: break;
1129: case 6:
1130: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1131: u2 = d2[i];
1132: if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
1133: if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
1134: if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
1135: if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
1136: if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
1137: }
1138: return 0;
1139: break;
1140: case 8:
1141: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1142: u2 = d2[i];
1143: if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
1144: if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
1145: if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
1146: if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
1147: }
1148: return 0;
1149: break;
1150: case 16:
1151: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1152: u2 = d2[i];
1153: if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
1154: if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
1155: }
1156: return 0;
1157: break;
1158: case 32:
1159: for ( i = nd_exporigin; i < nd_wpd; i++ )
1160: if ( d1[i]+d2[i]<d1[i] ) return 1;
1161: return 0;
1162: break;
1163: default:
1164: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1165: u2 = d2[i];
1166: k = (nd_epw-1)*nd_bpe;
1167: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1168: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1169: }
1170: return 0;
1171: break;
1172: }
1173: #else
1174: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1175: u2 = d2[i];
1176: k = (nd_epw-1)*nd_bpe;
1177: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1178: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1179: }
1180: return 0;
1181: #endif
1182: }
1183:
1184: int ndl_check_bound2(int index,UINT *d2)
1185: {
1186: return ndl_check_bound(nd_bound[index],d2);
1187: }
1188:
1189: INLINE int ndl_hash_value(UINT *d)
1190: {
1191: int i;
1.11 noro 1192: UINT r;
1.1 noro 1193:
1194: r = 0;
1195: for ( i = 0; i < nd_wpd; i++ )
1.12 noro 1196: r = (r*1511+d[i]);
1.11 noro 1197: r %= REDTAB_LEN;
1.1 noro 1198: return r;
1199: }
1200:
1201: INLINE int ndl_find_reducer(UINT *dg)
1202: {
1203: RHist r;
1204: int d,k,i;
1205:
1206: d = ndl_hash_value(dg);
1207: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1208: if ( ndl_equal(dg,DL(r)) ) {
1209: if ( k > 0 ) nd_notfirst++;
1210: nd_found++;
1211: return r->index;
1212: }
1213: }
1214: if ( Reverse )
1215: for ( i = nd_psn-1; i >= 0; i-- ) {
1216: r = nd_psh[i];
1217: if ( ndl_reducible(dg,DL(r)) ) {
1218: nd_create++;
1219: nd_append_red(dg,i);
1220: return i;
1221: }
1222: }
1223: else
1224: for ( i = 0; i < nd_psn; i++ ) {
1225: r = nd_psh[i];
1226: if ( ndl_reducible(dg,DL(r)) ) {
1227: nd_create++;
1228: nd_append_red(dg,i);
1229: return i;
1230: }
1231: }
1232: return -1;
1233: }
1234:
1.41 noro 1235: INLINE int ndl_find_reducer_nonsig(UINT *dg)
1236: {
1237: RHist r;
1238: int i;
1239:
1240: for ( i = 0; i < nd_psn; i++ ) {
1241: r = nd_psh[i];
1242: if ( ndl_reducible(dg,DL(r)) ) return i;
1243: }
1244: return -1;
1245: }
1246:
1.24 noro 1247: // ret=0,...,nd_psn-1 => reducer found
1248: // ret=nd_psn => reducer not found
1249: // ret=-1 => singular top reducible
1250:
1251: int comp_sig(SIG s1,SIG s2);
1252: void _ndltodl(UINT *ndl,DL dl);
1253:
1254: void print_sig(SIG s)
1255: {
1256: int i;
1257:
1258: fprintf(asir_out,"<<");
1259: for ( i = 0; i < nd_nvar; i++ ) {
1260: fprintf(asir_out,"%d",s->dl->d[i]);
1261: if ( i != nd_nvar-1 ) fprintf(asir_out,",");
1262: }
1263: fprintf(asir_out,">>*e%d",s->pos);
1264: }
1265:
1.45 noro 1266: void print_siglist(NODE l)
1267: {
1268: for ( ; l; l = NEXT(l) )
1269: print_sig((SIG)l->body);
1270: }
1271:
1272:
1.35 noro 1273: // assuming increasing order wrt signature
1274:
1.24 noro 1275: INLINE int ndl_find_reducer_s(UINT *dg,SIG sig)
1276: {
1277: RHist r;
1.27 noro 1278: int i,singular,ret,d,k;
1.26 noro 1279: static int wpd,nvar;
1.24 noro 1280: static SIG quo;
1281: static UINT *tmp;
1282:
1.26 noro 1283: if ( !quo || nvar != nd_nvar ) NEWSIG(quo);
1284: if ( wpd != nd_wpd ) {
1.24 noro 1285: wpd = nd_wpd;
1286: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
1287: }
1.27 noro 1288: d = ndl_hash_value(dg);
1.35 noro 1289: #if 1
1.27 noro 1290: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1291: if ( ndl_equal(dg,DL(r)) ) {
1292: return r->index;
1293: }
1294: }
1.35 noro 1295: #endif
1.24 noro 1296: singular = 0;
1297: for ( i = 0; i < nd_psn; i++ ) {
1298: r = nd_psh[i];
1299: if ( ndl_reducible(dg,DL(r)) ) {
1.27 noro 1300: ndl_sub(dg,DL(r),tmp);
1.24 noro 1301: _ndltodl(tmp,DL(quo));
1302: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
1303: quo->pos = nd_psh[i]->sig->pos;
1.55 noro 1304: _adddl(nd_nvar,DL(quo),nd_sba_hm[quo->pos],DL2(quo));
1.24 noro 1305: ret = comp_sig(sig,quo);
1306: if ( ret > 0 ) { singular = 0; break; }
1.38 noro 1307: if ( ret == 0 ) { /* fprintf(asir_out,"s"); fflush(asir_out); */ singular = 1; }
1.24 noro 1308: }
1309: }
1310: if ( singular ) return -1;
1.27 noro 1311: else if ( i < nd_psn )
1312: nd_append_red(dg,i);
1313: return i;
1.24 noro 1314: }
1315:
1.1 noro 1316: ND nd_merge(ND p1,ND p2)
1317: {
1318: int n,c;
1319: int t,can,td1,td2;
1320: ND r;
1321: NM m1,m2,mr0,mr,s;
1322:
1323: if ( !p1 ) return p2;
1324: else if ( !p2 ) return p1;
1325: else {
1326: can = 0;
1327: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1328: c = DL_COMPARE(DL(m1),DL(m2));
1329: switch ( c ) {
1330: case 0:
1331: s = m1; m1 = NEXT(m1);
1332: can++; NEXTNM2(mr0,mr,s);
1333: s = m2; m2 = NEXT(m2); FREENM(s);
1334: break;
1335: case 1:
1336: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1337: break;
1338: case -1:
1339: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1340: break;
1341: }
1342: }
1343: if ( !mr0 )
1344: if ( m1 ) mr0 = m1;
1345: else if ( m2 ) mr0 = m2;
1346: else return 0;
1347: else if ( m1 ) NEXT(mr) = m1;
1348: else if ( m2 ) NEXT(mr) = m2;
1349: else NEXT(mr) = 0;
1350: BDY(p1) = mr0;
1351: SG(p1) = MAX(SG(p1),SG(p2));
1352: LEN(p1) = LEN(p1)+LEN(p2)-can;
1353: FREEND(p2);
1354: return p1;
1355: }
1356: }
1357:
1358: ND nd_add(int mod,ND p1,ND p2)
1359: {
1360: int n,c;
1361: int t,can,td1,td2;
1362: ND r;
1363: NM m1,m2,mr0,mr,s;
1364:
1.11 noro 1365: Nnd_add++;
1.1 noro 1366: if ( !p1 ) return p2;
1367: else if ( !p2 ) return p1;
1368: else if ( mod == -1 ) return nd_add_sf(p1,p2);
1369: else if ( mod == -2 ) return nd_add_lf(p1,p2);
1370: else if ( !mod ) return nd_add_q(p1,p2);
1371: else {
1372: can = 0;
1373: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1374: c = DL_COMPARE(DL(m1),DL(m2));
1375: switch ( c ) {
1376: case 0:
1377: t = ((CM(m1))+(CM(m2))) - mod;
1378: if ( t < 0 ) t += mod;
1379: s = m1; m1 = NEXT(m1);
1380: if ( t ) {
1381: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1382: } else {
1383: can += 2; FREENM(s);
1384: }
1385: s = m2; m2 = NEXT(m2); FREENM(s);
1386: break;
1387: case 1:
1388: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1389: break;
1390: case -1:
1391: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1392: break;
1393: }
1394: }
1395: if ( !mr0 )
1396: if ( m1 ) mr0 = m1;
1397: else if ( m2 ) mr0 = m2;
1398: else return 0;
1399: else if ( m1 ) NEXT(mr) = m1;
1400: else if ( m2 ) NEXT(mr) = m2;
1401: else NEXT(mr) = 0;
1402: BDY(p1) = mr0;
1403: SG(p1) = MAX(SG(p1),SG(p2));
1404: LEN(p1) = LEN(p1)+LEN(p2)-can;
1405: FREEND(p2);
1406: return p1;
1407: }
1408: }
1409:
1410: /* XXX on opteron, the inlined manipulation of destructive additon of
1411: * two NM seems to make gcc optimizer get confused, so the part is
1412: * done in a function.
1413: */
1414:
1415: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1416: {
1417: NM s;
1418: P t;
1419: int can;
1420:
1421: addp(nd_vc,CP(*m1),CP(*m2),&t);
1422: s = *m1; *m1 = NEXT(*m1);
1423: if ( t ) {
1424: can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
1425: } else {
1426: can = 2; FREENM(s);
1427: }
1428: s = *m2; *m2 = NEXT(*m2); FREENM(s);
1429: return can;
1430: }
1431:
1432: ND nd_add_q(ND p1,ND p2)
1433: {
1434: int n,c,can;
1435: ND r;
1436: NM m1,m2,mr0,mr,s;
1437: P t;
1438:
1439: if ( !p1 ) return p2;
1440: else if ( !p2 ) return p1;
1441: else {
1442: can = 0;
1443: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1444: c = DL_COMPARE(DL(m1),DL(m2));
1445: switch ( c ) {
1446: case 0:
1447: #if defined(__x86_64__)
1448: can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1449: #else
1450: addp(nd_vc,CP(m1),CP(m2),&t);
1451: s = m1; m1 = NEXT(m1);
1452: if ( t ) {
1453: can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
1454: } else {
1455: can += 2; FREENM(s);
1456: }
1457: s = m2; m2 = NEXT(m2); FREENM(s);
1458: #endif
1459: break;
1460: case 1:
1461: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1462: break;
1463: case -1:
1464: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1465: break;
1466: }
1467: }
1468: if ( !mr0 )
1469: if ( m1 ) mr0 = m1;
1470: else if ( m2 ) mr0 = m2;
1471: else return 0;
1472: else if ( m1 ) NEXT(mr) = m1;
1473: else if ( m2 ) NEXT(mr) = m2;
1474: else NEXT(mr) = 0;
1475: BDY(p1) = mr0;
1476: SG(p1) = MAX(SG(p1),SG(p2));
1477: LEN(p1) = LEN(p1)+LEN(p2)-can;
1478: FREEND(p2);
1479: return p1;
1480: }
1481: }
1482:
1483: ND nd_add_sf(ND p1,ND p2)
1484: {
1485: int n,c,can;
1486: ND r;
1487: NM m1,m2,mr0,mr,s;
1488: int t;
1489:
1490: if ( !p1 ) return p2;
1491: else if ( !p2 ) return p1;
1492: else {
1493: can = 0;
1494: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1495: c = DL_COMPARE(DL(m1),DL(m2));
1496: switch ( c ) {
1497: case 0:
1498: t = _addsf(CM(m1),CM(m2));
1499: s = m1; m1 = NEXT(m1);
1500: if ( t ) {
1501: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1502: } else {
1503: can += 2; FREENM(s);
1504: }
1505: s = m2; m2 = NEXT(m2); FREENM(s);
1506: break;
1507: case 1:
1508: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1509: break;
1510: case -1:
1511: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1512: break;
1513: }
1514: }
1515: if ( !mr0 )
1516: if ( m1 ) mr0 = m1;
1517: else if ( m2 ) mr0 = m2;
1518: else return 0;
1519: else if ( m1 ) NEXT(mr) = m1;
1520: else if ( m2 ) NEXT(mr) = m2;
1521: else NEXT(mr) = 0;
1522: BDY(p1) = mr0;
1523: SG(p1) = MAX(SG(p1),SG(p2));
1524: LEN(p1) = LEN(p1)+LEN(p2)-can;
1525: FREEND(p2);
1526: return p1;
1527: }
1528: }
1529:
1530:
1531: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn,Obj *divp)
1532: {
1533: int c,c1,c2;
1534: Z cg,cred,gcd,tq;
1535: P cgp,credp,gcdp;
1536: Obj tr,tr1;
1537:
1538: if ( mod == -1 ) {
1539: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1540: *divp = (Obj)ONE;
1541: } else if ( mod == -2 ) {
1542: Z inv,t;
1543: divlf(ONE,HCZ(p),&inv);
1544: chsgnlf(HCZ(g),&t);
1545: mullf(inv,t,&CZ(mul));
1546: *divp = (Obj)ONE;
1547: } else if ( mod ) {
1548: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1549: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1550: *divp = (Obj)ONE;
1551: } else if ( nd_vc ) {
1552: ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
1553: divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
1554: chsgnp(cgp,&CP(mul));
1555: nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
1556: if ( dn ) {
1557: mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
1558: reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
1559: }
1560: *divp = (Obj)credp;
1561: } else {
1.6 noro 1562: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1563: chsgnz(cg,&CZ(mul));
1.1 noro 1564: nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
1565: if ( dn ) {
1566: mulz(dn->z,cred,&tq); dn->z = tq;
1567: }
1568: *divp = (Obj)cred;
1569: }
1570: return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1571: }
1572:
1573: /* ret=1 : success, ret=0 : overflow */
1.6 noro 1574: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1.1 noro 1575: {
1576: NM m,mrd,tail;
1577: NM mul;
1578: int n,sugar,psugar,sugar0,stat,index;
1579: int c,c1,c2,dummy;
1580: RHist h;
1581: NDV p,red;
1582: Q cg,cred,gcd,tq,qq;
1583: Z iq;
1584: DP dmul;
1585: NODE node;
1586: LIST hist;
1587: double hmag;
1588: P tp,tp1;
1589: Obj tr,tr1,div;
1590: union oNDC hg;
1591: P cont;
1592:
1593: if ( !g ) {
1594: *rp = d;
1595: return 1;
1596: }
1597: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1598:
1599: sugar0 = sugar = SG(g);
1600: n = NV(g);
1601: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1602: if ( d )
1603: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1604: for ( ; g; ) {
1605: index = ndl_find_reducer(HDL(g));
1606: if ( index >= 0 ) {
1607: h = nd_psh[index];
1608: ndl_sub(HDL(g),DL(h),DL(mul));
1609: if ( ndl_check_bound2(index,DL(mul)) ) {
1610: nd_free(g); nd_free(d);
1611: return 0;
1612: }
1613: p = nd_demand ? ndv_load(index) : ps[index];
1614: /* d+g -> div*(d+g)+mul*p */
1.6 noro 1615: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1.1 noro 1616: if ( nd_gentrace ) {
1617: /* Trace=[div,index,mul,ONE] */
1.6 noro 1618: STOZ(index,iq);
1.1 noro 1619: nmtodp(mod,mul,&dmul);
1620: node = mknode(4,div,iq,dmul,ONE);
1621: }
1622: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1623: if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) {
1624: hg = HCU(g);
1625: nd_removecont2(d,g);
1.6 noro 1626: if ( nd_gentrace ) {
1.1 noro 1627: /* overwrite cont : Trace=[div,index,mul,cont] */
1.6 noro 1628: /* exact division */
1.1 noro 1629: cont = ndc_div(mod,hg,HCU(g));
1630: if ( nd_gentrace && !UNIQ(cont) ) ARG3(node) = (pointer)cont;
1631: }
1632: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1633: }
1634: MKLIST(hist,node);
1635: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1636: } else if ( !full ) {
1637: *rp = g;
1638: return 1;
1639: } else {
1640: m = BDY(g);
1641: if ( NEXT(m) ) {
1642: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1643: } else {
1644: FREEND(g); g = 0;
1645: }
1646: if ( d ) {
1647: NEXT(tail)=m; tail=m; LEN(d)++;
1648: } else {
1649: MKND(n,m,1,d); tail = BDY(d);
1650: }
1651: }
1652: }
1653: if ( d ) SG(d) = sugar;
1654: *rp = d;
1655: return 1;
1656: }
1657:
1.24 noro 1658: // ret=1 => success
1659: // ret=0 => overflow
1660: // ret=-1 => singular top reducible
1661:
1662: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1663: {
1664: NM m,mrd,tail;
1665: NM mul;
1666: int n,sugar,psugar,sugar0,stat,index;
1667: int c,c1,c2,dummy;
1668: RHist h;
1669: NDV p,red;
1670: Q cg,cred,gcd,tq,qq;
1671: Z iq;
1672: DP dmul;
1673: NODE node;
1674: LIST hist;
1675: double hmag;
1676: P tp,tp1;
1677: Obj tr,tr1,div;
1678: union oNDC hg;
1679: P cont;
1680: SIG sig;
1681:
1682: if ( !g ) {
1683: *rp = d;
1684: return 1;
1685: }
1686: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1687:
1688: sugar0 = sugar = SG(g);
1689: n = NV(g);
1690: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1691: if ( d )
1692: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1693: sig = g->sig;
1694: for ( ; g; ) {
1695: index = ndl_find_reducer_s(HDL(g),sig);
1696: if ( index >= 0 && index < nd_psn ) {
1697: // reducer found
1698: h = nd_psh[index];
1699: ndl_sub(HDL(g),DL(h),DL(mul));
1700: if ( ndl_check_bound2(index,DL(mul)) ) {
1701: nd_free(g); nd_free(d);
1702: return 0;
1703: }
1704: p = ps[index];
1705: /* d+g -> div*(d+g)+mul*p */
1706: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1707: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1708: if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
1709: hg = HCU(g);
1710: nd_removecont2(d,g);
1711: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1712: }
1.55 noro 1713: if ( nd_gentrace ) {
1714: /* Trace=[div,index,mul,ONE] */
1715: STOZ(index,iq);
1716: nmtodp(mod,mul,&dmul);
1717: node = mknode(4,div,iq,dmul,ONE);
1718: }
1719: MKLIST(hist,node);
1720: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1.24 noro 1721: } else if ( index == -1 ) {
1722: // singular top reducible
1723: return -1;
1724: } else if ( !full ) {
1725: *rp = g;
1726: g->sig = sig;
1727: return 1;
1728: } else {
1729: m = BDY(g);
1730: if ( NEXT(m) ) {
1731: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1732: } else {
1733: FREEND(g); g = 0;
1734: }
1735: if ( d ) {
1736: NEXT(tail)=m; tail=m; LEN(d)++;
1737: } else {
1738: MKND(n,m,1,d); tail = BDY(d);
1739: }
1740: }
1741: }
1742: if ( d ) {
1743: SG(d) = sugar;
1744: d->sig = sig;
1745: }
1746: *rp = d;
1747: return 1;
1748: }
1749:
1.1 noro 1750: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1751: {
1752: int hindex,index;
1753: NDV p;
1754: ND u,d,red;
1755: NODE l;
1756: NM mul,m,mrd,tail;
1757: int sugar,psugar,n,h_reducible;
1758: PGeoBucket bucket;
1759: int c,c1,c2;
1760: Z cg,cred,gcd,zzz;
1761: RHist h;
1762: double hmag,gmag;
1763: int count = 0;
1764: int hcount = 0;
1765:
1766: if ( !g ) {
1767: *rp = 0;
1768: return 1;
1769: }
1770: sugar = SG(g);
1771: n = NV(g);
1.6 noro 1772: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1773: bucket = create_pbucket();
1774: add_pbucket(mod,bucket,g);
1775: d = 0;
1776: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1777: while ( 1 ) {
1778: if ( mod > 0 || mod == -1 )
1779: hindex = head_pbucket(mod,bucket);
1780: else if ( mod == -2 )
1781: hindex = head_pbucket_lf(bucket);
1782: else
1783: hindex = head_pbucket_q(bucket);
1784: if ( hindex < 0 ) {
1785: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1786: if ( d ) SG(d) = sugar;
1787: *rp = d;
1788: return 1;
1789: }
1790: g = bucket->body[hindex];
1791: index = ndl_find_reducer(HDL(g));
1792: if ( index >= 0 ) {
1793: count++;
1794: if ( !d ) hcount++;
1795: h = nd_psh[index];
1796: ndl_sub(HDL(g),DL(h),DL(mul));
1797: if ( ndl_check_bound2(index,DL(mul)) ) {
1798: nd_free(d);
1799: free_pbucket(bucket);
1800: *rp = 0;
1801: return 0;
1802: }
1803: p = ps[index];
1804: if ( mod == -1 )
1805: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1806: else if ( mod == -2 ) {
1807: Z inv,t;
1808: divlf(ONE,HCZ(p),&inv);
1809: chsgnlf(HCZ(g),&t);
1810: mullf(inv,t,&CZ(mul));
1811: } else if ( mod ) {
1812: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1813: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1814: } else {
1.6 noro 1815: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1816: chsgnz(cg,&CZ(mul));
1.1 noro 1817: nd_mul_c_q(d,(P)cred);
1818: mulq_pbucket(bucket,cred);
1819: g = bucket->body[hindex];
1.6 noro 1820: gmag = (double)p_mag((P)HCZ(g));
1.1 noro 1821: }
1822: red = ndv_mul_nm(mod,mul,p);
1823: bucket->body[hindex] = nd_remove_head(g);
1824: red = nd_remove_head(red);
1825: add_pbucket(mod,bucket,red);
1826: psugar = SG(p)+TD(DL(mul));
1827: sugar = MAX(sugar,psugar);
1828: if ( !mod && hmag && (gmag > hmag) ) {
1829: g = normalize_pbucket(mod,bucket);
1830: if ( !g ) {
1831: if ( d ) SG(d) = sugar;
1832: *rp = d;
1833: return 1;
1834: }
1835: nd_removecont2(d,g);
1.6 noro 1836: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1837: add_pbucket(mod,bucket,g);
1838: }
1839: } else if ( !full ) {
1840: g = normalize_pbucket(mod,bucket);
1841: if ( g ) SG(g) = sugar;
1842: *rp = g;
1843: return 1;
1844: } else {
1845: m = BDY(g);
1846: if ( NEXT(m) ) {
1847: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1848: } else {
1849: FREEND(g); g = 0;
1850: }
1851: bucket->body[hindex] = g;
1852: NEXT(m) = 0;
1853: if ( d ) {
1854: NEXT(tail)=m; tail=m; LEN(d)++;
1855: } else {
1856: MKND(n,m,1,d); tail = BDY(d);
1857: }
1858: }
1859: }
1860: }
1861:
1.25 noro 1862: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *rp)
1863: {
1864: int hindex,index;
1865: NDV p;
1866: ND u,d,red;
1867: NODE l;
1868: NM mul,m,mrd,tail;
1869: int sugar,psugar,n,h_reducible;
1870: PGeoBucket bucket;
1871: int c,c1,c2;
1872: Z cg,cred,gcd,zzz;
1873: RHist h;
1874: double hmag,gmag;
1875: int count = 0;
1876: int hcount = 0;
1877: SIG sig;
1878:
1879: if ( !g ) {
1880: *rp = 0;
1881: return 1;
1882: }
1883: sugar = SG(g);
1884: n = NV(g);
1885: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1886: bucket = create_pbucket();
1887: add_pbucket(mod,bucket,g);
1888: d = 0;
1889: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1890: sig = g->sig;
1891: while ( 1 ) {
1892: if ( mod > 0 || mod == -1 )
1893: hindex = head_pbucket(mod,bucket);
1894: else if ( mod == -2 )
1895: hindex = head_pbucket_lf(bucket);
1896: else
1897: hindex = head_pbucket_q(bucket);
1898: if ( hindex < 0 ) {
1899: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1900: if ( d ) {
1901: SG(d) = sugar;
1902: d->sig = sig;
1903: }
1904: *rp = d;
1905: return 1;
1906: }
1907: g = bucket->body[hindex];
1908: index = ndl_find_reducer_s(HDL(g),sig);
1909: if ( index >= 0 && index < nd_psn ) {
1910: count++;
1911: if ( !d ) hcount++;
1912: h = nd_psh[index];
1913: ndl_sub(HDL(g),DL(h),DL(mul));
1914: if ( ndl_check_bound2(index,DL(mul)) ) {
1915: nd_free(d);
1916: free_pbucket(bucket);
1917: *rp = 0;
1918: return 0;
1919: }
1920: p = ps[index];
1921: if ( mod == -1 )
1922: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1923: else if ( mod == -2 ) {
1924: Z inv,t;
1925: divlf(ONE,HCZ(p),&inv);
1926: chsgnlf(HCZ(g),&t);
1927: mullf(inv,t,&CZ(mul));
1928: } else if ( mod ) {
1929: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1930: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1931: } else {
1932: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1933: chsgnz(cg,&CZ(mul));
1934: nd_mul_c_q(d,(P)cred);
1935: mulq_pbucket(bucket,cred);
1936: g = bucket->body[hindex];
1937: gmag = (double)p_mag((P)HCZ(g));
1938: }
1939: red = ndv_mul_nm(mod,mul,p);
1940: bucket->body[hindex] = nd_remove_head(g);
1941: red = nd_remove_head(red);
1942: add_pbucket(mod,bucket,red);
1943: psugar = SG(p)+TD(DL(mul));
1944: sugar = MAX(sugar,psugar);
1945: if ( !mod && hmag && (gmag > hmag) ) {
1946: g = normalize_pbucket(mod,bucket);
1947: if ( !g ) {
1948: if ( d ) {
1949: SG(d) = sugar;
1950: d->sig = sig;
1951: }
1952: *rp = d;
1953: return 1;
1954: }
1955: nd_removecont2(d,g);
1956: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1957: add_pbucket(mod,bucket,g);
1958: }
1959: } else if ( index == -1 ) {
1960: // singular top reducible
1961: return -1;
1962: } else if ( !full ) {
1963: g = normalize_pbucket(mod,bucket);
1964: if ( g ) {
1965: SG(g) = sugar;
1966: g->sig = sig;
1967: }
1968: *rp = g;
1969: return 1;
1970: } else {
1971: m = BDY(g);
1972: if ( NEXT(m) ) {
1973: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1974: } else {
1975: FREEND(g); g = 0;
1976: }
1977: bucket->body[hindex] = g;
1978: NEXT(m) = 0;
1979: if ( d ) {
1980: NEXT(tail)=m; tail=m; LEN(d)++;
1981: } else {
1982: MKND(n,m,1,d); tail = BDY(d);
1983: }
1984: }
1985: }
1986: }
1987:
1.1 noro 1988: /* input : list of NDV, cand : list of NDV */
1989:
1990: int ndv_check_membership(int m,NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1991: {
1992: int n,i,stat;
1993: ND nf,d;
1994: NDV r;
1995: NODE t,s;
1996: union oNDC dn;
1997: Z q;
1998: LIST list;
1999:
1.24 noro 2000: ndv_setup(m,0,cand,nd_gentrace?1:0,1,0);
1.1 noro 2001: n = length(cand);
2002:
2003: if ( nd_gentrace ) { nd_alltracelist = 0; nd_tracelist = 0; }
2004: /* membercheck : list is a subset of Id(cand) ? */
2005: for ( t = input, i = 0; t; t = NEXT(t), i++ ) {
2006: again:
2007: nd_tracelist = 0;
2008: if ( nd_bpe > obpe )
2009: r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
2010: else
2011: r = (NDV)BDY(t);
2012: #if 0
2013: // moved to nd_f4_lf_trace()
2014: if ( m == -2 ) ndv_mod(m,r);
2015: #endif
2016: d = ndvtond(m,r);
1.6 noro 2017: stat = nd_nf(m,0,d,nd_ps,0,&nf);
1.1 noro 2018: if ( !stat ) {
2019: nd_reconstruct(0,0);
2020: goto again;
2021: } else if ( nf ) return 0;
2022: if ( nd_gentrace ) {
2023: nd_tracelist = reverse_node(nd_tracelist);
2024: MKLIST(list,nd_tracelist);
1.6 noro 2025: STOZ(i,q); s = mknode(2,q,list); MKLIST(list,s);
1.1 noro 2026: MKNODE(s,list,nd_alltracelist);
2027: nd_alltracelist = s; nd_tracelist = 0;
2028: }
2029: if ( DP_Print ) { printf("."); fflush(stdout); }
2030: }
2031: if ( DP_Print ) { printf("\n"); }
2032: return 1;
2033: }
2034:
2035: ND nd_remove_head(ND p)
2036: {
2037: NM m;
2038:
2039: m = BDY(p);
2040: if ( !NEXT(m) ) {
2041: FREEND(p); p = 0;
2042: } else {
2043: BDY(p) = NEXT(m); LEN(p)--;
2044: }
2045: FREENM(m);
2046: return p;
2047: }
2048:
2049: ND nd_separate_head(ND p,ND *head)
2050: {
2051: NM m,m0;
2052: ND r;
2053:
2054: m = BDY(p);
2055: if ( !NEXT(m) ) {
2056: *head = p; p = 0;
2057: } else {
2058: m0 = m;
2059: BDY(p) = NEXT(m); LEN(p)--;
2060: NEXT(m0) = 0;
2061: MKND(NV(p),m0,1,r);
2062: *head = r;
2063: }
2064: return p;
2065: }
2066:
2067: PGeoBucket create_pbucket()
2068: {
2069: PGeoBucket g;
2070:
2071: g = CALLOC(1,sizeof(struct oPGeoBucket));
2072: g->m = -1;
2073: return g;
2074: }
2075:
2076: void free_pbucket(PGeoBucket b) {
2077: int i;
2078:
2079: for ( i = 0; i <= b->m; i++ )
2080: if ( b->body[i] ) {
2081: nd_free(b->body[i]);
2082: b->body[i] = 0;
2083: }
2084: GCFREE(b);
2085: }
2086:
1.39 noro 2087: #if 0
1.1 noro 2088: void add_pbucket_symbolic(PGeoBucket g,ND d)
2089: {
2090: int l,i,k,m;
2091:
2092: if ( !d )
2093: return;
2094: l = LEN(d);
2095: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2096: /* 2^(k-1) < l <= 2^k (=m) */
2097: d = nd_merge(g->body[k],d);
2098: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2099: g->body[k] = 0;
2100: d = nd_merge(g->body[k+1],d);
2101: }
2102: g->body[k] = d;
2103: g->m = MAX(g->m,k);
2104: }
1.39 noro 2105: #else
2106: void add_pbucket_symbolic(PGeoBucket g,ND d)
2107: {
2108: int l,i,k,m,m0;
2109:
2110: if ( !d )
2111: return;
2112: m0 = g->m;
2113: while ( 1 ) {
2114: l = LEN(d);
2115: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2116: /* 2^(k-1) < l <= 2^k (=m) */
2117: if ( g->body[k] == 0 ) {
2118: g->body[k] = d;
2119: m0 = MAX(k,m0);
2120: break;
2121: } else {
2122: d = nd_merge(g->body[k],d);
2123: g->body[k] = 0;
2124: }
2125: }
2126: g->m = m0;
2127: }
2128: #endif
1.1 noro 2129:
1.39 noro 2130: #if 0
1.1 noro 2131: void add_pbucket(int mod,PGeoBucket g,ND d)
2132: {
2133: int l,i,k,m;
2134:
2135: if ( !d )
2136: return;
2137: l = LEN(d);
2138: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2139: /* 2^(k-1) < l <= 2^k (=m) */
2140: d = nd_add(mod,g->body[k],d);
2141: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2142: g->body[k] = 0;
2143: d = nd_add(mod,g->body[k+1],d);
2144: }
2145: g->body[k] = d;
2146: g->m = MAX(g->m,k);
2147: }
1.39 noro 2148: #else
2149: void add_pbucket(int mod,PGeoBucket g,ND d)
2150: {
2151: int l,i,k,m,m0;
2152:
2153: m0 = g->m;
2154: while ( d != 0 ) {
2155: l = LEN(d);
2156: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2157: /* 2^(k-1) < l <= 2^k (=m) */
2158: if ( g->body[k] == 0 ) {
2159: g->body[k] = d;
2160: m0 = MAX(k,m0);
2161: break;
2162: } else {
2163: d = nd_add(mod,g->body[k],d);
2164: g->body[k] = 0;
2165: }
2166: }
2167: g->m = m0;
2168: }
2169: #endif
1.1 noro 2170:
2171: void mulq_pbucket(PGeoBucket g,Z c)
2172: {
2173: int k;
2174:
2175: for ( k = 0; k <= g->m; k++ )
2176: nd_mul_c_q(g->body[k],(P)c);
2177: }
2178:
2179: NM remove_head_pbucket_symbolic(PGeoBucket g)
2180: {
2181: int j,i,k,c;
2182: NM head;
2183:
2184: k = g->m;
2185: j = -1;
2186: for ( i = 0; i <= k; i++ ) {
2187: if ( !g->body[i] ) continue;
2188: if ( j < 0 ) j = i;
2189: else {
2190: c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
2191: if ( c > 0 )
2192: j = i;
2193: else if ( c == 0 )
2194: g->body[i] = nd_remove_head(g->body[i]);
2195: }
2196: }
2197: if ( j < 0 ) return 0;
2198: else {
2199: head = BDY(g->body[j]);
2200: if ( !NEXT(head) ) {
2201: FREEND(g->body[j]);
2202: g->body[j] = 0;
2203: } else {
2204: BDY(g->body[j]) = NEXT(head);
2205: LEN(g->body[j])--;
2206: }
2207: return head;
2208: }
2209: }
2210:
2211: int head_pbucket(int mod,PGeoBucket g)
2212: {
2213: int j,i,c,k,nv,sum;
2214: UINT *di,*dj;
2215: ND gi,gj;
2216:
2217: k = g->m;
2218: while ( 1 ) {
2219: j = -1;
2220: for ( i = 0; i <= k; i++ ) {
2221: if ( !(gi = g->body[i]) )
2222: continue;
2223: if ( j < 0 ) {
2224: j = i;
2225: gj = g->body[j];
2226: dj = HDL(gj);
2227: sum = HCM(gj);
2228: } else {
2229: c = DL_COMPARE(HDL(gi),dj);
2230: if ( c > 0 ) {
2231: if ( sum ) HCM(gj) = sum;
2232: else g->body[j] = nd_remove_head(gj);
2233: j = i;
2234: gj = g->body[j];
2235: dj = HDL(gj);
2236: sum = HCM(gj);
2237: } else if ( c == 0 ) {
2238: if ( mod == -1 )
2239: sum = _addsf(sum,HCM(gi));
2240: else {
2241: sum = sum+HCM(gi)-mod;
2242: if ( sum < 0 ) sum += mod;
2243: }
2244: g->body[i] = nd_remove_head(gi);
2245: }
2246: }
2247: }
2248: if ( j < 0 ) return -1;
2249: else if ( sum ) {
2250: HCM(gj) = sum;
2251: return j;
2252: } else
2253: g->body[j] = nd_remove_head(gj);
2254: }
2255: }
2256:
2257: int head_pbucket_q(PGeoBucket g)
2258: {
2259: int j,i,c,k,nv;
2260: Z sum,t;
2261: ND gi,gj;
2262:
2263: k = g->m;
2264: while ( 1 ) {
2265: j = -1;
2266: for ( i = 0; i <= k; i++ ) {
2267: if ( !(gi = g->body[i]) ) continue;
2268: if ( j < 0 ) {
2269: j = i;
2270: gj = g->body[j];
1.6 noro 2271: sum = HCZ(gj);
1.1 noro 2272: } else {
2273: nv = NV(gi);
2274: c = DL_COMPARE(HDL(gi),HDL(gj));
2275: if ( c > 0 ) {
1.6 noro 2276: if ( sum ) HCZ(gj) = sum;
1.1 noro 2277: else g->body[j] = nd_remove_head(gj);
2278: j = i;
2279: gj = g->body[j];
1.6 noro 2280: sum = HCZ(gj);
1.1 noro 2281: } else if ( c == 0 ) {
1.6 noro 2282: addz(sum,HCZ(gi),&t);
1.1 noro 2283: sum = t;
2284: g->body[i] = nd_remove_head(gi);
2285: }
2286: }
2287: }
2288: if ( j < 0 ) return -1;
2289: else if ( sum ) {
1.6 noro 2290: HCZ(gj) = sum;
1.1 noro 2291: return j;
2292: } else
2293: g->body[j] = nd_remove_head(gj);
2294: }
2295: }
2296:
2297: int head_pbucket_lf(PGeoBucket g)
2298: {
2299: int j,i,c,k,nv;
2300: Z sum,t;
2301: ND gi,gj;
2302:
2303: k = g->m;
2304: while ( 1 ) {
2305: j = -1;
2306: for ( i = 0; i <= k; i++ ) {
2307: if ( !(gi = g->body[i]) ) continue;
2308: if ( j < 0 ) {
2309: j = i;
2310: gj = g->body[j];
2311: sum = HCZ(gj);
2312: } else {
2313: nv = NV(gi);
2314: c = DL_COMPARE(HDL(gi),HDL(gj));
2315: if ( c > 0 ) {
2316: if ( sum ) HCZ(gj) = sum;
2317: else g->body[j] = nd_remove_head(gj);
2318: j = i;
2319: gj = g->body[j];
2320: sum = HCZ(gj);
2321: } else if ( c == 0 ) {
2322: addlf(sum,HCZ(gi),&t);
2323: sum = t;
2324: g->body[i] = nd_remove_head(gi);
2325: }
2326: }
2327: }
2328: if ( j < 0 ) return -1;
2329: else if ( sum ) {
2330: HCZ(gj) = sum;
2331: return j;
2332: } else
2333: g->body[j] = nd_remove_head(gj);
2334: }
2335: }
2336:
2337: ND normalize_pbucket(int mod,PGeoBucket g)
2338: {
2339: int i;
2340: ND r,t;
2341:
2342: r = 0;
2343: for ( i = 0; i <= g->m; i++ ) {
2344: r = nd_add(mod,r,g->body[i]);
2345: g->body[i] = 0;
2346: }
2347: g->m = -1;
2348: return r;
2349: }
2350:
2351: #if 0
2352: void register_hcf(NDV p)
2353: {
2354: DCP dc,t;
2355: P hc,h;
2356: int c;
2357: NODE l,l1,prev;
2358:
2359: hc = p->body->c.p;
2360: if ( !nd_vc || NUM(hc) ) return;
2361: fctrp(nd_vc,hc,&dc);
2362: for ( t = dc; t; t = NEXT(t) ) {
2363: h = t->c;
2364: if ( NUM(h) ) continue;
2365: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2366: c = compp(nd_vc,h,(P)BDY(l));
2367: if ( c >= 0 ) break;
2368: }
2369: if ( !l || c > 0 ) {
2370: MKNODE(l1,h,l);
2371: if ( !prev )
2372: nd_hcf = l1;
2373: else
2374: NEXT(prev) = l1;
2375: }
2376: }
2377: }
2378: #else
2379: void register_hcf(NDV p)
2380: {
2381: DCP dc,t;
2382: P hc,h,q;
2383: Q dmy;
2384: int c;
2385: NODE l,l1,prev;
2386:
2387: hc = p->body->c.p;
2388: if ( NUM(hc) ) return;
2389: ptozp(hc,1,&dmy,&h);
2390: #if 1
2391: for ( l = nd_hcf; l; l = NEXT(l) ) {
2392: while ( 1 ) {
2393: if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
2394: else break;
2395: }
2396: }
2397: if ( NUM(h) ) return;
2398: #endif
2399: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2400: c = compp(nd_vc,h,(P)BDY(l));
2401: if ( c >= 0 ) break;
2402: }
2403: if ( !l || c > 0 ) {
2404: MKNODE(l1,h,l);
2405: if ( !prev )
2406: nd_hcf = l1;
2407: else
2408: NEXT(prev) = l1;
2409: }
2410: }
2411: #endif
2412:
2413: int do_diagonalize(int sugar,int m)
2414: {
1.6 noro 2415: int i,nh,stat;
2416: NODE r,g,t;
2417: ND h,nf,s,head;
2418: NDV nfv;
2419: Q q;
2420: P nm,nmp,dn,mnp,dnp,cont,cont1;
2421: union oNDC hc;
2422: NODE node;
2423: LIST l;
2424: Z iq;
1.1 noro 2425:
1.6 noro 2426: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2427: if ( nd_gentrace ) {
2428: /* Trace = [1,index,1,1] */
2429: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2430: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2431: }
2432: if ( nd_demand )
2433: nfv = ndv_load(i);
2434: else
2435: nfv = nd_ps[i];
2436: s = ndvtond(m,nfv);
2437: s = nd_separate_head(s,&head);
2438: stat = nd_nf(m,head,s,nd_ps,1,&nf);
2439: if ( !stat ) return 0;
2440: ndv_free(nfv);
2441: hc = HCU(nf); nd_removecont(m,nf);
2442: /* exact division */
2443: cont = ndc_div(m,hc,HCU(nf));
1.1 noro 2444: if ( nd_gentrace ) finalize_tracelist(i,cont);
1.6 noro 2445: nfv = ndtondv(m,nf);
2446: nd_free(nf);
2447: nd_bound[i] = ndv_compute_bound(nfv);
2448: if ( !m ) register_hcf(nfv);
2449: if ( nd_demand ) {
2450: ndv_save(nfv,i);
2451: ndv_free(nfv);
2452: } else
2453: nd_ps[i] = nfv;
2454: }
2455: return 1;
1.1 noro 2456: }
2457:
2458: LIST compute_splist()
2459: {
2460: NODE g,tn0,tn,node;
2461: LIST l0;
2462: ND_pairs d,t;
2463: int i;
2464: Z i1,i2;
2465:
2466: g = 0; d = 0;
2467: for ( i = 0; i < nd_psn; i++ ) {
2468: d = update_pairs(d,g,i,0);
2469: g = update_base(g,i);
2470: }
2471: for ( t = d, tn0 = 0; t; t = NEXT(t) ) {
2472: NEXTNODE(tn0,tn);
1.6 noro 2473: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 2474: node = mknode(2,i1,i2); MKLIST(l0,node);
2475: BDY(tn) = l0;
2476: }
2477: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
2478: return l0;
2479: }
2480:
1.49 noro 2481: typedef struct oHPDATA {
1.56 noro 2482: int n;
2483: P hn; // HP(t)=hn(t)/((1-t^w0)*...*(1-t^w(n-1)))
1.49 noro 2484: VECT x; // BDY(x)[i] = <<0,...,1,...,0>>
1.56 noro 2485: int *w;
1.49 noro 2486: } *HPDATA;
2487:
2488: void make_reduced(VECT b,int nv);
2489: void mhp_rec(VECT b,VECT x,P t,P *r);
2490: P mhp_ctop(P *r,P *plist,int n);
2491: DL monomial_colon(DL a,DL b,int n);
1.56 noro 2492: LIST dp_monomial_hilbert_poincare(VECT b,VECT x);
2493: LIST dp_monomial_hilbert_poincare_weight(VECT b,VECT x,int *w);
1.49 noro 2494:
2495: void setup_hpdata(HPDATA final,HPDATA current)
2496: {
1.56 noro 2497: int n,i,wlen;
1.49 noro 2498: DL *p;
1.56 noro 2499: VECT b,x;
1.49 noro 2500: DL dl;
1.56 noro 2501: LIST weight;
2502: LIST ret;
2503: int *w;
2504: NODE nd;
2505:
2506: final->n = n = nd_nvar;
2507: final->hn = (P)BDY(nd_hpdata);
2508: if ( NEXT(nd_hpdata) != 0 && (weight=(LIST)BDY(NEXT(nd_hpdata))) != 0 ) {
2509: wlen = length(BDY(weight));
2510: if ( n != wlen )
2511: error("setup_hpdata : inconsistent weight length");
2512: w = (int *)MALLOC(n*sizeof(int));
2513: for ( i = 0, nd = BDY((LIST)weight); i < n; i++, nd = NEXT(nd) )
2514: w[i] = ZTOS((Z)BDY(nd));
2515: } else
2516: w = 0;
1.49 noro 2517: MKVECT(x,n);
2518: for ( i = 0; i < n; i++ ) {
2519: NEWDL(dl,n); dl->d[i] = 1; dl->td = 1; BDY(x)[i] = dl;
2520: }
2521: final->x = x;
1.56 noro 2522: final->w = w;
1.49 noro 2523:
2524: MKVECT(b,nd_psn); p = (DL *)BDY(b);
2525: for ( i = 0; i < nd_psn; i++ ) {
2526: p[i] = ndltodl(n,nd_psh[i]->dl);
2527: }
1.56 noro 2528: if ( w ) {
2529: ret = dp_monomial_hilbert_poincare_weight(b,x,w);
2530: } else
2531: ret = dp_monomial_hilbert_poincare(b,x);
2532: current->n = n;
2533: current->hn = (P)BDY(BDY(ret));
1.49 noro 2534: current->x = x;
1.56 noro 2535: current->w = w;
2536: }
2537:
2538: int comp_hn(P a, P b)
2539: {
2540: P s;
2541: DCP dc;
2542:
2543: subp(CO,a,b,&s);
1.57 ! noro 2544: if ( !s ) return -1;
1.56 noro 2545: else if ( OID(s) == 1 ) return 0;
2546: else {
2547: for ( dc = DC(s); NEXT(dc); dc = NEXT(dc) );
2548: return (int)ZTOS((Z)dc->d);
2549: }
1.49 noro 2550: }
2551:
1.56 noro 2552: void update_hpdata(HPDATA current,int nh)
1.49 noro 2553: {
2554: NODE data1,nd,t;
2555: DL new,dl;
2556: int len,i,n;
2557: Z dz;
2558: DL *p;
2559: VECT b,head;
2560: P tv,td,s,hn,hpoly;
2561: LIST list1;
2562:
2563: n = nd_nvar;
2564: new = ndltodl(n,nd_psh[nh]->dl);
2565: MKVECT(b,nh); p = (DL *)BDY(b);
2566: for ( i = 0; i < nh; i++ ) {
2567: p[i] = monomial_colon(ndltodl(n,nd_psh[i]->dl),new,n);
2568: }
2569: // compute HP(I:new)
1.56 noro 2570: if ( current->w )
2571: list1 = dp_monomial_hilbert_poincare_weight(b,current->x,current->w);
2572: else
2573: list1 = dp_monomial_hilbert_poincare(b,current->x);
1.49 noro 2574: data1 = BDY((LIST)list1);
2575: // HP(I+<new>) = H(I)-t^d*H(I:new), d=tdeg(new)
2576: makevar("t",&tv); UTOZ(new->td,dz);
2577: pwrp(CO,tv,dz,&td);
2578: mulp(CO,(P)ARG0(data1),td,&s);
2579: subp(CO,current->hn,s,&hn);
2580: current->hn = hn;
2581: }
2582:
2583: ND_pairs nd_remove_same_sugar( ND_pairs d, int sugar)
2584: {
2585: struct oND_pairs root;
2586: ND_pairs prev,cur;
2587:
2588: root.next = d;
2589: prev = &root; cur = d;
2590: while ( cur ) {
2591: if ( SG(cur) == sugar )
2592: prev->next = cur->next;
2593: else
2594: prev = cur;
2595: cur = cur->next;
2596: }
2597: return root.next;
2598: }
2599:
1.1 noro 2600: /* return value = 0 => input is not a GB */
2601:
2602: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2603: {
1.6 noro 2604: int i,nh,sugar,stat;
2605: NODE r,g,t;
2606: ND_pairs d;
2607: ND_pairs l;
2608: ND h,nf,s,head,nf1;
2609: NDV nfv;
2610: Z q;
2611: union oNDC dn,hc;
2612: int diag_count = 0;
1.41 noro 2613: int Nnfnz = 0,Nnfz = 0;
1.6 noro 2614: P cont;
2615: LIST list;
1.49 noro 2616: struct oHPDATA current_hpdata,final_hpdata;
2617: int final_hpvalue;
2618:
1.27 noro 2619: struct oEGT eg1,eg2,eg_update;
1.6 noro 2620:
1.27 noro 2621: init_eg(&eg_update);
1.11 noro 2622: Nnd_add = 0;
1.6 noro 2623: g = 0; d = 0;
2624: for ( i = 0; i < nd_psn; i++ ) {
2625: d = update_pairs(d,g,i,gensyz);
2626: g = update_base(g,i);
2627: }
2628: sugar = 0;
1.49 noro 2629: if ( nd_hpdata ) {
1.52 noro 2630: if ( DP_Print ) fprintf(asir_out,"Hilbert driven algorithm.\n");
1.49 noro 2631: setup_hpdata(&final_hpdata,¤t_hpdata);
2632: }
1.6 noro 2633: while ( d ) {
1.1 noro 2634: again:
1.6 noro 2635: l = nd_minp(d,&d);
2636: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2637: if ( SG(l) != sugar ) {
2638: if ( ishomo ) {
2639: diag_count = 0;
2640: stat = do_diagonalize(sugar,m);
1.1 noro 2641: if ( !stat ) {
1.6 noro 2642: NEXT(l) = d; d = l;
2643: d = nd_reconstruct(0,d);
2644: goto again;
1.1 noro 2645: }
1.6 noro 2646: }
2647: sugar = SG(l);
2648: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2649: }
2650: stat = nd_sp(m,0,l,&h);
2651: if ( !stat ) {
2652: NEXT(l) = d; d = l;
2653: d = nd_reconstruct(0,d);
2654: goto again;
2655: }
1.1 noro 2656: #if USE_GEOBUCKET
1.39 noro 2657: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf)
2658: :nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2659: #else
1.39 noro 2660: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2661: #endif
1.6 noro 2662: if ( !stat ) {
2663: NEXT(l) = d; d = l;
2664: d = nd_reconstruct(0,d);
2665: goto again;
2666: } else if ( nf ) {
1.41 noro 2667: Nnfnz++;
1.6 noro 2668: if ( checkonly || gensyz ) return 0;
1.1 noro 2669: if ( nd_newelim ) {
2670: if ( nd_module ) {
2671: if ( MPOS(HDL(nf)) > 1 ) return 0;
2672: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2673: }
1.6 noro 2674: if ( DP_Print ) { printf("+"); fflush(stdout); }
2675: hc = HCU(nf);
2676: nd_removecont(m,nf);
2677: if ( !m && nd_nalg ) {
2678: nd_monic(0,&nf);
2679: nd_removecont(m,nf);
2680: }
2681: if ( nd_gentrace ) {
2682: /* exact division */
1.1 noro 2683: cont = ndc_div(m,hc,HCU(nf));
2684: if ( m || !UNIQ(cont) ) {
1.6 noro 2685: t = mknode(4,NULLP,NULLP,NULLP,cont);
2686: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2687: nd_tracelist = t;
2688: }
2689: }
1.6 noro 2690: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2691: nh = ndv_newps(m,nfv,0);
1.6 noro 2692: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2693: diag_count = 0;
2694: stat = do_diagonalize(sugar,m);
2695: if ( !stat ) {
2696: NEXT(l) = d; d = l;
2697: d = nd_reconstruct(1,d);
2698: goto again;
1.1 noro 2699: }
1.6 noro 2700: }
1.27 noro 2701: get_eg(&eg1);
1.6 noro 2702: d = update_pairs(d,g,nh,0);
1.27 noro 2703: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2704: g = update_base(g,nh);
2705: FREENDP(l);
1.49 noro 2706: if ( nd_hpdata ) {
1.57 ! noro 2707: int dg,sugar0;
1.56 noro 2708:
2709: update_hpdata(¤t_hpdata,nh);
2710: dg = comp_hn(final_hpdata.hn,current_hpdata.hn);
1.57 ! noro 2711: if ( dg < 0 ) {
! 2712: fprintf(asir_out,"We found a gb\n");
! 2713: d = 0;
! 2714: }
1.56 noro 2715: if ( dg > sugar ) {
1.57 ! noro 2716: // printexpr(CO,(Obj)current_hpdata.hn);
! 2717: fprintf(asir_out,"\n");
1.56 noro 2718: }
1.57 ! noro 2719: sugar0 = sugar;
! 2720: while ( d && dg > sugar0 ) {
1.56 noro 2721: if ( DP_Print ) fprintf(asir_out,"sugar=%d done.\n",sugar);
1.49 noro 2722: d = nd_remove_same_sugar(d,sugar);
1.57 ! noro 2723: sugar0++;
1.49 noro 2724: }
2725: }
1.41 noro 2726: } else {
2727: Nnfz++;
2728: if ( nd_gentrace && gensyz ) {
2729: nd_tracelist = reverse_node(nd_tracelist);
2730: MKLIST(list,nd_tracelist);
2731: STOZ(-1,q); t = mknode(2,q,list); MKLIST(list,t);
2732: MKNODE(t,list,nd_alltracelist);
2733: nd_alltracelist = t; nd_tracelist = 0;
2734: }
1.57 ! noro 2735: if ( DP_Print ) { fprintf(asir_out,"."); fflush(asir_out); }
1.41 noro 2736: FREENDP(l);
2737: }
1.36 noro 2738: }
2739: conv_ilist(nd_demand,0,g,indp);
1.41 noro 2740: if ( !checkonly && DP_Print ) {
1.57 ! noro 2741: fprintf(asir_out,"\nnd_gb done. Nnd_add=%d,Npairs=%d, Nnfnz=%d,Nnfz=%d,",Nnd_add,Npairs,Nnfnz,Nnfz);
! 2742: fprintf(asir_out,"Nremoved=%d\n",NcriB+NcriMF+Ncri2);
1.41 noro 2743: fflush(asir_out);
2744: }
2745: if ( DP_Print ) {
2746: print_eg("update",&eg_update); fprintf(asir_out,"\n");
2747: }
1.36 noro 2748: return g;
1.1 noro 2749: }
2750:
1.30 noro 2751: ND_pairs update_pairs_s(ND_pairs d,int t,NODE *syz);
1.47 noro 2752: int update_pairs_array_s(ND_pairs *d,int t,NODE *syz);
1.30 noro 2753: ND_pairs nd_newpairs_s(int t ,NODE *syz);
1.47 noro 2754: ND_pairs *nd_newpairs_array_s(int t ,NODE *syz);
1.24 noro 2755:
2756: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *nf);
2757: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *nf);
2758:
2759: void _copydl(int n,DL d1,DL d2);
2760: void _subfromdl(int n,DL d1,DL d2);
2761: extern int (*cmpdl)(int n,DL d1,DL d2);
1.53 noro 2762: int _dl_redble_ext(DL,DL,DL,int);
2763:
2764: int primitive_irred(ND p,SIG sig)
2765: {
2766: static int wpd=0,dlen=0;
2767: static DL dquo,squo;
2768: static UINT *quo;
2769: int i;
2770:
2771: if ( dlen < nd_nvar ) {
2772: NEWDL(dquo,nd_nvar);
2773: NEWDL(squo,nd_nvar);
2774: dlen = nd_nvar;
2775: }
2776: if ( wpd != nd_wpd ) {
2777: wpd = nd_wpd;
2778: quo = (UINT *)MALLOC(wpd*sizeof(UINT));
2779: }
2780: for ( i = 0; i < nd_psn; i++ ) {
2781: if ( sig->pos == nd_psh[i]->sig->pos &&
2782: _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),squo,nd_nvar) )
2783: if ( ndl_reducible(HDL(p),DL(nd_psh[i])) ) {
2784: if ( DP_Print ) fprintf(asir_out,"D");
2785: ndl_sub(HDL(p),DL(nd_psh[i]),quo);
2786: _ndltodl(quo,dquo);
2787: if ( _eqdl(nd_nvar,squo,dquo) )
2788: return 0;
2789: }
2790: }
2791: return 1;
2792: }
1.24 noro 2793:
2794: NODE insert_sig(NODE l,SIG s)
2795: {
2796: int pos;
2797: DL sig;
2798: struct oNODE root;
2799: NODE p,prev,r;
2800: SIG t;
2801:
2802: pos = s->pos; sig = DL(s);
2803: root.next = l; prev = &root;
2804: for ( p = l; p; p = p->next ) {
2805: t = (SIG)p->body;
2806: if ( t->pos == pos ) {
2807: if ( _dl_redble(DL(t),sig,nd_nvar) )
2808: return root.next;
2809: else if ( _dl_redble(sig,DL(t),nd_nvar) )
2810: // remove p
2811: prev->next = p->next;
1.45 noro 2812: else
2813: prev = p;
1.24 noro 2814: } else
2815: prev = p;
2816: }
1.27 noro 2817: NEWNODE(r); r->body = (pointer)s; r->next = 0;
2818: for ( p = &root; p->next; p = p->next );
2819: p->next = r;
2820: // r->next = root.next;
2821: // return r;
2822: return root.next;
1.24 noro 2823: }
2824:
2825: ND_pairs remove_spair_s(ND_pairs d,SIG sig)
2826: {
2827: struct oND_pairs root;
2828: ND_pairs prev,p;
2829: SIG spsig;
2830:
2831: root.next = d;
2832: prev = &root; p = d;
2833: while ( p ) {
2834: spsig = p->sig;
1.26 noro 2835: if ( sig->pos == spsig->pos && _dl_redble(DL(sig),DL(spsig),nd_nvar) ) {
1.24 noro 2836: // remove p
2837: prev->next = p->next;
1.26 noro 2838: Nsyz++;
2839: } else
1.24 noro 2840: prev = p;
2841: p = p->next;
2842: }
2843: return (ND_pairs)root.next;
2844: }
2845:
1.28 noro 2846: int small_lcm(ND_pairs l)
2847: {
2848: SIG sig;
2849: int i;
1.29 noro 2850: NODE t;
1.28 noro 2851: static DL lcm,mul,quo;
1.44 noro 2852: static int nvar = 0;
1.28 noro 2853:
1.38 noro 2854: if ( nd_sba_largelcm ) return 0;
1.28 noro 2855: if ( nvar < nd_nvar ) {
2856: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(quo,nvar); NEWDL(mul,nvar);
2857: }
2858: sig = l->sig;
2859: _ndltodl(l->lcm,lcm);
1.29 noro 2860: #if 0
1.28 noro 2861: for ( i = 0; i < nd_psn; i++ ) {
2862: if ( sig->pos == nd_psh[i]->sig->pos &&
1.29 noro 2863: _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
1.28 noro 2864: _ndltodl(DL(nd_psh[i]),mul);
2865: _addtodl(nd_nvar,quo,mul);
2866: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2867: break;
2868: }
2869: }
2870: if ( i < nd_psn ) return 1;
2871: else return 0;
1.29 noro 2872: #else
2873: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2874: i = (long)BDY(t);
2875: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2876: _ndltodl(DL(nd_psh[i]),mul);
2877: _addtodl(nd_nvar,quo,mul);
2878: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2879: break;
2880: }
2881: }
2882: if ( t ) return 1;
2883: else return 0;
2884: #endif
1.28 noro 2885: }
2886:
1.41 noro 2887: ND_pairs find_smallest_lcm(ND_pairs l)
2888: {
2889: SIG sig;
2890: int i,minindex;
2891: NODE t;
2892: ND_pairs r;
2893: struct oSIG sig1;
1.55 noro 2894: static DL mul,quo,quo2,minlm;
1.44 noro 2895: static int nvar = 0;
1.41 noro 2896:
2897: if ( nvar < nd_nvar ) {
2898: nvar = nd_nvar;
1.55 noro 2899: NEWDL(quo,nvar); NEWDL(quo2,nvar); NEWDL(mul,nvar);
1.41 noro 2900: NEWDL(minlm,nvar);
2901: }
2902: sig = l->sig;
2903: // find mg s.t. m*s(g)=sig and m*lm(g) is minimal
2904: _ndltodl(l->lcm,minlm); minindex = -1;
2905: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2906: i = (long)BDY(t);
2907: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2908: _ndltodl(DL(nd_psh[i]),mul);
2909: _addtodl(nd_nvar,quo,mul);
2910: if ( (*cmpdl)(nd_nvar,minlm,mul) > 0 ) {
2911: minindex = i;
1.47 noro 2912: break;
1.41 noro 2913: _copydl(nd_nvar,mul,minlm);
2914: }
2915: }
2916: }
2917: // l->lcm is minimal; return l itself
2918: if ( minindex < 0 ) return l;
1.47 noro 2919: else return 0;
1.41 noro 2920: for ( i = 0; i < nd_psn; i++ ) {
2921: if ( i == minindex ) continue;
2922: _ndltodl(DL(nd_psh[i]),mul);
2923: if ( _dl_redble_ext(mul,minlm,quo,nd_nvar) ) {
2924: _addtodl(nd_nvar,nd_ps[i]->sig->dl,quo);
2925: sig1.pos = nd_ps[i]->sig->pos;
2926: sig1.dl = quo;
1.55 noro 2927: sig1.dl2 = quo2;
2928: _adddl(nd_nvar,sig1.dl,nd_sba_hm[sig1.pos],sig1.dl2);
1.41 noro 2929: if ( comp_sig(sig,&sig1) > 0 ) {
2930: // printf("X");
2931: NEWND_pairs(r);
2932: r->sig = sig;
2933: r->i1 = minindex;
2934: r->i2 = i;
2935: dltondl(nd_nvar,minlm,r->lcm);
2936: r->next = 0;
2937: return r;
2938: }
2939: }
2940: }
2941: // there is no suitable spair
2942: return 0;
2943: }
2944:
1.28 noro 2945: ND_pairs remove_large_lcm(ND_pairs d)
2946: {
2947: struct oND_pairs root;
2948: ND_pairs prev,p;
2949:
2950: root.next = d;
2951: prev = &root; p = d;
2952: while ( p ) {
1.41 noro 2953: #if 0
1.28 noro 2954: if ( small_lcm(p) ) {
2955: // remove p
2956: prev->next = p->next;
2957: } else
1.41 noro 2958: #else
2959: if ( find_smallest_lcm(p) == 0 ) {
2960: // remove p
2961: prev->next = p->next;
2962: } else
2963: #endif
1.28 noro 2964: prev = p;
2965: p = p->next;
2966: }
2967: return (ND_pairs)root.next;
2968: }
2969:
1.26 noro 2970: struct oEGT eg_create,eg_newpairs,eg_merge;
2971:
1.30 noro 2972: NODE conv_ilist_s(int demand,int trace,int **indp);
2973:
1.44 noro 2974: // S(fj*ei-fi*ej)
2975:
1.45 noro 2976: void _subdl(int,DL,DL,DL);
2977:
1.44 noro 2978: SIG trivial_sig(int i,int j)
2979: {
1.45 noro 2980: static DL lcm;
1.44 noro 2981: static struct oSIG sigi,sigj;
2982: static int nvar = 0;
2983: SIG sig;
2984:
2985: if ( nvar != nd_nvar ) {
1.45 noro 2986: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(sigi.dl,nvar); NEWDL(sigj.dl,nvar);
1.55 noro 2987: NEWDL(sigi.dl2,nvar); NEWDL(sigj.dl2,nvar);
1.45 noro 2988: }
1.46 noro 2989: if ( nd_sba_inputisgb != 0 ) {
1.45 noro 2990: lcm_of_DL(nd_nvar,nd_sba_hm[i],nd_sba_hm[j],lcm);
2991: sigi.pos = i; _subdl(nd_nvar,lcm,nd_sba_hm[i],sigi.dl);
1.55 noro 2992: _copydl(nd_nvar,lcm,sigi.dl2);
1.45 noro 2993: sigj.pos = j; _subdl(nd_nvar,lcm,nd_sba_hm[j],sigj.dl);
1.55 noro 2994: _copydl(nd_nvar,lcm,sigj.dl2);
1.45 noro 2995: if ( comp_sig(&sigi,&sigj) > 0 ) sig = dup_sig(&sigi);
2996: else sig = dup_sig(&sigj);
2997: } else {
2998: sigi.pos = i; _copydl(nd_nvar,nd_sba_hm[j],sigi.dl);
1.55 noro 2999: _adddl(nd_nvar,sigi.dl,nd_sba_hm[i],sigi.dl2);
1.45 noro 3000: sigj.pos = j; _copydl(nd_nvar,nd_sba_hm[i],sigj.dl);
1.55 noro 3001: _adddl(nd_nvar,sigj.dl,nd_sba_hm[j],sigj.dl2);
1.45 noro 3002: if ( comp_sig(&sigi,&sigj) > 0 ) sig = dup_sig(&sigi);
3003: else sig = dup_sig(&sigj);
1.44 noro 3004: }
3005: return sig;
3006: }
3007:
1.47 noro 3008: int nd_minsig(ND_pairs *d)
3009: {
3010: int min,i,ret;
3011:
3012: min = -1;
3013: for ( i = 0; i < nd_nbase; i++ ) {
3014: if ( d[i] != 0 ) {
3015: if ( min < 0 ) min = i;
3016: else {
3017: ret = comp_sig(d[i]->sig,d[min]->sig);
3018: if ( ret < 0 ) min = i;
3019: }
3020: }
3021: }
3022: return min;
3023: }
3024:
3025: int dlength(ND_pairs d)
3026: {
3027: int i;
3028: for ( i = 0; d; d = d->next, i++ );
3029: return i;
3030: }
3031:
1.44 noro 3032: NODE nd_sba_buch(int m,int ishomo,int **indp,NODE *syzp)
1.24 noro 3033: {
1.39 noro 3034: int i,j,nh,sugar,stat,pos;
1.30 noro 3035: NODE r,t,g;
1.47 noro 3036: ND_pairs *d;
1.41 noro 3037: ND_pairs l,l1;
1.24 noro 3038: ND h,nf,s,head,nf1;
3039: NDV nfv;
3040: Z q;
3041: union oNDC dn,hc;
3042: P cont;
3043: LIST list;
3044: SIG sig;
1.29 noro 3045: NODE *syzlist;
1.47 noro 3046: int ngen,ind;
1.41 noro 3047: int Nnominimal,Nredundant;
1.28 noro 3048: DL lcm,quo,mul;
1.49 noro 3049: struct oHPDATA final_hpdata,current_hpdata;
1.50 noro 3050: struct oEGT eg1,eg2,eg3,eg4,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
3051: struct oEGT eg_minsig,eg_smallest,eg_removecont,eg_hpdata,eg_updatepairs,eg_sbabuch,eg_sp;
1.47 noro 3052: int Nnfs=0,Nnfz=0,Nnfnz=0,dlen,nsyz;
1.24 noro 3053:
1.27 noro 3054: init_eg(&eg_remove);
1.29 noro 3055: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.47 noro 3056: d = (ND_pairs *)MALLOC(nd_psn*sizeof(ND_pairs));
3057: nd_nbase = nd_psn;
1.26 noro 3058: Nsyz = 0;
1.24 noro 3059: Nnd_add = 0;
1.41 noro 3060: Nnominimal = 0;
1.26 noro 3061: Nredundant = 0;
1.44 noro 3062: ngen = nd_psn;
1.56 noro 3063: if ( !do_weyl || nd_sba_inputisgb ) {
1.48 noro 3064: for ( i = 0; i < nd_psn; i++ )
3065: for ( j = i+1; j < nd_psn; j++ ) {
3066: sig = trivial_sig(i,j);
3067: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
3068: }
1.29 noro 3069: }
1.47 noro 3070: dlen = 0;
1.41 noro 3071: for ( i = 0; i < nd_psn; i++ ) {
1.47 noro 3072: dlen += update_pairs_array_s(d,i,syzlist);
1.41 noro 3073: }
1.24 noro 3074: sugar = 0;
1.39 noro 3075: pos = 0;
1.49 noro 3076: if ( nd_hpdata ) {
3077: setup_hpdata(&final_hpdata,¤t_hpdata);
3078: }
1.26 noro 3079: NEWDL(lcm,nd_nvar); NEWDL(quo,nd_nvar); NEWDL(mul,nd_nvar);
1.50 noro 3080: init_eg(&eg_sp);
1.26 noro 3081: init_eg(&eg_create);
3082: init_eg(&eg_merge);
1.47 noro 3083: init_eg(&eg_minsig);
3084: init_eg(&eg_smallest);
1.29 noro 3085: init_eg(&eg_large);
1.31 noro 3086: init_eg(&eg_nf);
3087: init_eg(&eg_nfzero);
1.50 noro 3088: init_eg(&eg_removecont);
3089: init_eg(&eg_updatepairs);
3090: init_eg(&eg_hpdata);
3091: init_eg(&eg_sbabuch);
3092: get_eg(&eg3);
1.47 noro 3093: while ( 1 ) {
1.53 noro 3094: if ( DP_Print && !nd_hpdata && dlen%1000 == 0 ) fprintf(asir_out,"(%d)",dlen);
1.47 noro 3095: again :
3096: get_eg(&eg1);
3097: ind = nd_minsig(d);
3098: get_eg(&eg2); add_eg(&eg_minsig,&eg1,&eg2);
3099: if ( ind < 0 ) break;
3100: l = d[ind];
3101: // printf("(%d,%d)",l->i1,l->i2); print_sig(l->sig); printf("\n");
3102: get_eg(&eg1);
1.41 noro 3103: l1 = find_smallest_lcm(l);
1.47 noro 3104: get_eg(&eg2); add_eg(&eg_smallest,&eg1,&eg2);
1.41 noro 3105: if ( l1 == 0 ) {
1.47 noro 3106: d[ind] = d[ind]->next; dlen--;
1.53 noro 3107: // if ( DP_Print && !nd_hpdata ) fprintf(asir_out,"M");
1.41 noro 3108: Nnominimal++;
3109: continue;
3110: }
3111: if ( SG(l1) != sugar ) {
3112: sugar = SG(l1);
3113: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
3114: }
3115: sig = l1->sig;
3116: if ( DP_Print && nd_sba_pot ) {
3117: if ( sig->pos != pos ) {
3118: fprintf(asir_out,"[%d]",sig->pos);
3119: pos = sig->pos;
3120: }
3121: }
1.50 noro 3122: get_eg(&eg1);
1.41 noro 3123: stat = nd_sp(m,0,l1,&h);
1.50 noro 3124: get_eg(&eg2); add_eg(&eg_sp,&eg1,&eg2);
1.24 noro 3125: if ( !stat ) {
1.47 noro 3126: nd_reconstruct_s(0,d);
1.24 noro 3127: goto again;
3128: }
1.31 noro 3129: get_eg(&eg1);
1.25 noro 3130: #if USE_GEOBUCKET
1.55 noro 3131: stat = (m&&!nd_gentrace)?nd_nf_pbucket_s(m,h,nd_ps,!nd_top&&!Top,&nf):nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.24 noro 3132: #else
1.39 noro 3133: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.24 noro 3134: #endif
1.31 noro 3135: get_eg(&eg2);
1.24 noro 3136: if ( !stat ) {
1.47 noro 3137: nd_reconstruct_s(0,d);
1.24 noro 3138: goto again;
3139: } else if ( stat == -1 ) {
1.47 noro 3140: d[ind] = d[ind]->next; dlen--;
1.41 noro 3141: Nnfs++;
1.24 noro 3142: if ( DP_Print ) { printf("S"); fflush(stdout); }
3143: } else if ( nf ) {
1.47 noro 3144: d[ind] = d[ind]->next; dlen--;
1.41 noro 3145: Nnfnz++;
3146: if ( DP_Print ) {
3147: if ( nd_sba_redundant_check ) {
3148: if ( ndl_find_reducer_nonsig(HDL(nf)) >= 0 ) {
3149: Nredundant++;
3150: printf("R");
3151: } else
3152: printf("+");
3153: } else
3154: printf("+");
3155: fflush(stdout);
3156: }
1.31 noro 3157: add_eg(&eg_nf,&eg1,&eg2);
1.24 noro 3158: hc = HCU(nf);
1.55 noro 3159: get_eg(&eg1);
3160: nd_removecont(m,nf);
3161: get_eg(&eg2); add_eg(&eg_removecont,&eg1,&eg2);
3162: nfv = ndtondv(m,nf); nd_free(nf);
3163: nh = ndv_newps(m,nfv,0);
3164:
3165: get_eg(&eg1);
3166: dlen += update_pairs_array_s(d,nh,syzlist);
3167: get_eg(&eg2); add_eg(&eg_updatepairs,&eg1,&eg2);
3168: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
3169: if ( nd_hpdata ) {
3170: get_eg(&eg1);
1.56 noro 3171: update_hpdata(¤t_hpdata,nh);
1.55 noro 3172: get_eg(&eg2); add_eg(&eg_hpdata,&eg1,&eg2);
3173: if ( !compp(CO,final_hpdata.hn,current_hpdata.hn) ) {
3174: if ( DP_Print ) { printf("\nWe found a gb.\n"); }
3175: break;
3176: }
1.49 noro 3177: }
1.24 noro 3178: } else {
1.47 noro 3179: d[ind] = d[ind]->next; dlen--;
1.41 noro 3180: Nnfz++;
1.31 noro 3181: add_eg(&eg_nfzero,&eg1,&eg2);
1.24 noro 3182: // syzygy
1.27 noro 3183: get_eg(&eg1);
1.47 noro 3184: nsyz = Nsyz;
3185: d[sig->pos] = remove_spair_s(d[sig->pos],sig);
3186: dlen -= Nsyz-nsyz;
1.27 noro 3187: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 3188: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.24 noro 3189: if ( DP_Print ) { printf("."); fflush(stdout); }
3190: }
3191: }
1.50 noro 3192: get_eg(&eg4); add_eg(&eg_sbabuch,&eg3,&eg4);
1.30 noro 3193: g = conv_ilist_s(nd_demand,0,indp);
1.26 noro 3194: if ( DP_Print ) {
1.47 noro 3195: printf("\ndlen=%d,nd_sba done. nd_add=%d,Nsyz=%d,Nsamesig=%d,Nnominimal=%d\n",dlen,Nnd_add,Nsyz,Nsamesig,Nnominimal);
1.41 noro 3196: printf("Nnfnz=%d,Nnfz=%d,Nnfsingular=%d\n",Nnfnz,Nnfz,Nnfs);
1.50 noro 3197: fflush(stdout);
1.41 noro 3198: if ( nd_sba_redundant_check )
3199: printf("Nredundant=%d\n",Nredundant);
1.50 noro 3200: fflush(stdout);
3201: print_eg("sp",&eg_sp);
1.26 noro 3202: print_eg("create",&eg_create);
3203: print_eg("merge",&eg_merge);
1.47 noro 3204: print_eg("minsig",&eg_minsig);
3205: print_eg("smallest",&eg_smallest);
3206: print_eg("remove",&eg_remove);
1.50 noro 3207: printf("\n");
1.47 noro 3208: print_eg("nf",&eg_nf);
3209: print_eg("nfzero",&eg_nfzero);
1.50 noro 3210: print_eg("removecont",&eg_removecont);
3211: print_eg("updatepairs",&eg_updatepairs);
3212: print_eg("hpdata",&eg_hpdata);
3213: print_eg("total",&eg_sbabuch);
1.47 noro 3214: printf("\n");
3215: }
3216: if ( nd_sba_syz ) {
1.27 noro 3217: print_eg("remove",&eg_remove);
1.31 noro 3218: print_eg("nf",&eg_nf);
3219: print_eg("nfzero",&eg_nfzero);
1.27 noro 3220: printf("\n");
1.26 noro 3221: }
1.44 noro 3222: if ( nd_sba_syz ) {
3223: NODE hsyz,tsyz,prev;
3224:
3225: hsyz = 0;
3226: for ( i = 0; i < ngen; i++ ) {
3227: tsyz = syzlist[i];
3228: for ( prev = 0; tsyz != 0; prev = tsyz, tsyz = NEXT(tsyz))
3229: BDY(tsyz) = (pointer)sigtodpm((SIG)BDY(tsyz));
3230: if ( prev != 0 ) {
3231: prev->next = hsyz; hsyz = syzlist[i];
3232: }
3233: }
3234: *syzp = hsyz;
3235: } else *syzp = 0;
1.24 noro 3236: return g;
3237: }
3238:
1.1 noro 3239: /* splist = [[i1,i2],...] */
3240:
3241: int check_splist(int m,NODE splist)
3242: {
3243: NODE t,p;
3244: ND_pairs d,r,l;
3245: int stat;
3246: ND h,nf;
3247:
3248: for ( d = 0, t = splist; t; t = NEXT(t) ) {
3249: p = BDY((LIST)BDY(t));
1.6 noro 3250: NEXTND_pairs(d,r);
3251: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
3252: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 3253: SG(r) = TD(LCM(r)); /* XXX */
3254: }
3255: if ( d ) NEXT(r) = 0;
3256:
1.6 noro 3257: while ( d ) {
1.1 noro 3258: again:
1.6 noro 3259: l = nd_minp(d,&d);
3260: stat = nd_sp(m,0,l,&h);
3261: if ( !stat ) {
3262: NEXT(l) = d; d = l;
3263: d = nd_reconstruct(0,d);
3264: goto again;
3265: }
1.39 noro 3266: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.6 noro 3267: if ( !stat ) {
3268: NEXT(l) = d; d = l;
3269: d = nd_reconstruct(0,d);
3270: goto again;
3271: } else if ( nf ) return 0;
1.1 noro 3272: if ( DP_Print) { printf("."); fflush(stdout); }
1.6 noro 3273: }
1.1 noro 3274: if ( DP_Print) { printf("done.\n"); fflush(stdout); }
3275: return 1;
3276: }
3277:
3278: int check_splist_f4(int m,NODE splist)
3279: {
3280: UINT *s0vect;
1.6 noro 3281: PGeoBucket bucket;
1.1 noro 3282: NODE p,rp0,t;
3283: ND_pairs d,r,l,ll;
3284: int col,stat;
3285:
3286: for ( d = 0, t = splist; t; t = NEXT(t) ) {
3287: p = BDY((LIST)BDY(t));
1.6 noro 3288: NEXTND_pairs(d,r);
3289: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
3290: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 3291: SG(r) = TD(LCM(r)); /* XXX */
3292: }
3293: if ( d ) NEXT(r) = 0;
3294:
1.6 noro 3295: while ( d ) {
3296: l = nd_minsugarp(d,&d);
3297: bucket = create_pbucket();
3298: stat = nd_sp_f4(m,0,l,bucket);
3299: if ( !stat ) {
3300: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3301: NEXT(ll) = d; d = l;
3302: d = nd_reconstruct(0,d);
3303: continue;
3304: }
3305: if ( bucket->m < 0 ) continue;
3306: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
3307: if ( !col ) {
3308: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3309: NEXT(ll) = d; d = l;
3310: d = nd_reconstruct(0,d);
3311: continue;
1.1 noro 3312: }
1.6 noro 3313: if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0;
3314: }
3315: return 1;
1.1 noro 3316: }
3317:
3318: int do_diagonalize_trace(int sugar,int m)
3319: {
1.6 noro 3320: int i,nh,stat;
3321: NODE r,g,t;
3322: ND h,nf,nfq,s,head;
3323: NDV nfv,nfqv;
3324: Q q,den,num;
3325: union oNDC hc;
3326: NODE node;
3327: LIST l;
3328: Z iq;
3329: P cont,cont1;
1.1 noro 3330:
1.6 noro 3331: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
3332: if ( nd_gentrace ) {
3333: /* Trace = [1,index,1,1] */
3334: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
3335: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3336: }
3337: /* for nd_ps */
3338: s = ndvtond(m,nd_ps[i]);
3339: s = nd_separate_head(s,&head);
3340: stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
3341: if ( !stat ) return 0;
3342: nf = nd_add(m,head,nf);
3343: ndv_free(nd_ps[i]);
3344: nd_ps[i] = ndtondv(m,nf);
3345: nd_free(nf);
3346:
3347: /* for nd_ps_trace */
3348: if ( nd_demand )
3349: nfv = ndv_load(i);
3350: else
3351: nfv = nd_ps_trace[i];
3352: s = ndvtond(0,nfv);
3353: s = nd_separate_head(s,&head);
3354: stat = nd_nf(0,head,s,nd_ps_trace,1,&nf);
3355: if ( !stat ) return 0;
3356: ndv_free(nfv);
3357: hc = HCU(nf); nd_removecont(0,nf);
3358: /* exact division */
1.1 noro 3359: cont = ndc_div(0,hc,HCU(nf));
1.6 noro 3360: if ( nd_gentrace ) finalize_tracelist(i,cont);
3361: nfv = ndtondv(0,nf);
3362: nd_free(nf);
3363: nd_bound[i] = ndv_compute_bound(nfv);
3364: register_hcf(nfv);
3365: if ( nd_demand ) {
3366: ndv_save(nfv,i);
3367: ndv_free(nfv);
3368: } else
3369: nd_ps_trace[i] = nfv;
3370: }
3371: return 1;
1.1 noro 3372: }
3373:
3374: static struct oEGT eg_invdalg;
3375: struct oEGT eg_le;
3376:
3377: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
3378: {
3379: NODE tn;
3380: P p1;
3381:
3382: for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
3383: substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
3384: }
3385: *r = p;
3386: }
3387:
3388: NODE nd_gb_trace(int m,int ishomo,int **indp)
3389: {
1.6 noro 3390: int i,nh,sugar,stat;
3391: NODE r,g,t;
3392: ND_pairs d;
3393: ND_pairs l;
3394: ND h,nf,nfq,s,head;
3395: NDV nfv,nfqv;
3396: Z q,den,num;
3397: P hc;
3398: union oNDC dn,hnfq;
3399: struct oEGT eg_monic,egm0,egm1;
3400: int diag_count = 0;
3401: P cont;
3402: LIST list;
1.49 noro 3403: struct oHPDATA current_hpdata,final_hpdata;
3404: int final_hpvalue;
1.6 noro 3405:
3406: init_eg(&eg_monic);
3407: init_eg(&eg_invdalg);
3408: init_eg(&eg_le);
3409: g = 0; d = 0;
3410: for ( i = 0; i < nd_psn; i++ ) {
3411: d = update_pairs(d,g,i,0);
3412: g = update_base(g,i);
3413: }
3414: sugar = 0;
1.49 noro 3415: if ( nd_hpdata ) {
1.52 noro 3416: if ( DP_Print ) fprintf(asir_out,"Hilbert driven algorithm.\n");
1.49 noro 3417: setup_hpdata(&final_hpdata,¤t_hpdata);
3418: }
3419:
1.6 noro 3420: while ( d ) {
1.1 noro 3421: again:
1.6 noro 3422: l = nd_minp(d,&d);
3423: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
3424: if ( SG(l) != sugar ) {
1.1 noro 3425: #if 1
1.6 noro 3426: if ( ishomo ) {
3427: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3428: stat = do_diagonalize_trace(sugar,m);
3429: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3430: diag_count = 0;
1.1 noro 3431: if ( !stat ) {
1.6 noro 3432: NEXT(l) = d; d = l;
3433: d = nd_reconstruct(1,d);
3434: goto again;
1.1 noro 3435: }
1.6 noro 3436: }
3437: #endif
3438: sugar = SG(l);
3439: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
3440: }
3441: stat = nd_sp(m,0,l,&h);
3442: if ( !stat ) {
3443: NEXT(l) = d; d = l;
3444: d = nd_reconstruct(1,d);
3445: goto again;
3446: }
1.1 noro 3447: #if USE_GEOBUCKET
1.39 noro 3448: stat = nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3449: #else
1.39 noro 3450: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3451: #endif
1.6 noro 3452: if ( !stat ) {
3453: NEXT(l) = d; d = l;
3454: d = nd_reconstruct(1,d);
3455: goto again;
3456: } else if ( nf ) {
3457: if ( nd_demand ) {
3458: nfqv = ndv_load(nd_psn);
3459: nfq = ndvtond(0,nfqv);
3460: } else
3461: nfq = 0;
3462: if ( !nfq ) {
1.39 noro 3463: if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!nd_top&&!Top,&nfq) ) {
1.6 noro 3464: NEXT(l) = d; d = l;
3465: d = nd_reconstruct(1,d);
3466: goto again;
3467: }
3468: }
3469: if ( nfq ) {
3470: /* m|HC(nfq) => failure */
3471: if ( nd_vc ) {
3472: nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Z)hc;
3473: } else
3474: q = HCZ(nfq);
3475: if ( !remqi((Q)q,m) ) return 0;
3476:
3477: if ( DP_Print ) { printf("+"); fflush(stdout); }
3478: hnfq = HCU(nfq);
3479: if ( nd_nalg ) {
3480: /* m|DN(HC(nf)^(-1)) => failure */
3481: get_eg(&egm0);
3482: if ( !nd_monic(m,&nfq) ) return 0;
3483: get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
3484: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3485: nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
3486: } else {
3487: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3488: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
3489: }
3490: if ( nd_gentrace ) {
3491: /* exact division */
3492: cont = ndc_div(0,hnfq,HCU(nfqv));
3493: if ( !UNIQ(cont) ) {
3494: t = mknode(4,NULLP,NULLP,NULLP,cont);
3495: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
3496: nd_tracelist = t;
3497: }
3498: }
1.24 noro 3499: nh = ndv_newps(0,nfv,nfqv);
1.6 noro 3500: if ( ishomo && ++diag_count == diag_period ) {
3501: diag_count = 0;
3502: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3503: stat = do_diagonalize_trace(sugar,m);
3504: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3505: if ( !stat ) {
1.1 noro 3506: NEXT(l) = d; d = l;
3507: d = nd_reconstruct(1,d);
3508: goto again;
1.6 noro 3509: }
1.1 noro 3510: }
1.6 noro 3511: d = update_pairs(d,g,nh,0);
3512: g = update_base(g,nh);
1.49 noro 3513: if ( nd_hpdata ) {
1.57 ! noro 3514: int dg,sugar0;
1.56 noro 3515:
3516: update_hpdata(¤t_hpdata,nh);
3517: dg = comp_hn(final_hpdata.hn,current_hpdata.hn);
1.57 ! noro 3518: if ( dg < 0 ) {
! 3519: fprintf(asir_out,"We found a gb\n");
! 3520: d = 0;
! 3521: }
1.56 noro 3522: if ( dg > sugar ) {
1.57 ! noro 3523: // printexpr(CO,(Obj)current_hpdata.hn);
! 3524: fprintf(asir_out,"\n");
1.56 noro 3525: }
1.57 ! noro 3526: sugar0 = sugar;
! 3527: while ( d && dg > sugar0 ) {
1.56 noro 3528: if ( DP_Print ) fprintf(asir_out,"sugar=%d done.\n",sugar);
1.49 noro 3529: d = nd_remove_same_sugar(d,sugar);
1.57 ! noro 3530: sugar0++;
1.49 noro 3531: }
3532: }
1.6 noro 3533: } else {
1.57 ! noro 3534: if ( DP_Print ) { fprintf(asir_out,"*"); fflush(asir_out); }
1.6 noro 3535: }
3536: } else {
1.57 ! noro 3537: if ( DP_Print ) { fprintf(asir_out,"."); fflush(asir_out); }
1.1 noro 3538: }
1.6 noro 3539: FREENDP(l);
3540: }
3541: if ( nd_nalg ) {
3542: if ( DP_Print ) {
3543: print_eg("monic",&eg_monic);
3544: print_eg("invdalg",&eg_invdalg);
3545: print_eg("le",&eg_le);
1.1 noro 3546: }
1.6 noro 3547: }
1.1 noro 3548: conv_ilist(nd_demand,1,g,indp);
1.57 ! noro 3549: if ( DP_Print ) { fprintf(asir_out,"\nnd_gb_trace done.\n"); fflush(asir_out); }
1.6 noro 3550: return g;
1.1 noro 3551: }
3552:
3553: int ndv_compare(NDV *p1,NDV *p2)
3554: {
3555: return DL_COMPARE(HDL(*p1),HDL(*p2));
3556: }
3557:
3558: int ndv_compare_rev(NDV *p1,NDV *p2)
3559: {
3560: return -DL_COMPARE(HDL(*p1),HDL(*p2));
3561: }
3562:
3563: int ndvi_compare(NDVI p1,NDVI p2)
3564: {
3565: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
3566: }
3567:
3568: int ndvi_compare_rev(NDVI p1,NDVI p2)
3569: {
3570: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3571: }
3572:
3573: NODE ndv_reduceall(int m,NODE f)
3574: {
3575: int i,j,n,stat;
3576: ND nf,g,head;
3577: NODE t,a0,a;
3578: union oNDC dn;
3579: Q q,num,den;
3580: NODE node;
3581: LIST l;
3582: Z iq,jq;
3583: int *perm;
3584: union oNDC hc;
3585: P cont,cont1;
3586:
3587: if ( nd_nora ) return f;
3588: n = length(f);
1.24 noro 3589: ndv_setup(m,0,f,0,1,0);
1.1 noro 3590: perm = (int *)MALLOC(n*sizeof(int));
3591: if ( nd_gentrace ) {
3592: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3593: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3594: }
3595: for ( i = 0; i < n; ) {
3596: if ( nd_gentrace ) {
3597: /* Trace = [1,index,1,1] */
1.6 noro 3598: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3599: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3600: }
3601: g = ndvtond(m,nd_ps[i]);
3602: g = nd_separate_head(g,&head);
1.6 noro 3603: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3604: if ( !stat )
3605: nd_reconstruct(0,0);
3606: else {
3607: if ( DP_Print ) { printf("."); fflush(stdout); }
3608: ndv_free(nd_ps[i]);
3609: hc = HCU(nf); nd_removecont(m,nf);
3610: if ( nd_gentrace ) {
3611: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3612: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3613: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3614: }
1.6 noro 3615: /* exact division */
1.1 noro 3616: cont = ndc_div(m,hc,HCU(nf));
3617: finalize_tracelist(perm[i],cont);
3618: }
3619: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3620: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3621: i++;
3622: }
3623: }
3624: if ( DP_Print ) { printf("\n"); }
3625: for ( a0 = 0, i = 0; i < n; i++ ) {
3626: NEXTNODE(a0,a);
3627: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3628: else {
3629: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3630: BDY(a) = (pointer)nd_ps[j];
3631: }
3632: }
3633: NEXT(a) = 0;
3634: return a0;
3635: }
3636:
1.41 noro 3637: int ndplength(ND_pairs d)
3638: {
3639: int i;
3640: for ( i = 0; d; i++ ) d = NEXT(d);
3641: return i;
3642: }
3643:
1.1 noro 3644: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3645: {
3646: ND_pairs d1,nd,cur,head,prev,remove;
1.41 noro 3647: int len0;
1.1 noro 3648:
3649: if ( !g ) return d;
3650: /* for testing */
3651: if ( gensyz && nd_gensyz == 2 ) {
3652: d1 = nd_newpairs(g,t);
3653: if ( !d )
3654: return d1;
3655: else {
3656: nd = d;
3657: while ( NEXT(nd) ) nd = NEXT(nd);
3658: NEXT(nd) = d1;
3659: return d;
3660: }
3661: }
3662: d = crit_B(d,t);
3663: d1 = nd_newpairs(g,t);
1.41 noro 3664: len0 = ndplength(d1);
1.1 noro 3665: d1 = crit_M(d1);
3666: d1 = crit_F(d1);
1.41 noro 3667: NcriMF += len0-ndplength(d1);
1.1 noro 3668: if ( gensyz || do_weyl )
3669: head = d1;
3670: else {
3671: prev = 0; cur = head = d1;
3672: while ( cur ) {
3673: if ( crit_2( cur->i1,cur->i2 ) ) {
3674: remove = cur;
3675: if ( !prev ) head = cur = NEXT(cur);
3676: else cur = NEXT(prev) = NEXT(cur);
1.41 noro 3677: FREENDP(remove); Ncri2++;
1.1 noro 3678: } else {
3679: prev = cur; cur = NEXT(cur);
3680: }
3681: }
3682: }
3683: if ( !d )
3684: return head;
3685: else {
3686: nd = d;
3687: while ( NEXT(nd) ) nd = NEXT(nd);
3688: NEXT(nd) = head;
3689: return d;
3690: }
3691: }
3692:
1.24 noro 3693: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3694:
1.30 noro 3695: ND_pairs update_pairs_s( ND_pairs d, int t,NODE *syz)
1.24 noro 3696: {
3697: ND_pairs d1;
1.26 noro 3698: struct oEGT eg1,eg2,eg3;
1.24 noro 3699:
1.30 noro 3700: if ( !t ) return d;
1.26 noro 3701: get_eg(&eg1);
1.30 noro 3702: d1 = nd_newpairs_s(t,syz);
1.26 noro 3703: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3704: d = merge_pairs_s(d,d1);
1.26 noro 3705: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3706: return d;
3707: }
1.1 noro 3708:
1.47 noro 3709: int update_pairs_array_s( ND_pairs *d, int t,NODE *syz)
3710: {
3711: ND_pairs *d1;
3712: struct oEGT eg1,eg2,eg3;
3713: int i;
3714:
3715: if ( !t ) return 0;
3716: get_eg(&eg1);
3717: Nnewpair = 0;
3718: d1 = nd_newpairs_array_s(t,syz);
3719: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
3720: for ( i = 0; i < nd_nbase; i++ )
3721: d[i] = merge_pairs_s(d[i],d1[i]);
3722: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
3723: return Nnewpair;
3724: }
3725:
1.1 noro 3726: ND_pairs nd_newpairs( NODE g, int t )
3727: {
3728: NODE h;
3729: UINT *dl;
3730: int ts,s,i,t0,min,max;
3731: ND_pairs r,r0;
3732:
3733: dl = DL(nd_psh[t]);
3734: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3735: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3736: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3737: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3738: continue;
3739: if ( nd_gbblock ) {
3740: t0 = (long)BDY(h);
3741: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3742: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3743: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3744: break;
3745: }
3746: if ( nd_gbblock[i] >= 0 )
3747: continue;
3748: }
1.41 noro 3749: NEXTND_pairs(r0,r); Npairs++;
1.1 noro 3750: r->i1 = (long)BDY(h);
3751: r->i2 = t;
3752: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3753: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3754: SG(r) = MAX(s,ts) + TD(LCM(r));
3755: /* experimental */
3756: if ( nd_sugarweight )
3757: r->sugar2 = ndl_weight2(r->lcm);
3758: }
3759: if ( r0 ) NEXT(r) = 0;
3760: return r0;
3761: }
3762:
1.46 noro 3763: int sig_cmpdl_op(int n,DL d1,DL d2)
3764: {
3765: int e1,e2,i,j,l;
3766: int *t1,*t2;
3767: int len,head;
3768: struct order_pair *pair;
3769:
3770: len = nd_sba_modord->block_length;
3771: pair = nd_sba_modord->order_pair;
3772:
3773: head = 0;
3774: for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {
3775: l = pair[i].length;
3776: switch ( pair[i].order ) {
3777: case 0:
3778: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3779: e1 += t1[j];
3780: e2 += t2[j];
3781: }
3782: if ( e1 > e2 )
3783: return 1;
3784: else if ( e1 < e2 )
3785: return -1;
3786: else {
3787: for ( j = l - 1; j >= 0 && t1[j] == t2[j]; j-- );
3788: if ( j >= 0 )
3789: return t1[j] < t2[j] ? 1 : -1;
3790: }
3791: break;
3792: case 1:
3793: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3794: e1 += t1[j];
3795: e2 += t2[j];
3796: }
3797: if ( e1 > e2 )
3798: return 1;
3799: else if ( e1 < e2 )
3800: return -1;
3801: else {
3802: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3803: if ( j < l )
3804: return t1[j] > t2[j] ? 1 : -1;
3805: }
3806: break;
3807: case 2:
3808: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3809: if ( j < l )
3810: return t1[j] > t2[j] ? 1 : -1;
3811: break;
3812: default:
3813: error("sig_cmpdl_op : invalid order"); break;
3814: }
3815: t1 += l; t2 += l; head += l;
3816: }
3817: return 0;
3818: }
3819:
3820: int sig_cmpdl_mat(int n,DL d1,DL d2)
3821: {
3822: int *v,*t1,*t2;
3823: int s,i,j,len;
3824: int **matrix;
3825: static int *w;
3826: static int nvar = 0;
3827:
3828: if ( nvar != n ) {
3829: nvar = n; w = (int *)MALLOC(n*sizeof(int));
3830: }
3831: for ( i = 0, t1 = d1->d, t2 = d2->d; i < n; i++ )
3832: w[i] = t1[i]-t2[i];
3833: len = nd_sba_modord->row;
3834: matrix = nd_sba_modord->matrix;
3835: for ( j = 0; j < len; j++ ) {
3836: v = matrix[j];
3837: for ( i = 0, s = 0; i < n; i++ )
3838: s += v[i]*w[i];
3839: if ( s > 0 )
3840: return 1;
3841: else if ( s < 0 )
3842: return -1;
3843: }
3844: return 0;
3845: }
3846:
3847: struct comp_sig_spec *create_comp_sig_spec(VL current_vl,VL old_vl,Obj ord,Obj weight)
3848: {
3849: struct comp_sig_spec *spec;
3850: VL ovl,vl;
3851: V ov;
3852: int i,j,n,nvar,s;
3853: NODE node,t,tn;
3854: struct order_pair *l;
3855: MAT m;
3856: Obj **b;
3857: int **w;
3858: int *a;
3859:
3860: spec = (struct comp_sig_spec *)MALLOC(sizeof(struct comp_sig_spec));
3861: for ( i = 0, vl = current_vl; vl; vl = NEXT(vl), i++ );
3862: spec->n = nvar = i;
3863: if ( old_vl != 0 ) {
3864: spec->oldv = (int *)MALLOC(nvar*sizeof(int));
3865: for ( i = 0, ovl = old_vl; i < nvar; ovl = NEXT(ovl), i++ ) {
3866: ov = ovl->v;
3867: for ( j = 0, vl = current_vl; vl; vl = NEXT(vl), j++ )
3868: if ( ov == vl->v ) break;
3869: spec->oldv[i] = j;
3870: }
3871: } else
3872: spec->oldv = 0;
3873: if ( !ord || NUM(ord) ) {
3874: switch ( ZTOS((Z)ord) ) {
3875: case 0:
3876: spec->cmpdl = cmpdl_revgradlex; break;
3877: case 1:
3878: spec->cmpdl = cmpdl_gradlex; break;
3879: case 2:
3880: spec->cmpdl = cmpdl_lex; break;
3881: default:
3882: error("create_comp_sig_spec : invalid spec"); break;
3883: }
3884: } else if ( OID(ord) == O_LIST ) {
3885: node = BDY((LIST)ord);
3886: for ( n = 0, t = node; t; t = NEXT(t), n++ );
3887: l = (struct order_pair *)MALLOC_ATOMIC(n*sizeof(struct order_pair));
3888: for ( i = 0, t = node, s = 0; i < n; t = NEXT(t), i++ ) {
3889: tn = BDY((LIST)BDY(t)); l[i].order = ZTOS((Q)BDY(tn));
3890: tn = NEXT(tn); l[i].length = ZTOS((Q)BDY(tn));
3891: s += l[i].length;
3892: }
3893: if ( s != nvar )
3894: error("create_comp_sig_spec : invalid spec");
3895: spec->order_pair = l;
3896: spec->block_length = n;
3897: spec->cmpdl = sig_cmpdl_op;
3898: } else if ( OID(ord) == O_MAT ) {
3899: m = (MAT)ord; b = (Obj **)BDY(m);
3900: if ( m->col != nvar )
3901: error("create_comp_sig_spec : invalid spec");
3902: w = almat(m->row,m->col);
3903: for ( i = 0; i < m->row; i++ )
3904: for ( j = 0; j < m->col; j++ )
3905: w[i][j] = ZTOS((Q)b[i][j]);
3906: spec->row = m->row;
3907: spec->matrix = w;
3908: spec->cmpdl = sig_cmpdl_mat;
3909: } else
3910: error("create_comp_sig_spec : invalid spec");
3911: if ( weight != 0 ) {
3912: node = BDY((LIST)weight);
3913: a = (int *)MALLOC(nvar*sizeof(int));
3914: for ( i = 0; i < nvar; i++, node = NEXT(node) )
3915: a[i] = ZTOS((Z)BDY(node));
3916: spec->weight = a;
3917: }
3918: return spec;
3919: }
3920:
3921: #define SIG_MUL_WEIGHT(a,i) (weight?(a)*weight[i]:(a))
3922:
3923: int comp_sig_monomial(int n,DL d1,DL d2)
3924: {
3925: static DL m1,m2;
3926: static int nvar = 0;
3927: int *oldv,*weight;
3928: int i,w1,w2;
3929:
3930: if ( nvar != n ) {
3931: nvar = n; NEWDL(m1,nvar); NEWDL(m2,nvar);
3932: }
3933: if ( !nd_sba_modord )
3934: return (*cmpdl)(n,d1,d2);
1.55 noro 3935: else if ( !nd_sba_modord->weight && !nd_sba_modord->oldv ) {
3936: return (*nd_sba_modord->cmpdl)(n,d1,d2);
3937: } else {
1.46 noro 3938: weight = nd_sba_modord->weight;
3939: oldv = nd_sba_modord->oldv;
3940: if ( oldv ) {
3941: for ( i = 0; i < n; i++ ) {
3942: m1->d[i] = d1->d[oldv[i]]; m2->d[i] = d2->d[oldv[i]];
3943: }
3944: } else {
3945: for ( i = 0; i < n; i++ ) {
3946: m1->d[i] = d1->d[i]; m2->d[i] = d2->d[i];
3947: }
3948: }
3949: for ( i = 0, w1 = w2 = 0; i < n; i++ ) {
3950: w1 += SIG_MUL_WEIGHT(m1->d[i],i);
3951: w2 += SIG_MUL_WEIGHT(m2->d[i],i);
3952: }
3953: m1->td = w1; m2->td = w2;
3954: return (*nd_sba_modord->cmpdl)(n,m1,m2);
3955: }
3956: }
3957:
1.24 noro 3958: int comp_sig(SIG s1,SIG s2)
3959: {
1.38 noro 3960: if ( nd_sba_pot ) {
3961: if ( s1->pos > s2->pos ) return 1;
3962: else if ( s1->pos < s2->pos ) return -1;
1.55 noro 3963: else return comp_sig_monomial(nd_nvar,DL(s1),DL(s2));
1.38 noro 3964: } else {
3965: static DL m1,m2;
1.44 noro 3966: static int nvar = 0;
1.38 noro 3967: int ret;
3968:
3969: if ( nvar != nd_nvar ) {
3970: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
3971: }
1.47 noro 3972: if ( !nd_sba_modord )
1.55 noro 3973: ret = (*cmpdl)(nd_nvar,DL2(s1),DL2(s2));
1.47 noro 3974: else
1.55 noro 3975: ret = comp_sig_monomial(nd_nvar,DL2(s1),DL2(s2));
1.38 noro 3976: if ( ret != 0 ) return ret;
3977: else if ( s1->pos > s2->pos ) return 1;
3978: else if ( s1->pos < s2->pos ) return -1;
3979: else return 0;
1.24 noro 3980: }
3981: }
3982:
3983: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3984: {
3985: int ret,s1,s2;
3986: RHist p1,p2;
3987: static int wpd;
3988: static UINT *lcm;
3989:
3990: sp->i1 = i1;
3991: sp->i2 = i2;
3992: p1 = nd_psh[i1];
3993: p2 = nd_psh[i2];
3994: ndl_lcm(DL(p1),DL(p2),sp->lcm);
1.49 noro 3995: #if 0
1.24 noro 3996: s1 = SG(p1)-TD(DL(p1));
3997: s2 = SG(p2)-TD(DL(p2));
3998: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
1.49 noro 3999: #endif
1.24 noro 4000:
1.26 noro 4001: if ( wpd != nd_wpd ) {
1.24 noro 4002: wpd = nd_wpd;
4003: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
4004: }
4005: // DL(sig1) <- sp->lcm
4006: // DL(sig1) -= DL(p1)
4007: // DL(sig1) += DL(p1->sig)
1.27 noro 4008: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 4009: _ndltodl(lcm,DL(sig1));
4010: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
4011: sig1->pos = p1->sig->pos;
1.55 noro 4012: _adddl(nd_nvar,DL(sig1),nd_sba_hm[sig1->pos],DL2(sig1));
1.24 noro 4013:
4014: // DL(sig2) <- sp->lcm
4015: // DL(sig2) -= DL(p2)
4016: // DL(sig2) += DL(p2->sig)
1.27 noro 4017: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 4018: _ndltodl(lcm,DL(sig2));
4019: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
4020: sig2->pos = p2->sig->pos;
1.55 noro 4021: _adddl(nd_nvar,DL(sig2),nd_sba_hm[sig2->pos],DL2(sig2));
1.24 noro 4022:
4023: ret = comp_sig(sig1,sig2);
4024: if ( ret == 0 ) return 0;
4025: else if ( ret > 0 ) sp->sig = sig1;
4026: else sp->sig = sig2;
1.49 noro 4027:
4028: s1 = DL(sig1)->td+nd_sba_hm[p1->sig->pos]->td;
4029: s2 = DL(sig2)->td+nd_sba_hm[p2->sig->pos]->td;
4030: SG(sp) = MAX(s1,s2);
4031:
1.24 noro 4032: return 1;
4033: }
4034:
4035: SIG dup_sig(SIG sig)
4036: {
4037: SIG r;
4038:
4039: if ( !sig ) return 0;
4040: else {
4041: NEWSIG(r);
4042: _copydl(nd_nvar,DL(sig),DL(r));
1.55 noro 4043: _copydl(nd_nvar,DL2(sig),DL2(r));
1.24 noro 4044: r->pos = sig->pos;
4045: return r;
4046: }
4047: }
4048:
4049: void dup_ND_pairs(ND_pairs to,ND_pairs from)
4050: {
4051: to->i1 = from->i1;
4052: to->i2 = from->i2;
4053: to->sugar = from->sugar;
4054: to->sugar2 = from->sugar2;
4055: ndl_copy(from->lcm,to->lcm);
4056: to->sig = dup_sig(from->sig);
4057: }
4058:
4059: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
4060: {
4061: struct oND_pairs root;
4062: ND_pairs q1,q2,r0,r;
4063: int ret;
4064:
4065: r = &root;
4066: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
4067: ret = comp_sig(q1->sig,q2->sig);
4068: if ( ret < 0 ) {
4069: r->next = q1; r = q1; q1 = q1->next;
4070: } else if ( ret > 0 ) {
4071: r->next = q2; r = q2; q2 = q2->next;
4072: } else {
1.47 noro 4073: Nnewpair--;
1.24 noro 4074: ret = DL_COMPARE(q1->lcm,q2->lcm);
1.35 noro 4075: Nsamesig++;
1.24 noro 4076: if ( ret < 0 ) {
4077: r->next = q1; r = q1; q1 = q1->next;
4078: q2 = q2->next;
4079: } else {
4080: r->next = q2; r = q2; q2 = q2->next;
4081: q1 = q1->next;
4082: }
4083: }
4084: }
4085: if ( q1 ) {
4086: r->next = q1;
4087: } else {
4088: r->next = q2;
4089: }
4090: return root.next;
4091: }
4092:
4093: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
4094: {
4095: ND_pairs p,prev;
1.47 noro 4096: int ret=1;
1.24 noro 4097:
4098: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
4099: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
4100: break;
4101: }
4102: if ( ret == 0 ) {
4103: ret = DL_COMPARE(s->lcm,p->lcm);
4104: if ( ret < 0 ) {
4105: // replace p with s
4106: s->next = p->next;
4107: if ( prev == 0 ) {
4108: return s;
4109: } else {
4110: prev->next = s;
4111: return l;
4112: }
4113: } else
4114: return l;
4115: } else {
4116: // insert s between prev and p
1.47 noro 4117: Nnewpair++;
1.24 noro 4118: s->next = p;
4119: if ( prev == 0 ) {
4120: return s;
4121: } else {
4122: prev->next = s;
4123: return l;
4124: }
4125: }
4126: }
4127:
1.29 noro 4128: INLINE int __dl_redble(DL d1,DL d2,int nvar)
4129: {
4130: int i;
4131:
4132: if ( d1->td > d2->td )
4133: return 0;
4134: for ( i = nvar-1; i >= 0; i-- )
4135: if ( d1->d[i] > d2->d[i] )
4136: break;
4137: if ( i >= 0 )
4138: return 0;
4139: else
4140: return 1;
4141: }
4142:
1.30 noro 4143: ND_pairs nd_newpairs_s(int t, NODE *syz)
1.24 noro 4144: {
4145: NODE h,s;
4146: UINT *dl;
1.27 noro 4147: int ts,ret,i;
1.24 noro 4148: ND_pairs r,r0,_sp,sp;
1.29 noro 4149: SIG spsig,tsig;
1.44 noro 4150: static int nvar = 0;
1.29 noro 4151: static SIG _sig1,_sig2;
1.26 noro 4152: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 4153:
4154: NEWND_pairs(_sp);
1.29 noro 4155: if ( !_sig1 || nvar != nd_nvar ) {
4156: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
4157: }
1.24 noro 4158: r0 = 0;
1.27 noro 4159: for ( i = 0; i < t; i++ ) {
4160: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
1.24 noro 4161: if ( ret ) {
4162: spsig = _sp->sig;
1.29 noro 4163: for ( s = syz[spsig->pos]; s; s = s->next ) {
1.24 noro 4164: tsig = (SIG)s->body;
1.29 noro 4165: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
1.24 noro 4166: break;
4167: }
4168: if ( s == 0 ) {
4169: NEWND_pairs(sp);
4170: dup_ND_pairs(sp,_sp);
4171: r0 = insert_pair_s(r0,sp);
1.26 noro 4172: } else
4173: Nsyz++;
1.24 noro 4174: }
4175: }
4176: return r0;
4177: }
4178:
1.47 noro 4179: ND_pairs *nd_newpairs_array_s(int t, NODE *syz)
4180: {
4181: NODE h,s;
4182: UINT *dl;
4183: int ts,ret,i;
4184: ND_pairs r,r0,_sp,sp;
4185: ND_pairs *d;
4186: SIG spsig,tsig;
4187: static int nvar = 0;
4188: static SIG _sig1,_sig2;
4189: struct oEGT eg1,eg2,eg3,eg4;
4190:
4191: NEWND_pairs(_sp);
4192: if ( !_sig1 || nvar != nd_nvar ) {
4193: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
4194: }
4195: d = (ND_pairs *)MALLOC(nd_nbase*sizeof(ND_pairs));
4196: Nnewpair = 0;
4197: for ( i = 0; i < t; i++ ) {
4198: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
4199: if ( ret ) {
4200: spsig = _sp->sig;
4201: for ( s = syz[spsig->pos]; s; s = s->next ) {
4202: tsig = (SIG)s->body;
4203: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
4204: break;
4205: }
4206: if ( s == 0 ) {
4207: NEWND_pairs(sp);
4208: dup_ND_pairs(sp,_sp);
4209: d[spsig->pos] = insert_pair_s(d[spsig->pos],sp);
4210: } else
4211: Nsyz++;
4212: }
4213: }
4214: return d;
4215: }
4216:
1.1 noro 4217: /* ipair = [i1,i2],[i1,i2],... */
4218: ND_pairs nd_ipairtospair(NODE ipair)
4219: {
4220: int s1,s2;
4221: NODE tn,t;
4222: ND_pairs r,r0;
4223:
4224: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
4225: NEXTND_pairs(r0,r);
4226: tn = BDY((LIST)BDY(t));
1.6 noro 4227: r->i1 = ZTOS((Q)ARG0(tn));
4228: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 4229: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
4230: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
4231: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
4232: SG(r) = MAX(s1,s2) + TD(LCM(r));
4233: /* experimental */
4234: if ( nd_sugarweight )
4235: r->sugar2 = ndl_weight2(r->lcm);
4236: }
4237: if ( r0 ) NEXT(r) = 0;
4238: return r0;
4239: }
4240:
4241: /* kokokara */
4242:
4243: ND_pairs crit_B( ND_pairs d, int s )
4244: {
4245: ND_pairs cur,head,prev,remove;
4246: UINT *t,*tl,*lcm;
4247: int td,tdl;
4248:
4249: if ( !d ) return 0;
4250: t = DL(nd_psh[s]);
4251: prev = 0;
4252: head = cur = d;
4253: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
4254: while ( cur ) {
4255: tl = cur->lcm;
4256: if ( ndl_reducible(tl,t) ) {
4257: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
4258: if ( !ndl_equal(lcm,tl) ) {
4259: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
4260: if (!ndl_equal(lcm,tl)) {
4261: remove = cur;
4262: if ( !prev ) {
4263: head = cur = NEXT(cur);
4264: } else {
4265: cur = NEXT(prev) = NEXT(cur);
4266: }
1.41 noro 4267: FREENDP(remove); NcriB++;
1.1 noro 4268: } else {
4269: prev = cur; cur = NEXT(cur);
4270: }
4271: } else {
4272: prev = cur; cur = NEXT(cur);
4273: }
4274: } else {
4275: prev = cur; cur = NEXT(cur);
4276: }
4277: }
4278: return head;
4279: }
4280:
4281: ND_pairs crit_M( ND_pairs d1 )
4282: {
4283: ND_pairs e,d2,d3,dd,p;
4284: UINT *id,*jd;
4285:
4286: if ( !d1 ) return d1;
4287: for ( dd = 0, e = d1; e; e = d3 ) {
4288: if ( !(d2 = NEXT(e)) ) {
4289: NEXT(e) = dd;
4290: return e;
4291: }
4292: id = LCM(e);
4293: for ( d3 = 0; d2; d2 = p ) {
4294: p = NEXT(d2);
4295: jd = LCM(d2);
4296: if ( ndl_equal(jd,id) )
4297: ;
4298: else if ( TD(jd) > TD(id) )
4299: if ( ndl_reducible(jd,id) ) continue;
4300: else ;
4301: else if ( ndl_reducible(id,jd) ) goto delit;
4302: NEXT(d2) = d3;
4303: d3 = d2;
4304: }
4305: NEXT(e) = dd;
4306: dd = e;
4307: continue;
4308: /**/
4309: delit: NEXT(d2) = d3;
4310: d3 = d2;
4311: for ( ; p; p = d2 ) {
4312: d2 = NEXT(p);
4313: NEXT(p) = d3;
4314: d3 = p;
4315: }
4316: FREENDP(e);
4317: }
4318: return dd;
4319: }
4320:
4321: ND_pairs crit_F( ND_pairs d1 )
4322: {
4323: ND_pairs rest, head,remove;
4324: ND_pairs last, p, r, w;
4325: int s;
4326:
4327: if ( !d1 ) return d1;
4328: for ( head = last = 0, p = d1; NEXT(p); ) {
4329: r = w = equivalent_pairs(p,&rest);
4330: s = SG(r);
4331: w = NEXT(w);
4332: while ( w ) {
4333: if ( crit_2(w->i1,w->i2) ) {
4334: r = w;
4335: w = NEXT(w);
4336: while ( w ) {
4337: remove = w;
4338: w = NEXT(w);
4339: FREENDP(remove);
4340: }
4341: break;
4342: } else if ( SG(w) < s ) {
4343: FREENDP(r);
4344: r = w;
4345: s = SG(r);
4346: w = NEXT(w);
4347: } else {
4348: remove = w;
4349: w = NEXT(w);
4350: FREENDP(remove);
4351: }
4352: }
4353: if ( last ) NEXT(last) = r;
4354: else head = r;
4355: NEXT(last = r) = 0;
4356: p = rest;
4357: if ( !p ) return head;
4358: }
4359: if ( !last ) return p;
4360: NEXT(last) = p;
4361: return head;
4362: }
4363:
4364: int crit_2( int dp1, int dp2 )
4365: {
4366: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
4367: }
4368:
4369: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
4370: {
4371: ND_pairs w,p,r,s;
4372: UINT *d;
4373:
4374: w = d1;
4375: d = LCM(w);
4376: s = NEXT(w);
4377: NEXT(w) = 0;
4378: for ( r = 0; s; s = p ) {
4379: p = NEXT(s);
4380: if ( ndl_equal(d,LCM(s)) ) {
4381: NEXT(s) = w; w = s;
4382: } else {
4383: NEXT(s) = r; r = s;
4384: }
4385: }
4386: *prest = r;
4387: return w;
4388: }
4389:
4390: NODE update_base(NODE nd,int ndp)
4391: {
4392: UINT *dl, *dln;
4393: NODE last, p, head;
4394:
4395: dl = DL(nd_psh[ndp]);
4396: for ( head = last = 0, p = nd; p; ) {
4397: dln = DL(nd_psh[(long)BDY(p)]);
4398: if ( ndl_reducible( dln, dl ) ) {
4399: p = NEXT(p);
4400: if ( last ) NEXT(last) = p;
4401: } else {
4402: if ( !last ) head = p;
4403: p = NEXT(last = p);
4404: }
4405: }
4406: head = append_one(head,ndp);
4407: return head;
4408: }
4409:
4410: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
4411: {
4412: ND_pairs m,ml,p,l;
4413: UINT *lcm;
4414: int s,td,len,tlen,c,c1;
4415:
4416: if ( !(p = NEXT(m = d)) ) {
4417: *prest = p;
4418: NEXT(m) = 0;
4419: return m;
4420: }
4421: if ( !NoSugar ) {
4422: if ( nd_sugarweight ) {
4423: s = m->sugar2;
4424: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4425: if ( (p->sugar2 < s)
4426: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4427: ml = l; m = p; s = m->sugar2;
4428: }
4429: } else {
4430: s = SG(m);
4431: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4432: if ( (SG(p) < s)
4433: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4434: ml = l; m = p; s = SG(m);
4435: }
4436: }
4437: } else {
4438: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4439: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
4440: ml = l; m = p; s = SG(m);
4441: }
4442: }
4443: if ( !ml ) *prest = NEXT(m);
4444: else {
4445: NEXT(ml) = NEXT(m);
4446: *prest = d;
4447: }
4448: NEXT(m) = 0;
4449: return m;
4450: }
4451:
4452: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
4453: {
4454: int msugar,i;
4455: ND_pairs t,dm0,dm,dr0,dr;
4456:
4457: if ( nd_sugarweight ) {
4458: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
4459: if ( t->sugar2 < msugar ) msugar = t->sugar2;
4460: dm0 = 0; dr0 = 0;
4461: for ( i = 0, t = d; t; t = NEXT(t) )
4462: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
4463: if ( dm0 ) NEXT(dm) = t;
4464: else dm0 = t;
4465: dm = t;
4466: i++;
4467: } else {
4468: if ( dr0 ) NEXT(dr) = t;
4469: else dr0 = t;
4470: dr = t;
4471: }
4472: } else {
4473: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
4474: if ( SG(t) < msugar ) msugar = SG(t);
4475: dm0 = 0; dr0 = 0;
4476: for ( i = 0, t = d; t; t = NEXT(t) )
4477: if ( i < nd_f4_nsp && SG(t) == msugar ) {
4478: if ( dm0 ) NEXT(dm) = t;
4479: else dm0 = t;
4480: dm = t;
4481: i++;
4482: } else {
4483: if ( dr0 ) NEXT(dr) = t;
4484: else dr0 = t;
4485: dr = t;
4486: }
4487: }
4488: NEXT(dm) = 0;
4489: if ( dr0 ) NEXT(dr) = 0;
4490: *prest = dr0;
4491: return dm0;
4492: }
4493:
1.28 noro 4494: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
4495: {
4496: int msugar;
4497: ND_pairs t,last;
4498:
4499: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
4500: if ( SG(t) == msugar ) last = t;
4501: *prest = last->next;
4502: last->next = 0;
4503: return d;
4504: }
4505:
1.1 noro 4506: int nd_tdeg(NDV c)
4507: {
4508: int wmax = 0;
4509: int i,len;
4510: NMV a;
4511:
4512: len = LEN(c);
4513: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4514: wmax = MAX(TD(DL(a)),wmax);
4515: return wmax;
4516: }
4517:
1.24 noro 4518: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 4519: {
4520: int len;
4521: RHist r;
4522: NDV b;
4523: NODE tn;
4524: LIST l;
4525: Z iq;
4526:
4527: if ( nd_psn == nd_pslen ) {
4528: nd_pslen *= 2;
4529: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
4530: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
4531: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
4532: nd_bound = (UINT **)
4533: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
4534: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
4535: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
4536: }
4537: NEWRHist(r); nd_psh[nd_psn] = r;
4538: nd_ps[nd_psn] = a;
4539: if ( aq ) {
4540: nd_ps_trace[nd_psn] = aq;
4541: if ( !m ) {
4542: register_hcf(aq);
4543: } else if ( m == -2 ) {
4544: /* do nothing */
4545: } else
4546: error("ndv_newps : invalud modulus");
4547: nd_bound[nd_psn] = ndv_compute_bound(aq);
4548: #if 1
4549: SG(r) = SG(aq);
4550: #else
4551: SG(r) = nd_tdeg(aq);
4552: #endif
4553: ndl_copy(HDL(aq),DL(r));
1.24 noro 4554: r->sig = dup_sig(aq->sig);
1.1 noro 4555: } else {
4556: if ( !m ) register_hcf(a);
4557: nd_bound[nd_psn] = ndv_compute_bound(a);
4558: #if 1
4559: SG(r) = SG(a);
4560: #else
4561: SG(r) = nd_tdeg(a);
4562: #endif
4563: ndl_copy(HDL(a),DL(r));
1.24 noro 4564: r->sig = dup_sig(a->sig);
1.1 noro 4565: }
4566: if ( nd_demand ) {
4567: if ( aq ) {
4568: ndv_save(nd_ps_trace[nd_psn],nd_psn);
4569: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4570: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4571: nd_ps_trace[nd_psn] = 0;
4572: } else {
4573: ndv_save(nd_ps[nd_psn],nd_psn);
4574: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
4575: nd_ps[nd_psn] = 0;
4576: }
4577: }
4578: if ( nd_gentrace ) {
4579: /* reverse the tracelist and append it to alltracelist */
4580: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 4581: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 4582: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
4583: }
4584: return nd_psn++;
4585: }
4586:
1.46 noro 4587: // find LM wrt the specified modord
4588: void ndv_lm_modord(NDV p,DL d)
1.45 noro 4589: {
4590: NMV m;
4591: DL tmp;
4592: int len,i,ret;
4593:
4594: NEWDL(tmp,nd_nvar);
4595: m = BDY(p); len = LEN(p);
1.46 noro 4596: _ndltodl(DL(m),d); // printdl(d); printf("->");
1.45 noro 4597: for ( i = 1, NMV_ADV(m); i < len; i++, NMV_ADV(m) ) {
4598: _ndltodl(DL(m),tmp);
1.46 noro 4599: ret = comp_sig_monomial(nd_nvar,tmp,d);
1.45 noro 4600: if ( ret > 0 ) _copydl(nd_nvar,tmp,d);
4601: }
1.46 noro 4602: // printdl(d); printf("\n");
1.45 noro 4603: }
4604:
1.1 noro 4605: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
4606: /* return 1 if success, 0 if failure (HC(a mod p)) */
4607:
1.24 noro 4608: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 4609: {
1.6 noro 4610: int i,j,td,len,max;
4611: NODE s,s0,f0,tn;
4612: UINT *d;
4613: RHist r;
4614: NDVI w;
4615: NDV a,am;
4616: union oNDC hc;
4617: NODE node;
4618: P hcp;
4619: Z iq,jq;
4620: LIST l;
4621:
4622: nd_found = 0; nd_notfirst = 0; nd_create = 0;
4623: /* initialize the tracelist */
4624: nd_tracelist = 0;
4625:
4626: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
4627: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
4628: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
4629: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
4630: if ( !dont_sort ) {
4631: /* XXX heuristic */
1.26 noro 4632: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 4633: qsort(w,nd_psn,sizeof(struct oNDVI),
4634: (int (*)(const void *,const void *))ndvi_compare_rev);
4635: else
4636: qsort(w,nd_psn,sizeof(struct oNDVI),
4637: (int (*)(const void *,const void *))ndvi_compare);
4638: }
4639: nd_pslen = 2*nd_psn;
4640: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4641: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4642: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4643: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4644: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
4645: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
4646: nd_hcf = 0;
1.1 noro 4647:
1.6 noro 4648: if ( trace && nd_vc )
4649: makesubst(nd_vc,&nd_subst);
4650: else
4651: nd_subst = 0;
1.1 noro 4652:
1.6 noro 4653: if ( !nd_red )
4654: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
4655: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
4656: for ( i = 0; i < nd_psn; i++ ) {
4657: hc = HCU(w[i].p);
4658: if ( trace ) {
4659: if ( mod == -2 ) {
4660: /* over a large finite field */
4661: /* trace = small modulus */
4662: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
4663: ndv_mod(-2,a);
4664: if ( !dont_removecont) ndv_removecont(-2,a);
4665: am = nd_ps[i] = ndv_dup(trace,w[i].p);
4666: ndv_mod(trace,am);
4667: if ( DL_COMPARE(HDL(am),HDL(a)) )
4668: return 0;
4669: ndv_removecont(trace,am);
4670: } else {
4671: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
4672: if ( !dont_removecont) ndv_removecont(0,a);
4673: register_hcf(a);
4674: am = nd_ps[i] = ndv_dup(mod,a);
4675: ndv_mod(mod,am);
4676: if ( DL_COMPARE(HDL(am),HDL(a)) )
4677: return 0;
4678: ndv_removecont(mod,am);
4679: }
4680: } else {
4681: a = nd_ps[i] = ndv_dup(mod,w[i].p);
4682: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
4683: if ( !mod ) register_hcf(a);
1.1 noro 4684: }
1.6 noro 4685: if ( nd_gentrace ) {
4686: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
4687: /* exact division */
1.1 noro 4688: if ( !dont_removecont )
1.6 noro 4689: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
4690: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
4691: }
4692: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
4693: nd_bound[i] = ndv_compute_bound(a);
4694: nd_psh[i] = r;
4695: if ( nd_demand ) {
4696: if ( trace ) {
4697: ndv_save(nd_ps_trace[i],i);
4698: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4699: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4700: nd_ps_trace[i] = 0;
4701: } else {
4702: ndv_save(nd_ps[i],i);
4703: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
4704: nd_ps[i] = 0;
4705: }
1.1 noro 4706: }
1.6 noro 4707: }
1.24 noro 4708: if ( sba ) {
1.27 noro 4709: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 4710: // setup signatures
1.27 noro 4711: for ( i = 0; i < nd_psn; i++ ) {
4712: SIG sig;
1.24 noro 4713:
1.27 noro 4714: NEWSIG(sig); sig->pos = i;
4715: nd_ps[i]->sig = sig;
4716: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
4717: nd_psh[i]->sig = sig;
4718: if ( trace ) {
4719: nd_ps_trace[i]->sig = sig;
4720: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
4721: }
4722: NEWDL(nd_sba_hm[i],nd_nvar);
1.46 noro 4723: if ( nd_sba_modord )
4724: ndv_lm_modord(nd_ps[i],nd_sba_hm[i]);
1.45 noro 4725: else
4726: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
1.55 noro 4727: _adddl(nd_nvar,DL(sig),nd_sba_hm[i],DL2(sig));
1.27 noro 4728: }
1.29 noro 4729: nd_sba_pos = (NODE *)MALLOC(nd_psn*sizeof(NODE));
4730: for ( i = 0; i < nd_psn; i++ ) {
4731: j = nd_psh[i]->sig->pos;
4732: nd_sba_pos[j] = append_one(nd_sba_pos[j],i);
4733: }
1.24 noro 4734: }
1.6 noro 4735: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
4736: return 1;
1.1 noro 4737: }
4738:
4739: struct order_spec *append_block(struct order_spec *spec,
4740: int nv,int nalg,int ord);
4741:
4742: extern VECT current_dl_weight_vector_obj;
4743: static VECT prev_weight_vector_obj;
4744:
4745: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
4746: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
4747: {
4748: NODE alist,t,s,r0,r,arg;
4749: VL tv;
4750: P poly;
4751: DP d;
4752: Alg alpha,dp;
4753: DAlg inv,da,hc;
4754: MP m;
4755: int i,nvar,nalg,n;
4756: NumberField nf;
4757: LIST f1,f2;
4758: struct order_spec *current_spec;
4759: VECT obj,obj0;
4760: VECT tmp;
4761:
4762: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
4763: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
4764:
4765: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
4766: NEXTNODE(alist,t); MKV(tv->v,poly);
4767: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
4768: tv->v = tv->v->priv;
4769: }
4770: NEXT(t) = 0;
4771:
4772: /* simplification, making polynomials monic */
4773: setfield_dalg(alist);
4774: obj_algtodalg((Obj)f,(Obj *)&f1);
4775: for ( t = BDY(f); t; t = NEXT(t) ) {
4776: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
4777: hc = (DAlg)BDY(d)->c;
4778: if ( NID(hc) == N_DA ) {
4779: invdalg(hc,&inv);
4780: for ( m = BDY(d); m; m = NEXT(m) ) {
4781: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
4782: }
4783: }
4784: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
4785: }
4786: obj_dalgtoalg((Obj)f1,(Obj *)&f);
4787:
4788: /* append alg vars to the var list */
4789: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
4790: NEXT(tv) = av;
4791:
4792: /* append a block to ord */
4793: *ord1p = append_block(ord,nvar,nalg,2);
4794:
4795: /* create generator list */
4796: nf = get_numberfield();
4797: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
4798: MKAlg(nf->defpoly[i],dp);
4799: MKNODE(s,dp,t); t = s;
4800: }
4801: MKLIST(f1,t);
4802: *alistp = alist;
4803: algobjtorat((Obj)f1,(Obj *)f1p);
4804:
4805: /* creating a new weight vector */
4806: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
4807: n = nvar+nalg+1;
4808: MKVECT(obj,n);
4809: if ( obj0 && obj0->len == nvar )
4810: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
4811: else
4812: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
4813: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
4814: BDY(obj)[n-1] = (pointer)ONE;
4815: arg = mknode(1,obj);
4816: Pdp_set_weight(arg,&tmp);
4817: }
4818:
4819: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
4820: {
4821: NODE s,t,u0,u;
4822: P p;
4823: VL tv;
4824: Obj obj;
4825: VECT tmp;
4826: NODE arg;
4827:
4828: u0 = 0;
4829: for ( t = r; t; t = NEXT(t) ) {
4830: p = (P)BDY(t);
4831: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
4832: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
4833: }
4834: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
4835: NEXTNODE(u0,u);
4836: BDY(u) = (pointer)p;
4837: }
4838: }
4839: arg = mknode(1,prev_weight_vector_obj);
4840: Pdp_set_weight(arg,&tmp);
4841:
4842: return u0;
4843: }
4844:
4845: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
4846: {
4847: VL tv,fv,vv,vc,av;
4848: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4849: int e,max,nvar,i;
4850: NDV b;
4851: int ishomo,nalg,mrank,trank,wmax,len;
4852: NMV a;
4853: Alg alpha,dp;
4854: P p,zp;
4855: Q dmy;
4856: LIST f1,f2,zpl;
4857: Obj obj;
4858: NumberField nf;
4859: struct order_spec *ord1;
4860: NODE tr,tl1,tl2,tl3,tl4,nzlist;
4861: LIST l1,l2,l3,l4,l5;
4862: int j;
4863: Z jq,bpe,last_nonzero;
4864: int *perm;
4865: EPOS oepos;
4866: int obpe,oadv,ompos,cbpe;
1.15 noro 4867: VECT hvect;
1.1 noro 4868:
1.41 noro 4869: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 4870: nd_module = 0;
4871: if ( !m && Demand ) nd_demand = 1;
4872: else nd_demand = 0;
4873:
4874: if ( DP_Multiple )
4875: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4876: #if 0
4877: ndv_alloc = 0;
4878: #endif
4879: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 4880: parse_nd_option(vv,current_option);
1.1 noro 4881: if ( m && nd_vc )
4882: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4883: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4884: switch ( ord->id ) {
4885: case 1:
4886: if ( ord->nv != nvar )
4887: error("nd_{gr,f4} : invalid order specification");
4888: break;
4889: default:
4890: break;
4891: }
4892: nd_nalg = 0;
4893: av = 0;
4894: if ( !m ) {
4895: get_algtree((Obj)f,&av);
4896: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4897: nd_ntrans = nvar;
4898: nd_nalg = nalg;
4899: /* #i -> t#i */
4900: if ( nalg ) {
4901: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4902: ord = ord1;
4903: f = f1;
4904: }
4905: nvar += nalg;
4906: }
4907: nd_init_ord(ord);
4908: mrank = 0;
4909: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4910: for ( tv = vv; tv; tv = NEXT(tv) ) {
4911: if ( nd_module ) {
1.16 noro 4912: if ( OID(BDY(t)) == O_DPM ) {
4913: e = dpm_getdeg((DPM)BDY(t),&trank);
4914: max = MAX(e,max);
4915: mrank = MAX(mrank,trank);
4916: } else {
4917: s = BDY((LIST)BDY(t));
4918: trank = length(s);
4919: mrank = MAX(mrank,trank);
4920: for ( ; s; s = NEXT(s) ) {
4921: e = getdeg(tv->v,(P)BDY(s));
4922: max = MAX(e,max);
4923: }
1.1 noro 4924: }
4925: } else {
1.43 noro 4926: if ( OID(BDY(t)) == O_DP ) {
4927: e = dp_getdeg((DP)BDY(t));
4928: max = MAX(e,max);
4929: } else {
4930: e = getdeg(tv->v,(P)BDY(t));
4931: max = MAX(e,max);
4932: }
1.1 noro 4933: }
4934: }
4935: nd_setup_parameters(nvar,nd_nzlist?0:max);
4936: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4937: ishomo = 1;
4938: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4939: if ( nd_module ) {
1.16 noro 4940: if ( OID(BDY(t)) == O_DPM ) {
4941: Z cont;
4942: DPM zdpm;
4943:
4944: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4945: else zdpm = (DPM)BDY(t);
4946: b = (pointer)dpmtondv(m,zdpm);
4947: } else {
4948: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4949: else zpl = (LIST)BDY(t);
1.1 noro 4950: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4951: }
1.1 noro 4952: } else {
1.43 noro 4953: if ( OID(BDY(t)) == O_DP ) {
4954: DP zdp;
4955:
4956: if ( !m && !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
4957: else zdp = (DP)BDY(t);
4958: b = (pointer)dptondv(m,zdp);
4959: } else {
4960: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4961: else zp = (P)BDY(t);
4962: b = (pointer)ptondv(CO,vv,zp);
4963: }
1.1 noro 4964: }
4965: if ( ishomo )
4966: ishomo = ishomo && ndv_ishomo(b);
4967: if ( m ) ndv_mod(m,b);
4968: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4969: }
4970: if ( fd0 ) NEXT(fd) = 0;
4971:
4972: if ( !ishomo && homo ) {
4973: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4974: b = (NDV)BDY(t); len = LEN(b);
4975: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4976: wmax = MAX(TD(DL(a)),wmax);
4977: }
4978: homogenize_order(ord,nvar,&ord1);
4979: nd_init_ord(ord1);
4980: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4981: for ( t = fd0; t; t = NEXT(t) )
4982: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4983: }
4984:
1.24 noro 4985: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4986: if ( nd_gentrace ) {
4987: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4988: }
4989: if ( nd_splist ) {
4990: *rp = compute_splist();
4991: return;
4992: }
4993: if ( nd_check_splist ) {
4994: if ( f4 ) {
4995: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4996: else *rp = 0;
4997: } else {
4998: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4999: else *rp = 0;
5000: }
5001: return;
5002: }
5003: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
5004: if ( !x ) {
5005: *rp = 0; return;
5006: }
1.15 noro 5007: if ( nd_gentrace ) {
5008: MKVECT(hvect,nd_psn);
5009: for ( i = 0; i < nd_psn; i++ )
5010: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5011: }
1.1 noro 5012: if ( !ishomo && homo ) {
5013: /* dehomogenization */
5014: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5015: nd_init_ord(ord);
5016: nd_setup_parameters(nvar,0);
5017: }
5018: nd_demand = 0;
5019: if ( nd_module && nd_intersect ) {
5020: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 5021: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 5022: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
5023: }
5024: conv_ilist(nd_demand,0,x,0);
5025: goto FINAL;
5026: }
5027: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
5028: x = ndv_reducebase(x,perm);
5029: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5030: x = ndv_reduceall(m,x);
5031: cbpe = nd_bpe;
5032: if ( nd_gentrace && !f4 ) {
5033: tl2 = nd_alltracelist; nd_alltracelist = 0;
5034: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
5035: tl3 = nd_alltracelist; nd_alltracelist = 0;
5036: if ( nd_gensyz ) {
5037: nd_gb(m,0,1,1,0);
5038: tl4 = nd_alltracelist; nd_alltracelist = 0;
5039: } else tl4 = 0;
5040: }
5041: nd_bpe = cbpe;
5042: nd_setup_parameters(nd_nvar,0);
5043: FINAL:
5044: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 5045: NEXTNODE(r0,r);
5046: if ( nd_module ) {
5047: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
5048: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
5049: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
5050: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 5051: }
5052: if ( r0 ) NEXT(r) = 0;
5053: if ( !m && nd_nalg )
5054: r0 = postprocess_algcoef(av,alist,r0);
5055: MKLIST(*rp,r0);
5056: if ( nd_gentrace ) {
5057: if ( f4 ) {
1.6 noro 5058: STOZ(16,bpe);
5059: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 5060: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 5061: } else {
5062: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5063: tl3 = reverse_node(tl3);
5064: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5065: for ( t = tl2; t; t = NEXT(t) ) {
5066: /* s = [i,[*,j,*,*],...] */
5067: s = BDY((LIST)BDY(t));
1.6 noro 5068: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5069: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5070: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5071: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5072: }
5073: }
5074: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5075: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5076: }
5077: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5078: MKLIST(l5,tl4);
1.6 noro 5079: STOZ(nd_bpe,bpe);
1.15 noro 5080: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5081: }
5082: }
5083: #if 0
5084: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
5085: #endif
5086: }
5087:
1.28 noro 5088: NODE nd_sba_f4(int m,int **indp);
5089:
5090: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 5091: {
5092: VL tv,fv,vv,vc,av;
1.55 noro 5093: NODE fd,fd0,r,r0,t,x,s,xx,nd,nd1,syz;
1.24 noro 5094: int e,max,nvar,i;
5095: NDV b;
5096: int ishomo,nalg,wmax,len;
5097: NMV a;
5098: P p,zp;
5099: Q dmy;
5100: struct order_spec *ord1;
5101: int j;
5102: int *perm;
5103: EPOS oepos;
5104: int obpe,oadv,ompos,cbpe;
1.51 noro 5105: struct oEGT eg0,eg1,egconv,egintred;
1.55 noro 5106: LIST l1,redind;
5107: Z z;
1.24 noro 5108:
5109: nd_module = 0;
5110: nd_demand = 0;
1.35 noro 5111: Nsamesig = 0;
1.24 noro 5112: if ( DP_Multiple )
5113: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
5114: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5115: parse_nd_option(vv,current_option);
1.24 noro 5116: if ( m && nd_vc )
5117: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
5118: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5119: switch ( ord->id ) {
5120: case 1:
5121: if ( ord->nv != nvar )
5122: error("nd_sba : invalid order specification");
5123: break;
5124: default:
5125: break;
5126: }
5127: nd_nalg = 0;
5128: nd_init_ord(ord);
5129: // for SIG comparison
5130: initd(ord);
5131: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
5132: for ( tv = vv; tv; tv = NEXT(tv) ) {
1.43 noro 5133: if ( OID(BDY(t)) == O_DP ) {
5134: e = dp_getdeg((DP)BDY(t));
5135: max = MAX(e,max);
5136: } else {
5137: e = getdeg(tv->v,(P)BDY(t));
5138: max = MAX(e,max);
5139: }
1.24 noro 5140: }
5141: }
1.25 noro 5142: nd_setup_parameters(nvar,max);
1.24 noro 5143: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
5144: ishomo = 1;
5145: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
1.43 noro 5146: if ( OID(BDY(t)) == O_DP ) {
5147: DP zdp;
5148:
5149: if ( !m ) dp_ptozp((DP)BDY(t),&zdp);
5150: else zdp = (DP)BDY(t);
5151: b = (pointer)dptondv(m,zdp);
5152: } else {
5153: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
5154: else zp = (P)BDY(t);
5155: b = (pointer)ptondv(CO,vv,zp);
5156: }
1.24 noro 5157: if ( ishomo )
5158: ishomo = ishomo && ndv_ishomo(b);
5159: if ( m ) ndv_mod(m,b);
5160: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
5161: }
5162: if ( fd0 ) NEXT(fd) = 0;
5163:
5164: if ( !ishomo && homo ) {
5165: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
5166: b = (NDV)BDY(t); len = LEN(b);
5167: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
5168: wmax = MAX(TD(DL(a)),wmax);
5169: }
5170: homogenize_order(ord,nvar,&ord1);
5171: nd_init_ord(ord1);
1.42 noro 5172: // for SIG comparison
5173: initd(ord1);
1.24 noro 5174: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
5175: for ( t = fd0; t; t = NEXT(t) )
5176: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5177: }
5178:
1.39 noro 5179: ndv_setup(m,0,fd0,nd_sba_dontsort,0,1);
1.55 noro 5180: if ( nd_gentrace ) {
5181: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5182: }
1.44 noro 5183: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm,&syz);
1.24 noro 5184: if ( !x ) {
5185: *rp = 0; return;
5186: }
5187: if ( !ishomo && homo ) {
5188: /* dehomogenization */
5189: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5190: nd_init_ord(ord);
1.42 noro 5191: // for SIG comparison
5192: initd(ord);
1.24 noro 5193: nd_setup_parameters(nvar,0);
5194: }
5195: nd_demand = 0;
1.51 noro 5196: get_eg(&eg0);
1.24 noro 5197: x = ndv_reducebase(x,perm);
1.55 noro 5198: for ( nd = 0, i = length(x)-1; i >= 0; i-- ) {
5199: STOZ(perm[i],z); MKNODE(nd1,z,nd); nd = nd1;
5200: }
5201: MKLIST(redind,nd);
1.24 noro 5202: x = ndv_reduceall(m,x);
1.51 noro 5203: get_eg(&eg1); init_eg(&egintred); add_eg(&egintred,&eg0,&eg1);
1.24 noro 5204: nd_setup_parameters(nd_nvar,0);
1.29 noro 5205: get_eg(&eg0);
1.24 noro 5206: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
5207: NEXTNODE(r0,r);
5208: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
1.34 noro 5209: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.24 noro 5210: }
5211: if ( r0 ) NEXT(r) = 0;
1.44 noro 5212: if ( nd_sba_syz ) {
5213: LIST gb,hsyz;
5214:
5215: MKLIST(gb,r0);
5216: MKLIST(hsyz,syz);
5217: nd = mknode(2,gb,hsyz);
5218: MKLIST(*rp,nd);
1.55 noro 5219: } else if ( nd_gentrace ) {
5220: LIST gb,trace;
5221:
5222: MKLIST(trace,nd_alltracelist);
5223: MKLIST(gb,r0);
5224: nd = mknode(3,gb,redind,trace);
5225: MKLIST(*rp,nd);
1.44 noro 5226: } else
5227: MKLIST(*rp,r0);
1.29 noro 5228: get_eg(&eg1); init_eg(&egconv); add_eg(&egconv,&eg0,&eg1);
1.51 noro 5229: print_eg("intred",&egintred); fprintf(asir_out,"\n");
1.29 noro 5230: print_eg("conv",&egconv); fprintf(asir_out,"\n");
1.24 noro 5231: }
5232:
1.1 noro 5233: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
5234: {
5235: VL tv,fv,vv,vc,av;
5236: NODE fd,fd0,r,r0,t,x,s,xx,alist;
5237: int e,max,nvar,i;
5238: NDV b;
5239: int ishomo,nalg;
5240: Alg alpha,dp;
5241: P p,zp;
5242: Q dmy;
5243: LIST f1,f2;
5244: Obj obj;
5245: NumberField nf;
5246: struct order_spec *ord1;
5247: int *perm;
5248:
5249: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5250: parse_nd_option(vv,current_option);
1.1 noro 5251: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5252: switch ( ord->id ) {
5253: case 1:
5254: if ( ord->nv != nvar )
5255: error("nd_check : invalid order specification");
5256: break;
5257: default:
5258: break;
5259: }
5260: nd_nalg = 0;
5261: av = 0;
5262: if ( !m ) {
5263: get_algtree((Obj)f,&av);
5264: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
5265: nd_ntrans = nvar;
5266: nd_nalg = nalg;
5267: /* #i -> t#i */
5268: if ( nalg ) {
5269: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
5270: ord = ord1;
5271: f = f1;
5272: }
5273: nvar += nalg;
5274: }
5275: nd_init_ord(ord);
5276: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
5277: for ( tv = vv; tv; tv = NEXT(tv) ) {
5278: e = getdeg(tv->v,(P)BDY(t));
5279: max = MAX(e,max);
5280: }
5281: nd_setup_parameters(nvar,max);
5282: ishomo = 1;
5283: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5284: ptozp((P)BDY(t),1,&dmy,&zp);
5285: b = (pointer)ptondv(CO,vv,zp);
5286: if ( ishomo )
5287: ishomo = ishomo && ndv_ishomo(b);
5288: if ( m ) ndv_mod(m,b);
5289: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
5290: }
5291: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 5292: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 5293: for ( x = 0, i = 0; i < nd_psn; i++ )
5294: x = update_base(x,i);
5295: if ( do_check ) {
5296: x = nd_gb(m,ishomo,1,0,&perm);
5297: if ( !x ) {
5298: *rp = 0;
5299: return;
5300: }
5301: } else {
5302: #if 0
5303: /* bug ? */
5304: for ( t = x; t; t = NEXT(t) )
5305: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
5306: #else
5307: conv_ilist(0,0,x,&perm);
5308: #endif
5309: }
5310: x = ndv_reducebase(x,perm);
5311: x = ndv_reduceall(m,x);
5312: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
5313: NEXTNODE(r0,r);
5314: BDY(r) = ndvtop(m,CO,vv,BDY(t));
5315: }
5316: if ( r0 ) NEXT(r) = 0;
5317: if ( !m && nd_nalg )
5318: r0 = postprocess_algcoef(av,alist,r0);
5319: MKLIST(*rp,r0);
5320: }
5321:
5322: NDV recompute_trace(NODE trace,NDV *p,int m);
5323: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
5324:
5325: NDV recompute_trace(NODE ti,NDV *p,int mod)
5326: {
5327: int c,c1,c2,i;
5328: NM mul,m,tail;
5329: ND d,r,rm;
5330: NODE sj;
5331: NDV red;
5332: Obj mj;
5333:
5334: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
5335: CM(mul) = 1;
5336: tail = 0;
5337: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
5338: sj = BDY((LIST)BDY(ti));
5339: if ( ARG0(sj) ) {
1.6 noro 5340: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 5341: mj = (Obj)ARG2(sj);
5342: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
5343: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
5344: rm = ndv_mul_nm(mod,mul,red);
5345: if ( !r ) r = rm;
5346: else {
5347: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
5348: if ( d ) {
5349: NEXT(tail) = m; tail = m; LEN(d)++;
5350: } else {
5351: MKND(nd_nvar,m,1,d); tail = BDY(d);
5352: }
5353: }
5354: if ( !m ) return 0; /* failure */
5355: else {
5356: BDY(r) = m;
5357: if ( mod > 0 || mod == -1 ) {
5358: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
5359: DMAR(c1,c2,0,mod,c);
5360: nd_mul_c(mod,rm,c);
5361: } else {
5362: Z t,u;
5363:
5364: chsgnlf(HCZ(r),&t);
5365: divlf(t,HCZ(rm),&u);
5366: nd_mul_c_lf(rm,u);
5367: }
5368: r = nd_add(mod,r,rm);
5369: }
5370: }
5371: }
5372: }
5373: if ( tail ) NEXT(tail) = 0;
5374: d = nd_add(mod,d,r);
5375: nd_mul_c(mod,d,invm(HCM(d),mod));
5376: return ndtondv(mod,d);
5377: }
5378:
5379: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
5380: {
5381: VL tv,fv,vv,vc,av;
5382: NODE fd,fd0,r,r0,t,x,s,xx,alist;
5383: int e,max,nvar,i;
5384: NDV b;
5385: int ishomo,nalg;
5386: Alg alpha,dp;
5387: P p,zp;
5388: Q dmy;
5389: LIST f1,f2;
5390: Obj obj;
5391: NumberField nf;
5392: struct order_spec *ord1;
5393: NODE permtrace,intred,ind,perm,trace,ti;
5394: int len,n,j;
5395: NDV *db,*pb;
5396:
5397: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5398: parse_nd_option(vv,current_option);
1.1 noro 5399: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5400: switch ( ord->id ) {
5401: case 1:
5402: if ( ord->nv != nvar )
5403: error("nd_check : invalid order specification");
5404: break;
5405: default:
5406: break;
5407: }
5408: nd_init_ord(ord);
1.6 noro 5409: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 5410: nd_setup_parameters(nvar,0);
5411:
5412: len = length(BDY(f));
5413: db = (NDV *)MALLOC(len*sizeof(NDV *));
5414: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
5415: ptozp((P)BDY(t),1,&dmy,&zp);
5416: b = ptondv(CO,vv,zp);
5417: ndv_mod(m,b);
5418: ndv_mul_c(m,b,invm(HCM(b),m));
5419: db[i] = b;
5420: }
5421:
5422: permtrace = BDY((LIST)ARG2(BDY(tlist)));
5423: intred = BDY((LIST)ARG3(BDY(tlist)));
5424: ind = BDY((LIST)ARG4(BDY(tlist)));
5425: perm = BDY((LIST)ARG0(permtrace));
5426: trace = NEXT(permtrace);
5427:
5428: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 5429: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 5430: if ( j > i ) i = j;
5431: }
5432: n = i+1;
5433: pb = (NDV *)MALLOC(n*sizeof(NDV *));
5434: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
5435: ti = BDY((LIST)BDY(t));
1.6 noro 5436: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 5437: }
5438: for ( t = trace; t; t = NEXT(t) ) {
5439: ti = BDY((LIST)BDY(t));
1.6 noro 5440: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5441: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5442: if ( DP_Print ) {
5443: fprintf(asir_out,"."); fflush(asir_out);
5444: }
5445: }
5446: for ( t = intred; t; t = NEXT(t) ) {
5447: ti = BDY((LIST)BDY(t));
1.6 noro 5448: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5449: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5450: if ( DP_Print ) {
5451: fprintf(asir_out,"*"); fflush(asir_out);
5452: }
5453: }
5454: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
5455: NEXTNODE(r0,r);
1.6 noro 5456: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 5457: ndv_mul_c(m,b,invm(HCM(b),m));
5458: #if 0
1.6 noro 5459: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5460: #else
1.6 noro 5461: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5462: #endif
5463: }
5464: if ( r0 ) NEXT(r) = 0;
5465: MKLIST(*rp,r0);
5466: if ( DP_Print ) fprintf(asir_out,"\n");
5467: }
5468:
1.16 noro 5469: void nd_gr_trace(LIST f,LIST v,int trace,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.1 noro 5470: {
5471: VL tv,fv,vv,vc,av;
5472: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
5473: int m,nocheck,nvar,mindex,e,max;
5474: NDV c;
5475: NMV a;
5476: P p,zp;
5477: Q dmy;
5478: EPOS oepos;
5479: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
5480: Alg alpha,dp;
5481: P poly;
5482: LIST f1,f2,zpl;
5483: Obj obj;
5484: NumberField nf;
5485: struct order_spec *ord1;
5486: struct oEGT eg_check,eg0,eg1;
5487: NODE tr,tl1,tl2,tl3,tl4;
5488: LIST l1,l2,l3,l4,l5;
5489: int *perm;
5490: int j,ret;
5491: Z jq,bpe;
1.15 noro 5492: VECT hvect;
1.1 noro 5493:
1.41 noro 5494: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 5495: nd_module = 0;
5496: nd_lf = 0;
1.46 noro 5497: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
5498: parse_nd_option(vv,current_option);
1.1 noro 5499: if ( nd_lf ) {
5500: if ( f4 )
5501: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
5502: else
5503: error("nd_gr_trace is not implemented yet over a large finite field");
5504: return;
5505: }
5506: if ( DP_Multiple )
5507: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
5508:
5509: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5510: switch ( ord->id ) {
5511: case 1:
5512: if ( ord->nv != nvar )
5513: error("nd_gr_trace : invalid order specification");
5514: break;
5515: default:
5516: break;
5517: }
5518:
5519: get_algtree((Obj)f,&av);
5520: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
5521: nd_ntrans = nvar;
5522: nd_nalg = nalg;
5523: /* #i -> t#i */
5524: if ( nalg ) {
5525: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
5526: ord = ord1;
5527: f = f1;
5528: }
5529: nvar += nalg;
5530:
5531: nocheck = 0;
5532: mindex = 0;
5533:
5534: if ( Demand ) nd_demand = 1;
5535: else nd_demand = 0;
5536:
5537: /* setup modulus */
5538: if ( trace < 0 ) {
5539: trace = -trace;
5540: nocheck = 1;
5541: }
5542: m = trace > 1 ? trace : get_lprime(mindex);
5543: nd_init_ord(ord);
5544: mrank = 0;
5545: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
5546: for ( tv = vv; tv; tv = NEXT(tv) ) {
5547: if ( nd_module ) {
1.16 noro 5548: if ( OID(BDY(t)) == O_DPM ) {
5549: e = dpm_getdeg((DPM)BDY(t),&trank);
5550: max = MAX(e,max);
5551: mrank = MAX(mrank,trank);
5552: } else {
1.1 noro 5553: s = BDY((LIST)BDY(t));
5554: trank = length(s);
5555: mrank = MAX(mrank,trank);
5556: for ( ; s; s = NEXT(s) ) {
5557: e = getdeg(tv->v,(P)BDY(s));
5558: max = MAX(e,max);
5559: }
1.16 noro 5560: }
1.1 noro 5561: } else {
1.43 noro 5562: if ( OID(BDY(t)) == O_DP ) {
5563: e = dp_getdeg((DP)BDY(t));
5564: max = MAX(e,max);
5565: } else {
1.1 noro 5566: e = getdeg(tv->v,(P)BDY(t));
5567: max = MAX(e,max);
1.43 noro 5568: }
1.1 noro 5569: }
5570: }
5571: nd_setup_parameters(nvar,max);
5572: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
5573: ishomo = 1;
5574: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5575: if ( nd_module ) {
1.16 noro 5576: if ( OID(BDY(t)) == O_DPM ) {
5577: Z cont;
5578: DPM zdpm;
5579:
1.17 noro 5580: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 5581: else zdpm = (DPM)BDY(t);
5582: c = (pointer)dpmtondv(m,zdpm);
5583: } else {
5584: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
5585: else zpl = (LIST)BDY(t);
1.1 noro 5586: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 5587: }
1.1 noro 5588: } else {
1.43 noro 5589: if ( OID(BDY(t)) == O_DP ) {
5590: DP zdp;
5591:
5592: if ( !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
5593: else zdp = (DP)BDY(t);
5594: c = (pointer)dptondv(m,zdp);
5595: } else {
5596: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
5597: else zp = (P)BDY(t);
5598: c = (pointer)ptondv(CO,vv,zp);
5599: }
1.1 noro 5600: }
5601: if ( ishomo )
5602: ishomo = ishomo && ndv_ishomo(c);
5603: if ( c ) {
5604: NEXTNODE(in0,in); BDY(in) = (pointer)c;
5605: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
5606: }
5607: }
5608: if ( in0 ) NEXT(in) = 0;
5609: if ( fd0 ) NEXT(fd) = 0;
5610: if ( !ishomo && homo ) {
5611: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
5612: c = (NDV)BDY(t); len = LEN(c);
5613: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
5614: wmax = MAX(TD(DL(a)),wmax);
5615: }
5616: homogenize_order(ord,nvar,&ord1);
5617: nd_init_ord(ord1);
5618: nd_setup_parameters(nvar+1,wmax);
5619: for ( t = fd0; t; t = NEXT(t) )
5620: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5621: }
5622: if ( MaxDeg > 0 ) nocheck = 1;
5623: while ( 1 ) {
5624: tl1 = tl2 = tl3 = tl4 = 0;
5625: if ( Demand )
5626: nd_demand = 1;
1.24 noro 5627: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 5628: if ( nd_gentrace ) {
5629: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5630: }
5631: if ( ret )
5632: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
5633: if ( !ret || !cand ) {
5634: /* failure */
5635: if ( trace > 1 ) { *rp = 0; return; }
5636: else m = get_lprime(++mindex);
5637: continue;
5638: }
1.15 noro 5639: if ( nd_gentrace ) {
5640: MKVECT(hvect,nd_psn);
5641: for ( i = 0; i < nd_psn; i++ )
5642: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5643: }
1.1 noro 5644: if ( !ishomo && homo ) {
5645: /* dehomogenization */
5646: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5647: nd_init_ord(ord);
5648: nd_setup_parameters(nvar,0);
5649: }
5650: nd_demand = 0;
5651: cand = ndv_reducebase(cand,perm);
5652: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5653: cand = ndv_reduceall(0,cand);
5654: cbpe = nd_bpe;
5655: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
5656: get_eg(&eg0);
5657: if ( nocheck )
5658: break;
5659: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
5660: if ( nd_gentrace ) {
5661: tl3 = nd_alltracelist; nd_alltracelist = 0;
5662: } else tl3 = 0;
5663: /* gbcheck : cand is a GB of Id(cand) ? */
1.54 noro 5664: if ( nd_vc || nd_gentrace || nd_gensyz || do_weyl )
1.1 noro 5665: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
5666: else
5667: ret = nd_f4(0,1,0)!=0;
5668: if ( nd_gentrace && nd_gensyz ) {
5669: tl4 = nd_alltracelist; nd_alltracelist = 0;
5670: } else tl4 = 0;
5671: }
5672: if ( ret ) break;
5673: else if ( trace > 1 ) {
5674: /* failure */
5675: *rp = 0; return;
5676: } else {
5677: /* try the next modulus */
5678: m = get_lprime(++mindex);
5679: /* reset the parameters */
5680: if ( !ishomo && homo ) {
5681: nd_init_ord(ord1);
5682: nd_setup_parameters(nvar+1,wmax);
5683: } else {
5684: nd_init_ord(ord);
5685: nd_setup_parameters(nvar,max);
5686: }
5687: }
5688: }
5689: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
5690: if ( DP_Print )
1.6 noro 5691: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 5692: /* dp->p */
5693: nd_bpe = cbpe;
5694: nd_setup_parameters(nd_nvar,0);
5695: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 5696: if ( nd_module ) {
1.17 noro 5697: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 5698: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 5699: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
5700: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 5701: }
5702: if ( nd_nalg )
5703: cand = postprocess_algcoef(av,alist,cand);
5704: MKLIST(*rp,cand);
5705: if ( nd_gentrace ) {
5706: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5707: tl3 = reverse_node(tl3);
5708: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5709: for ( t = tl2; t; t = NEXT(t) ) {
5710: /* s = [i,[*,j,*,*],...] */
5711: s = BDY((LIST)BDY(t));
1.6 noro 5712: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5713: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5714: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5715: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5716: }
5717: }
5718: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5719: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5720: }
5721: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5722: MKLIST(l5,tl4);
1.6 noro 5723: STOZ(nd_bpe,bpe);
1.15 noro 5724: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5725: }
5726: }
5727:
5728: /* XXX : module element is not considered */
5729:
5730: void dltondl(int n,DL dl,UINT *r)
5731: {
5732: UINT *d;
5733: int i,j,l,s,ord_l;
5734: struct order_pair *op;
5735:
5736: d = (unsigned int *)dl->d;
5737: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
5738: if ( nd_blockmask ) {
5739: l = nd_blockmask->n;
5740: op = nd_blockmask->order_pair;
5741: for ( j = 0, s = 0; j < l; j++ ) {
5742: ord_l = op[j].length;
5743: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
5744: }
5745: TD(r) = ndl_weight(r);
5746: ndl_weight_mask(r);
5747: } else {
5748: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
5749: TD(r) = ndl_weight(r);
5750: }
5751: }
5752:
5753: DL ndltodl(int n,UINT *ndl)
5754: {
5755: DL dl;
5756: int *d;
5757: int i,j,l,s,ord_l;
5758: struct order_pair *op;
5759:
1.33 noro 5760: NEWDL_NOINIT(dl,n);
1.1 noro 5761: dl->td = TD(ndl);
5762: d = dl->d;
5763: if ( nd_blockmask ) {
5764: l = nd_blockmask->n;
5765: op = nd_blockmask->order_pair;
5766: for ( j = 0, s = 0; j < l; j++ ) {
5767: ord_l = op[j].length;
5768: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5769: }
5770: } else {
5771: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5772: }
5773: return dl;
5774: }
5775:
1.24 noro 5776: void _ndltodl(UINT *ndl,DL dl)
5777: {
5778: int *d;
5779: int i,j,l,s,ord_l,n;
5780: struct order_pair *op;
5781:
5782: n = nd_nvar;
5783: dl->td = TD(ndl);
5784: d = dl->d;
5785: if ( nd_blockmask ) {
5786: l = nd_blockmask->n;
5787: op = nd_blockmask->order_pair;
5788: for ( j = 0, s = 0; j < l; j++ ) {
5789: ord_l = op[j].length;
5790: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5791: }
5792: } else {
5793: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5794: }
5795: }
5796:
1.1 noro 5797: void nmtodp(int mod,NM m,DP *r)
5798: {
5799: DP dp;
5800: MP mr;
5801:
5802: NEWMP(mr);
5803: mr->dl = ndltodl(nd_nvar,DL(m));
5804: mr->c = (Obj)ndctop(mod,m->c);
5805: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5806: *r = dp;
5807: }
5808:
1.15 noro 5809: void ndltodp(UINT *d,DP *r)
5810: {
5811: DP dp;
5812: MP mr;
5813:
5814: NEWMP(mr);
5815: mr->dl = ndltodl(nd_nvar,d);
5816: mr->c = (Obj)ONE;
5817: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5818: *r = dp;
5819: }
5820:
1.1 noro 5821: void ndl_print(UINT *dl)
5822: {
5823: int n;
5824: int i,j,l,ord_l,s,s0;
5825: struct order_pair *op;
5826:
5827: n = nd_nvar;
5828: printf("<<");
5829: if ( nd_blockmask ) {
5830: l = nd_blockmask->n;
5831: op = nd_blockmask->order_pair;
5832: for ( j = 0, s = s0 = 0; j < l; j++ ) {
5833: ord_l = op[j].length;
5834: for ( i = 0; i < ord_l; i++, s++ )
5835: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
5836: }
5837: } else {
5838: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
5839: }
5840: printf(">>");
5841: if ( nd_module && MPOS(dl) )
5842: printf("*e%d",MPOS(dl));
5843: }
5844:
5845: void nd_print(ND p)
5846: {
5847: NM m;
5848:
5849: if ( !p )
5850: printf("0\n");
5851: else {
5852: for ( m = BDY(p); m; m = NEXT(m) ) {
5853: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 5854: else printf("+%ld*",CM(m));
1.1 noro 5855: ndl_print(DL(m));
5856: }
5857: printf("\n");
5858: }
5859: }
5860:
5861: void nd_print_q(ND p)
5862: {
5863: NM m;
5864:
5865: if ( !p )
5866: printf("0\n");
5867: else {
5868: for ( m = BDY(p); m; m = NEXT(m) ) {
5869: printf("+");
1.6 noro 5870: printexpr(CO,(Obj)CZ(m));
1.1 noro 5871: printf("*");
5872: ndl_print(DL(m));
5873: }
5874: printf("\n");
5875: }
5876: }
5877:
5878: void ndp_print(ND_pairs d)
5879: {
5880: ND_pairs t;
5881:
5882: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
5883: printf("\n");
5884: }
5885:
5886: void nd_removecont(int mod,ND p)
5887: {
5888: int i,n;
5889: Z *w;
5890: NM m;
5891: struct oVECT v;
5892:
5893: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
5894: else if ( mod == -2 ) {
5895: Z inv;
5896: divlf(ONE,HCZ(p),&inv);
5897: nd_mul_c_lf(p,inv);
5898: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
5899: else {
5900: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
5901: w = (Z *)MALLOC(n*sizeof(Q));
5902: v.len = n;
5903: v.body = (pointer *)w;
1.6 noro 5904: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5905: removecont_array((P *)w,n,1);
1.6 noro 5906: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5907: }
5908: }
5909:
5910: void nd_removecont2(ND p1,ND p2)
5911: {
5912: int i,n1,n2,n;
5913: Z *w;
5914: NM m;
5915: struct oVECT v;
5916:
5917: n1 = nd_length(p1);
5918: n2 = nd_length(p2);
5919: n = n1+n2;
5920: w = (Z *)MALLOC(n*sizeof(Q));
5921: v.len = n;
5922: v.body = (pointer *)w;
5923: i = 0;
5924: if ( p1 )
1.6 noro 5925: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5926: if ( p2 )
1.6 noro 5927: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5928: removecont_array((P *)w,n,1);
5929: i = 0;
5930: if ( p1 )
1.6 noro 5931: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5932: if ( p2 )
1.6 noro 5933: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5934: }
5935:
5936: void ndv_removecont(int mod,NDV p)
5937: {
5938: int i,len,all_p;
5939: Z *c;
5940: P *w;
5941: Z dvr,t;
5942: P g,cont,tp;
5943: NMV m;
5944:
5945: if ( mod == -1 )
5946: ndv_mul_c(mod,p,_invsf(HCM(p)));
5947: else if ( mod == -2 ) {
5948: Z inv;
5949: divlf(ONE,HCZ(p),&inv);
5950: ndv_mul_c_lf(p,inv);
5951: } else if ( mod )
5952: ndv_mul_c(mod,p,invm(HCM(p),mod));
5953: else {
5954: len = p->len;
5955: w = (P *)MALLOC(len*sizeof(P));
5956: c = (Z *)MALLOC(len*sizeof(Q));
5957: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5958: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5959: all_p = all_p && !NUM(w[i]);
5960: }
5961: if ( all_p ) {
5962: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5963: mulp(nd_vc,(P)dvr,g,&cont);
5964: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5965: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5966: }
5967: } else {
5968: sortbynm((Q *)c,len);
5969: qltozl((Q *)c,len,&dvr);
5970: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5971: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5972: }
5973: }
5974: }
5975: }
5976:
5977: /* koko */
5978:
5979: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5980: {
5981: int len,i,max;
5982: NMV m,mr0,mr,t;
5983:
5984: len = p->len;
1.14 noro 5985: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5986: max = MAX(max,TD(DL(m)));
5987: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5988: m = (NMV)((char *)mr0+(len-1)*oadv);
5989: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5990: t = (NMV)MALLOC(nmv_adv);
5991: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5992: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5993: CZ(mr) = CZ(m);
1.1 noro 5994: ndl_copy(DL(t),DL(mr));
5995: }
5996: NV(p)++;
5997: BDY(p) = mr0;
5998: }
5999:
6000: void ndv_dehomogenize(NDV p,struct order_spec *ord)
6001: {
6002: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
6003: int pos;
6004: Q *w;
6005: Q dvr,t;
6006: NMV m,r;
6007:
6008: len = p->len;
6009: newnvar = nd_nvar-1;
6010: newexporigin = nd_get_exporigin(ord);
6011: if ( nd_module ) newmpos = newexporigin-1;
6012: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
6013: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
6014: ndl_dehomogenize(DL(m));
6015: if ( newwpd != nd_wpd ) {
6016: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
6017: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 6018: CZ(r) = CZ(m);
1.1 noro 6019: if ( nd_module ) pos = MPOS(DL(m));
6020: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
6021: adj = nd_exporigin-newexporigin;
6022: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
6023: if ( nd_module ) {
6024: DL(r)[newmpos] = pos;
6025: }
6026: }
6027: }
6028: NV(p)--;
6029: }
6030:
6031: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
6032: {
6033: int i;
6034: P *tpl,*tpl1;
6035: NODE l;
6036: P h,gcd,t;
6037:
6038: tpl = (P *)MALLOC(m*sizeof(P));
6039: tpl1 = (P *)MALLOC(m*sizeof(P));
6040: bcopy(pl,tpl,m*sizeof(P));
6041: gcd = (P)ONE;
6042: for ( l = nd_hcf; l; l = NEXT(l) ) {
6043: h = (P)BDY(l);
6044: while ( 1 ) {
6045: for ( i = 0; i < m; i++ )
6046: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
6047: break;
6048: if ( i == m ) {
6049: bcopy(tpl1,tpl,m*sizeof(P));
6050: mulp(vl,gcd,h,&t); gcd = t;
6051: } else
6052: break;
6053: }
6054: }
6055: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
6056: if ( full ) {
6057: heu_nezgcdnpz(vl,tpl,m,&t);
6058: mulp(vl,gcd,t,pr);
6059: } else
6060: *pr = gcd;
6061: }
6062:
6063: void removecont_array(P *p,int n,int full)
6064: {
6065: int all_p,all_q,i;
6066: Z *c;
6067: P *w;
6068: P t,s;
6069:
6070: for ( all_q = 1, i = 0; i < n; i++ )
6071: all_q = all_q && NUM(p[i]);
6072: if ( all_q ) {
6073: removecont_array_q((Z *)p,n);
6074: } else {
6075: c = (Z *)MALLOC(n*sizeof(Z));
6076: w = (P *)MALLOC(n*sizeof(P));
6077: for ( i = 0; i < n; i++ ) {
6078: ptozp(p[i],1,(Q *)&c[i],&w[i]);
6079: }
6080: removecont_array_q(c,n);
6081: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
6082: for ( i = 0; i < n; i++ ) {
6083: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
6084: }
6085: }
6086: }
6087:
6088: /* c is an int array */
6089:
6090: void removecont_array_q(Z *c,int n)
6091: {
6092: struct oVECT v;
6093: Z d0,d1,a,u,u1,gcd;
6094: int i,j;
6095: Z *q,*r;
6096:
6097: q = (Z *)MALLOC(n*sizeof(Z));
6098: r = (Z *)MALLOC(n*sizeof(Z));
6099: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
6100: gcdvz_estimate(&v,&d0);
6101: for ( i = 0; i < n; i++ ) {
6102: divqrz(c[i],d0,&q[i],&r[i]);
6103: }
6104: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
6105: if ( i < n ) {
6106: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
6107: gcdvz(&v,&d1);
6108: gcdz(d0,d1,&gcd);
1.6 noro 6109: /* exact division */
6110: divsz(d0,gcd,&a);
1.1 noro 6111: for ( i = 0; i < n; i++ ) {
6112: mulz(a,q[i],&u);
6113: if ( r[i] ) {
1.6 noro 6114: /* exact division */
6115: divsz(r[i],gcd,&u1);
1.1 noro 6116: addz(u,u1,&q[i]);
6117: } else
6118: q[i] = u;
6119: }
6120: }
6121: for ( i = 0; i < n; i++ ) c[i] = q[i];
6122: }
6123:
1.4 noro 6124: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
6125:
6126: void mpz_removecont_array(mpz_t *c,int n)
6127: {
6128: mpz_t d0,a,u,u1,gcd;
6129: int i,j;
1.13 noro 6130: static mpz_t *q,*r;
6131: static int c_len = 0;
1.4 noro 6132:
6133: for ( i = 0; i < n; i++ )
6134: if ( mpz_sgn(c[i]) ) break;
6135: if ( i == n ) return;
6136: gcdv_mpz_estimate(d0,c,n);
1.13 noro 6137: if ( n > c_len ) {
6138: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
6139: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
6140: c_len = n;
6141: }
1.4 noro 6142: for ( i = 0; i < n; i++ ) {
6143: mpz_init(q[i]); mpz_init(r[i]);
6144: mpz_fdiv_qr(q[i],r[i],c[i],d0);
6145: }
6146: for ( i = 0; i < n; i++ )
6147: if ( mpz_sgn(r[i]) ) break;
6148: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
6149: if ( i < n ) {
6150: mpz_gcd(gcd,d0,r[i]);
6151: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
6152: mpz_div(a,d0,gcd);
6153: for ( i = 0; i < n; i++ ) {
6154: mpz_mul(u,a,q[i]);
6155: if ( mpz_sgn(r[i]) ) {
6156: mpz_div(u1,r[i],gcd);
6157: mpz_add(q[i],u,u1);
6158: } else
6159: mpz_set(q[i],u);
6160: }
6161: }
6162: for ( i = 0; i < n; i++ )
6163: mpz_set(c[i],q[i]);
6164: }
6165:
1.1 noro 6166: void nd_mul_c(int mod,ND p,int mul)
6167: {
6168: NM m;
6169: int c,c1;
6170:
6171: if ( !p ) return;
6172: if ( mul == 1 ) return;
6173: if ( mod == -1 )
6174: for ( m = BDY(p); m; m = NEXT(m) )
6175: CM(m) = _mulsf(CM(m),mul);
6176: else
6177: for ( m = BDY(p); m; m = NEXT(m) ) {
6178: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6179: }
6180: }
6181:
6182: void nd_mul_c_lf(ND p,Z mul)
6183: {
6184: NM m;
6185: Z c;
6186:
6187: if ( !p ) return;
6188: if ( UNIZ(mul) ) return;
6189: for ( m = BDY(p); m; m = NEXT(m) ) {
6190: mullf(CZ(m),mul,&c); CZ(m) = c;
6191: }
6192: }
6193:
6194: void nd_mul_c_q(ND p,P mul)
6195: {
6196: NM m;
6197: P c;
6198:
6199: if ( !p ) return;
6200: if ( UNIQ(mul) ) return;
6201: for ( m = BDY(p); m; m = NEXT(m) ) {
6202: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
6203: }
6204: }
6205:
6206: void nd_mul_c_p(VL vl,ND p,P mul)
6207: {
6208: NM m;
6209: P c;
6210:
6211: if ( !p ) return;
6212: for ( m = BDY(p); m; m = NEXT(m) ) {
6213: mulp(vl,CP(m),mul,&c); CP(m) = c;
6214: }
6215: }
6216:
6217: void nd_free(ND p)
6218: {
6219: NM t,s;
6220:
6221: if ( !p ) return;
6222: t = BDY(p);
6223: while ( t ) {
6224: s = NEXT(t);
6225: FREENM(t);
6226: t = s;
6227: }
6228: FREEND(p);
6229: }
6230:
6231: void ndv_free(NDV p)
6232: {
6233: GCFREE(BDY(p));
6234: }
6235:
6236: void nd_append_red(UINT *d,int i)
6237: {
6238: RHist m,m0;
6239: int h;
6240:
6241: NEWRHist(m);
6242: h = ndl_hash_value(d);
6243: m->index = i;
6244: ndl_copy(d,DL(m));
6245: NEXT(m) = nd_red[h];
6246: nd_red[h] = m;
6247: }
6248:
6249: UINT *ndv_compute_bound(NDV p)
6250: {
6251: UINT *d1,*d2,*t;
6252: UINT u;
6253: int i,j,k,l,len,ind;
6254: NMV m;
6255:
6256: if ( !p )
6257: return 0;
6258: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6259: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6260: len = LEN(p);
6261: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
6262: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
6263: ndl_max(DL(m),d1,d2);
6264: t = d1; d1 = d2; d2 = t;
6265: }
6266: l = nd_nvar+31;
6267: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
6268: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
6269: u = d1[i];
6270: k = (nd_epw-1)*nd_bpe;
6271: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
6272: t[ind] = (u>>k)&nd_mask0;
6273: }
6274: for ( ; ind < l; ind++ ) t[ind] = 0;
6275: return t;
6276: }
6277:
6278: UINT *nd_compute_bound(ND p)
6279: {
6280: UINT *d1,*d2,*t;
6281: UINT u;
6282: int i,j,k,l,len,ind;
6283: NM m;
6284:
6285: if ( !p )
6286: return 0;
6287: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6288: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6289: len = LEN(p);
6290: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
6291: for ( m = NEXT(m); m; m = NEXT(m) ) {
6292: ndl_lcm(DL(m),d1,d2);
6293: t = d1; d1 = d2; d2 = t;
6294: }
6295: l = nd_nvar+31;
6296: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
6297: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
6298: u = d1[i];
6299: k = (nd_epw-1)*nd_bpe;
6300: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
6301: t[ind] = (u>>k)&nd_mask0;
6302: }
6303: for ( ; ind < l; ind++ ) t[ind] = 0;
6304: return t;
6305: }
6306:
6307: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
6308: /* of a term. In this case we need additional 1 word. */
6309:
6310: int nd_get_exporigin(struct order_spec *ord)
6311: {
6312: switch ( ord->id ) {
1.21 noro 6313: case 0: case 2: case 256: case 258: case 300:
1.1 noro 6314: return 1+nd_module;
6315: case 1: case 257:
6316: /* block order */
6317: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
6318: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
6319: return ord->ord.block.length+1+nd_module;
6320: case 3: case 259:
6321: #if 0
6322: error("nd_get_exporigin : composite order is not supported yet.");
6323: #else
6324: return 1+nd_module;
6325: #endif
6326: default:
6327: error("nd_get_exporigin : ivalid argument.");
6328: return 0;
6329: }
6330: }
6331:
6332: void nd_setup_parameters(int nvar,int max) {
6333: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
6334: struct order_pair *op;
1.45 noro 6335: extern int CNVars;
1.1 noro 6336:
6337: nd_nvar = nvar;
1.45 noro 6338: CNVars = nvar;
1.1 noro 6339: if ( max ) {
6340: /* XXX */
6341: if ( do_weyl ) nd_bpe = 32;
6342: else if ( max < 2 ) nd_bpe = 1;
6343: else if ( max < 4 ) nd_bpe = 2;
6344: else if ( max < 8 ) nd_bpe = 3;
6345: else if ( max < 16 ) nd_bpe = 4;
6346: else if ( max < 32 ) nd_bpe = 5;
6347: else if ( max < 64 ) nd_bpe = 6;
6348: else if ( max < 256 ) nd_bpe = 8;
6349: else if ( max < 1024 ) nd_bpe = 10;
6350: else if ( max < 65536 ) nd_bpe = 16;
6351: else nd_bpe = 32;
6352: }
6353: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
6354: UINT t;
6355: int st;
6356: int *v;
6357: /* t = max(weights) */
6358: t = 0;
6359: if ( current_dl_weight_vector )
6360: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
6361: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
6362: if ( t < st ) t = st;
6363: }
6364: if ( nd_matrix )
6365: for ( i = 0; i < nd_matrix_len; i++ )
6366: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
6367: if ( (st=v[j]) < 0 ) st = -st;
6368: if ( t < st ) t = st;
6369: }
6370: /* i = bitsize of t */
6371: for ( i = 0; t; t >>=1, i++ );
6372: /* i += bitsize of nd_nvar */
6373: for ( t = nd_nvar; t; t >>=1, i++);
6374: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
6375: if ( (nd_bpe+i) >= 31 )
6376: error("nd_setup_parameters : too large weight");
6377: }
6378: nd_epw = (sizeof(UINT)*8)/nd_bpe;
6379: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
6380: nd_exporigin = nd_get_exporigin(nd_ord);
6381: wpd = nd_exporigin+elen;
6382: if ( nd_module )
6383: nd_mpos = nd_exporigin-1;
6384: else
6385: nd_mpos = -1;
6386: if ( wpd != nd_wpd ) {
6387: nd_free_private_storage();
6388: nd_wpd = wpd;
6389: }
6390: if ( nd_bpe < 32 ) {
6391: nd_mask0 = (1<<nd_bpe)-1;
6392: } else {
6393: nd_mask0 = 0xffffffff;
6394: }
6395: bzero(nd_mask,sizeof(nd_mask));
6396: nd_mask1 = 0;
6397: for ( i = 0; i < nd_epw; i++ ) {
6398: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
6399: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
6400: }
6401: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
6402: nd_epos = nd_create_epos(nd_ord);
6403: nd_blockmask = nd_create_blockmask(nd_ord);
6404: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
6405: }
6406:
6407: ND_pairs nd_reconstruct(int trace,ND_pairs d)
6408: {
6409: int i,obpe,oadv,h;
6410: static NM prev_nm_free_list;
6411: static ND_pairs prev_ndp_free_list;
6412: RHist mr0,mr;
6413: RHist r;
6414: RHist *old_red;
6415: ND_pairs s0,s,t;
6416: EPOS oepos;
6417:
6418: obpe = nd_bpe;
6419: oadv = nmv_adv;
6420: oepos = nd_epos;
6421: if ( obpe < 2 ) nd_bpe = 2;
6422: else if ( obpe < 3 ) nd_bpe = 3;
6423: else if ( obpe < 4 ) nd_bpe = 4;
6424: else if ( obpe < 5 ) nd_bpe = 5;
6425: else if ( obpe < 6 ) nd_bpe = 6;
6426: else if ( obpe < 8 ) nd_bpe = 8;
6427: else if ( obpe < 10 ) nd_bpe = 10;
6428: else if ( obpe < 16 ) nd_bpe = 16;
6429: else if ( obpe < 32 ) nd_bpe = 32;
6430: else error("nd_reconstruct : exponent too large");
6431:
6432: nd_setup_parameters(nd_nvar,0);
6433: prev_nm_free_list = _nm_free_list;
6434: prev_ndp_free_list = _ndp_free_list;
6435: _nm_free_list = 0;
6436: _ndp_free_list = 0;
6437: for ( i = nd_psn-1; i >= 0; i-- ) {
6438: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6439: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6440: }
6441: if ( trace )
6442: for ( i = nd_psn-1; i >= 0; i-- ) {
6443: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6444: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6445: }
6446: s0 = 0;
6447: for ( t = d; t; t = NEXT(t) ) {
6448: NEXTND_pairs(s0,s);
6449: s->i1 = t->i1;
6450: s->i2 = t->i2;
1.24 noro 6451: s->sig = t->sig;
1.1 noro 6452: SG(s) = SG(t);
6453: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6454: }
6455:
6456: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6457: for ( i = 0; i < REDTAB_LEN; i++ ) {
6458: old_red[i] = nd_red[i];
6459: nd_red[i] = 0;
6460: }
6461: for ( i = 0; i < REDTAB_LEN; i++ )
6462: for ( r = old_red[i]; r; r = NEXT(r) ) {
6463: NEWRHist(mr);
6464: mr->index = r->index;
6465: SG(mr) = SG(r);
6466: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6467: h = ndl_hash_value(DL(mr));
6468: NEXT(mr) = nd_red[h];
6469: nd_red[h] = mr;
1.24 noro 6470: mr->sig = r->sig;
1.1 noro 6471: }
6472: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6473: old_red = 0;
6474: for ( i = 0; i < nd_psn; i++ ) {
6475: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6476: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 6477: r->sig = nd_psh[i]->sig;
1.1 noro 6478: nd_psh[i] = r;
6479: }
6480: if ( s0 ) NEXT(s) = 0;
6481: prev_nm_free_list = 0;
6482: prev_ndp_free_list = 0;
6483: #if 0
6484: GC_gcollect();
6485: #endif
6486: return s0;
6487: }
6488:
1.30 noro 6489: void nd_reconstruct_s(int trace,ND_pairs *d)
6490: {
6491: int i,obpe,oadv,h;
6492: static NM prev_nm_free_list;
6493: static ND_pairs prev_ndp_free_list;
6494: RHist mr0,mr;
6495: RHist r;
6496: RHist *old_red;
6497: ND_pairs s0,s,t;
6498: EPOS oepos;
6499:
6500: obpe = nd_bpe;
6501: oadv = nmv_adv;
6502: oepos = nd_epos;
6503: if ( obpe < 2 ) nd_bpe = 2;
6504: else if ( obpe < 3 ) nd_bpe = 3;
6505: else if ( obpe < 4 ) nd_bpe = 4;
6506: else if ( obpe < 5 ) nd_bpe = 5;
6507: else if ( obpe < 6 ) nd_bpe = 6;
6508: else if ( obpe < 8 ) nd_bpe = 8;
6509: else if ( obpe < 10 ) nd_bpe = 10;
6510: else if ( obpe < 16 ) nd_bpe = 16;
6511: else if ( obpe < 32 ) nd_bpe = 32;
6512: else error("nd_reconstruct_s : exponent too large");
6513:
6514: nd_setup_parameters(nd_nvar,0);
6515: prev_nm_free_list = _nm_free_list;
6516: prev_ndp_free_list = _ndp_free_list;
6517: _nm_free_list = 0;
6518: _ndp_free_list = 0;
6519: for ( i = nd_psn-1; i >= 0; i-- ) {
6520: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6521: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6522: }
6523: if ( trace )
6524: for ( i = nd_psn-1; i >= 0; i-- ) {
6525: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6526: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6527: }
6528:
6529: for ( i = 0; i < nd_nbase; i++ ) {
6530: s0 = 0;
6531: for ( t = d[i]; t; t = NEXT(t) ) {
6532: NEXTND_pairs(s0,s);
6533: s->i1 = t->i1;
6534: s->i2 = t->i2;
6535: s->sig = t->sig;
6536: SG(s) = SG(t);
6537: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6538: }
1.47 noro 6539: if ( s0 ) NEXT(s) = 0;
1.30 noro 6540: d[i] = s0;
6541: }
6542:
6543: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6544: for ( i = 0; i < REDTAB_LEN; i++ ) {
6545: old_red[i] = nd_red[i];
6546: nd_red[i] = 0;
6547: }
6548: for ( i = 0; i < REDTAB_LEN; i++ )
6549: for ( r = old_red[i]; r; r = NEXT(r) ) {
6550: NEWRHist(mr);
6551: mr->index = r->index;
6552: SG(mr) = SG(r);
6553: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6554: h = ndl_hash_value(DL(mr));
6555: NEXT(mr) = nd_red[h];
6556: nd_red[h] = mr;
6557: mr->sig = r->sig;
6558: }
6559: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6560: old_red = 0;
6561: for ( i = 0; i < nd_psn; i++ ) {
6562: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6563: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
6564: r->sig = nd_psh[i]->sig;
6565: nd_psh[i] = r;
6566: }
6567: if ( s0 ) NEXT(s) = 0;
6568: prev_nm_free_list = 0;
6569: prev_ndp_free_list = 0;
6570: #if 0
6571: GC_gcollect();
6572: #endif
6573: }
6574:
1.1 noro 6575: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
6576: {
6577: int n,i,ei,oepw,omask0,j,s,ord_l,l;
6578: struct order_pair *op;
6579:
6580: n = nd_nvar;
6581: oepw = (sizeof(UINT)*8)/obpe;
6582: omask0 = (1<<obpe)-1;
6583: TD(r) = TD(d);
6584: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
6585: if ( nd_blockmask ) {
6586: l = nd_blockmask->n;
6587: op = nd_blockmask->order_pair;
6588: for ( i = 1; i < nd_exporigin; i++ )
6589: r[i] = d[i];
6590: for ( j = 0, s = 0; j < l; j++ ) {
6591: ord_l = op[j].length;
6592: for ( i = 0; i < ord_l; i++, s++ ) {
6593: ei = GET_EXP_OLD(d,s);
6594: PUT_EXP(r,s,ei);
6595: }
6596: }
6597: } else {
6598: for ( i = 0; i < n; i++ ) {
6599: ei = GET_EXP_OLD(d,i);
6600: PUT_EXP(r,i,ei);
6601: }
6602: }
6603: if ( nd_module ) MPOS(r) = MPOS(d);
6604: }
6605:
6606: ND nd_copy(ND p)
6607: {
6608: NM m,mr,mr0;
6609: int c,n;
6610: ND r;
6611:
6612: if ( !p )
6613: return 0;
6614: else {
6615: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
6616: NEXTNM(mr0,mr);
6617: CM(mr) = CM(m);
6618: ndl_copy(DL(m),DL(mr));
6619: }
6620: NEXT(mr) = 0;
6621: MKND(NV(p),mr0,LEN(p),r);
6622: SG(r) = SG(p);
6623: return r;
6624: }
6625: }
6626:
6627: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
6628: {
6629: NM m1,m2;
6630: NDV p1,p2;
6631: ND t1,t2;
6632: UINT *lcm;
6633: P gp,tp;
6634: Z g,t;
6635: Z iq;
6636: int td;
6637: LIST hist;
6638: NODE node;
6639: DP d;
6640:
6641: if ( !mod && nd_demand ) {
6642: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
6643: } else {
6644: if ( trace ) {
6645: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
6646: } else {
6647: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
6648: }
6649: }
6650: lcm = LCM(p);
6651: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
6652: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
6653: FREENM(m1); return 0;
6654: }
6655: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
6656: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
6657: FREENM(m1); FREENM(m2); return 0;
6658: }
6659:
6660: if ( mod == -1 ) {
6661: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
6662: } else if ( mod > 0 ) {
6663: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
6664: } else if ( mod == -2 ) {
6665: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
6666: } else if ( nd_vc ) {
6667: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
6668: divsp(nd_vc,HCP(p2),gp,&CP(m1));
6669: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
6670: } else {
1.6 noro 6671: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 6672: }
6673: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
6674: *rp = nd_add(mod,t1,t2);
6675: if ( nd_gentrace ) {
6676: /* nd_tracelist is initialized */
1.6 noro 6677: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6678: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 6679: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6680: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
6681: nd_tracelist = node;
6682: }
1.24 noro 6683: if ( *rp )
6684: (*rp)->sig = p->sig;
1.1 noro 6685: FREENM(m1); FREENM(m2);
6686: return 1;
6687: }
6688:
6689: void ndv_mul_c(int mod,NDV p,int mul)
6690: {
6691: NMV m;
6692: int c,c1,len,i;
6693:
6694: if ( !p ) return;
6695: len = LEN(p);
6696: if ( mod == -1 )
6697: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
6698: CM(m) = _mulsf(CM(m),mul);
6699: else
6700: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6701: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6702: }
6703: }
6704:
6705: void ndv_mul_c_lf(NDV p,Z mul)
6706: {
6707: NMV m;
6708: Z c;
6709: int len,i;
6710:
6711: if ( !p ) return;
6712: len = LEN(p);
6713: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6714: mullf(CZ(m),mul,&c); CZ(m) = c;
6715: }
6716: }
6717:
6718: /* for nd_det */
6719: void ndv_mul_c_q(NDV p,Z mul)
6720: {
6721: NMV m;
6722: Z c;
6723: int len,i;
6724:
6725: if ( !p ) return;
6726: len = LEN(p);
6727: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 6728: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 6729: }
6730: }
6731:
6732: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
6733: int n2,i,j,l,n,tlen;
6734: UINT *d0;
6735: NM *tab,*psum;
6736: ND s,r;
6737: NM t;
6738: NMV m1;
6739:
6740: if ( !p ) return 0;
6741: n = NV(p); n2 = n>>1;
6742: d0 = DL(m0);
6743: l = LEN(p);
6744: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
6745: tab = (NM *)MALLOC(tlen*sizeof(NM));
6746: psum = (NM *)MALLOC(tlen*sizeof(NM));
6747: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
6748: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
6749: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
6750: /* m0(NM) * m1(NMV) => tab(NM) */
6751: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
6752: for ( j = 0; j < tlen; j++ ) {
6753: if ( tab[j] ) {
6754: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
6755: }
6756: }
6757: }
6758: for ( i = tlen-1, r = 0; i >= 0; i-- )
6759: if ( psum[i] ) {
6760: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
6761: MKND(n,psum[i],j,s);
6762: r = nd_add(mod,r,s);
6763: }
6764: if ( r ) SG(r) = SG(p)+TD(d0);
6765: return r;
6766: }
6767:
6768: /* product of monomials */
6769: /* XXX block order is not handled correctly */
6770:
6771: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
6772: {
6773: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
6774: UINT *d0,*d1,*d,*dt,*ctab;
6775: Z *ctab_q;
6776: Z q,q1;
6777: UINT c0,c1,c;
6778: NM *p;
6779: NM m,t;
6780: int mpos;
6781:
6782: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
6783: if ( !m0 || !m1 ) return;
6784: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
6785: if ( nd_module )
6786: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
6787:
6788: NEWNM(m); d = DL(m);
6789: if ( mod ) {
6790: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
6791: } else if ( nd_vc )
6792: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
6793: else
1.6 noro 6794: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 6795: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
6796: homo = n&1 ? 1 : 0;
6797: if ( homo ) {
6798: /* offset of h-degree */
6799: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
6800: PUT_EXP(DL(m),n-1,h);
6801: TD(DL(m)) = h;
6802: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6803: }
6804: tab[0] = m;
6805: NEWNM(m); d = DL(m);
6806: for ( i = 0, curlen = 1; i < n2; i++ ) {
6807: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
6808: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
6809: /* xi^a*(Di^k*xi^l)*Di^b */
6810: a += l; b += k;
6811: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
6812: if ( !k || !l ) {
6813: for ( j = 0; j < curlen; j++ )
6814: if ( (t = tab[j]) != 0 ) {
6815: dt = DL(t);
6816: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
6817: if ( nd_blockmask ) ndl_weight_mask(dt);
6818: }
6819: curlen *= k+1;
6820: continue;
6821: }
6822: min = MIN(k,l);
6823: if ( mod ) {
6824: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
6825: mkwcm(k,l,mod,(int *)ctab);
6826: } else {
6827: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
6828: mkwc(k,l,ctab_q);
6829: }
6830: for ( j = min; j >= 0; j-- ) {
6831: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
6832: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
6833: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
6834: if ( homo ) {
6835: TD(d) = s;
6836: PUT_EXP(d,n-1,s-h);
6837: } else TD(d) = h;
6838: if ( nd_blockmask ) ndl_weight_mask(d);
6839: if ( mod ) c = ctab[j];
6840: else q = ctab_q[j];
6841: p = tab+curlen*j;
6842: if ( j == 0 ) {
6843: for ( u = 0; u < curlen; u++, p++ ) {
6844: if ( tab[u] ) {
6845: ndl_addto(DL(tab[u]),d);
6846: if ( mod ) {
6847: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
6848: } else if ( nd_vc )
6849: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
6850: else {
1.6 noro 6851: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 6852: }
6853: }
6854: }
6855: } else {
6856: for ( u = 0; u < curlen; u++, p++ ) {
6857: if ( tab[u] ) {
6858: NEWNM(t);
6859: ndl_add(DL(tab[u]),d,DL(t));
6860: if ( mod ) {
6861: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
6862: } else if ( nd_vc )
6863: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
6864: else
1.6 noro 6865: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 6866: *p = t;
6867: }
6868: }
6869: }
6870: }
6871: curlen *= k+1;
6872: }
6873: FREENM(m);
6874: if ( nd_module ) {
6875: mpos = MPOS(d1);
6876: for ( i = 0; i < tlen; i++ )
6877: if ( tab[i] ) {
6878: d = DL(tab[i]);
6879: MPOS(d) = mpos;
6880: TD(d) = ndl_weight(d);
6881: }
6882: }
6883: }
6884:
6885: ND ndv_mul_nm_symbolic(NM m0,NDV p)
6886: {
6887: NM mr,mr0;
6888: NMV m;
6889: UINT *d,*dt,*dm;
6890: int c,n,td,i,c1,c2,len;
6891: Q q;
6892: ND r;
6893:
6894: if ( !p ) return 0;
6895: else {
6896: n = NV(p); m = BDY(p);
6897: d = DL(m0);
6898: len = LEN(p);
6899: mr0 = 0;
6900: td = TD(d);
6901: c = CM(m0);
6902: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6903: NEXTNM(mr0,mr);
6904: CM(mr) = 1;
6905: ndl_add(DL(m),d,DL(mr));
6906: }
6907: NEXT(mr) = 0;
6908: MKND(NV(p),mr0,len,r);
6909: SG(r) = SG(p) + TD(d);
6910: return r;
6911: }
6912: }
6913:
6914: ND ndv_mul_nm(int mod,NM m0,NDV p)
6915: {
6916: NM mr,mr0;
6917: NMV m;
6918: UINT *d,*dt,*dm;
6919: int c,n,td,i,c1,c2,len;
6920: P q;
6921: ND r;
6922:
6923: if ( !p ) return 0;
6924: else if ( do_weyl ) {
6925: if ( mod < 0 ) {
6926: error("ndv_mul_nm : not implemented (weyl)");
6927: return 0;
6928: } else
6929: return weyl_ndv_mul_nm(mod,m0,p);
6930: } else {
6931: n = NV(p); m = BDY(p);
6932: d = DL(m0);
6933: len = LEN(p);
6934: mr0 = 0;
6935: td = TD(d);
6936: if ( mod == -1 ) {
6937: c = CM(m0);
6938: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6939: NEXTNM(mr0,mr);
6940: CM(mr) = _mulsf(CM(m),c);
6941: ndl_add(DL(m),d,DL(mr));
6942: }
6943: } else if ( mod == -2 ) {
6944: Z cl;
6945: cl = CZ(m0);
6946: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6947: NEXTNM(mr0,mr);
6948: mullf(CZ(m),cl,&CZ(mr));
6949: ndl_add(DL(m),d,DL(mr));
6950: }
6951: } else if ( mod ) {
6952: c = CM(m0);
6953: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6954: NEXTNM(mr0,mr);
6955: c1 = CM(m);
6956: DMAR(c1,c,0,mod,c2);
6957: CM(mr) = c2;
6958: ndl_add(DL(m),d,DL(mr));
6959: }
6960: } else {
6961: q = CP(m0);
6962: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6963: NEXTNM(mr0,mr);
6964: mulp(nd_vc,CP(m),q,&CP(mr));
6965: ndl_add(DL(m),d,DL(mr));
6966: }
6967: }
6968: NEXT(mr) = 0;
6969: MKND(NV(p),mr0,len,r);
6970: SG(r) = SG(p) + TD(d);
6971: return r;
6972: }
6973: }
6974:
6975: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
6976: {
6977: NM mq0,mq;
6978: NMV tm;
6979: Q q;
6980: int i,nv,sg,c,c1,c2,hindex;
6981: ND p,t,r;
6982:
6983: if ( bucket->m < 0 ) return 0;
6984: else {
6985: nv = NV(d);
6986: mq0 = 0;
6987: tm = (NMV)MALLOC(nmv_adv);
6988: while ( 1 ) {
6989: if ( mod > 0 || mod == -1 )
6990: hindex = head_pbucket(mod,bucket);
6991: else if ( mod == -2 )
6992: hindex = head_pbucket_lf(bucket);
6993: else
6994: hindex = head_pbucket_q(bucket);
6995: if ( hindex < 0 ) break;
6996: p = bucket->body[hindex];
6997: NEXTNM(mq0,mq);
6998: ndl_sub(HDL(p),HDL(d),DL(mq));
6999: ndl_copy(DL(mq),DL(tm));
7000: if ( mod ) {
7001: c1 = invm(HCM(d),mod); c2 = HCM(p);
7002: DMAR(c1,c2,0,mod,c); CM(mq) = c;
7003: CM(tm) = mod-c;
7004: } else {
1.6 noro 7005: divsz(HCZ(p),HCZ(d),&CZ(mq));
7006: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 7007: }
7008: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
7009: bucket->body[hindex] = nd_remove_head(p);
7010: t = nd_remove_head(t);
7011: add_pbucket(mod,bucket,t);
7012: }
7013: if ( !mq0 )
7014: r = 0;
7015: else {
7016: NEXT(mq) = 0;
7017: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
7018: MKND(nv,mq0,i,r);
7019: /* XXX */
7020: SG(r) = HTD(r);
7021: }
7022: return r;
7023: }
7024: }
7025:
7026: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
7027: {
7028: NMV m,mr,mr0,t;
7029: int len,i,k;
7030:
7031: if ( !p ) return;
7032: m = BDY(p); len = LEN(p);
7033: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
7034: m = (NMV)((char *)mr0+(len-1)*oadv);
7035: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
7036: t = (NMV)MALLOC(nmv_adv);
7037: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 7038: CZ(t) = CZ(m);
1.1 noro 7039: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
7040: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 7041: CZ(mr) = CZ(t);
1.1 noro 7042: ndl_copy(DL(t),DL(mr));
7043: }
7044: BDY(p) = mr0;
7045: }
7046:
7047: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
7048: {
7049: NMV m,mr,mr0;
7050: int len,i;
7051: NDV r;
7052:
7053: if ( !p ) return 0;
7054: m = BDY(p); len = LEN(p);
7055: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
7056: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
7057: ndl_zero(DL(mr));
7058: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 7059: CZ(mr) = CZ(m);
1.1 noro 7060: }
7061: MKNDV(NV(p),mr0,len,r);
7062: SG(r) = SG(p);
1.24 noro 7063: r->sig = p->sig;
1.1 noro 7064: return r;
7065: }
7066:
7067: /* duplicate p */
7068:
7069: NDV ndv_dup(int mod,NDV p)
7070: {
7071: NDV d;
7072: NMV t,m,m0;
7073: int i,len;
7074:
7075: if ( !p ) return 0;
7076: len = LEN(p);
7077: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
7078: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
7079: ndl_copy(DL(t),DL(m));
1.6 noro 7080: CZ(m) = CZ(t);
1.1 noro 7081: }
7082: MKNDV(NV(p),m0,len,d);
7083: SG(d) = SG(p);
7084: return d;
7085: }
7086:
7087: NDV ndv_symbolic(int mod,NDV p)
7088: {
7089: NDV d;
7090: NMV t,m,m0;
7091: int i,len;
7092:
7093: if ( !p ) return 0;
7094: len = LEN(p);
7095: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
7096: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
7097: ndl_copy(DL(t),DL(m));
1.6 noro 7098: CZ(m) = ONE;
1.1 noro 7099: }
7100: MKNDV(NV(p),m0,len,d);
7101: SG(d) = SG(p);
7102: return d;
7103: }
7104:
7105: ND nd_dup(ND p)
7106: {
7107: ND d;
7108: NM t,m,m0;
7109:
7110: if ( !p ) return 0;
7111: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
7112: NEXTNM(m0,m);
7113: ndl_copy(DL(t),DL(m));
1.6 noro 7114: CZ(m) = CZ(t);
1.1 noro 7115: }
7116: if ( m0 ) NEXT(m) = 0;
7117: MKND(NV(p),m0,LEN(p),d);
7118: SG(d) = SG(p);
7119: return d;
7120: }
7121:
7122: /* XXX if p->len == 0 then it represents 0 */
7123:
7124: void ndv_mod(int mod,NDV p)
7125: {
7126: NMV t,d;
7127: int r,s,u;
7128: int i,len,dlen;
7129: P cp;
7130: Z c;
7131: Obj gfs;
7132:
7133: if ( !p ) return;
7134: len = LEN(p);
7135: dlen = 0;
7136: if ( mod == -1 )
7137: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7138: simp_ff((Obj)CP(t),&gfs);
7139: if ( gfs ) {
7140: r = FTOIF(CONT((GFS)gfs));
7141: CM(d) = r;
7142: ndl_copy(DL(t),DL(d));
7143: NMV_ADV(d);
7144: dlen++;
7145: }
7146: }
7147: else if ( mod == -2 )
7148: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7149: simp_ff((Obj)CP(t),&gfs);
7150: if ( gfs ) {
7151: lmtolf((LM)gfs,&CZ(d));
7152: ndl_copy(DL(t),DL(d));
7153: NMV_ADV(d);
7154: dlen++;
7155: }
7156: }
7157: else
7158: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7159: if ( nd_vc ) {
7160: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
7161: c = (Z)cp;
7162: } else
1.6 noro 7163: c = CZ(t);
1.1 noro 7164: r = remqi((Q)c,mod);
7165: if ( r ) {
7166: CM(d) = r;
7167: ndl_copy(DL(t),DL(d));
7168: NMV_ADV(d);
7169: dlen++;
7170: }
7171: }
7172: LEN(p) = dlen;
7173: }
7174:
7175: NDV ptondv(VL vl,VL dvl,P p)
7176: {
7177: ND nd;
7178:
7179: nd = ptond(vl,dvl,p);
7180: return ndtondv(0,nd);
7181: }
7182:
7183: void pltozpl(LIST l,Q *cont,LIST *pp)
7184: {
1.16 noro 7185: NODE nd,nd1;
7186: int n;
7187: P *pl;
7188: Q *cl;
7189: int i;
7190: P dmy;
7191: Z dvr,inv;
7192: LIST r;
7193:
7194: nd = BDY(l); n = length(nd);
7195: pl = (P *)MALLOC(n*sizeof(P));
7196: cl = (Q *)MALLOC(n*sizeof(Q));
7197: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
7198: ptozp((P)BDY(nd),1,&cl[i],&dmy);
7199: }
7200: qltozl(cl,n,&dvr);
7201: divz(ONE,dvr,&inv);
7202: nd = BDY(l);
7203: for ( i = 0; i < n; i++, nd = NEXT(nd) )
7204: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
7205: nd = 0;
7206: for ( i = n-1; i >= 0; i-- ) {
7207: MKNODE(nd1,pl[i],nd); nd = nd1;
7208: }
7209: MKLIST(r,nd);
7210: *pp = r;
1.1 noro 7211: }
7212:
7213: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
7214:
7215: NDV pltondv(VL vl,VL dvl,LIST p)
7216: {
7217: int i;
7218: NODE t;
7219: ND r,ri;
7220: NM m;
7221:
7222: if ( !nd_module ) error("pltond : module order must be set");
7223: r = 0;
7224: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
7225: ri = ptond(vl,dvl,(P)BDY(t));
7226: if ( ri )
7227: for ( m = BDY(ri); m; m = NEXT(m) ) {
7228: MPOS(DL(m)) = i;
7229: TD(DL(m)) = ndl_weight(DL(m));
7230: if ( nd_blockmask ) ndl_weight_mask(DL(m));
7231: }
7232: r = nd_add(0,r,ri);
7233: }
7234: return ndtondv(0,r);
7235: }
7236:
7237: ND ptond(VL vl,VL dvl,P p)
7238: {
7239: int n,i,j,k,e;
7240: VL tvl;
7241: V v;
7242: DCP dc;
7243: DCP *w;
7244: ND r,s,t,u;
7245: P x;
7246: int c;
7247: UINT *d;
7248: NM m,m0;
7249:
7250: if ( !p )
7251: return 0;
7252: else if ( NUM(p) ) {
7253: NEWNM(m);
7254: ndl_zero(DL(m));
1.48 noro 7255: if ( RATN(p) && !INT((Q)p) )
1.1 noro 7256: error("ptond : input must be integer-coefficient");
1.6 noro 7257: CZ(m) = (Z)p;
1.1 noro 7258: NEXT(m) = 0;
7259: MKND(nd_nvar,m,1,r);
7260: SG(r) = 0;
7261: return r;
7262: } else {
7263: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
7264: w = (DCP *)MALLOC(k*sizeof(DCP));
7265: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
7266: for ( i = 0, tvl = dvl, v = VR(p);
7267: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
7268: if ( !tvl ) {
7269: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
7270: t = ptond(vl,dvl,COEF(w[j]));
7271: pwrp(vl,x,DEG(w[j]),&p);
7272: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
7273: }
7274: return s;
7275: } else {
7276: NEWNM(m0); d = DL(m0);
7277: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 7278: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 7279: TD(d) = MUL_WEIGHT(e,i);
7280: if ( nd_blockmask) ndl_weight_mask(d);
7281: if ( nd_module ) MPOS(d) = 0;
7282: t = ptond(vl,dvl,COEF(w[j]));
7283: for ( m = BDY(t); m; m = NEXT(m) )
7284: ndl_addto(DL(m),d);
7285: SG(t) += TD(d);
7286: s = nd_add(0,s,t);
7287: }
7288: FREENM(m0);
7289: return s;
7290: }
7291: }
7292: }
7293:
7294: P ndvtop(int mod,VL vl,VL dvl,NDV p)
7295: {
7296: VL tvl;
7297: int len,n,j,i,e;
7298: NMV m;
7299: Z q;
7300: P c;
7301: UINT *d;
7302: P s,r,u,t,w;
7303: GFS gfs;
7304:
7305: if ( !p ) return 0;
7306: else {
7307: len = LEN(p);
7308: n = NV(p);
7309: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7310: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
7311: if ( mod == -1 ) {
7312: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7313: } else if ( mod == -2 ) {
7314: c = (P)CZ(m);
7315: } else if ( mod > 0 ) {
1.6 noro 7316: STOZ(CM(m),q); c = (P)q;
1.1 noro 7317: } else
7318: c = CP(m);
7319: d = DL(m);
7320: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7321: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7322: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7323: }
7324: addp(vl,s,t,&u); s = u;
7325: }
7326: return s;
7327: }
7328: }
7329:
7330: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
7331: {
7332: VL tvl;
7333: int len,n,j,i,e;
7334: NMV m;
7335: Z q;
7336: P c;
7337: UINT *d;
7338: P s,r,u,t,w;
7339: GFS gfs;
7340: P *a;
7341: LIST l;
7342: NODE nd,nd1;
7343:
7344: if ( !p ) return 0;
7345: else {
7346: a = (P *)MALLOC((rank+1)*sizeof(P));
7347: for ( i = 0; i <= rank; i++ ) a[i] = 0;
7348: len = LEN(p);
7349: n = NV(p);
7350: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7351: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
7352: if ( mod == -1 ) {
7353: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7354: } else if ( mod ) {
1.6 noro 7355: STOZ(CM(m),q); c = (P)q;
1.1 noro 7356: } else
7357: c = CP(m);
7358: d = DL(m);
7359: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7360: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7361: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7362: }
7363: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
7364: }
7365: nd = 0;
7366: for ( i = rank; i > 0; i-- ) {
7367: MKNODE(nd1,a[i],nd); nd = nd1;
7368: }
7369: MKLIST(l,nd);
7370: return l;
7371: }
7372: }
7373:
7374: NDV ndtondv(int mod,ND p)
7375: {
7376: NDV d;
7377: NMV m,m0;
7378: NM t;
7379: int i,len;
7380:
7381: if ( !p ) return 0;
7382: len = LEN(p);
7383: if ( mod > 0 || mod == -1 )
7384: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7385: else
7386: m0 = m = MALLOC(len*nmv_adv);
7387: #if 0
7388: ndv_alloc += nmv_adv*len;
7389: #endif
7390: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
7391: ndl_copy(DL(t),DL(m));
1.6 noro 7392: CZ(m) = CZ(t);
1.1 noro 7393: }
7394: MKNDV(NV(p),m0,len,d);
7395: SG(d) = SG(p);
1.24 noro 7396: d->sig = p->sig;
1.1 noro 7397: return d;
7398: }
7399:
1.16 noro 7400: static int dmm_comp_nv;
7401:
7402: int dmm_comp(DMM *a,DMM *b)
7403: {
7404: return -compdmm(dmm_comp_nv,*a,*b);
7405: }
7406:
7407: void dmm_sort_by_ord(DMM *a,int len,int nv)
7408: {
7409: dmm_comp_nv = nv;
7410: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
7411: }
7412:
7413: void dpm_sort(DPM p,DPM *rp)
7414: {
7415: DMM t,t1;
7416: int len,i,n;
7417: DMM *a;
7418: DPM d;
7419:
7420: if ( !p ) *rp = 0;
7421: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7422: a = (DMM *)MALLOC(len*sizeof(DMM));
7423: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7424: n = p->nv;
7425: dmm_sort_by_ord(a,len,n);
7426: t = 0;
7427: for ( i = len-1; i >= 0; i-- ) {
7428: NEWDMM(t1);
7429: t1->c = a[i]->c;
7430: t1->dl = a[i]->dl;
7431: t1->pos = a[i]->pos;
7432: t1->next = t;
7433: t = t1;
7434: }
7435: MKDPM(n,t,d);
7436: SG(d) = SG(p);
7437: *rp = d;
7438: }
7439:
1.18 noro 7440: int dpm_comp(DPM *a,DPM *b)
7441: {
1.22 noro 7442: return -compdpm(CO,*a,*b);
1.18 noro 7443: }
7444:
7445: NODE dpm_sort_list(NODE l)
7446: {
7447: int i,len;
7448: NODE t,t1;
7449: DPM *a;
7450:
7451: len = length(l);
7452: a = (DPM *)MALLOC(len*sizeof(DPM));
7453: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
7454: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
7455: t = 0;
7456: for ( i = len-1; i >= 0; i-- ) {
7457: MKNODE(t1,(pointer)a[i],t); t = t1;
7458: }
7459: return t;
7460: }
7461:
1.20 noro 7462: int nmv_comp(NMV a,NMV b)
7463: {
1.21 noro 7464: int t;
7465: t = DL_COMPARE(a->dl,b->dl);
7466: return -t;
1.20 noro 7467: }
7468:
1.43 noro 7469: NDV dptondv(int mod,DP p)
7470: {
7471: NDV d;
7472: NMV m,m0;
7473: MP t;
7474: MP *a;
7475: int i,len,n;
7476:
7477: if ( !p ) return 0;
7478: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7479: n = p->nv;
7480: if ( mod > 0 || mod == -1 )
7481: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7482: else
7483: m0 = m = MALLOC(len*nmv_adv);
7484: for ( i = 0, t = BDY(p); i < len; i++, NMV_ADV(m), t = NEXT(t) ) {
7485: dltondl(n,t->dl,DL(m));
7486: TD(DL(m)) = ndl_weight(DL(m));
7487: CZ(m) = (Z)t->c;
7488: }
7489: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
7490: MKNDV(NV(p),m0,len,d);
7491: SG(d) = SG(p);
7492: return d;
7493: }
7494:
1.16 noro 7495: NDV dpmtondv(int mod,DPM p)
7496: {
7497: NDV d;
7498: NMV m,m0;
7499: DMM t;
7500: DMM *a;
7501: int i,len,n;
7502:
7503: if ( !p ) return 0;
7504: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7505: a = (DMM *)MALLOC(len*sizeof(DMM));
7506: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7507: n = p->nv;
7508: dmm_sort_by_ord(a,len,n);
7509: if ( mod > 0 || mod == -1 )
7510: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7511: else
7512: m0 = m = MALLOC(len*nmv_adv);
7513: #if 0
7514: ndv_alloc += nmv_adv*len;
7515: #endif
7516: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
7517: dltondl(n,a[i]->dl,DL(m));
7518: MPOS(DL(m)) = a[i]->pos;
1.20 noro 7519: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 7520: CZ(m) = (Z)a[i]->c;
7521: }
1.20 noro 7522: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 7523: MKNDV(NV(p),m0,len,d);
7524: SG(d) = SG(p);
7525: return d;
7526: }
7527:
1.1 noro 7528: ND ndvtond(int mod,NDV p)
7529: {
7530: ND d;
7531: NM m,m0;
7532: NMV t;
7533: int i,len;
7534:
7535: if ( !p ) return 0;
7536: m0 = 0;
7537: len = p->len;
7538: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7539: NEXTNM(m0,m);
7540: ndl_copy(DL(t),DL(m));
1.6 noro 7541: CZ(m) = CZ(t);
1.1 noro 7542: }
7543: NEXT(m) = 0;
7544: MKND(NV(p),m0,len,d);
7545: SG(d) = SG(p);
1.28 noro 7546: d->sig = p->sig;
1.1 noro 7547: return d;
7548: }
7549:
7550: DP ndvtodp(int mod,NDV p)
7551: {
7552: MP m,m0;
7553: DP d;
7554: NMV t;
7555: int i,len;
7556:
7557: if ( !p ) return 0;
7558: m0 = 0;
7559: len = p->len;
7560: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7561: NEXTMP(m0,m);
7562: m->dl = ndltodl(nd_nvar,DL(t));
7563: m->c = (Obj)ndctop(mod,t->c);
7564: }
7565: NEXT(m) = 0;
7566: MKDP(nd_nvar,m0,d);
7567: SG(d) = SG(p);
7568: return d;
7569: }
7570:
1.44 noro 7571: DPM sigtodpm(SIG s)
7572: {
7573: DMM m;
7574: DPM d;
7575:
7576: NEWDMM(m);
7577: m->c = (Obj)ONE;
7578: m->dl = s->dl;
7579: m->pos = s->pos+1;
7580: m->next = 0;
7581: MKDPM(nd_nvar,m,d);
7582: SG(d) = s->dl->td;
7583: return d;
7584: }
7585:
1.16 noro 7586: DPM ndvtodpm(int mod,NDV p)
7587: {
7588: DMM m,m0;
7589: DPM d;
7590: NMV t;
7591: int i,len;
7592:
7593: if ( !p ) return 0;
7594: m0 = 0;
7595: len = p->len;
7596: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7597: NEXTDMM(m0,m);
7598: m->dl = ndltodl(nd_nvar,DL(t));
7599: m->c = (Obj)ndctop(mod,t->c);
7600: m->pos = MPOS(DL(t));
7601: }
7602: NEXT(m) = 0;
7603: MKDPM(nd_nvar,m0,d);
7604: SG(d) = SG(p);
7605: return d;
7606: }
7607:
7608:
1.1 noro 7609: DP ndtodp(int mod,ND p)
7610: {
7611: MP m,m0;
7612: DP d;
7613: NM t;
7614: int i,len;
7615:
7616: if ( !p ) return 0;
7617: m0 = 0;
7618: len = p->len;
7619: for ( t = BDY(p); t; t = NEXT(t) ) {
7620: NEXTMP(m0,m);
7621: m->dl = ndltodl(nd_nvar,DL(t));
7622: m->c = (Obj)ndctop(mod,t->c);
7623: }
7624: NEXT(m) = 0;
7625: MKDP(nd_nvar,m0,d);
7626: SG(d) = SG(p);
7627: return d;
7628: }
7629:
7630: void ndv_print(NDV p)
7631: {
7632: NMV m;
7633: int i,len;
7634:
7635: if ( !p ) printf("0\n");
7636: else {
7637: len = LEN(p);
7638: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7639: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 7640: else printf("+%ld*",CM(m));
1.1 noro 7641: ndl_print(DL(m));
7642: }
7643: printf("\n");
7644: }
7645: }
7646:
7647: void ndv_print_q(NDV p)
7648: {
7649: NMV m;
7650: int i,len;
7651:
7652: if ( !p ) printf("0\n");
7653: else {
7654: len = LEN(p);
7655: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7656: printf("+");
1.6 noro 7657: printexpr(CO,(Obj)CZ(m));
1.1 noro 7658: printf("*");
7659: ndl_print(DL(m));
7660: }
7661: printf("\n");
7662: }
7663: }
7664:
7665: NODE ndv_reducebase(NODE x,int *perm)
7666: {
7667: int len,i,j;
7668: NDVI w;
7669: NODE t,t0;
7670:
1.41 noro 7671: if ( nd_norb ) return x;
1.1 noro 7672: len = length(x);
7673: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
7674: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
7675: w[i].p = BDY(t); w[i].i = perm[i];
7676: }
7677: for ( i = 0; i < len; i++ ) {
7678: for ( j = 0; j < i; j++ ) {
7679: if ( w[i].p && w[j].p ) {
7680: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
7681: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
7682: }
7683: }
7684: }
7685: for ( i = j = 0, t0 = 0; i < len; i++ ) {
7686: if ( w[i].p ) {
7687: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
7688: perm[j++] = w[i].i;
7689: }
7690: }
7691: NEXT(t) = 0; x = t0;
7692: return x;
7693: }
7694:
7695: /* XXX incomplete */
7696:
1.21 noro 7697: extern DMMstack dmm_stack;
7698: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 7699:
1.1 noro 7700: void nd_init_ord(struct order_spec *ord)
7701: {
7702: nd_module = (ord->id >= 256);
7703: if ( nd_module ) {
7704: nd_dcomp = -1;
1.21 noro 7705: nd_module_ordtype = ord->module_ordtype;
1.1 noro 7706: nd_pot_nelim = ord->pot_nelim;
7707: nd_poly_weight_len = ord->nv;
7708: nd_poly_weight = ord->top_weight;
7709: nd_module_rank = ord->module_rank;
7710: nd_module_weight = ord->module_top_weight;
7711: }
7712: nd_matrix = 0;
7713: nd_matrix_len = 0;
7714: switch ( ord->id ) {
7715: case 0:
7716: switch ( ord->ord.simple ) {
7717: case 0:
7718: nd_dcomp = 1;
7719: nd_isrlex = 1;
7720: break;
7721: case 1:
7722: nd_dcomp = 1;
7723: nd_isrlex = 0;
7724: break;
7725: case 2:
7726: nd_dcomp = 0;
7727: nd_isrlex = 0;
7728: ndl_compare_function = ndl_lex_compare;
7729: break;
7730: case 11:
7731: /* XXX */
7732: nd_dcomp = 0;
7733: nd_isrlex = 1;
7734: ndl_compare_function = ndl_ww_lex_compare;
7735: break;
7736: default:
7737: error("nd_gr : unsupported order");
7738: }
7739: break;
7740: case 1:
7741: /* block order */
7742: /* XXX */
7743: nd_dcomp = -1;
7744: nd_isrlex = 0;
7745: ndl_compare_function = ndl_block_compare;
7746: break;
7747: case 2:
7748: /* matrix order */
7749: /* XXX */
7750: nd_dcomp = -1;
7751: nd_isrlex = 0;
7752: nd_matrix_len = ord->ord.matrix.row;
7753: nd_matrix = ord->ord.matrix.matrix;
7754: ndl_compare_function = ndl_matrix_compare;
7755: break;
7756: case 3:
7757: /* composite order */
7758: nd_dcomp = -1;
7759: nd_isrlex = 0;
7760: nd_worb_len = ord->ord.composite.length;
7761: nd_worb = ord->ord.composite.w_or_b;
7762: ndl_compare_function = ndl_composite_compare;
7763: break;
7764:
7765: /* module order */
7766: case 256:
7767: switch ( ord->ord.simple ) {
7768: case 0:
1.21 noro 7769: nd_dcomp = 0;
1.1 noro 7770: nd_isrlex = 1;
1.21 noro 7771: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 7772: break;
7773: case 1:
1.21 noro 7774: nd_dcomp = 0;
1.1 noro 7775: nd_isrlex = 0;
7776: ndl_compare_function = ndl_module_glex_compare;
7777: break;
7778: case 2:
1.21 noro 7779: nd_dcomp = 0;
1.1 noro 7780: nd_isrlex = 0;
1.21 noro 7781: ndl_compare_function = ndl_module_compare;
7782: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 7783: break;
7784: default:
1.21 noro 7785: error("nd_init_ord : unsupported order");
1.1 noro 7786: }
7787: break;
7788: case 257:
7789: /* block order */
7790: nd_isrlex = 0;
1.21 noro 7791: ndl_compare_function = ndl_module_compare;
7792: ndl_base_compare_function = ndl_block_compare;
1.1 noro 7793: break;
7794: case 258:
7795: /* matrix order */
7796: nd_isrlex = 0;
7797: nd_matrix_len = ord->ord.matrix.row;
7798: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 7799: ndl_compare_function = ndl_module_compare;
7800: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 7801: break;
7802: case 259:
7803: /* composite order */
7804: nd_isrlex = 0;
7805: nd_worb_len = ord->ord.composite.length;
7806: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 7807: ndl_compare_function = ndl_module_compare;
7808: ndl_base_compare_function = ndl_composite_compare;
7809: break;
7810: case 300:
7811: /* schreyer order */
7812: if ( ord->base->id != 256 )
7813: error("nd_init_ord : unsupported base order");
7814: ndl_compare_function = ndl_module_schreyer_compare;
7815: dmm_stack = ord->dmmstack;
7816: switch ( ord->base->ord.simple ) {
7817: case 0:
7818: nd_isrlex = 1;
7819: ndl_base_compare_function = ndl_glex_compare;
7820: dl_base_compare_function = cmpdl_revgradlex;
7821: break;
7822: case 1:
7823: nd_isrlex = 0;
7824: ndl_base_compare_function = ndl_glex_compare;
7825: dl_base_compare_function = cmpdl_gradlex;
7826: break;
7827: case 2:
7828: nd_isrlex = 0;
7829: ndl_base_compare_function = ndl_lex_compare;
7830: dl_base_compare_function = cmpdl_lex;
7831: break;
7832: default:
7833: error("nd_init_ord : unsupported order");
7834: }
1.1 noro 7835: break;
7836: }
7837: nd_ord = ord;
7838: }
7839:
7840: BlockMask nd_create_blockmask(struct order_spec *ord)
7841: {
7842: int n,i,j,s,l;
7843: UINT *t;
7844: BlockMask bm;
7845:
7846: /* we only create mask table for block order */
7847: if ( ord->id != 1 && ord->id != 257 )
7848: return 0;
7849: n = ord->ord.block.length;
7850: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
7851: bm->n = n;
7852: bm->order_pair = ord->ord.block.order_pair;
7853: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
7854: for ( i = 0, s = 0; i < n; i++ ) {
7855: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
7856: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
7857: l = bm->order_pair[i].length;
7858: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
7859: }
7860: return bm;
7861: }
7862:
7863: EPOS nd_create_epos(struct order_spec *ord)
7864: {
7865: int i,j,l,s,ord_l,ord_o;
7866: EPOS epos;
7867: struct order_pair *op;
7868:
7869: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
7870: switch ( ord->id ) {
1.21 noro 7871: case 0: case 256: case 300:
1.1 noro 7872: if ( nd_isrlex ) {
7873: for ( i = 0; i < nd_nvar; i++ ) {
7874: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
7875: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
7876: }
7877: } else {
7878: for ( i = 0; i < nd_nvar; i++ ) {
7879: epos[i].i = nd_exporigin + i/nd_epw;
7880: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7881: }
7882: }
7883: break;
7884: case 1: case 257:
7885: /* block order */
7886: l = ord->ord.block.length;
7887: op = ord->ord.block.order_pair;
7888: for ( j = 0, s = 0; j < l; j++ ) {
7889: ord_o = op[j].order;
7890: ord_l = op[j].length;
7891: if ( !ord_o )
7892: for ( i = 0; i < ord_l; i++ ) {
7893: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
7894: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
7895: }
7896: else
7897: for ( i = 0; i < ord_l; i++ ) {
7898: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
7899: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
7900: }
7901: s += ord_l;
7902: }
7903: break;
7904: case 2:
7905: /* matrix order */
7906: case 3:
7907: /* composite order */
7908: default:
7909: for ( i = 0; i < nd_nvar; i++ ) {
7910: epos[i].i = nd_exporigin + i/nd_epw;
7911: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7912: }
7913: break;
7914: }
7915: return epos;
7916: }
7917:
7918: /* external interface */
7919:
7920: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
7921: {
7922: NODE t,in0,in;
7923: ND ndf,nf;
7924: NDV ndvf;
7925: VL vv,tv;
7926: int stat,nvar,max,mrank;
7927: union oNDC dn;
7928: Q cont;
7929: P pp;
7930: LIST ppl;
7931:
7932: if ( !f ) {
7933: *rp = 0;
7934: return;
7935: }
7936: pltovl(v,&vv);
7937: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
7938:
7939: /* max=65536 implies nd_bpe=32 */
7940: max = 65536;
7941:
7942: nd_module = 0;
7943: /* nd_module will be set if ord is a module ordering */
7944: nd_init_ord(ord);
7945: nd_setup_parameters(nvar,max);
7946: if ( nd_module && OID(f) != O_LIST )
7947: error("nd_nf_p : the first argument must be a list");
7948: if ( nd_module ) mrank = length(BDY((LIST)f));
7949: /* conversion to ndv */
7950: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
7951: NEXTNODE(in0,in);
7952: if ( nd_module ) {
7953: if ( !BDY(t) || OID(BDY(t)) != O_LIST
7954: || length(BDY((LIST)BDY(t))) != mrank )
7955: error("nd_nf_p : inconsistent basis element");
7956: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
7957: else ppl = (LIST)BDY(t);
7958: BDY(in) = (pointer)pltondv(CO,vv,ppl);
7959: } else {
7960: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
7961: else pp = (P)BDY(t);
7962: BDY(in) = (pointer)ptondv(CO,vv,pp);
7963: }
7964: if ( m ) ndv_mod(m,(NDV)BDY(in));
7965: }
7966: if ( in0 ) NEXT(in) = 0;
7967:
7968: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
7969: else ndvf = ptondv(CO,vv,(P)f);
7970: if ( m ) ndv_mod(m,ndvf);
7971: ndf = (pointer)ndvtond(m,ndvf);
7972:
7973: /* dont sort, dont removecont */
1.24 noro 7974: ndv_setup(m,0,in0,1,1,0);
1.1 noro 7975: nd_scale=2;
1.6 noro 7976: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 7977: if ( !stat )
7978: error("nd_nf_p : exponent too large");
7979: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
7980: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
7981: }
7982:
7983: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
7984: {
7985: NM m;
7986: UINT *t,*s;
7987: int i;
7988:
7989: for ( i = 0; i < n; i++ ) r[i] = 0;
7990: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7991: t = DL(m);
7992: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7993: r[i] = CM(m);
7994: }
7995: for ( i = 0; !r[i]; i++ );
7996: return i;
7997: }
7998:
7999: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
8000: {
8001: NM m;
8002: UINT *t,*s;
8003: int i;
8004:
8005: for ( i = 0; i < n; i++ ) r[i] = 0;
8006: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
8007: t = DL(m);
8008: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 8009: r[i] = CZ(m);
1.1 noro 8010: }
8011: for ( i = 0; !r[i]; i++ );
8012: return i;
8013: }
8014:
8015: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
8016: {
8017: NM m;
8018: UINT *t,*s;
8019: int i;
8020:
8021: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
8022: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
8023: t = DL(m);
8024: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
8025: mpz_set(r[i],BDY(CZ(m)));
8026: }
8027: for ( i = 0; !mpz_sgn(r[i]); i++ );
8028: return i;
8029: }
8030:
8031: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
8032: {
8033: NM m;
8034: unsigned long *v;
8035: int i,j,h,size;
8036: UINT *s,*t;
8037:
8038: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
8039: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
8040: bzero(v,size);
8041: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
8042: t = DL(m);
8043: h = ndl_hash_value(t);
8044: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
8045: v[i/BLEN] |= 1L <<(i%BLEN);
8046: }
8047: return v;
8048: }
8049:
8050: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
8051: {
8052: NMV mr;
8053: UINT *d,*t,*s;
8054: int i,j,len,h,head;
8055:
8056: d = DL(m);
8057: len = LEN(p);
8058: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8059: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
8060: ndl_add(d,DL(mr),t);
8061: h = ndl_hash_value(t);
8062: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
8063: if ( j == 0 ) head = i;
8064: v[i/BLEN] |= 1L <<(i%BLEN);
8065: }
8066: return head;
8067: }
8068:
8069: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
8070: {
8071: NM m;
8072: NMV mr;
8073: UINT *d,*t,*s;
8074: NDV p;
8075: int i,j,len;
8076: Z *r;
8077:
8078: m = pair->mul;
8079: d = DL(m);
8080: p = nd_ps[pair->index];
8081: len = LEN(p);
8082: r = (Z *)CALLOC(n,sizeof(Q));
8083: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8084: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
8085: ndl_add(d,DL(mr),t);
8086: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 8087: r[i] = CZ(mr);
1.1 noro 8088: }
8089: return r;
8090: }
8091:
1.11 noro 8092: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 8093: {
8094: NM m;
8095: NMV mr;
1.11 noro 8096: UINT *d,*t,*s,*u;
1.1 noro 8097: NDV p;
8098: unsigned char *ivc;
8099: unsigned short *ivs;
8100: UINT *v,*ivi,*s0v;
1.11 noro 8101: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 8102: IndArray r;
8103:
8104: m = pair->mul;
8105: d = DL(m);
8106: if ( trace )
8107: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
8108: else
8109: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
8110:
8111: len = LEN(p);
8112: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8113: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 8114: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
8115: ndl_add(d,DL(mr),t);
8116: st = prev;
8117: ed = n;
8118: while ( ed > st ) {
8119: md = (st+ed)/2;
8120: u = s0+md*nd_wpd;
8121: c = DL_COMPARE(u,t);
8122: if ( c == 0 ) break;
8123: else if ( c > 0 ) st = md;
8124: else ed = md;
8125: }
8126: prev = v[j] = md;
1.1 noro 8127: }
8128: r = (IndArray)MALLOC(sizeof(struct oIndArray));
8129: r->head = v[0];
8130: diff = 0;
8131: for ( i = 1; i < len; i++ ) {
8132: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
8133: }
8134: if ( diff < 256 ) {
8135: r->width = 1;
8136: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
8137: r->index.c = ivc;
8138: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
8139: } else if ( diff < 65536 ) {
8140: r->width = 2;
8141: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
8142: r->index.s = ivs;
8143: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
8144: } else {
8145: r->width = 4;
8146: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
8147: r->index.i = ivi;
8148: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
8149: }
8150: return r;
8151: }
8152:
8153: int compress_array(Z *svect,Z *cvect,int n)
8154: {
8155: int i,j;
8156:
8157: for ( i = j = 0; i < n; i++ )
8158: if ( svect[i] ) cvect[j++] = svect[i];
8159: return j;
8160: }
8161:
8162: void expand_array(Z *svect,Z *cvect,int n)
8163: {
8164: int i,j;
8165:
8166: for ( i = j = 0; j < n; i++ )
8167: if ( svect[i] ) svect[i] = cvect[j++];
8168: }
8169:
1.8 noro 8170: #if 0
1.1 noro 8171: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8172: {
8173: int i,j,k,len,pos,prev,nz;
8174: Z cs,mcs,c1,c2,cr,gcd,t;
8175: IndArray ivect;
8176: unsigned char *ivc;
8177: unsigned short *ivs;
8178: unsigned int *ivi;
8179: NDV redv;
8180: NMV mr;
8181: NODE rp;
8182: int maxrs;
8183: double hmag;
8184: Z *cvect;
1.3 noro 8185: int l;
1.1 noro 8186:
8187: maxrs = 0;
8188: for ( i = 0; i < col && !svect[i]; i++ );
8189: if ( i == col ) return maxrs;
8190: hmag = p_mag((P)svect[i])*nd_scale;
8191: cvect = (Z *)MALLOC(col*sizeof(Q));
8192: for ( i = 0; i < nred; i++ ) {
8193: ivect = imat[i];
8194: k = ivect->head;
8195: if ( svect[k] ) {
8196: maxrs = MAX(maxrs,rp0[i]->sugar);
8197: redv = nd_demand?ndv_load(rp0[i]->index)
8198: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
8199: len = LEN(redv); mr = BDY(redv);
1.6 noro 8200: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 8201: chsgnz(cs,&mcs);
8202: if ( !UNIQ(cr) ) {
8203: for ( j = 0; j < col; j++ ) {
8204: mulz(svect[j],cr,&c1); svect[j] = c1;
8205: }
8206: }
8207: svect[k] = 0; prev = k;
8208: switch ( ivect->width ) {
8209: case 1:
8210: ivc = ivect->index.c;
8211: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8212: pos = prev+ivc[j]; prev = pos;
1.6 noro 8213: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8214: }
8215: break;
8216: case 2:
8217: ivs = ivect->index.s;
8218: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8219: pos = prev+ivs[j]; prev = pos;
1.6 noro 8220: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8221: }
8222: break;
8223: case 4:
8224: ivi = ivect->index.i;
8225: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8226: pos = prev+ivi[j]; prev = pos;
1.6 noro 8227: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8228: }
8229: break;
8230: }
8231: for ( j = k+1; j < col && !svect[j]; j++ );
8232: if ( j == col ) break;
8233: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
8234: nz = compress_array(svect,cvect,col);
8235: removecont_array((P *)cvect,nz,1);
8236: expand_array(svect,cvect,nz);
8237: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
8238: }
8239: }
8240: }
8241: nz = compress_array(svect,cvect,col);
8242: removecont_array((P *)cvect,nz,1);
8243: expand_array(svect,cvect,nz);
8244: if ( DP_Print ) {
8245: fprintf(asir_out,"-"); fflush(asir_out);
8246: }
8247: return maxrs;
8248: }
1.4 noro 8249: #else
1.9 noro 8250:
1.4 noro 8251: /* direct mpz version */
8252: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8253: {
8254: int i,j,k,len,pos,prev;
8255: mpz_t cs,cr,gcd;
8256: IndArray ivect;
8257: unsigned char *ivc;
8258: unsigned short *ivs;
8259: unsigned int *ivi;
8260: NDV redv;
8261: NMV mr;
8262: NODE rp;
8263: int maxrs;
8264: double hmag;
8265: int l;
1.13 noro 8266: static mpz_t *svect;
8267: static int svect_len=0;
1.4 noro 8268:
8269: maxrs = 0;
8270: for ( i = 0; i < col && !svect0[i]; i++ );
8271: if ( i == col ) return maxrs;
8272: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 8273: if ( col > svect_len ) {
8274: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
8275: svect_len = col;
8276: }
1.4 noro 8277: for ( i = 0; i < col; i++ ) {
8278: mpz_init(svect[i]);
8279: if ( svect0[i] )
8280: mpz_set(svect[i],BDY(svect0[i]));
8281: else
8282: mpz_set_ui(svect[i],0);
8283: }
8284: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
8285: for ( i = 0; i < nred; i++ ) {
8286: ivect = imat[i];
8287: k = ivect->head;
8288: if ( mpz_sgn(svect[k]) ) {
8289: maxrs = MAX(maxrs,rp0[i]->sugar);
8290: redv = nd_demand?ndv_load(rp0[i]->index)
8291: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
8292: len = LEN(redv); mr = BDY(redv);
1.6 noro 8293: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 8294: mpz_div(cs,svect[k],gcd);
1.6 noro 8295: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 8296: mpz_neg(cs,cs);
1.9 noro 8297: if ( MUNIMPZ(cr) )
8298: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
8299: else if ( !UNIMPZ(cr) )
8300: for ( j = 0; j < col; j++ ) {
8301: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
8302: }
1.4 noro 8303: mpz_set_ui(svect[k],0);
8304: prev = k;
8305: switch ( ivect->width ) {
8306: case 1:
8307: ivc = ivect->index.c;
8308: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8309: pos = prev+ivc[j]; prev = pos;
1.6 noro 8310: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8311: }
8312: break;
8313: case 2:
8314: ivs = ivect->index.s;
8315: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8316: pos = prev+ivs[j]; prev = pos;
1.6 noro 8317: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8318: }
8319: break;
8320: case 4:
8321: ivi = ivect->index.i;
8322: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8323: pos = prev+ivi[j]; prev = pos;
1.6 noro 8324: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8325: }
8326: break;
8327: }
8328: for ( j = k+1; j < col && !svect[j]; j++ );
8329: if ( j == col ) break;
8330: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
8331: mpz_removecont_array(svect,col);
8332: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
8333: }
8334: }
8335: }
8336: mpz_removecont_array(svect,col);
8337: if ( DP_Print ) {
8338: fprintf(asir_out,"-"); fflush(asir_out);
8339: }
8340: for ( i = 0; i < col; i++ )
8341: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
8342: else svect0[i] = 0;
8343: return maxrs;
8344: }
8345: #endif
1.1 noro 8346:
1.40 noro 8347: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.1 noro 8348: {
8349: int i,j,k,len,pos,prev;
8350: UINT c,c1,c2,c3,up,lo,dmy;
8351: IndArray ivect;
8352: unsigned char *ivc;
8353: unsigned short *ivs;
8354: unsigned int *ivi;
8355: NDV redv;
8356: NMV mr;
8357: NODE rp;
8358: int maxrs;
8359:
8360: maxrs = 0;
8361: for ( i = 0; i < nred; i++ ) {
8362: ivect = imat[i];
8363: k = ivect->head; svect[k] %= m;
1.40 noro 8364: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.1 noro 8365: maxrs = MAX(maxrs,rp0[i]->sugar);
8366: c = m-c; redv = nd_ps[rp0[i]->index];
8367: len = LEN(redv); mr = BDY(redv);
8368: svect[k] = 0; prev = k;
8369: switch ( ivect->width ) {
8370: case 1:
8371: ivc = ivect->index.c;
8372: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8373: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.40 noro 8374: if ( c1 ) {
8375: c2 = svect[pos];
1.1 noro 8376: DMA(c1,c,c2,up,lo);
8377: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8378: } else svect[pos] = lo;
1.40 noro 8379: }
1.1 noro 8380: }
8381: break;
8382: case 2:
8383: ivs = ivect->index.s;
8384: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8385: pos = prev+ivs[j]; c1 = CM(mr);
8386: prev = pos;
1.40 noro 8387: if ( c1 ) {
8388: c2 = svect[pos];
1.1 noro 8389: DMA(c1,c,c2,up,lo);
8390: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8391: } else svect[pos] = lo;
1.40 noro 8392: }
1.1 noro 8393: }
8394: break;
8395: case 4:
8396: ivi = ivect->index.i;
8397: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8398: pos = prev+ivi[j]; c1 = CM(mr);
8399: prev = pos;
1.40 noro 8400: if ( c1 ) {
8401: c2 = svect[pos];
1.1 noro 8402: DMA(c1,c,c2,up,lo);
8403: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8404: } else svect[pos] = lo;
1.40 noro 8405: }
1.1 noro 8406: }
8407: break;
8408: }
8409: }
8410: }
8411: for ( i = 0; i < col; i++ )
8412: if ( svect[i] >= (UINT)m ) svect[i] %= m;
8413: return maxrs;
8414: }
8415:
8416: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8417: {
8418: int i,j,k,len,pos,prev;
8419: UINT c,c1,c2,c3,up,lo,dmy;
8420: IndArray ivect;
8421: unsigned char *ivc;
8422: unsigned short *ivs;
8423: unsigned int *ivi;
8424: NDV redv;
8425: NMV mr;
8426: NODE rp;
8427: int maxrs;
8428:
8429: maxrs = 0;
8430: for ( i = 0; i < nred; i++ ) {
8431: ivect = imat[i];
8432: k = ivect->head;
8433: if ( (c = svect[k]) != 0 ) {
8434: maxrs = MAX(maxrs,rp0[i]->sugar);
8435: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
8436: len = LEN(redv); mr = BDY(redv);
8437: svect[k] = 0; prev = k;
8438: switch ( ivect->width ) {
8439: case 1:
8440: ivc = ivect->index.c;
8441: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8442: pos = prev+ivc[j]; prev = pos;
8443: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8444: }
8445: break;
8446: case 2:
8447: ivs = ivect->index.s;
8448: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8449: pos = prev+ivs[j]; prev = pos;
8450: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8451: }
8452: break;
8453: case 4:
8454: ivi = ivect->index.i;
8455: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8456: pos = prev+ivi[j]; prev = pos;
8457: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8458: }
8459: break;
8460: }
8461: }
8462: }
8463: return maxrs;
8464: }
8465:
8466: ND nd_add_lf(ND p1,ND p2)
8467: {
8468: int n,c,can;
8469: ND r;
8470: NM m1,m2,mr0,mr,s;
8471: Z t;
8472:
8473: if ( !p1 ) return p2;
8474: else if ( !p2 ) return p1;
8475: else {
8476: can = 0;
8477: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
8478: c = DL_COMPARE(DL(m1),DL(m2));
8479: switch ( c ) {
8480: case 0:
8481: addlf(CZ(m1),CZ(m2),&t);
8482: s = m1; m1 = NEXT(m1);
8483: if ( t ) {
8484: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
8485: } else {
8486: can += 2; FREENM(s);
8487: }
8488: s = m2; m2 = NEXT(m2); FREENM(s);
8489: break;
8490: case 1:
8491: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
8492: break;
8493: case -1:
8494: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
8495: break;
8496: }
8497: }
8498: if ( !mr0 )
8499: if ( m1 ) mr0 = m1;
8500: else if ( m2 ) mr0 = m2;
8501: else return 0;
8502: else if ( m1 ) NEXT(mr) = m1;
8503: else if ( m2 ) NEXT(mr) = m2;
8504: else NEXT(mr) = 0;
8505: BDY(p1) = mr0;
8506: SG(p1) = MAX(SG(p1),SG(p2));
8507: LEN(p1) = LEN(p1)+LEN(p2)-can;
8508: FREEND(p2);
8509: return p1;
8510: }
8511: }
8512:
8513: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8514: {
8515: int i,j,k,len,pos,prev;
8516: mpz_t c,mc,c1;
8517: IndArray ivect;
8518: unsigned char *ivc;
8519: unsigned short *ivs;
8520: unsigned int *ivi;
8521: NDV redv;
8522: NMV mr;
8523: NODE rp;
8524: int maxrs;
8525:
8526: maxrs = 0;
8527: lf_lazy = 1;
8528: for ( i = 0; i < nred; i++ ) {
8529: ivect = imat[i];
8530: k = ivect->head;
8531: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
8532: if ( mpz_sgn(svect[k]) ) {
8533: maxrs = MAX(maxrs,rp0[i]->sugar);
8534: mpz_neg(svect[k],svect[k]);
8535: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
8536: len = LEN(redv); mr = BDY(redv);
8537: prev = k;
8538: switch ( ivect->width ) {
8539: case 1:
8540: ivc = ivect->index.c;
8541: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8542: pos = prev+ivc[j]; prev = pos;
8543: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8544: }
8545: break;
8546: case 2:
8547: ivs = ivect->index.s;
8548: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8549: pos = prev+ivs[j]; prev = pos;
8550: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8551: }
8552: break;
8553: case 4:
8554: ivi = ivect->index.i;
8555: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8556: pos = prev+ivi[j]; prev = pos;
8557: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8558: }
8559: break;
8560: }
8561: mpz_set_ui(svect[k],0);
8562: }
8563: }
8564: lf_lazy=0;
8565: for ( i = 0; i < col; i++ ) {
8566: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
8567: }
8568: return maxrs;
8569: }
8570:
8571: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
8572: {
8573: int i,j,k,l,rank,s;
8574: mpz_t a,a1,inv;
8575: mpz_t *t,*pivot,*pk;
8576: mpz_t **mat;
8577: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
8578: int size,size1;
8579:
8580: mpz_init(inv);
8581: mpz_init(a);
8582: mat = (mpz_t **)mat0;
8583: size = 0;
8584: for ( rank = 0, j = 0; j < col; j++ ) {
8585: for ( i = rank; i < row; i++ ) {
8586: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
8587: }
8588: for ( i = rank; i < row; i++ )
8589: if ( mpz_sgn(mat[i][j]) )
8590: break;
8591: if ( i == row ) {
8592: colstat[j] = 0;
8593: continue;
8594: } else
8595: colstat[j] = 1;
8596: if ( i != rank ) {
8597: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8598: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8599: }
8600: pivot = mat[rank];
8601: s = sugar[rank];
8602: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
8603: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8604: if ( mpz_sgn(*pk) ) {
8605: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
8606: }
8607: for ( i = rank+1; i < row; i++ ) {
8608: t = mat[i];
8609: if ( mpz_sgn(t[j]) ) {
8610: sugar[i] = MAX(sugar[i],s);
8611: mpz_neg(a,t[j]);
8612: red_by_vect_lf(t+j,pivot+j,a,col-j);
8613: }
8614: }
8615: rank++;
8616: }
8617: for ( j = col-1, l = rank-1; j >= 0; j-- )
8618: if ( colstat[j] ) {
8619: pivot = mat[l];
8620: s = sugar[l];
8621: for ( k = j; k < col; k++ )
8622: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
8623: for ( i = 0; i < l; i++ ) {
8624: t = mat[i];
8625: if ( mpz_sgn(t[j]) ) {
8626: sugar[i] = MAX(sugar[i],s);
8627: mpz_neg(a,t[j]);
8628: red_by_vect_lf(t+j,pivot+j,a,col-j);
8629: }
8630: }
8631: l--;
8632: }
8633: for ( j = 0, l = 0; l < rank; j++ )
8634: if ( colstat[j] ) {
8635: t = mat[l];
8636: for ( k = j; k < col; k++ ) {
8637: mpz_mod(t[k],t[k],BDY(current_mod_lf));
8638: }
8639: l++;
8640: }
8641: return rank;
8642: }
8643:
8644:
8645: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
8646: {
8647: int j,k,len;
8648: UINT *p;
8649: UINT c;
8650: NDV r;
8651: NMV mr0,mr;
8652:
8653: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8654: if ( !len ) return 0;
8655: else {
8656: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8657: #if 0
8658: ndv_alloc += nmv_adv*len;
8659: #endif
8660: mr = mr0;
8661: p = s0vect;
8662: for ( j = k = 0; j < col; j++, p += nd_wpd )
8663: if ( !rhead[j] ) {
8664: if ( (c = vect[k++]) != 0 ) {
8665: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8666: }
8667: }
8668: MKNDV(nd_nvar,mr0,len,r);
8669: return r;
8670: }
8671: }
8672:
1.40 noro 8673: NDV vect_to_ndv_s(UINT *vect,int col,UINT *s0vect)
8674: {
8675: int j,k,len;
8676: UINT *p;
8677: UINT c;
8678: NDV r;
8679: NMV mr0,mr;
8680:
8681: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8682: if ( !len ) return 0;
8683: else {
8684: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8685: mr = mr0;
8686: p = s0vect;
8687: for ( j = k = 0; j < col; j++, p += nd_wpd )
8688: if ( (c = vect[k++]) != 0 ) {
8689: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8690: }
8691: MKNDV(nd_nvar,mr0,len,r);
8692: return r;
8693: }
8694: }
8695:
1.1 noro 8696: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
8697: {
8698: int j,k,len;
8699: UINT *p;
8700: NDV r;
8701: NMV mr0,mr;
8702:
8703: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
8704: if ( !len ) return 0;
8705: else {
8706: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8707: mr = mr0;
8708: p = s0vect;
8709: for ( j = 0; j < col; j++, p += nd_wpd )
8710: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
8711: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
8712: }
8713: MKNDV(nd_nvar,mr0,len,r);
8714: return r;
8715: }
8716: }
8717:
8718: /* for preprocessed vector */
8719:
8720: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
8721: {
1.6 noro 8722: int j,k,len;
8723: UINT *p;
8724: Z c;
8725: NDV r;
8726: NMV mr0,mr;
1.1 noro 8727:
1.6 noro 8728: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8729: if ( !len ) return 0;
8730: else {
8731: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 8732: #if 0
1.6 noro 8733: ndv_alloc += nmv_adv*len;
1.1 noro 8734: #endif
1.6 noro 8735: mr = mr0;
8736: p = s0vect;
8737: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
8738: if ( !rhead[j] ) {
8739: if ( (c = vect[k++]) != 0 ) {
8740: if ( !INT(c) )
8741: error("vect_to_ndv_q : components must be integers");
8742: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
8743: }
8744: }
1.1 noro 8745: }
1.6 noro 8746: MKNDV(nd_nvar,mr0,len,r);
8747: return r;
8748: }
1.1 noro 8749: }
8750:
8751: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
8752: {
8753: int j,k,len;
8754: UINT *p;
8755: mpz_t c;
8756: NDV r;
8757: NMV mr0,mr;
8758:
8759: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
8760: if ( !len ) return 0;
8761: else {
8762: mr0 = (NMV)MALLOC(nmv_adv*len);
8763: #if 0
8764: ndv_alloc += nmv_adv*len;
8765: #endif
8766: mr = mr0;
8767: p = s0vect;
8768: for ( j = k = 0; j < col; j++, p += nd_wpd )
8769: if ( !rhead[j] ) {
8770: c[0] = vect[k++][0];
8771: if ( mpz_sgn(c) ) {
8772: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
8773: }
8774: }
8775: MKNDV(nd_nvar,mr0,len,r);
8776: return r;
8777: }
8778: }
8779:
8780: /* for plain vector */
8781:
8782: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
8783: {
8784: int j,k,len;
8785: UINT *p;
8786: Z c;
8787: NDV r;
8788: NMV mr0,mr;
8789:
8790: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8791: if ( !len ) return 0;
8792: else {
8793: mr0 = (NMV)MALLOC(nmv_adv*len);
8794: #if 0
8795: ndv_alloc += nmv_adv*len;
8796: #endif
8797: mr = mr0;
8798: p = s0vect;
8799: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
8800: if ( (c = vect[k]) != 0 ) {
8801: if ( !INT(c) )
1.6 noro 8802: error("plain_vect_to_ndv_q : components must be integers");
8803: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 8804: }
8805: MKNDV(nd_nvar,mr0,len,r);
8806: return r;
8807: }
8808: }
8809:
8810: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
8811: {
8812: ND_pairs t;
8813: NODE sp0,sp;
8814: int stat;
8815: ND spol;
8816:
8817: for ( t = l; t; t = NEXT(t) ) {
8818: stat = nd_sp(m,trace,t,&spol);
8819: if ( !stat ) return 0;
8820: if ( spol ) {
8821: add_pbucket_symbolic(bucket,spol);
8822: }
8823: }
8824: return 1;
8825: }
8826:
8827: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
8828: {
8829: NODE rp0,rp;
8830: NM mul,head,s0,s;
8831: int index,col,i,sugar;
8832: RHist h;
8833: UINT *s0v,*p;
8834: NM_ind_pair pair;
8835: ND red;
8836: NDV *ps;
8837:
8838: s0 = 0; rp0 = 0; col = 0;
8839: if ( nd_demand )
8840: ps = trace?nd_ps_trace_sym:nd_ps_sym;
8841: else
8842: ps = trace?nd_ps_trace:nd_ps;
8843: while ( 1 ) {
8844: head = remove_head_pbucket_symbolic(bucket);
8845: if ( !head ) break;
8846: if ( !s0 ) s0 = head;
8847: else NEXT(s) = head;
8848: s = head;
8849: index = ndl_find_reducer(DL(head));
8850: if ( index >= 0 ) {
8851: h = nd_psh[index];
8852: NEWNM(mul);
8853: ndl_sub(DL(head),DL(h),DL(mul));
8854: if ( ndl_check_bound2(index,DL(mul)) )
8855: return 0;
8856: sugar = TD(DL(mul))+SG(ps[index]);
1.28 noro 8857: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 8858: red = ndv_mul_nm_symbolic(mul,ps[index]);
8859: add_pbucket_symbolic(bucket,nd_remove_head(red));
8860: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
8861: }
8862: col++;
8863: }
8864: if ( rp0 ) NEXT(rp) = 0;
8865: NEXT(s) = 0;
8866: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
8867: for ( i = 0, p = s0v, s = s0; i < col;
8868: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
8869: *s0vect = s0v;
8870: *r = rp0;
8871: return col;
8872: }
8873:
8874: void print_ndp(ND_pairs l)
8875: {
8876: ND_pairs t;
8877:
8878: for ( t = l; t; t = NEXT(t) )
8879: printf("[%d,%d] ",t->i1,t->i2);
8880: printf("\n");
8881: }
8882:
8883: NODE nd_f4(int m,int checkonly,int **indp)
8884: {
8885: int i,nh,stat,index,f4red;
8886: NODE r,g,tn0,tn,node;
8887: ND_pairs d,l,t,ll0,ll,lh;
8888: LIST l0,l1;
8889: ND spol,red;
8890: NDV nf,redv;
8891: NM s0,s;
8892: NODE rp0,srp0,nflist,nzlist,nzlist_t;
8893: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
8894: UINT c;
8895: UINT **spmat;
8896: UINT *s0vect,*svect,*p,*v;
8897: int *colstat;
8898: IndArray *imat;
8899: int *rhead;
8900: int spcol,sprow;
8901: int sugar,sugarh;
8902: PGeoBucket bucket;
8903: struct oEGT eg0,eg1,eg_f4;
8904: Z i1,i2,sugarq;
1.12 noro 8905:
8906: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 8907: #if 0
8908: ndv_alloc = 0;
8909: #endif
1.11 noro 8910: Nf4_red=0;
1.1 noro 8911: g = 0; d = 0;
8912: for ( i = 0; i < nd_psn; i++ ) {
8913: d = update_pairs(d,g,i,0);
8914: g = update_base(g,i);
8915: }
8916: nzlist = 0;
8917: nzlist_t = nd_nzlist;
8918: f4red = 1;
8919: nd_last_nonzero = 0;
8920: while ( d ) {
8921: get_eg(&eg0);
8922: l = nd_minsugarp(d,&d);
8923: sugar = nd_sugarweight?l->sugar2:SG(l);
8924: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8925: if ( nzlist_t ) {
8926: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 8927: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 8928: tn = BDY((LIST)ARG1(node));
8929: if ( !tn ) {
8930: nzlist_t = NEXT(nzlist_t);
8931: continue;
8932: }
8933: /* tn = [[i1,i2],...] */
8934: lh = nd_ipairtospair(tn);
8935: }
8936: bucket = create_pbucket();
8937: stat = nd_sp_f4(m,0,l,bucket);
8938: if ( !stat ) {
8939: for ( t = l; NEXT(t); t = NEXT(t) );
8940: NEXT(t) = d; d = l;
8941: d = nd_reconstruct(0,d);
8942: continue;
8943: }
8944: if ( bucket->m < 0 ) continue;
8945: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8946: if ( !col ) {
8947: for ( t = l; NEXT(t); t = NEXT(t) );
8948: NEXT(t) = d; d = l;
8949: d = nd_reconstruct(0,d);
8950: continue;
8951: }
1.12 noro 8952: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 8953: if ( DP_Print )
1.6 noro 8954: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 8955: sugar,eg_f4.exectime);
1.1 noro 8956: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
8957: if ( checkonly && nflist ) return 0;
8958: /* adding new bases */
8959: if ( nflist ) nd_last_nonzero = f4red;
8960: for ( r = nflist; r; r = NEXT(r) ) {
8961: nf = (NDV)BDY(r);
1.38 noro 8962: if ( nd_f4_td ) SG(nf) = nd_tdeg(nf);
1.1 noro 8963: ndv_removecont(m,nf);
8964: if ( !m && nd_nalg ) {
8965: ND nf1;
8966:
8967: nf1 = ndvtond(m,nf);
8968: nd_monic(0,&nf1);
8969: nd_removecont(m,nf1);
8970: nf = ndtondv(m,nf1);
8971: }
1.24 noro 8972: nh = ndv_newps(m,nf,0);
1.1 noro 8973: d = update_pairs(d,g,nh,0);
8974: g = update_base(g,nh);
8975: }
8976: if ( DP_Print ) {
8977: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
8978: }
8979: if ( nd_gentrace ) {
8980: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
8981: NEXTNODE(tn0,tn);
1.6 noro 8982: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 8983: node = mknode(2,i1,i2); MKLIST(l0,node);
8984: BDY(tn) = l0;
8985: }
8986: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 8987: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 8988: MKNODE(node,l1,nzlist); nzlist = node;
8989: }
8990: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
8991: f4red++;
8992: if ( nd_f4red && f4red > nd_f4red ) break;
8993: if ( nd_rank0 && !nflist ) break;
8994: }
8995: if ( nd_gentrace ) {
8996: MKLIST(l0,reverse_node(nzlist));
8997: MKNODE(nd_alltracelist,l0,0);
8998: }
8999: #if 0
9000: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
9001: #endif
1.12 noro 9002: if ( DP_Print ) {
9003: fprintf(asir_out,"number of red=%d,",Nf4_red);
9004: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
9005: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
1.41 noro 9006: fprintf(asir_out,"number of removed pairs=%d\n,",NcriB+NcriMF+Ncri2);
1.12 noro 9007: }
1.1 noro 9008: conv_ilist(nd_demand,0,g,indp);
9009: return g;
9010: }
9011:
9012: NODE nd_f4_trace(int m,int **indp)
9013: {
9014: int i,nh,stat,index;
9015: NODE r,g;
9016: ND_pairs d,l,l0,t;
9017: ND spol,red;
9018: NDV nf,redv,nfqv,nfv;
9019: NM s0,s;
9020: NODE rp0,srp0,nflist;
9021: int nsp,nred,col,rank,len,k,j,a;
9022: UINT c;
9023: UINT **spmat;
9024: UINT *s0vect,*svect,*p,*v;
9025: int *colstat;
9026: IndArray *imat;
9027: int *rhead;
9028: int spcol,sprow;
9029: int sugar;
9030: PGeoBucket bucket;
9031: struct oEGT eg0,eg1,eg_f4;
9032:
9033: g = 0; d = 0;
9034: for ( i = 0; i < nd_psn; i++ ) {
9035: d = update_pairs(d,g,i,0);
9036: g = update_base(g,i);
9037: }
9038: while ( d ) {
9039: get_eg(&eg0);
9040: l = nd_minsugarp(d,&d);
9041: sugar = SG(l);
9042: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
9043: bucket = create_pbucket();
9044: stat = nd_sp_f4(m,0,l,bucket);
9045: if ( !stat ) {
9046: for ( t = l; NEXT(t); t = NEXT(t) );
9047: NEXT(t) = d; d = l;
9048: d = nd_reconstruct(1,d);
9049: continue;
9050: }
9051: if ( bucket->m < 0 ) continue;
9052: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
9053: if ( !col ) {
9054: for ( t = l; NEXT(t); t = NEXT(t) );
9055: NEXT(t) = d; d = l;
9056: d = nd_reconstruct(1,d);
9057: continue;
9058: }
9059: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
9060: if ( DP_Print )
1.3 noro 9061: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 9062: sugar,eg_f4.exectime);
1.1 noro 9063: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
9064: if ( !l0 ) continue;
9065: l = l0;
9066:
9067: /* over Q */
9068: bucket = create_pbucket();
9069: stat = nd_sp_f4(0,1,l,bucket);
9070: if ( !stat ) {
9071: for ( t = l; NEXT(t); t = NEXT(t) );
9072: NEXT(t) = d; d = l;
9073: d = nd_reconstruct(1,d);
9074: continue;
9075: }
9076: if ( bucket->m < 0 ) continue;
9077: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
9078: if ( !col ) {
9079: for ( t = l; NEXT(t); t = NEXT(t) );
9080: NEXT(t) = d; d = l;
9081: d = nd_reconstruct(1,d);
9082: continue;
9083: }
9084: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
9085: /* adding new bases */
9086: for ( r = nflist; r; r = NEXT(r) ) {
9087: nfqv = (NDV)BDY(r);
9088: ndv_removecont(0,nfqv);
1.6 noro 9089: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 9090: if ( nd_nalg ) {
9091: ND nf1;
9092:
9093: nf1 = ndvtond(m,nfqv);
9094: nd_monic(0,&nf1);
9095: nd_removecont(0,nf1);
9096: nfqv = ndtondv(0,nf1); nd_free(nf1);
9097: }
9098: nfv = ndv_dup(0,nfqv);
9099: ndv_mod(m,nfv);
9100: ndv_removecont(m,nfv);
1.24 noro 9101: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 9102: d = update_pairs(d,g,nh,0);
9103: g = update_base(g,nh);
9104: }
9105: }
9106: #if 0
9107: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
9108: #endif
9109: conv_ilist(nd_demand,1,g,indp);
9110: return g;
9111: }
9112:
9113: int rref(matrix mat,int *sugar)
9114: {
9115: int row,col,i,j,k,l,s,wcol,wj;
9116: unsigned long bj;
9117: unsigned long **a;
9118: unsigned long *ai,*ak,*as,*t;
9119: int *pivot;
9120:
9121: row = mat->row;
9122: col = mat->col;
9123: a = mat->a;
9124: wcol = (col+BLEN-1)/BLEN;
9125: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
9126: i = 0;
9127: for ( j = 0; j < col; j++ ) {
9128: wj = j/BLEN; bj = 1L<<(j%BLEN);
9129: for ( k = i; k < row; k++ )
9130: if ( a[k][wj] & bj ) break;
9131: if ( k == row ) continue;
9132: pivot[i] = j;
9133: if ( k != i ) {
9134: t = a[i]; a[i] = a[k]; a[k] = t;
9135: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
9136: }
9137: ai = a[i];
9138: for ( k = i+1; k < row; k++ ) {
9139: ak = a[k];
9140: if ( ak[wj] & bj ) {
9141: for ( l = wj; l < wcol; l++ )
9142: ak[l] ^= ai[l];
9143: sugar[k] = MAX(sugar[k],sugar[i]);
9144: }
9145: }
9146: i++;
9147: }
9148: for ( k = i-1; k >= 0; k-- ) {
9149: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
9150: ak = a[k];
9151: for ( s = 0; s < k; s++ ) {
9152: as = a[s];
9153: if ( as[wj] & bj ) {
9154: for ( l = wj; l < wcol; l++ )
9155: as[l] ^= ak[l];
9156: sugar[s] = MAX(sugar[s],sugar[k]);
9157: }
9158: }
9159: }
9160: return i;
9161: }
9162:
9163: void print_matrix(matrix mat)
9164: {
9165: int row,col,i,j;
9166: unsigned long *ai;
9167:
9168: row = mat->row;
9169: col = mat->col;
9170: printf("%d x %d\n",row,col);
9171: for ( i = 0; i < row; i++ ) {
9172: ai = mat->a[i];
9173: for ( j = 0; j < col; j++ ) {
9174: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
9175: else putchar('0');
9176: }
9177: putchar('\n');
9178: }
9179: }
9180:
9181: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
9182:
9183: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
9184: {
9185: int row,col,wcol,wj,i,j;
9186: unsigned long bj;
9187: unsigned long *ai;
9188: unsigned long **a;
9189: int len;
9190: int *pos;
9191:
9192: row = mat->row;
9193: col = mat->col;
9194: wcol = (col+BLEN-1)/BLEN;
9195: pos = (int *)MALLOC(wcol*sizeof(int));
9196: bzero(pos,wcol*sizeof(int));
9197: for ( i = j = 0; i < wcol; i++ )
9198: if ( v[i] ) pos[j++] = i;;
9199: len = j;
9200: wj = rhead/BLEN;
9201: bj = 1L<<rhead%BLEN;
9202: a = mat->a;
9203: for ( i = 0; i < row; i++ ) {
9204: ai = a[i];
9205: if ( ai[wj]&bj ) {
9206: for ( j = 0; j < len; j++ )
9207: ai[pos[j]] ^= v[pos[j]];
9208: sugar[i] = MAX(sugar[i],rsugar);
9209: }
9210: }
9211: }
9212:
9213: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
9214: {
9215: int nsp,nred,i,i0,k,rank,row;
9216: NODE r0,rp;
9217: ND_pairs sp;
9218: ND spol;
9219: NM_ind_pair rt;
9220: int *s0hash;
9221: UINT *s;
9222: int *pivot,*sugar,*head;
9223: matrix mat;
9224: NM m;
9225: NODE r;
9226: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
9227: int rhead,rsugar,size;
9228: unsigned long *v;
9229:
9230: get_eg(&eg0);
9231: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
9232: nred = length(rp0);
9233: mat = alloc_matrix(nsp,col);
9234: s0hash = (int *)MALLOC(col*sizeof(int));
9235: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
9236: s0hash[i] = ndl_hash_value(s);
9237:
9238: sugar = (int *)MALLOC(nsp*sizeof(int));
9239: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
9240: nd_sp(2,0,sp,&spol);
9241: if ( spol ) {
9242: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
9243: sugar[i] = SG(spol);
9244: i++;
9245: }
9246: }
9247: mat->row = i;
9248: if ( DP_Print ) {
9249: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
9250: }
9251: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
9252: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
9253: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
9254: rt = (NM_ind_pair)BDY(rp);
9255: bzero(v,size);
9256: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
9257: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
9258: red_by_vect_2(mat,sugar,v,rhead,rsugar);
9259: }
9260:
9261: get_eg(&eg1);
9262: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
9263: rank = rref(mat,sugar);
9264:
9265: for ( i = 0, r0 = 0; i < rank; i++ ) {
9266: NEXTNODE(r0,r);
9267: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
9268: SG((NDV)BDY(r)) = sugar[i];
9269: }
9270: if ( r0 ) NEXT(r) = 0;
9271: get_eg(&eg2);
9272: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
9273: if ( DP_Print ) {
9274: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 9275: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 9276: fflush(asir_out);
9277: }
9278: return r0;
9279: }
9280:
9281:
9282: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
9283: {
9284: IndArray *imat;
1.11 noro 9285: int nsp,nred,i,start;
1.1 noro 9286: int *rhead;
9287: NODE r0,rp;
9288: ND_pairs sp;
9289: NM_ind_pair *rvect;
9290: UINT *s;
9291: int *s0hash;
1.11 noro 9292: struct oEGT eg0,eg1,eg_conv;
1.1 noro 9293:
9294: if ( m == 2 && nd_rref2 )
9295: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
9296:
9297: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
9298: nred = length(rp0);
9299: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
9300: rhead = (int *)MALLOC(col*sizeof(int));
9301: for ( i = 0; i < col; i++ ) rhead[i] = 0;
9302:
9303: /* construction of index arrays */
1.11 noro 9304: get_eg(&eg0);
1.1 noro 9305: if ( DP_Print ) {
1.11 noro 9306: fprintf(asir_out,"%dx%d,",nsp+nred,col);
9307: fflush(asir_out);
1.1 noro 9308: }
9309: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 9310: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 9311: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 9312: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 9313: rhead[imat[i]->head] = 1;
1.11 noro 9314: start = imat[i]->head;
9315: }
1.12 noro 9316: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 9317: if ( DP_Print ) {
9318: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
9319: fflush(asir_out);
1.1 noro 9320: }
9321: if ( m > 0 )
1.7 noro 9322: #if SIZEOF_LONG==8
1.1 noro 9323: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9324: #else
9325: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9326: #endif
9327: else if ( m == -1 )
9328: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9329: else if ( m == -2 )
9330: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9331: else
9332: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9333: return r0;
9334: }
9335:
9336: /* for Fp, 2<=p<2^16 */
9337:
9338: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9339: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9340: {
9341: int spcol,sprow,a;
9342: int i,j,k,l,rank;
9343: NODE r0,r;
9344: ND_pairs sp;
9345: ND spol;
9346: UINT **spmat;
9347: UINT *svect,*v;
9348: int *colstat;
9349: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9350: int maxrs;
9351: int *spsugar;
9352: ND_pairs *spactive;
9353:
9354: spcol = col-nred;
9355: get_eg(&eg0);
9356: /* elimination (1st step) */
9357: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9358: svect = (UINT *)MALLOC(col*sizeof(UINT));
9359: spsugar = (int *)MALLOC(nsp*sizeof(int));
9360: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9361: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9362: nd_sp(m,0,sp,&spol);
9363: if ( !spol ) continue;
9364: nd_to_vect(m,s0vect,col,spol,svect);
9365: if ( m == -1 )
9366: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9367: else
1.40 noro 9368: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,0);
1.1 noro 9369: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9370: if ( i < col ) {
9371: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9372: for ( j = k = 0; j < col; j++ )
9373: if ( !rhead[j] ) v[k++] = svect[j];
9374: spsugar[sprow] = MAX(maxrs,SG(spol));
9375: if ( nz )
9376: spactive[sprow] = sp;
9377: sprow++;
9378: }
9379: nd_free(spol);
9380: }
9381: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9382: if ( DP_Print ) {
1.5 noro 9383: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9384: fflush(asir_out);
9385: }
9386: /* free index arrays */
9387: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9388:
9389: /* elimination (2nd step) */
9390: colstat = (int *)MALLOC(spcol*sizeof(int));
9391: if ( m == -1 )
9392: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9393: else
9394: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
9395: r0 = 0;
9396: for ( i = 0; i < rank; i++ ) {
9397: NEXTNODE(r0,r); BDY(r) =
9398: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9399: SG((NDV)BDY(r)) = spsugar[i];
9400: GCFREE(spmat[i]);
9401: }
9402: if ( r0 ) NEXT(r) = 0;
9403:
9404: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9405: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9406: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9407: if ( DP_Print ) {
1.5 noro 9408: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9409: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9410: nsp,nred,sprow,spcol,rank);
1.5 noro 9411: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9412: }
9413: if ( nz ) {
9414: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9415: if ( rank > 0 ) {
9416: NEXT(spactive[rank-1]) = 0;
9417: *nz = spactive[0];
9418: } else
9419: *nz = 0;
9420: }
9421: return r0;
9422: }
9423:
1.40 noro 9424: NODE nd_f4_red_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9425: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
9426: {
9427: int spcol,sprow,a;
9428: int i,j,k,l,rank;
9429: NODE r0,r;
9430: ND_pairs sp;
9431: ND spol;
9432: UINT **spmat;
9433: UINT *svect,*cvect;
9434: UINT *v;
9435: int *colstat;
9436: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9437: int maxrs;
9438: int *spsugar;
9439: ND_pairs *spactive;
9440: SIG *spsig;
9441:
9442: get_eg(&eg0);
9443: /* elimination (1st step) */
9444: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9445: spsugar = (int *)MALLOC(nsp*sizeof(int));
9446: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
9447: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9448: nd_sp(m,0,sp,&spol);
9449: if ( !spol ) {
9450: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9451: continue;
9452: }
9453: svect = (UINT *)MALLOC(col*sizeof(UINT));
9454: nd_to_vect(m,s0vect,col,spol,svect);
9455: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,spol->sig);
9456: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9457: if ( i < col ) {
9458: spmat[sprow] = svect;
9459: spsugar[sprow] = MAX(maxrs,SG(spol));
9460: spsig[sprow] = sp->sig;
9461: sprow++;
9462: } else {
9463: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9464: }
9465: nd_free(spol);
9466: }
9467: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
9468: if ( DP_Print ) {
9469: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
9470: fflush(asir_out);
9471: }
9472: /* free index arrays */
9473: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9474:
9475: /* elimination (2nd step) */
9476: colstat = (int *)MALLOC(col*sizeof(int));
9477: rank = nd_gauss_elim_mod_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
9478: r0 = 0;
9479: for ( i = 0; i < sprow; i++ ) {
9480: if ( spsugar[i] >= 0 ) {
9481: NEXTNODE(r0,r);
9482: BDY(r) = vect_to_ndv_s(spmat[i],col,s0vect);
9483: SG((NDV)BDY(r)) = spsugar[i];
9484: ((NDV)BDY(r))->sig = spsig[i];
9485: } else
9486: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
9487: GCFREE(spmat[i]);
9488: }
9489: if ( r0 ) NEXT(r) = 0;
9490: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
9491: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9492: if ( DP_Print ) {
9493: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
9494: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9495: nsp,nred,sprow,col,rank);
9496: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
9497: }
9498: return r0;
9499: }
9500:
1.1 noro 9501:
9502: /* for small finite fields */
9503:
9504: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9505: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9506: {
9507: int spcol,sprow,a;
9508: int i,j,k,l,rank;
9509: NODE r0,r;
9510: ND_pairs sp;
9511: ND spol;
9512: UINT **spmat;
9513: UINT *svect,*v;
9514: int *colstat;
9515: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9516: int maxrs;
9517: int *spsugar;
9518: ND_pairs *spactive;
9519:
9520: spcol = col-nred;
9521: get_eg(&eg0);
9522: /* elimination (1st step) */
9523: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9524: svect = (UINT *)MALLOC(col*sizeof(UINT));
9525: spsugar = (int *)MALLOC(nsp*sizeof(int));
9526: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9527: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9528: nd_sp(m,0,sp,&spol);
9529: if ( !spol ) continue;
9530: nd_to_vect(m,s0vect,col,spol,svect);
9531: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9532: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9533: if ( i < col ) {
9534: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9535: for ( j = k = 0; j < col; j++ )
9536: if ( !rhead[j] ) v[k++] = svect[j];
9537: spsugar[sprow] = MAX(maxrs,SG(spol));
9538: if ( nz )
9539: spactive[sprow] = sp;
9540: sprow++;
9541: }
9542: nd_free(spol);
9543: }
9544: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9545: if ( DP_Print ) {
1.5 noro 9546: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9547: fflush(asir_out);
9548: }
9549: /* free index arrays */
9550: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9551:
9552: /* elimination (2nd step) */
9553: colstat = (int *)MALLOC(spcol*sizeof(int));
9554: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9555: r0 = 0;
9556: for ( i = 0; i < rank; i++ ) {
9557: NEXTNODE(r0,r); BDY(r) =
9558: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9559: SG((NDV)BDY(r)) = spsugar[i];
9560: GCFREE(spmat[i]);
9561: }
9562: if ( r0 ) NEXT(r) = 0;
9563:
9564: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9565: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9566: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9567: if ( DP_Print ) {
1.5 noro 9568: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9569: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9570: nsp,nred,sprow,spcol,rank);
1.5 noro 9571: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9572: }
9573: if ( nz ) {
9574: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9575: if ( rank > 0 ) {
9576: NEXT(spactive[rank-1]) = 0;
9577: *nz = spactive[0];
9578: } else
9579: *nz = 0;
9580: }
9581: return r0;
9582: }
9583:
9584: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9585: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9586: {
9587: int spcol,sprow,a;
9588: int i,j,k,l,rank;
9589: NODE r0,r;
9590: ND_pairs sp;
9591: ND spol;
9592: mpz_t **spmat;
9593: mpz_t *svect,*v;
9594: int *colstat;
9595: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9596: int maxrs;
9597: int *spsugar;
9598: pointer *w;
9599:
9600: spcol = col-nred;
9601: get_eg(&eg0);
9602: /* elimination (1st step) */
9603: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
9604: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
9605: spsugar = (int *)MALLOC(nsp*sizeof(int));
9606: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9607: nd_sp(m,trace,sp,&spol);
9608: if ( !spol ) continue;
9609: nd_to_vect_lf(s0vect,col,spol,svect);
9610: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
9611: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
9612: if ( i < col ) {
9613: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
9614: for ( j = k = 0; j < col; j++ )
9615: if ( !rhead[j] ) v[k++][0] = svect[j][0];
9616: spsugar[sprow] = MAX(maxrs,SG(spol));
9617: sprow++;
9618: }
9619: /* nd_free(spol); */
9620: }
9621: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9622: if ( DP_Print ) {
1.5 noro 9623: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9624: fflush(asir_out);
9625: }
9626: /* free index arrays */
9627: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9628:
9629: /* elimination (2nd step) */
9630: colstat = (int *)MALLOC(spcol*sizeof(int));
9631: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
9632: w = (pointer *)MALLOC(rank*sizeof(pointer));
9633: for ( i = 0; i < rank; i++ ) {
9634: #if 0
9635: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9636: SG((NDV)w[rank-i-1]) = spsugar[i];
9637: #else
9638: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9639: SG((NDV)w[i]) = spsugar[i];
9640: #endif
9641: /* GCFREE(spmat[i]); */
9642:
9643: }
9644: #if 0
9645: qsort(w,rank,sizeof(NDV),
9646: (int (*)(const void *,const void *))ndv_compare);
9647: #endif
9648: r0 = 0;
9649: for ( i = 0; i < rank; i++ ) {
9650: NEXTNODE(r0,r); BDY(r) = w[i];
9651: }
9652: if ( r0 ) NEXT(r) = 0;
9653:
9654: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9655: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9656: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9657: if ( DP_Print ) {
1.5 noro 9658: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9659: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9660: nsp,nred,sprow,spcol,rank);
1.5 noro 9661: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9662: }
9663: return r0;
9664: }
9665:
9666: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9667: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9668: {
9669: int spcol,sprow,a;
9670: int i,j,k,l,rank;
9671: NODE r0,r;
9672: ND_pairs sp;
9673: ND spol;
9674: Z **spmat;
9675: Z *svect,*v;
9676: int *colstat;
9677: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9678: int maxrs;
9679: int *spsugar;
9680: pointer *w;
9681:
9682: spcol = col-nred;
9683: get_eg(&eg0);
9684: /* elimination (1st step) */
9685: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
9686: svect = (Z *)MALLOC(col*sizeof(Q));
9687: spsugar = (int *)MALLOC(nsp*sizeof(int));
9688: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9689: nd_sp(0,trace,sp,&spol);
9690: if ( !spol ) continue;
9691: nd_to_vect_q(s0vect,col,spol,svect);
9692: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
9693: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9694: if ( i < col ) {
9695: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
9696: for ( j = k = 0; j < col; j++ )
9697: if ( !rhead[j] ) v[k++] = svect[j];
9698: spsugar[sprow] = MAX(maxrs,SG(spol));
9699: sprow++;
9700: }
9701: /* nd_free(spol); */
9702: }
9703: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9704: if ( DP_Print ) {
1.5 noro 9705: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9706: fflush(asir_out);
9707: }
9708: /* free index arrays */
9709: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9710:
9711: /* elimination (2nd step) */
9712: colstat = (int *)MALLOC(spcol*sizeof(int));
9713: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
9714: w = (pointer *)MALLOC(rank*sizeof(pointer));
9715: for ( i = 0; i < rank; i++ ) {
9716: #if 0
9717: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9718: SG((NDV)w[rank-i-1]) = spsugar[i];
9719: #else
9720: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9721: SG((NDV)w[i]) = spsugar[i];
9722: #endif
9723: /* GCFREE(spmat[i]); */
9724: }
9725: #if 0
9726: qsort(w,rank,sizeof(NDV),
9727: (int (*)(const void *,const void *))ndv_compare);
9728: #endif
9729: r0 = 0;
9730: for ( i = 0; i < rank; i++ ) {
9731: NEXTNODE(r0,r); BDY(r) = w[i];
9732: }
9733: if ( r0 ) NEXT(r) = 0;
9734:
9735: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9736: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9737: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9738: if ( DP_Print ) {
1.5 noro 9739: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9740: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9741: nsp,nred,sprow,spcol,rank);
1.5 noro 9742: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9743: }
9744: return r0;
9745: }
9746:
9747: FILE *nd_write,*nd_read;
9748:
9749: void nd_send_int(int a) {
9750: write_int(nd_write,(unsigned int *)&a);
9751: }
9752:
9753: void nd_send_intarray(int *p,int len) {
9754: write_intarray(nd_write,(unsigned int *)p,len);
9755: }
9756:
9757: int nd_recv_int() {
9758: int a;
9759:
9760: read_int(nd_read,(unsigned int *)&a);
9761: return a;
9762: }
9763:
9764: void nd_recv_intarray(int *p,int len) {
9765: read_intarray(nd_read,(unsigned int *)p,len);
9766: }
9767:
9768: void nd_send_ndv(NDV p) {
9769: int len,i;
9770: NMV m;
9771:
9772: if ( !p ) nd_send_int(0);
9773: else {
9774: len = LEN(p);
9775: nd_send_int(len);
9776: m = BDY(p);
9777: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9778: nd_send_int(CM(m));
9779: nd_send_intarray((int *)DL(m),nd_wpd);
9780: }
9781: }
9782: }
9783:
9784: void nd_send_nd(ND p) {
9785: int len,i;
9786: NM m;
9787:
9788: if ( !p ) nd_send_int(0);
9789: else {
9790: len = LEN(p);
9791: nd_send_int(len);
9792: m = BDY(p);
9793: for ( i = 0; i < len; i++, m = NEXT(m) ) {
9794: nd_send_int(CM(m));
9795: nd_send_intarray((int *)DL(m),nd_wpd);
9796: }
9797: }
9798: }
9799:
9800: NDV nd_recv_ndv()
9801: {
9802: int len,i;
9803: NMV m,m0;
9804: NDV r;
9805:
9806: len = nd_recv_int();
9807: if ( !len ) return 0;
9808: else {
9809: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
9810: #if 0
9811: ndv_alloc += len*nmv_adv;
9812: #endif
9813: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9814: CM(m) = nd_recv_int();
9815: nd_recv_intarray((int *)DL(m),nd_wpd);
9816: }
9817: MKNDV(nd_nvar,m0,len,r);
9818: return r;
9819: }
9820: }
9821:
9822: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
9823: {
9824: int i,j,t,c,rank,inv;
9825: int *ci,*ri;
9826: Z dn;
9827: MAT m,nm;
9828:
9829: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
9830: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
9831: for ( i = 0; i < row; i++ )
9832: for ( j = 0; j < col; j++ )
9833: mat0[i][j] = 0;
9834: c = col-rank;
9835: for ( i = 0; i < rank; i++ ) {
9836: mat0[i][ri[i]] = dn;
9837: for ( j = 0; j < c; j++ )
9838: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
9839: }
9840: return rank;
9841: }
9842:
9843: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
9844: {
9845: int i,j,k,l,inv,a,rank,s;
9846: unsigned int *t,*pivot,*pk;
9847: unsigned int **mat;
9848: ND_pairs pair;
9849:
9850: mat = (unsigned int **)mat0;
9851: for ( rank = 0, j = 0; j < col; j++ ) {
9852: for ( i = rank; i < row; i++ )
9853: mat[i][j] %= md;
9854: for ( i = rank; i < row; i++ )
9855: if ( mat[i][j] )
9856: break;
9857: if ( i == row ) {
9858: colstat[j] = 0;
9859: continue;
9860: } else
9861: colstat[j] = 1;
9862: if ( i != rank ) {
9863: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9864: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9865: if ( spactive ) {
9866: pair = spactive[i]; spactive[i] = spactive[rank];
9867: spactive[rank] = pair;
9868: }
9869: }
9870: pivot = mat[rank];
9871: s = sugar[rank];
9872: inv = invm(pivot[j],md);
9873: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9874: if ( *pk ) {
9875: if ( *pk >= (unsigned int)md )
9876: *pk %= md;
9877: DMAR(*pk,inv,0,md,*pk)
9878: }
9879: for ( i = rank+1; i < row; i++ ) {
9880: t = mat[i];
9881: if ( (a = t[j]) != 0 ) {
9882: sugar[i] = MAX(sugar[i],s);
9883: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9884: }
9885: }
9886: rank++;
9887: }
9888: for ( j = col-1, l = rank-1; j >= 0; j-- )
9889: if ( colstat[j] ) {
9890: pivot = mat[l];
9891: s = sugar[l];
9892: for ( i = 0; i < l; i++ ) {
9893: t = mat[i];
9894: t[j] %= md;
9895: if ( (a = t[j]) != 0 ) {
9896: sugar[i] = MAX(sugar[i],s);
9897: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9898: }
9899: }
9900: l--;
9901: }
9902: for ( j = 0, l = 0; l < rank; j++ )
9903: if ( colstat[j] ) {
9904: t = mat[l];
9905: for ( k = j; k < col; k++ )
9906: if ( t[k] >= (unsigned int)md )
9907: t[k] %= md;
9908: l++;
9909: }
9910: return rank;
9911: }
9912:
1.40 noro 9913: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
9914: {
9915: int i,j,k,l,rank,s,imin;
9916: UINT inv;
9917: UINT a;
9918: UINT *t,*pivot,*pk;
9919: UINT *ck;
9920: UINT *ct;
9921: ND_pairs pair;
9922: SIG sg;
9923: int *used;
9924:
9925: used = (int *)MALLOC(row*sizeof(int));
9926: for ( j = 0; j < col; j++ ) {
9927: for ( i = 0; i < row; i++ )
9928: a = mat[i][j] %= md;
9929: for ( i = 0; i < row; i++ )
9930: if ( !used[i] && mat[i][j] ) break;
9931: if ( i == row ) {
9932: colstat[j] = 0;
9933: continue;
9934: } else {
9935: colstat[j] = 1;
9936: used[i] = 1;
9937: }
9938: /* column j is normalized */
9939: s = sugar[i];
9940: inv = invm(mat[i][j],md);
9941: /* normalize pivot row */
9942: for ( k = j, pk = mat[i]+j; k < col; k++, pk++, ck++ ) {
9943: DMAR(*pk,inv,0,md,*pk);
9944: }
9945: for ( k = i+1; k < row; k++ ) {
9946: if ( (a = mat[k][j]) != 0 ) {
9947: sugar[k] = MAX(sugar[k],s);
9948: red_by_vect(md,mat[k]+j,mat[i]+j,(int)(md-a),col-j);
9949: Nf4_red++;
9950: }
9951: }
9952: }
9953: rank = 0;
9954: for ( i = 0; i < row; i++ ) {
9955: for ( j = 0; j < col; j++ )
9956: if ( mat[i][j] ) break;
9957: if ( j == col ) sugar[i] = -1;
9958: else rank++;
9959: }
9960: return rank;
9961: }
9962:
1.1 noro 9963:
1.7 noro 9964: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 9965: {
1.7 noro 9966: int i,j,k,l,inv,a,rank,s;
9967: unsigned int *t,*pivot,*pk;
9968: unsigned int **mat;
9969:
9970: mat = (unsigned int **)mat0;
9971: for ( rank = 0, j = 0; j < col; j++ ) {
9972: for ( i = rank; i < row; i++ )
9973: if ( mat[i][j] )
9974: break;
9975: if ( i == row ) {
9976: colstat[j] = 0;
9977: continue;
9978: } else
9979: colstat[j] = 1;
9980: if ( i != rank ) {
9981: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9982: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9983: }
9984: pivot = mat[rank];
9985: s = sugar[rank];
9986: inv = _invsf(pivot[j]);
9987: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9988: if ( *pk )
9989: *pk = _mulsf(*pk,inv);
9990: for ( i = rank+1; i < row; i++ ) {
9991: t = mat[i];
9992: if ( (a = t[j]) != 0 ) {
9993: sugar[i] = MAX(sugar[i],s);
9994: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9995: }
9996: }
9997: rank++;
9998: }
9999: for ( j = col-1, l = rank-1; j >= 0; j-- )
10000: if ( colstat[j] ) {
10001: pivot = mat[l];
10002: s = sugar[l];
10003: for ( i = 0; i < l; i++ ) {
10004: t = mat[i];
10005: if ( (a = t[j]) != 0 ) {
10006: sugar[i] = MAX(sugar[i],s);
10007: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
10008: }
10009: }
10010: l--;
10011: }
10012: return rank;
10013: }
1.1 noro 10014:
1.7 noro 10015: int ndv_ishomo(NDV p)
10016: {
10017: NMV m;
10018: int len,h;
1.1 noro 10019:
10020: if ( !p ) return 1;
10021: len = LEN(p);
10022: m = BDY(p);
10023: h = TD(DL(m));
10024: NMV_ADV(m);
10025: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 10026: if ( TD(DL(m)) != h ) {
10027: return 0;
10028: }
1.1 noro 10029: return 1;
10030: }
10031:
10032: void ndv_save(NDV p,int index)
10033: {
10034: FILE *s;
10035: char name[BUFSIZ];
10036: short id;
10037: int nv,sugar,len,n,i,td,e,j;
10038: NMV m;
10039: unsigned int *dl;
10040: int mpos;
10041:
10042: sprintf(name,"%s/%d",Demand,index);
10043: s = fopen(name,"w");
10044: savevl(s,0);
10045: if ( !p ) {
10046: saveobj(s,0);
10047: return;
10048: }
10049: id = O_DP;
10050: nv = NV(p);
10051: sugar = SG(p);
10052: len = LEN(p);
10053: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
10054: write_int(s,(unsigned int *)&len);
10055:
10056: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 10057: saveobj(s,(Obj)CZ(m));
1.1 noro 10058: dl = DL(m);
10059: td = TD(dl);
10060: write_int(s,(unsigned int *)&td);
10061: for ( j = 0; j < nv; j++ ) {
10062: e = GET_EXP(dl,j);
10063: write_int(s,(unsigned int *)&e);
10064: }
10065: if ( nd_module ) {
10066: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
10067: }
10068: }
10069: fclose(s);
10070: }
10071:
10072: void nd_save_mod(ND p,int index)
10073: {
10074: FILE *s;
10075: char name[BUFSIZ];
10076: int nv,sugar,len,c;
10077: NM m;
10078:
10079: sprintf(name,"%s/%d",Demand,index);
10080: s = fopen(name,"w");
10081: if ( !p ) {
10082: len = 0;
10083: write_int(s,(unsigned int *)&len);
10084: fclose(s);
10085: return;
10086: }
10087: nv = NV(p);
10088: sugar = SG(p);
10089: len = LEN(p);
10090: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
10091: for ( m = BDY(p); m; m = NEXT(m) ) {
10092: c = CM(m); write_int(s,(unsigned int *)&c);
10093: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
10094: }
10095: fclose(s);
10096: }
10097:
10098: NDV ndv_load(int index)
10099: {
10100: FILE *s;
10101: char name[BUFSIZ];
10102: short id;
10103: int nv,sugar,len,n,i,td,e,j;
10104: NDV d;
10105: NMV m0,m;
10106: unsigned int *dl;
10107: Obj obj;
10108: int mpos;
10109:
10110: sprintf(name,"%s/%d",Demand,index);
10111: s = fopen(name,"r");
10112: if ( !s ) return 0;
10113:
10114: skipvl(s);
10115: read_short(s,(unsigned short *)&id);
10116: if ( !id ) return 0;
10117: read_int(s,(unsigned int *)&nv);
10118: read_int(s,(unsigned int *)&sugar);
10119: read_int(s,(unsigned int *)&len);
10120:
10121: m0 = m = MALLOC(len*nmv_adv);
10122: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 10123: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 10124: dl = DL(m);
10125: ndl_zero(dl);
10126: read_int(s,(unsigned int *)&td); TD(dl) = td;
10127: for ( j = 0; j < nv; j++ ) {
10128: read_int(s,(unsigned int *)&e);
10129: PUT_EXP(dl,j,e);
10130: }
10131: if ( nd_module ) {
10132: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
10133: }
10134: if ( nd_blockmask ) ndl_weight_mask(dl);
10135: }
10136: fclose(s);
10137: MKNDV(nv,m0,len,d);
10138: SG(d) = sugar;
10139: return d;
10140: }
10141:
10142: ND nd_load_mod(int index)
10143: {
10144: FILE *s;
10145: char name[BUFSIZ];
10146: int nv,sugar,len,i,c;
10147: ND d;
10148: NM m0,m;
10149:
10150: sprintf(name,"%s/%d",Demand,index);
10151: s = fopen(name,"r");
10152: /* if the file does not exist, it means p[index]=0 */
10153: if ( !s ) return 0;
10154:
10155: read_int(s,(unsigned int *)&nv);
10156: if ( !nv ) { fclose(s); return 0; }
10157:
10158: read_int(s,(unsigned int *)&sugar);
10159: read_int(s,(unsigned int *)&len);
10160: for ( m0 = 0, i = 0; i < len; i++ ) {
10161: NEXTNM(m0,m);
10162: read_int(s,(unsigned int *)&c); CM(m) = c;
10163: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
10164: }
10165: NEXT(m) = 0;
10166: MKND(nv,m0,len,d);
10167: SG(d) = sugar;
10168: fclose(s);
10169: return d;
10170: }
10171:
10172: void nd_det(int mod,MAT f,P *rp)
10173: {
10174: VL fv,tv;
10175: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
10176: pointer **m;
10177: P **w;
10178: P mp,r;
10179: NDV **dm;
10180: NDV *t,*mi,*mj;
10181: NDV d,s,mij,mjj;
10182: ND u;
10183: NMV nmv;
10184: UINT *bound;
10185: PGeoBucket bucket;
10186: struct order_spec *ord;
10187: Z dq,dt,ds;
10188: Z mone;
10189: Z gn,qn,dn0,nm,dn;
10190:
10191: create_order_spec(0,0,&ord);
10192: nd_init_ord(ord);
10193: get_vars((Obj)f,&fv);
10194: if ( f->row != f->col )
10195: error("nd_det : non-square matrix");
10196: n = f->row;
10197: m = f->body;
10198: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
10199:
10200: if ( !nvar ) {
10201: if ( !mod )
10202: detp(CO,(P **)m,n,rp);
10203: else {
10204: w = (P **)almat_pointer(n,n);
10205: for ( i = 0; i < n; i++ )
10206: for ( j = 0; j < n; j++ )
10207: ptomp(mod,(P)m[i][j],&w[i][j]);
10208: detmp(CO,mod,w,n,&mp);
10209: mptop(mp,rp);
10210: }
10211: return;
10212: }
10213:
10214: if ( !mod ) {
10215: w = (P **)almat_pointer(n,n);
10216: dq = ONE;
10217: for ( i = 0; i < n; i++ ) {
10218: dn0 = ONE;
10219: for ( j = 0; j < n; j++ ) {
10220: if ( !m[i][j] ) continue;
10221: lgp(m[i][j],&nm,&dn);
1.6 noro 10222: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 10223: }
10224: if ( !UNIZ(dn0) ) {
10225: ds = dn0;
10226: for ( j = 0; j < n; j++ )
10227: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
10228: mulz(dq,ds,&dt); dq = dt;
10229: } else
10230: for ( j = 0; j < n; j++ )
10231: w[i][j] = (P)m[i][j];
10232: }
10233: m = (pointer **)w;
10234: }
10235:
10236: for ( i = 0, max = 1; i < n; i++ )
10237: for ( j = 0; j < n; j++ )
10238: for ( tv = fv; tv; tv = NEXT(tv) ) {
10239: e = getdeg(tv->v,(P)m[i][j]);
10240: max = MAX(e,max);
10241: }
10242: nd_setup_parameters(nvar,max);
10243: dm = (NDV **)almat_pointer(n,n);
10244: for ( i = 0, max = 1; i < n; i++ )
10245: for ( j = 0; j < n; j++ ) {
10246: dm[i][j] = ptondv(CO,fv,m[i][j]);
10247: if ( mod ) ndv_mod(mod,dm[i][j]);
10248: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
10249: }
10250: d = ptondv(CO,fv,(P)ONE);
10251: if ( mod ) ndv_mod(mod,d);
10252: chsgnz(ONE,&mone);
10253: for ( j = 0, sgn = 1; j < n; j++ ) {
10254: if ( DP_Print ) {
10255: fprintf(asir_out,".");
10256: }
10257: for ( i = j; i < n && !dm[i][j]; i++ );
10258: if ( i == n ) {
10259: *rp = 0;
10260: return;
10261: }
10262: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
10263: for ( k = j; k < n; k++ )
10264: for ( l = j; l < n; l++ )
10265: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
10266: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
10267: }
10268: if ( k0 != j ) {
10269: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
10270: sgn = -sgn;
10271: }
10272: if ( l0 != j ) {
10273: for ( k = j; k < n; k++ ) {
10274: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
10275: }
10276: sgn = -sgn;
10277: }
10278: bound = nd_det_compute_bound(dm,n,j);
10279: for ( k = 0; k < nd_nvar; k++ )
10280: if ( bound[k]*2 > nd_mask0 ) break;
10281: if ( k < nd_nvar )
10282: nd_det_reconstruct(dm,n,j,d);
10283:
10284: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
10285: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
10286: mi = dm[i]; mij = mi[j];
10287: if ( mod )
10288: ndv_mul_c(mod,mij,mod-1);
10289: else
10290: ndv_mul_c_q(mij,mone);
10291: for ( k = j+1; k < n; k++ ) {
10292: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
10293: bucket = create_pbucket();
10294: if ( mi[k] ) {
10295: nmv = BDY(mjj); len = LEN(mjj);
10296: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10297: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
10298: add_pbucket(mod,bucket,u);
10299: }
10300: }
10301: if ( mj[k] && mij ) {
10302: nmv = BDY(mij); len = LEN(mij);
10303: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10304: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
10305: add_pbucket(mod,bucket,u);
10306: }
10307: }
10308: u = nd_quo(mod,bucket,d);
10309: mi[k] = ndtondv(mod,u);
10310: }
10311: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
10312: }
10313: d = mjj;
10314: }
10315: if ( DP_Print ) {
10316: fprintf(asir_out,"\n");
10317: }
10318: if ( sgn < 0 ) {
10319: if ( mod )
10320: ndv_mul_c(mod,d,mod-1);
10321: else
10322: ndv_mul_c_q(d,mone);
10323: }
10324: r = ndvtop(mod,CO,fv,d);
10325: if ( !mod && !UNIQ(dq) )
10326: divsp(CO,r,(P)dq,rp);
10327: else
10328: *rp = r;
10329: }
10330:
10331: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
10332: {
10333: NM mr,mr0;
10334: NM tnm;
10335: NMV m;
10336: UINT *d0,*dt,*dm;
10337: int c,n,td,i,c1,c2,len;
10338: Z q;
10339: ND r;
10340:
10341: if ( !p ) return 0;
10342: else {
10343: n = NV(p); m = BDY(p); len = LEN(p);
10344: d0 = DL(m0);
10345: td = TD(d);
10346: mr0 = 0;
10347: NEWNM(tnm);
10348: if ( mod ) {
10349: c = CM(m0);
10350: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10351: ndl_add(DL(m),d0,DL(tnm));
10352: if ( ndl_reducible(DL(tnm),d) ) {
10353: NEXTNM(mr0,mr);
10354: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
10355: ndl_copy(DL(tnm),DL(mr));
10356: }
10357: }
10358: } else {
1.6 noro 10359: q = CZ(m0);
1.1 noro 10360: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10361: ndl_add(DL(m),d0,DL(tnm));
10362: if ( ndl_reducible(DL(tnm),d) ) {
10363: NEXTNM(mr0,mr);
1.6 noro 10364: mulz(CZ(m),q,&CZ(mr));
1.1 noro 10365: ndl_copy(DL(tnm),DL(mr));
10366: }
10367: }
10368: }
10369: if ( !mr0 )
10370: return 0;
10371: else {
10372: NEXT(mr) = 0;
10373: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10374: MKND(NV(p),mr0,len,r);
10375: SG(r) = SG(p) + TD(d0);
10376: return r;
10377: }
10378: }
10379: }
10380:
10381: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
10382: {
10383: int i,obpe,oadv,h,k,l;
10384: static NM prev_nm_free_list;
10385: EPOS oepos;
10386:
10387: obpe = nd_bpe;
10388: oadv = nmv_adv;
10389: oepos = nd_epos;
10390: if ( obpe < 2 ) nd_bpe = 2;
10391: else if ( obpe < 3 ) nd_bpe = 3;
10392: else if ( obpe < 4 ) nd_bpe = 4;
10393: else if ( obpe < 5 ) nd_bpe = 5;
10394: else if ( obpe < 6 ) nd_bpe = 6;
10395: else if ( obpe < 8 ) nd_bpe = 8;
10396: else if ( obpe < 10 ) nd_bpe = 10;
10397: else if ( obpe < 16 ) nd_bpe = 16;
10398: else if ( obpe < 32 ) nd_bpe = 32;
10399: else error("nd_det_reconstruct : exponent too large");
10400:
10401: nd_setup_parameters(nd_nvar,0);
10402: prev_nm_free_list = _nm_free_list;
10403: _nm_free_list = 0;
10404: for ( k = j; k < n; k++ )
10405: for (l = j; l < n; l++ )
10406: ndv_realloc(dm[k][l],obpe,oadv,oepos);
10407: ndv_realloc(d,obpe,oadv,oepos);
10408: prev_nm_free_list = 0;
10409: #if 0
10410: GC_gcollect();
10411: #endif
10412: }
10413:
10414: /* returns a UINT array containing degree bounds */
10415:
10416: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
10417: {
10418: UINT *d0,*d1,*d,*t,*r;
10419: int k,l,i;
10420:
10421: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
10422: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
10423: for ( k = j; k < n; k++ )
10424: for ( l = j; l < n; l++ )
10425: if ( dm[k][l] ) {
10426: d = ndv_compute_bound(dm[k][l]);
10427: for ( i = 0; i < nd_nvar; i++ )
10428: d0[i] = MAX(d0[i],d[i]);
10429: }
10430: return d0;
10431: }
10432:
10433: DL nd_separate_d(UINT *d,UINT *trans)
10434: {
10435: int n,td,i,e,j;
10436: DL a;
10437:
10438: ndl_zero(trans);
10439: td = 0;
10440: for ( i = 0; i < nd_ntrans; i++ ) {
10441: e = GET_EXP(d,i);
10442: PUT_EXP(trans,i,e);
10443: td += MUL_WEIGHT(e,i);
10444: }
10445: if ( nd_ntrans+nd_nalg < nd_nvar ) {
10446: /* homogenized */
10447: i = nd_nvar-1;
10448: e = GET_EXP(d,i);
10449: PUT_EXP(trans,i,e);
10450: td += MUL_WEIGHT(e,i);
10451: }
10452: TD(trans) = td;
10453: if ( nd_blockmask) ndl_weight_mask(trans);
10454: NEWDL(a,nd_nalg);
10455: td = 0;
10456: for ( i = 0; i < nd_nalg; i++ ) {
10457: j = nd_ntrans+i;
10458: e = GET_EXP(d,j);
10459: a->d[i] = e;
10460: td += e;
10461: }
10462: a->td = td;
10463: return a;
10464: }
10465:
10466: int nd_monic(int mod,ND *p)
10467: {
10468: UINT *trans,*t;
10469: DL alg;
10470: MP mp0,mp;
10471: NM m,m0,m1,ma0,ma,mb,mr0,mr;
10472: ND r;
10473: DL dl;
10474: DP nm;
10475: NDV ndv;
10476: DAlg inv,cd;
10477: ND s,c;
10478: Z l,mul;
10479: Z ln;
10480: int n,ntrans,i,e,td,is_lc,len;
10481: NumberField nf;
10482: struct oEGT eg0,eg1;
10483:
10484: if ( !(nf = get_numberfield()) )
10485: error("nd_monic : current_numberfield is not set");
10486:
10487: /* Q coef -> DAlg coef */
10488: NEWNM(ma0); ma = ma0;
10489: m = BDY(*p);
10490: is_lc = 1;
10491: while ( 1 ) {
10492: NEWMP(mp0); mp = mp0;
1.6 noro 10493: mp->c = (Obj)CZ(m);
1.1 noro 10494: mp->dl = nd_separate_d(DL(m),DL(ma));
10495: NEWNM(mb);
10496: for ( m = NEXT(m); m; m = NEXT(m) ) {
10497: alg = nd_separate_d(DL(m),DL(mb));
10498: if ( !ndl_equal(DL(ma),DL(mb)) )
10499: break;
1.6 noro 10500: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 10501: }
10502: NEXT(mp) = 0;
10503: MKDP(nd_nalg,mp0,nm);
10504: MKDAlg(nm,ONE,cd);
10505: if ( is_lc == 1 ) {
10506: /* if the lc is a rational number, we have nothing to do */
10507: if ( !mp0->dl->td )
10508: return 1;
10509:
10510: get_eg(&eg0);
10511: invdalg(cd,&inv);
10512: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
10513: /* check the validity of inv */
10514: if ( mod && !remqi((Q)inv->dn,mod) )
10515: return 0;
10516: CA(ma) = nf->one;
10517: is_lc = 0;
10518: ln = ONE;
10519: } else {
10520: muldalg(cd,inv,&CA(ma));
10521: lcmz(ln,CA(ma)->dn,&ln);
10522: }
10523: if ( m ) {
10524: NEXT(ma) = mb; ma = mb;
10525: } else {
10526: NEXT(ma) = 0;
10527: break;
10528: }
10529: }
10530: /* l = lcm(denoms) */
10531: l = ln;
10532: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 10533: divsz(l,CA(m)->dn,&mul);
1.1 noro 10534: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
10535: NEXTNM(mr0,mr);
1.6 noro 10536: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 10537: dl = mp->dl;
10538: td = TD(DL(m));
10539: ndl_copy(DL(m),DL(mr));
10540: for ( i = 0; i < nd_nalg; i++ ) {
10541: e = dl->d[i];
10542: PUT_EXP(DL(mr),i+nd_ntrans,e);
10543: td += MUL_WEIGHT(e,i+nd_ntrans);
10544: }
10545: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
10546: TD(DL(mr)) = td;
10547: if ( nd_blockmask) ndl_weight_mask(DL(mr));
10548: }
10549: }
10550: NEXT(mr) = 0;
10551: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10552: MKND(NV(*p),mr0,len,r);
10553: /* XXX */
10554: SG(r) = SG(*p);
10555: nd_free(*p);
10556: *p = r;
10557: return 1;
10558: }
10559:
10560: NODE reverse_node(NODE n)
10561: {
10562: NODE t,t1;
10563:
10564: for ( t = 0; n; n = NEXT(n) ) {
10565: MKNODE(t1,BDY(n),t); t = t1;
10566: }
10567: return t;
10568: }
10569:
10570: P ndc_div(int mod,union oNDC a,union oNDC b)
10571: {
10572: union oNDC c;
10573: int inv,t;
10574:
10575: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 10576: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 10577: else if ( mod ) {
10578: inv = invm(b.m,mod);
10579: DMAR(a.m,inv,0,mod,t); c.m = t;
10580: } else if ( nd_vc )
10581: divsp(nd_vc,a.p,b.p,&c.p);
10582: else
10583: divsz(a.z,b.z,&c.z);
10584: return ndctop(mod,c);
10585: }
10586:
10587: P ndctop(int mod,union oNDC c)
10588: {
10589: Z q;
10590: int e;
10591: GFS gfs;
10592:
10593: if ( mod == -1 ) {
10594: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
10595: } else if ( mod == -2 ) {
1.10 noro 10596: q = c.z; return (P)q;
1.1 noro 10597: } else if ( mod > 0 ) {
1.6 noro 10598: STOZ(c.m,q); return (P)q;
1.1 noro 10599: } else
10600: return (P)c.p;
10601: }
10602:
10603: /* [0,0,0,cont] = p -> p/cont */
10604:
10605: void finalize_tracelist(int i,P cont)
10606: {
10607: LIST l;
10608: NODE node;
10609: Z iq;
10610:
10611: if ( !UNIQ(cont) ) {
10612: node = mknode(4,NULLP,NULLP,NULLP,cont);
10613: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
10614: nd_tracelist = node;
10615: }
1.6 noro 10616: STOZ(i,iq);
1.1 noro 10617: nd_tracelist = reverse_node(nd_tracelist);
10618: MKLIST(l,nd_tracelist);
10619: node = mknode(2,iq,l); MKLIST(l,node);
10620: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
10621: nd_alltracelist = node; nd_tracelist = 0;
10622: }
10623:
10624: void conv_ilist(int demand,int trace,NODE g,int **indp)
10625: {
10626: int n,i,j;
10627: int *ind;
10628: NODE t;
10629:
10630: n = length(g);
10631: ind = (int *)MALLOC(n*sizeof(int));
10632: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
10633: j = (long)BDY(t); ind[i] = j;
10634: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
10635: }
10636: if ( indp ) *indp = ind;
10637: }
10638:
1.30 noro 10639: NODE conv_ilist_s(int demand,int trace,int **indp)
10640: {
10641: int n,i,j;
10642: int *ind;
10643: NODE g0,g;
10644:
10645: n = nd_psn;
10646: ind = (int *)MALLOC(n*sizeof(int));
10647: g0 = 0;
10648: for ( i = 0; i < n; i++ ) {
10649: ind[i] = i;
10650: NEXTNODE(g0,g);
10651: BDY(g) = (pointer)(demand?ndv_load(i):(trace?nd_ps_trace[i]:nd_ps[i]));
10652: }
10653: if ( g0 ) NEXT(g) = 0;
10654: if ( indp ) *indp = ind;
10655: return g0;
10656: }
10657:
1.46 noro 10658: void parse_nd_option(VL vl,NODE opt)
1.1 noro 10659: {
1.38 noro 10660: NODE t,p,u;
1.1 noro 10661: int i,s,n;
1.38 noro 10662: char *key;
10663: Obj value;
1.46 noro 10664: VL oldvl;
1.1 noro 10665:
1.41 noro 10666: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_norb = 0; nd_gbblock = 0;
1.1 noro 10667: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
10668: nd_splist = 0; nd_check_splist = 0;
1.38 noro 10669: nd_sugarweight = 0; nd_f4red =0; nd_rank0 = 0;
10670: nd_f4_td = 0; nd_sba_f4step = 2; nd_sba_pot = 0; nd_sba_largelcm = 0;
1.41 noro 10671: nd_sba_dontsort = 0; nd_top = 0; nd_sba_redundant_check = 0;
1.46 noro 10672: nd_sba_syz = 0; nd_sba_modord = 0; nd_sba_inputisgb = 0;
1.49 noro 10673: nd_hpdata = 0;
1.39 noro 10674:
1.38 noro 10675: for ( t = opt; t; t = NEXT(t) ) {
10676: p = BDY((LIST)BDY(t));
10677: key = BDY((STRING)BDY(p));
10678: value = (Obj)BDY(NEXT(p));
10679: if ( !strcmp(key,"gentrace") )
10680: nd_gentrace = value?1:0;
10681: else if ( !strcmp(key,"gensyz") )
10682: nd_gensyz = value?1:0;
10683: else if ( !strcmp(key,"nora") )
10684: nd_nora = value?1:0;
1.41 noro 10685: else if ( !strcmp(key,"norb") )
10686: nd_norb = value?1:0;
1.38 noro 10687: else if ( !strcmp(key,"gbblock") ) {
10688: if ( value && OID(value) == O_LIST ) {
1.1 noro 10689: u = BDY((LIST)value);
1.38 noro 10690: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
1.1 noro 10691: for ( i = 0; u; u = NEXT(u) ) {
10692: p = BDY((LIST)BDY(u));
1.6 noro 10693: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
10694: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 10695: }
10696: nd_gbblock[i] = -1;
1.38 noro 10697: } else
10698: nd_gbblock = 0;
1.1 noro 10699: } else if ( !strcmp(key,"newelim") )
10700: nd_newelim = value?1:0;
10701: else if ( !strcmp(key,"intersect") )
10702: nd_intersect = value?1:0;
1.17 noro 10703: else if ( !strcmp(key,"syzgen") )
10704: nd_intersect = ZTOS((Q)value);
1.1 noro 10705: else if ( !strcmp(key,"lf") )
10706: nd_lf = value?1:0;
10707: else if ( !strcmp(key,"trace") ) {
1.38 noro 10708: if ( value ) {
10709: u = BDY((LIST)value);
10710: nd_nzlist = BDY((LIST)ARG2(u));
10711: nd_bpe = ZTOS((Q)ARG3(u));
10712: }
1.1 noro 10713: } else if ( !strcmp(key,"f4red") ) {
1.38 noro 10714: nd_f4red = ZTOS((Q)value);
1.1 noro 10715: } else if ( !strcmp(key,"rank0") ) {
1.38 noro 10716: nd_rank0 = value?1:0;
1.1 noro 10717: } else if ( !strcmp(key,"splist") ) {
1.38 noro 10718: nd_splist = value?1:0;
1.1 noro 10719: } else if ( !strcmp(key,"check_splist") ) {
10720: nd_check_splist = BDY((LIST)value);
1.49 noro 10721: } else if ( !strcmp(key,"hpdata") ) {
1.50 noro 10722: if ( value )
10723: nd_hpdata = BDY((LIST)value);
1.1 noro 10724: } else if ( !strcmp(key,"sugarweight") ) {
10725: u = BDY((LIST)value);
1.38 noro 10726: n = length(u);
10727: nd_sugarweight = MALLOC(n*sizeof(int));
1.1 noro 10728: for ( i = 0; i < n; i++, u = NEXT(u) )
1.38 noro 10729: nd_sugarweight[i] = ZTOS((Q)BDY(u));
10730: } else if ( !strcmp(key,"f4_td") ) {
10731: nd_f4_td = value?1:0;
10732: } else if ( !strcmp(key,"sba_f4step") ) {
10733: nd_sba_f4step = value?ZTOS((Q)value):0;
10734: } else if ( !strcmp(key,"sba_pot") ) {
1.44 noro 10735: nd_sba_pot = ZTOS((Q)value);
1.38 noro 10736: } else if ( !strcmp(key,"sba_largelcm") ) {
10737: nd_sba_largelcm = value?1:0;
1.39 noro 10738: } else if ( !strcmp(key,"sba_dontsort") ) {
10739: nd_sba_dontsort = value?1:0;
1.44 noro 10740: } else if ( !strcmp(key,"sba_syz") ) {
10741: nd_sba_syz = value?1:0;
1.46 noro 10742: } else if ( !strcmp(key,"sba_modord") ) {
10743: // value=[vlist,ordspec,weight]
10744: u = BDY((LIST)value);
10745: pltovl((LIST)ARG0(u),&oldvl);
10746: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10747: } else if ( !strcmp(key,"sba_gbinput") ) {
10748: nd_sba_inputisgb = value?1:0;
10749: if ( nd_sba_inputisgb != 0 ) {
10750: // value=[vlist,ordspec,weight]
10751: u = BDY((LIST)value);
10752: pltovl((LIST)ARG0(u),&oldvl);
10753: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10754: }
1.41 noro 10755: } else if ( !strcmp(key,"sba_redundant_check") ) {
10756: nd_sba_redundant_check = value?1:0;
1.39 noro 10757: } else if ( !strcmp(key,"top") ) {
10758: nd_top = value?1:0;
1.1 noro 10759: }
1.38 noro 10760: }
1.44 noro 10761: if ( nd_sba_syz ) nd_sba_dontsort = 1;
1.1 noro 10762: }
10763:
10764: ND mdptond(DP d);
10765: ND nd_mul_nm(int mod,NM m0,ND p);
10766: ND nd_mul_nm_lf(NM m0,ND p);
10767: ND *btog(NODE ti,ND **p,int nb,int mod);
10768: ND btog_one(NODE ti,ND *p,int nb,int mod);
10769: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
10770: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
10771:
10772: /* d:monomial */
10773: ND mdptond(DP d)
10774: {
10775: NM m;
10776: ND r;
10777:
10778: if ( OID(d) == 1 )
10779: r = ptond(CO,CO,(P)d);
10780: else {
10781: NEWNM(m);
10782: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 10783: CZ(m) = (Z)BDY(d)->c;
1.1 noro 10784: NEXT(m) = 0;
10785: MKND(NV(d),m,1,r);
10786: }
10787: return r;
10788: }
10789:
10790: ND nd_mul_nm(int mod,NM m0,ND p)
10791: {
10792: UINT *d0;
10793: int c0,c1,c;
10794: NM tm,mr,mr0;
10795: ND r;
10796:
10797: if ( !p ) return 0;
10798: d0 = DL(m0);
10799: c0 = CM(m0);
10800: mr0 = 0;
10801: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10802: NEXTNM(mr0,mr);
10803: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
10804: ndl_add(d0,DL(tm),DL(mr));
10805: }
10806: NEXT(mr) = 0;
10807: MKND(NV(p),mr0,LEN(p),r);
10808: return r;
10809: }
10810:
10811: ND nd_mul_nm_lf(NM m0,ND p)
10812: {
10813: UINT *d0;
10814: Z c0,c1,c;
10815: NM tm,mr,mr0;
10816: ND r;
10817:
10818: if ( !p ) return 0;
10819: d0 = DL(m0);
10820: c0 = CZ(m0);
10821: mr0 = 0;
10822: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10823: NEXTNM(mr0,mr);
10824: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
10825: ndl_add(d0,DL(tm),DL(mr));
10826: }
10827: NEXT(mr) = 0;
10828: MKND(NV(p),mr0,LEN(p),r);
10829: return r;
10830: }
10831:
10832: ND *btog(NODE ti,ND **p,int nb,int mod)
10833: {
10834: PGeoBucket *r;
10835: int i,ci;
10836: NODE t,s;
10837: ND m,tp;
10838: ND *pi,*rd;
10839: P c;
10840:
10841: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10842: for ( i = 0; i < nb; i++ )
10843: r[i] = create_pbucket();
10844: for ( t = ti; t; t = NEXT(t) ) {
10845: s = BDY((LIST)BDY(t));
10846: if ( ARG0(s) ) {
10847: m = mdptond((DP)ARG2(s));
1.6 noro 10848: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10849: if ( (ci = ((MQ)c)->cont) != 0 ) {
10850: HCM(m) = ci;
1.6 noro 10851: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10852: for ( i = 0; i < nb; i++ ) {
10853: tp = nd_mul_nm(mod,BDY(m),pi[i]);
10854: add_pbucket(mod,r[i],tp);
10855: }
10856: }
10857: ci = 1;
10858: } else {
10859: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10860: ci = invm(ci,mod);
10861: }
10862: }
10863: rd = (ND *)MALLOC(nb*sizeof(ND));
10864: for ( i = 0; i < nb; i++ )
10865: rd[i] = normalize_pbucket(mod,r[i]);
10866: if ( ci != 1 )
10867: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
10868: return rd;
10869: }
10870:
10871: /* YYY */
10872: ND *btog_lf(NODE ti,ND **p,int nb)
10873: {
10874: PGeoBucket *r;
10875: int i;
10876: NODE t,s;
10877: ND m,tp;
10878: ND *pi,*rd;
10879: LM lm;
10880: Z lf,c;
10881:
10882: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10883: for ( i = 0; i < nb; i++ )
10884: r[i] = create_pbucket();
10885: for ( t = ti; t; t = NEXT(t) ) {
10886: s = BDY((LIST)BDY(t));
10887: if ( ARG0(s) ) {
10888: m = mdptond((DP)ARG2(s));
1.6 noro 10889: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 10890: if ( lm ) {
10891: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 10892: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10893: for ( i = 0; i < nb; i++ ) {
10894: tp = nd_mul_nm_lf(BDY(m),pi[i]);
10895: add_pbucket(-2,r[i],tp);
10896: }
10897: }
10898: c = ONE;
10899: } else {
10900: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
10901: }
10902: }
10903: rd = (ND *)MALLOC(nb*sizeof(ND));
10904: for ( i = 0; i < nb; i++ )
10905: rd[i] = normalize_pbucket(-2,r[i]);
10906: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
10907: return rd;
10908: }
10909:
10910: ND btog_one(NODE ti,ND *p,int nb,int mod)
10911: {
10912: PGeoBucket r;
10913: int i,ci,j;
10914: NODE t,s;
10915: ND m,tp;
10916: ND pi,rd;
10917: P c;
10918:
10919: r = create_pbucket();
10920: for ( t = ti; t; t = NEXT(t) ) {
10921: s = BDY((LIST)BDY(t));
10922: if ( ARG0(s) ) {
10923: m = mdptond((DP)ARG2(s));
1.6 noro 10924: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10925: if ( (ci = ((MQ)c)->cont) != 0 ) {
10926: HCM(m) = ci;
1.6 noro 10927: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 10928: if ( !pi ) {
10929: pi = nd_load_mod(j);
10930: tp = nd_mul_nm(mod,BDY(m),pi);
10931: nd_free(pi);
10932: add_pbucket(mod,r,tp);
10933: } else {
10934: tp = nd_mul_nm(mod,BDY(m),pi);
10935: add_pbucket(mod,r,tp);
10936: }
10937: }
10938: ci = 1;
10939: } else {
10940: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10941: ci = invm(ci,mod);
10942: }
10943: }
10944: rd = normalize_pbucket(mod,r);
10945: free_pbucket(r);
10946: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
10947: return rd;
10948: }
10949:
10950: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
10951:
10952: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
10953: {
10954: int i,j,n,m,nb,pi0,pi1,nvar;
10955: VL fv,tv,vv;
10956: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10957: ND **p;
10958: ND *c;
10959: ND u;
10960: P inv;
10961: MAT mat;
10962:
10963: if ( mod == -2 )
10964: return nd_btog_lf(f,v,ord,tlist,rp);
10965:
10966: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10967: parse_nd_option(vv,current_option);
1.1 noro 10968: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10969: switch ( ord->id ) {
10970: case 1:
10971: if ( ord->nv != nvar )
10972: error("nd_check : invalid order specification");
10973: break;
10974: default:
10975: break;
10976: }
10977: nd_init_ord(ord);
10978: #if 0
1.6 noro 10979: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10980: #else
10981: nd_bpe = 32;
10982: #endif
10983: nd_setup_parameters(nvar,0);
10984: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10985: intred = BDY((LIST)ARG3(BDY(tlist)));
10986: ind = BDY((LIST)ARG4(BDY(tlist)));
10987: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10988: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10989: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10990: if ( j > i ) i = j;
10991: }
10992: n = i+1;
10993: nb = length(BDY(f));
10994: p = (ND **)MALLOC(n*sizeof(ND *));
10995: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10996: pi = BDY((LIST)BDY(t));
1.6 noro 10997: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10998: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10999: ptomp(mod,(P)ARG2(pi),&inv);
11000: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
11001: u = ptond(CO,vv,(P)ONE);
11002: HCM(u) = ((MQ)inv)->cont;
11003: c[pi1] = u;
11004: }
11005: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11006: printf("%d ",i); fflush(stdout);
11007: ti = BDY((LIST)BDY(t));
1.6 noro 11008: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11009: }
11010: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11011: printf("%d ",i); fflush(stdout);
11012: ti = BDY((LIST)BDY(t));
1.6 noro 11013: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11014: }
11015: m = length(ind);
11016: MKMAT(mat,nb,m);
11017: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 11018: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 11019: BDY(mat)[i][j] = ndtodp(mod,c[i]);
11020: return mat;
11021: }
11022:
11023: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
11024: {
11025: int i,j,n,m,nb,pi0,pi1,nvar;
11026: VL fv,tv,vv;
11027: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
11028: ND **p;
11029: ND *c;
11030: ND u;
11031: MAT mat;
11032: LM lm;
11033: Z lf,inv;
11034:
11035: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11036: parse_nd_option(vv,current_option);
1.1 noro 11037: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11038: switch ( ord->id ) {
11039: case 1:
11040: if ( ord->nv != nvar )
11041: error("nd_check : invalid order specification");
11042: break;
11043: default:
11044: break;
11045: }
11046: nd_init_ord(ord);
11047: #if 0
1.6 noro 11048: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 11049: #else
11050: nd_bpe = 32;
11051: #endif
11052: nd_setup_parameters(nvar,0);
11053: permtrace = BDY((LIST)ARG2(BDY(tlist)));
11054: intred = BDY((LIST)ARG3(BDY(tlist)));
11055: ind = BDY((LIST)ARG4(BDY(tlist)));
11056: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
11057: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 11058: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 11059: if ( j > i ) i = j;
11060: }
11061: n = i+1;
11062: nb = length(BDY(f));
11063: p = (ND **)MALLOC(n*sizeof(ND *));
11064: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
11065: pi = BDY((LIST)BDY(t));
1.6 noro 11066: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 11067: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
11068: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
11069: u = ptond(CO,vv,(P)ONE);
11070: HCZ(u) = inv;
11071: c[pi1] = u;
11072: }
11073: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11074: printf("%d ",i); fflush(stdout);
11075: ti = BDY((LIST)BDY(t));
1.6 noro 11076: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 11077: }
11078: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11079: printf("%d ",i); fflush(stdout);
11080: ti = BDY((LIST)BDY(t));
1.6 noro 11081: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 11082: }
11083: m = length(ind);
11084: MKMAT(mat,nb,m);
11085: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 11086: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 11087: BDY(mat)[i][j] = ndtodp(-2,c[i]);
11088: return mat;
11089: }
11090:
11091: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
11092: LIST tlist,int pos,MAT *rp)
11093: {
11094: int i,j,n,m,nb,pi0,pi1,nvar;
11095: VL fv,tv,vv;
11096: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
11097: ND *p;
11098: ND *c;
11099: ND u;
11100: P inv;
11101: VECT vect;
11102:
11103: if ( mod == -2 )
11104: error("nd_btog_one : not implemented yet for a large finite field");
11105:
11106: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11107: parse_nd_option(vv,current_option);
1.1 noro 11108: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11109: switch ( ord->id ) {
11110: case 1:
11111: if ( ord->nv != nvar )
11112: error("nd_check : invalid order specification");
11113: break;
11114: default:
11115: break;
11116: }
11117: nd_init_ord(ord);
11118: #if 0
1.6 noro 11119: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 11120: #else
11121: nd_bpe = 32;
11122: #endif
11123: nd_setup_parameters(nvar,0);
11124: permtrace = BDY((LIST)ARG2(BDY(tlist)));
11125: intred = BDY((LIST)ARG3(BDY(tlist)));
11126: ind = BDY((LIST)ARG4(BDY(tlist)));
11127: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
11128: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 11129: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 11130: if ( j > i ) i = j;
11131: }
11132: n = i+1;
11133: nb = length(BDY(f));
11134: p = (ND *)MALLOC(n*sizeof(ND *));
11135: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
11136: pi = BDY((LIST)BDY(t));
1.6 noro 11137: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 11138: if ( pi1 == pos ) {
11139: ptomp(mod,(P)ARG2(pi),&inv);
11140: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
11141: u = ptond(CO,vv,(P)ONE);
11142: HCM(u) = ((MQ)inv)->cont;
11143: p[pi0] = u;
11144: }
11145: }
11146: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11147: printf("%d ",i); fflush(stdout);
11148: ti = BDY((LIST)BDY(t));
1.6 noro 11149: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11150: if ( Demand ) {
11151: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
11152: }
11153: }
11154: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11155: printf("%d ",i); fflush(stdout);
11156: ti = BDY((LIST)BDY(t));
1.6 noro 11157: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11158: if ( Demand ) {
11159: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
11160: }
11161: }
11162: m = length(ind);
11163: MKVECT(vect,m);
11164: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 11165: u = p[ZTOS((Q)BDY(t))];
1.1 noro 11166: if ( !u ) {
1.6 noro 11167: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 11168: BDY(vect)[j] = ndtodp(mod,u);
11169: nd_free(u);
11170: } else
11171: BDY(vect)[j] = ndtodp(mod,u);
11172: }
11173: return vect;
11174: }
11175:
11176: void ndv_print_lf(NDV p)
11177: {
11178: NMV m;
11179: int i,len;
11180:
11181: if ( !p ) printf("0\n");
11182: else {
11183: len = LEN(p);
11184: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
11185: printf("+");
11186: mpz_out_str(asir_out,10,BDY(CZ(m)));
11187: printf("*");
11188: ndl_print(DL(m));
11189: }
11190: printf("\n");
11191: }
11192: }
11193:
11194: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
11195: {
11196: VL tv,fv,vv,vc,av;
11197: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
11198: int m,nocheck,nvar,mindex,e,max;
11199: NDV c;
11200: NMV a;
11201: P p,zp;
11202: Q dmy;
11203: EPOS oepos;
11204: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
11205: Alg alpha,dp;
11206: P poly;
11207: LIST f1,f2,zpl;
11208: Obj obj;
11209: NumberField nf;
11210: struct order_spec *ord1;
11211: struct oEGT eg_check,eg0,eg1;
11212: NODE tr,tl1,tl2,tl3,tl4;
11213: LIST l1,l2,l3,l4,l5;
11214: int *perm;
11215: int j,ret;
11216: NODE retn;
11217: Q jq,bpe;
11218:
11219: nd_module = 0;
11220: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11221: parse_nd_option(vv,current_option);
1.1 noro 11222: if ( nd_vc )
11223: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
11224: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11225: switch ( ord->id ) {
11226: case 1:
11227: if ( ord->nv != nvar )
11228: error("nd_f4_lf_trace : invalid order specification");
11229: break;
11230: default:
11231: break;
11232: }
11233:
11234: nd_ntrans = nvar;
11235: nd_nalg = 0;
11236:
11237: nocheck = 0;
11238: mindex = 0;
11239:
11240: /* do not use on-demand load/save */
11241: nd_demand = 0;
11242: m = trace > 1 ? trace : get_lprime(mindex);
11243: nd_init_ord(ord);
11244: mrank = 0;
11245: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
11246: for ( tv = vv; tv; tv = NEXT(tv) ) {
11247: if ( nd_module ) {
11248: s = BDY((LIST)BDY(t));
11249: trank = length(s);
11250: mrank = MAX(mrank,trank);
11251: for ( ; s; s = NEXT(s) ) {
11252: e = getdeg(tv->v,(P)BDY(s));
11253: max = MAX(e,max);
11254: }
11255: } else {
11256: e = getdeg(tv->v,(P)BDY(t));
11257: max = MAX(e,max);
11258: }
11259: }
11260: nd_setup_parameters(nvar,max);
11261: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
11262: ishomo = 1;
11263: /* XXX */
11264: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
11265: if ( nd_module ) {
11266: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
11267: } else {
11268: c = (pointer)ptondv(CO,vv,(P)BDY(t));
11269: }
11270: if ( ishomo )
11271: ishomo = ishomo && ndv_ishomo(c);
11272: if ( c ) {
11273: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
11274: ndv_mod(-2,c);
11275: NEXTNODE(in0,in); BDY(in) = (pointer)c;
11276: }
11277: }
11278: if ( in0 ) NEXT(in) = 0;
11279: if ( fd0 ) NEXT(fd) = 0;
11280: if ( !ishomo && homo ) {
11281: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
11282: c = (NDV)BDY(t); len = LEN(c);
11283: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
11284: wmax = MAX(TD(DL(a)),wmax);
11285: }
11286: homogenize_order(ord,nvar,&ord1);
11287: nd_init_ord(ord1);
11288: nd_setup_parameters(nvar+1,wmax);
11289: for ( t = fd0; t; t = NEXT(t) )
11290: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
11291: }
11292: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 11293: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 11294: if ( ret )
11295: cand = nd_f4_lf_trace_main(m,&perm);
11296: if ( !ret || !cand ) {
11297: *rp = 0; return;
11298: }
11299: if ( !ishomo && homo ) {
11300: /* dehomogenization */
11301: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
11302: nd_init_ord(ord);
11303: nd_setup_parameters(nvar,0);
11304: }
11305: cand = ndv_reducebase(cand,perm);
11306: cand = ndv_reduceall(-2,cand);
11307: cbpe = nd_bpe;
11308: get_eg(&eg0);
11309: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
11310: /* gbcheck : cand is a GB of Id(cand) ? */
11311: retn = nd_f4(-2,0,0);
11312: }
11313: if ( !retn ) {
11314: /* failure */
11315: *rp = 0; return;
11316: }
11317: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
11318: if ( DP_Print )
1.5 noro 11319: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 11320: /* dp->p */
11321: nd_bpe = cbpe;
11322: nd_setup_parameters(nd_nvar,0);
11323: for ( r = cand; r; r = NEXT(r) ) {
11324: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
11325: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
11326: }
11327: MKLIST(*rp,cand);
11328: }
11329:
11330: NODE nd_f4_lf_trace_main(int m,int **indp)
11331: {
11332: int i,nh,stat,index;
11333: NODE r,rm,g;
11334: ND_pairs d,l,l0,t;
11335: ND spol,red;
11336: NDV nf,redv,nfqv,nfv;
11337: NM s0,s;
11338: NODE rp0,srp0,nflist,nflist_lf;
11339: int nsp,nred,col,rank,len,k,j,a;
11340: UINT c;
11341: UINT **spmat;
11342: UINT *s0vect,*svect,*p,*v;
11343: int *colstat;
11344: IndArray *imat;
11345: int *rhead;
11346: int spcol,sprow;
11347: int sugar;
11348: PGeoBucket bucket;
11349: struct oEGT eg0,eg1,eg_f4;
11350:
11351: g = 0; d = 0;
11352: for ( i = 0; i < nd_psn; i++ ) {
11353: d = update_pairs(d,g,i,0);
11354: g = update_base(g,i);
11355: }
11356: while ( d ) {
11357: get_eg(&eg0);
11358: l = nd_minsugarp(d,&d);
11359: sugar = SG(l);
11360: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
11361: bucket = create_pbucket();
11362: stat = nd_sp_f4(m,0,l,bucket);
11363: if ( !stat ) {
11364: for ( t = l; NEXT(t); t = NEXT(t) );
11365: NEXT(t) = d; d = l;
11366: d = nd_reconstruct(1,d);
11367: continue;
11368: }
11369: if ( bucket->m < 0 ) continue;
11370: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
11371: if ( !col ) {
11372: for ( t = l; NEXT(t); t = NEXT(t) );
11373: NEXT(t) = d; d = l;
11374: d = nd_reconstruct(1,d);
11375: continue;
11376: }
11377: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
11378: if ( DP_Print )
1.5 noro 11379: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 11380: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
11381: if ( !l0 ) continue;
11382: l = l0;
11383:
11384: /* over LF */
11385: bucket = create_pbucket();
11386: stat = nd_sp_f4(-2,1,l,bucket);
11387: if ( !stat ) {
11388: for ( t = l; NEXT(t); t = NEXT(t) );
11389: NEXT(t) = d; d = l;
11390: d = nd_reconstruct(1,d);
11391: continue;
11392: }
11393: if ( bucket->m < 0 ) continue;
11394: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
11395: if ( !col ) {
11396: for ( t = l; NEXT(t); t = NEXT(t) );
11397: NEXT(t) = d; d = l;
11398: d = nd_reconstruct(1,d);
11399: continue;
11400: }
11401: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
11402: /* adding new bases */
11403: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
11404: nfv = (NDV)BDY(rm);
11405: nfqv = (NDV)BDY(r);
11406: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
11407: ndv_removecont(m,nfv);
11408: ndv_removecont(-2,nfqv);
1.24 noro 11409: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 11410: d = update_pairs(d,g,nh,0);
11411: g = update_base(g,nh);
11412: }
11413: if ( r || rm ) return 0;
11414: }
11415: conv_ilist(nd_demand,1,g,indp);
11416: return g;
11417: }
11418:
1.7 noro 11419: #if SIZEOF_LONG==8
11420:
11421: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
11422: {
11423: int j,k,len;
11424: UINT *p;
11425: UINT c;
11426: NDV r;
11427: NMV mr0,mr;
11428:
11429: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
11430: if ( !len ) return 0;
11431: else {
11432: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11433: #if 0
11434: ndv_alloc += nmv_adv*len;
11435: #endif
11436: mr = mr0;
11437: p = s0vect;
11438: for ( j = k = 0; j < col; j++, p += nd_wpd )
11439: if ( !rhead[j] ) {
11440: if ( (c = (UINT)vect[k++]) != 0 ) {
11441: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11442: }
11443: }
11444: MKNDV(nd_nvar,mr0,len,r);
11445: return r;
11446: }
11447: }
11448:
1.28 noro 11449: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
11450: {
11451: int j,k,len;
11452: UINT *p;
11453: UINT c;
11454: NDV r;
11455: NMV mr0,mr;
11456:
11457: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
11458: if ( !len ) return 0;
11459: else {
11460: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11461: mr = mr0;
11462: p = s0vect;
11463: for ( j = k = 0; j < col; j++, p += nd_wpd )
11464: if ( (c = (UINT)vect[k++]) != 0 ) {
11465: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11466: }
11467: MKNDV(nd_nvar,mr0,len,r);
11468: return r;
11469: }
11470: }
11471:
1.7 noro 11472: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
11473: {
11474: NM m;
1.11 noro 11475: UINT *t,*s,*u;
11476: int i,st,ed,md,prev,c;
1.7 noro 11477:
11478: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 11479: prev = 0;
11480: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
11481: t = DL(m);
11482: st = prev;
11483: ed = n;
11484: while ( ed > st ) {
11485: md = (st+ed)/2;
11486: u = s0+md*nd_wpd;
11487: c = DL_COMPARE(u,t);
11488: if ( c == 0 ) break;
11489: else if ( c > 0 ) st = md;
11490: else ed = md;
11491: }
11492: r[md] = (mp_limb_t)CM(m);
11493: prev = md;
1.7 noro 11494: }
11495: for ( i = 0; !r[i]; i++ );
11496: return i;
11497: }
11498:
11499: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
11500:
1.28 noro 11501: int ndv_reduce_vect64(int m,mp_limb_t *svect,mp_limb_t *cvect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.7 noro 11502: {
11503: int i,j,k,len,pos,prev;
11504: mp_limb_t a,c,c1,c2;
11505: IndArray ivect;
11506: unsigned char *ivc;
11507: unsigned short *ivs;
11508: unsigned int *ivi;
11509: NDV redv;
11510: NMV mr;
11511: NODE rp;
11512: int maxrs;
11513:
11514: for ( i = 0; i < col; i++ ) cvect[i] = 0;
11515: maxrs = 0;
11516: for ( i = 0; i < nred; i++ ) {
11517: ivect = imat[i];
11518: k = ivect->head;
11519: a = svect[k]; c = cvect[k];
11520: MOD128(a,c,m);
11521: svect[k] = a; cvect[k] = 0;
1.28 noro 11522: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 11523: Nf4_red++;
1.7 noro 11524: maxrs = MAX(maxrs,rp0[i]->sugar);
11525: c = m-c; redv = nd_ps[rp0[i]->index];
11526: len = LEN(redv); mr = BDY(redv);
11527: svect[k] = 0; prev = k;
11528: switch ( ivect->width ) {
11529: case 1:
11530: ivc = ivect->index.c;
11531: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11532: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 11533: c2 = svect[pos]+c1*c;
11534: if ( c2 < svect[pos] ) cvect[pos]++;
11535: svect[pos] = c2;
1.7 noro 11536: }
11537: break;
11538: case 2:
11539: ivs = ivect->index.s;
11540: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11541: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 11542: c2 = svect[pos]+c1*c;
11543: if ( c2 < svect[pos] ) cvect[pos]++;
11544: svect[pos] = c2;
1.7 noro 11545: }
11546: break;
11547: case 4:
11548: ivi = ivect->index.i;
11549: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11550: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 11551: c2 = svect[pos]+c1*c;
11552: if ( c2 < svect[pos] ) cvect[pos]++;
11553: svect[pos] = c2;
1.7 noro 11554: }
11555: break;
11556: }
11557: }
11558: }
11559: for ( i = 0; i < col; i++ ) {
11560: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
11561: }
11562: return maxrs;
11563: }
11564:
11565: /* for Fp, 2^15=<p<2^29 */
11566:
11567: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11568: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
11569: {
11570: int spcol,sprow,a;
11571: int i,j,k,l,rank;
11572: NODE r0,r;
11573: ND_pairs sp;
11574: ND spol;
11575: mp_limb_t **spmat;
11576: mp_limb_t *svect,*cvect;
11577: mp_limb_t *v;
11578: int *colstat;
11579: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11580: int maxrs;
11581: int *spsugar;
11582: ND_pairs *spactive;
11583:
11584: spcol = col-nred;
11585: get_eg(&eg0);
11586: /* elimination (1st step) */
11587: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11588: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11589: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11590: spsugar = (int *)MALLOC(nsp*sizeof(int));
11591: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
11592: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11593: nd_sp(m,0,sp,&spol);
11594: if ( !spol ) continue;
11595: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 noro 11596: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 11597: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11598: if ( i < col ) {
11599: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
11600: for ( j = k = 0; j < col; j++ )
11601: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
11602: spsugar[sprow] = MAX(maxrs,SG(spol));
11603: if ( nz )
11604: spactive[sprow] = sp;
11605: sprow++;
11606: }
11607: nd_free(spol);
11608: }
1.12 noro 11609: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 11610: if ( DP_Print ) {
11611: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11612: fflush(asir_out);
11613: }
11614: /* free index arrays */
11615: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11616:
11617: /* elimination (2nd step) */
11618: colstat = (int *)MALLOC(spcol*sizeof(int));
11619: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
11620: r0 = 0;
11621: for ( i = 0; i < rank; i++ ) {
11622: NEXTNODE(r0,r); BDY(r) =
11623: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
11624: SG((NDV)BDY(r)) = spsugar[i];
11625: GCFREE(spmat[i]);
11626: }
11627: if ( r0 ) NEXT(r) = 0;
11628:
11629: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 11630: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 11631: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11632: if ( DP_Print ) {
11633: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11634: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11635: nsp,nred,sprow,spcol,rank);
11636: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11637: }
11638: if ( nz ) {
11639: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
11640: if ( rank > 0 ) {
11641: NEXT(spactive[rank-1]) = 0;
11642: *nz = spactive[0];
11643: } else
11644: *nz = 0;
11645: }
11646: return r0;
11647: }
11648:
11649: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
11650: {
11651: int i,j,k,l,rank,s;
11652: mp_limb_t inv;
11653: mp_limb_t a;
11654: UINT c;
11655: mp_limb_t *t,*pivot,*pk;
11656: UINT *ck;
11657: UINT **cmat;
11658: UINT *ct;
11659: ND_pairs pair;
11660:
11661: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11662: for ( i = 0; i < row; i++ ) {
11663: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11664: bzero(cmat[i],col*sizeof(UINT));
11665: }
11666:
11667: for ( rank = 0, j = 0; j < col; j++ ) {
11668: for ( i = rank; i < row; i++ ) {
11669: a = mat[i][j]; c = cmat[i][j];
11670: MOD128(a,c,md);
11671: mat[i][j] = a; cmat[i][j] = 0;
11672: }
11673: for ( i = rank; i < row; i++ )
11674: if ( mat[i][j] )
11675: break;
11676: if ( i == row ) {
11677: colstat[j] = 0;
11678: continue;
11679: } else
11680: colstat[j] = 1;
11681: if ( i != rank ) {
11682: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
11683: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
11684: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
11685: if ( spactive ) {
11686: pair = spactive[i]; spactive[i] = spactive[rank];
11687: spactive[rank] = pair;
11688: }
11689: }
11690: /* column j is normalized */
11691: s = sugar[rank];
11692: inv = invm((UINT)mat[rank][j],md);
11693: /* normalize pivot row */
11694: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
11695: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11696: }
11697: for ( i = rank+1; i < row; i++ ) {
11698: if ( (a = mat[i][j]) != 0 ) {
11699: sugar[i] = MAX(sugar[i],s);
11700: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 11701: Nf4_red++;
1.7 noro 11702: }
11703: }
11704: rank++;
11705: }
11706: for ( j = col-1, l = rank-1; j >= 0; j-- )
11707: if ( colstat[j] ) {
11708: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
11709: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
11710: }
11711: s = sugar[l];
11712: for ( i = 0; i < l; i++ ) {
11713: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
11714: if ( a ) {
11715: sugar[i] = MAX(sugar[i],s);
11716: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 11717: Nf4_red++;
1.7 noro 11718: }
11719: }
11720: l--;
11721: }
11722: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11723: GCFREE(cmat);
11724: return rank;
11725: }
11726:
1.28 noro 11727: int nd_gauss_elim_mod64_s(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
11728: {
11729: int i,j,k,l,rank,s,imin;
11730: mp_limb_t inv;
11731: mp_limb_t a;
11732: UINT c;
11733: mp_limb_t *t,*pivot,*pk;
11734: UINT *ck;
11735: UINT **cmat;
11736: UINT *ct;
11737: ND_pairs pair;
11738: SIG sg;
1.31 noro 11739: int *used;
1.28 noro 11740:
1.31 noro 11741: used = (int *)MALLOC(row*sizeof(int));
1.28 noro 11742: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11743: for ( i = 0; i < row; i++ ) {
11744: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11745: bzero(cmat[i],col*sizeof(UINT));
11746: }
11747:
1.31 noro 11748: for ( j = 0; j < col; j++ ) {
11749: for ( i = 0; i < row; i++ ) {
1.28 noro 11750: a = mat[i][j]; c = cmat[i][j];
11751: MOD128(a,c,md);
11752: mat[i][j] = a; cmat[i][j] = 0;
11753: }
1.31 noro 11754: for ( i = 0; i < row; i++ )
11755: if ( !used[i] && mat[i][j] ) break;
11756: if ( i == row ) {
1.28 noro 11757: colstat[j] = 0;
11758: continue;
1.31 noro 11759: } else {
1.28 noro 11760: colstat[j] = 1;
1.31 noro 11761: used[i] = 1;
1.28 noro 11762: }
11763: /* column j is normalized */
1.31 noro 11764: s = sugar[i];
11765: inv = invm((UINT)mat[i][j],md);
1.28 noro 11766: /* normalize pivot row */
1.31 noro 11767: for ( k = j, pk = mat[i]+j, ck = cmat[i]+j; k < col; k++, pk++, ck++ ) {
1.28 noro 11768: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11769: }
1.31 noro 11770: for ( k = i+1; k < row; k++ ) {
11771: if ( (a = mat[k][j]) != 0 ) {
11772: sugar[k] = MAX(sugar[k],s);
11773: red_by_vect64(md,mat[k]+j,cmat[k]+j,mat[i]+j,(int)(md-a),col-j);
1.28 noro 11774: Nf4_red++;
11775: }
11776: }
11777: }
1.31 noro 11778: rank = 0;
11779: for ( i = 0; i < row; i++ ) {
11780: for ( j = 0; j < col; j++ )
11781: if ( mat[i][j] ) break;
11782: if ( j == col ) sugar[i] = -1;
11783: else rank++;
11784: }
1.28 noro 11785: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11786: GCFREE(cmat);
11787: return rank;
11788: }
11789:
11790: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11791: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
11792: {
11793: int spcol,sprow,a;
11794: int i,j,k,l,rank;
11795: NODE r0,r;
11796: ND_pairs sp;
11797: ND spol;
11798: mp_limb_t **spmat;
11799: mp_limb_t *svect,*cvect;
11800: mp_limb_t *v;
11801: int *colstat;
11802: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11803: int maxrs;
11804: int *spsugar;
11805: ND_pairs *spactive;
11806: SIG *spsig;
11807:
11808: get_eg(&eg0);
11809: /* elimination (1st step) */
11810: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11811: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11812: spsugar = (int *)MALLOC(nsp*sizeof(int));
11813: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
11814: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11815: nd_sp(m,0,sp,&spol);
11816: if ( !spol ) {
1.29 noro 11817: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11818: continue;
11819: }
11820: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11821: nd_to_vect64(m,s0vect,col,spol,svect);
11822: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
11823: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11824: if ( i < col ) {
11825: spmat[sprow] = svect;
11826: spsugar[sprow] = MAX(maxrs,SG(spol));
11827: spsig[sprow] = sp->sig;
11828: sprow++;
11829: } else {
1.29 noro 11830: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11831: }
11832: nd_free(spol);
11833: }
11834: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
11835: if ( DP_Print ) {
11836: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11837: fflush(asir_out);
11838: }
11839: /* free index arrays */
11840: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11841:
11842: /* elimination (2nd step) */
11843: colstat = (int *)MALLOC(col*sizeof(int));
11844: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
11845: r0 = 0;
1.31 noro 11846: for ( i = 0; i < sprow; i++ ) {
11847: if ( spsugar[i] >= 0 ) {
11848: NEXTNODE(r0,r);
11849: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
11850: SG((NDV)BDY(r)) = spsugar[i];
11851: ((NDV)BDY(r))->sig = spsig[i];
11852: } else
11853: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
1.28 noro 11854: GCFREE(spmat[i]);
11855: }
11856: if ( r0 ) NEXT(r) = 0;
11857: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
11858: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11859: if ( DP_Print ) {
11860: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11861: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11862: nsp,nred,sprow,col,rank);
11863: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11864: }
11865: return r0;
11866: }
1.40 noro 11867: #endif
1.28 noro 11868:
11869: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
11870: {
11871: IndArray *imat;
11872: int nsp,nred,i,start;
11873: int *rhead;
11874: NODE r0,rp;
11875: ND_pairs sp;
11876: NM_ind_pair *rvect;
11877: UINT *s;
11878: int *s0hash;
11879: struct oEGT eg0,eg1,eg_conv;
11880:
11881: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
11882: nred = length(rp0);
11883: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
11884: rhead = (int *)MALLOC(col*sizeof(int));
11885: for ( i = 0; i < col; i++ ) rhead[i] = 0;
11886:
11887: /* construction of index arrays */
11888: get_eg(&eg0);
11889: if ( DP_Print ) {
11890: fprintf(asir_out,"%dx%d,",nsp+nred,col);
11891: fflush(asir_out);
11892: }
11893: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
11894: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
11895: rvect[i] = (NM_ind_pair)BDY(rp);
11896: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
11897: rhead[imat[i]->head] = 1;
11898: start = imat[i]->head;
11899: }
11900: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
11901: if ( DP_Print ) {
11902: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
11903: fflush(asir_out);
11904: }
11905: if ( m > 0 )
1.40 noro 11906: #if SIZEOF_LONG==8
1.28 noro 11907: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
1.40 noro 11908: #else
11909: r0 = nd_f4_red_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
11910: #endif
1.28 noro 11911: else
11912: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
11913: error("nd_f4_red_q_main_s : not implemented yet");
11914: return r0;
11915: }
11916:
11917: INLINE int ndl_find_reducer_minsig(UINT *dg)
11918: {
11919: RHist r;
11920: int i,singular,ret,d,k,imin;
11921: SIG t;
11922: static int wpd,nvar;
11923: static SIG quo,quomin;
11924: static UINT *tmp;
11925:
11926: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
11927: if ( wpd != nd_wpd ) {
11928: wpd = nd_wpd;
11929: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
11930: }
11931: #if 0
11932: d = ndl_hash_value(dg);
11933: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
11934: if ( ndl_equal(dg,DL(r)) ) {
11935: return r->index;
11936: }
11937: }
11938: #endif
11939: imin = -1;
11940: for ( i = 0; i < nd_psn; i++ ) {
11941: r = nd_psh[i];
11942: if ( ndl_reducible(dg,DL(r)) ) {
11943: ndl_sub(dg,DL(r),tmp);
11944: _ndltodl(tmp,DL(quo));
11945: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
11946: quo->pos = nd_psh[i]->sig->pos;
1.55 noro 11947: _adddl(nd_nvar,DL(quo),nd_sba_hm[quo->pos],DL2(quo));
1.28 noro 11948: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
11949: t = quo; quo = quomin; quomin = t;
11950: imin = i;
11951: }
11952: }
11953: }
11954: if ( imin == -1 ) return nd_psn;
11955: else {
11956: #if 0
11957: nd_append_red(dg,i);
11958: #endif
11959: return imin;
11960: }
11961: }
11962:
11963: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
11964: {
11965: NODE rp0,rp;
11966: NM mul,head,s0,s;
11967: int index,col,i,sugar;
11968: RHist h;
11969: UINT *s0v,*p;
11970: NM_ind_pair pair;
11971: ND red;
11972: NDV *ps;
11973: SIG sig;
11974:
11975: s0 = 0; rp0 = 0; col = 0;
11976: if ( nd_demand )
11977: ps = trace?nd_ps_trace_sym:nd_ps_sym;
11978: else
11979: ps = trace?nd_ps_trace:nd_ps;
11980: while ( 1 ) {
11981: head = remove_head_pbucket_symbolic(bucket);
11982: if ( !head ) break;
11983: if ( !s0 ) s0 = head;
11984: else NEXT(s) = head;
11985: s = head;
11986: index = ndl_find_reducer_minsig(DL(head));
11987: if ( index >= 0 && index < nd_psn ) {
11988: h = nd_psh[index];
11989: NEWNM(mul);
11990: ndl_sub(DL(head),DL(h),DL(mul));
11991: if ( ndl_check_bound2(index,DL(mul)) )
11992: return 0;
11993: sugar = TD(DL(mul))+SG(ps[index]);
11994: NEWSIG(sig);
11995: _ndltodl(DL(mul),DL(sig));
11996: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
11997: sig->pos = nd_psh[index]->sig->pos;
1.55 noro 11998: _adddl(nd_nvar,DL(sig),nd_sba_hm[sig->pos],DL2(sig));
1.28 noro 11999: MKNM_ind_pair(pair,mul,index,sugar,sig);
12000: red = ndv_mul_nm_symbolic(mul,ps[index]);
12001: add_pbucket_symbolic(bucket,nd_remove_head(red));
12002: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
12003: }
12004: col++;
12005: }
12006: if ( rp0 ) NEXT(rp) = 0;
12007: NEXT(s) = 0;
12008: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
12009: for ( i = 0, p = s0v, s = s0; i < col;
12010: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
12011: *s0vect = s0v;
12012: *r = rp0;
12013:
12014: return col;
12015: }
12016:
12017: NODE nd_sba_f4(int m,int **indp)
12018: {
1.34 noro 12019: int i,nh,stat,index,f4red,f4step;
1.33 noro 12020: int col,rank,len,k,j,a,sugar,nbase,psugar,ms;
12021: NODE r,g,rp0,nflist;
1.41 noro 12022: ND_pairs d,l,t,l1;
1.33 noro 12023: ND h,nf;
12024: NDV nfv;
12025: union oNDC hc;
12026: UINT *s0vect;
1.28 noro 12027: UINT c;
12028: PGeoBucket bucket;
1.33 noro 12029: NODE *syzlist;
12030: SIG sig;
1.28 noro 12031: struct oEGT eg0,eg1,eg_f4;
1.33 noro 12032: struct oEGT eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.28 noro 12033:
12034: Nf4_red=0;
1.30 noro 12035: d = 0;
1.29 noro 12036: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.28 noro 12037: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 12038: d = update_pairs_s(d,i,syzlist);
1.28 noro 12039: }
1.30 noro 12040: nd_nbase = nd_psn;
1.28 noro 12041: f4red = 1;
1.33 noro 12042: psugar = 0;
1.34 noro 12043: f4step = 0;
1.28 noro 12044: while ( d ) {
1.33 noro 12045: for ( t = d, ms = SG(d); t; t = NEXT(t) )
12046: if ( SG(t) < ms ) ms = SG(t);
1.38 noro 12047: if ( ms == psugar && f4step >= nd_sba_f4step ) {
1.33 noro 12048: again:
12049: l = d; d = d->next;
1.41 noro 12050: #if 0
1.33 noro 12051: if ( small_lcm(l) ) {
12052: if ( DP_Print ) fprintf(asir_out,"M");
12053: continue;
12054: }
12055: sig = l->sig;
12056: stat = nd_sp(m,0,l,&h);
1.41 noro 12057: #else
12058: l1 = find_smallest_lcm(l);
12059: if ( l1 == 0 ) {
12060: if ( DP_Print ) fprintf(asir_out,"M");
12061: continue;
12062: }
12063: sig = l1->sig;
12064: stat = nd_sp(m,0,l1,&h);
12065: #endif
1.33 noro 12066: if ( !stat ) {
12067: NEXT(l) = d; d = l;
12068: d = nd_reconstruct(0,d);
12069: goto again;
12070: }
12071: get_eg(&eg1);
12072: #if USE_GEOBUCKET
1.39 noro 12073: stat = m?nd_nf_pbucket_s(m,h,nd_ps,!nd_top&&!Top,&nf):nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 12074: #else
1.39 noro 12075: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 12076: #endif
12077: get_eg(&eg2);
12078: if ( !stat ) {
12079: NEXT(l) = d; d = l;
12080: d = nd_reconstruct(0,d);
12081: goto again;
12082: } else if ( stat == -1 ) {
12083: if ( DP_Print ) { printf("S"); fflush(stdout); }
12084: FREENDP(l);
12085: } else if ( nf ) {
12086: if ( DP_Print ) { printf("+"); fflush(stdout); }
12087: add_eg(&eg_nf,&eg1,&eg2);
12088: hc = HCU(nf);
12089: nd_removecont(m,nf);
12090: nfv = ndtondv(m,nf); nd_free(nf);
12091: nh = ndv_newps(m,nfv,0);
12092:
1.30 noro 12093: d = update_pairs_s(d,nh,syzlist);
12094: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.33 noro 12095: FREENDP(l);
1.28 noro 12096: } else {
1.33 noro 12097: add_eg(&eg_nfzero,&eg1,&eg2);
12098: // syzygy
12099: get_eg(&eg1);
12100: d = remove_spair_s(d,sig);
12101: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 12102: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.33 noro 12103: if ( DP_Print ) { printf("."); fflush(stdout); }
12104: FREENDP(l);
12105: }
12106: } else {
1.34 noro 12107: if ( ms != psugar ) f4step = 1;
12108: else f4step++;
1.33 noro 12109: again2:
12110: psugar = ms;
12111: l = nd_minsugarp_s(d,&d);
12112: sugar = nd_sugarweight?d->sugar2:SG(d);
12113: bucket = create_pbucket();
12114: stat = nd_sp_f4(m,0,l,bucket);
12115: if ( !stat ) {
12116: for ( t = l; NEXT(t); t = NEXT(t) );
12117: NEXT(t) = d; d = l;
12118: d = nd_reconstruct(0,d);
12119: goto again2;
12120: }
12121: if ( bucket->m < 0 ) continue;
12122: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
12123: if ( !col ) {
1.37 noro 12124: for ( t = l; NEXT(t); t = NEXT(t) )
12125: ;
12126: NEXT(t) = d; d = l;
1.33 noro 12127: d = nd_reconstruct(0,d);
12128: goto again2;
12129: }
1.34 noro 12130: if ( DP_Print ) fprintf(asir_out,"\nsugar=%d,",psugar);
1.33 noro 12131: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,syzlist);
12132: /* adding new bases */
12133: for ( r = nflist; r; r = NEXT(r) ) {
12134: nfv = (NDV)BDY(r);
1.38 noro 12135: if ( nd_f4_td ) SG(nfv) = nd_tdeg(nfv);
1.33 noro 12136: ndv_removecont(m,nfv);
12137: nh = ndv_newps(m,nfv,0);
12138: d = update_pairs_s(d,nh,syzlist);
12139: nd_sba_pos[nfv->sig->pos] = append_one(nd_sba_pos[nfv->sig->pos],nh);
12140: }
12141: for ( i = 0; i < nd_nbase; i++ )
12142: for ( r = syzlist[i]; r; r = NEXT(r) )
12143: d = remove_spair_s(d,(SIG)BDY(r));
12144: d = remove_large_lcm(d);
12145: if ( DP_Print ) {
1.34 noro 12146: fprintf(asir_out,"f4red=%d,gblen=%d",f4red,nd_psn); fflush(asir_out);
1.33 noro 12147: }
12148: f4red++;
1.28 noro 12149: }
12150: }
12151: if ( DP_Print ) {
1.34 noro 12152: fprintf(asir_out,"\nnumber of red=%d,",Nf4_red);
1.28 noro 12153: }
1.30 noro 12154: g = conv_ilist_s(nd_demand,0,indp);
1.28 noro 12155: return g;
12156: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>