Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.60
1.60 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.59 2021/12/14 01:02:40 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);
1.59 noro 2508: #if 0
1.56 noro 2509: if ( NEXT(nd_hpdata) != 0 && (weight=(LIST)BDY(NEXT(nd_hpdata))) != 0 ) {
2510: wlen = length(BDY(weight));
2511: if ( n != wlen )
2512: error("setup_hpdata : inconsistent weight length");
2513: w = (int *)MALLOC(n*sizeof(int));
2514: for ( i = 0, nd = BDY((LIST)weight); i < n; i++, nd = NEXT(nd) )
2515: w[i] = ZTOS((Z)BDY(nd));
2516: } else
2517: w = 0;
1.59 noro 2518: #else
2519: w = current_dl_weight_vector;
2520: #endif
1.49 noro 2521: MKVECT(x,n);
2522: for ( i = 0; i < n; i++ ) {
2523: NEWDL(dl,n); dl->d[i] = 1; dl->td = 1; BDY(x)[i] = dl;
2524: }
2525: final->x = x;
1.56 noro 2526: final->w = w;
1.49 noro 2527:
2528: MKVECT(b,nd_psn); p = (DL *)BDY(b);
2529: for ( i = 0; i < nd_psn; i++ ) {
2530: p[i] = ndltodl(n,nd_psh[i]->dl);
2531: }
1.56 noro 2532: if ( w ) {
2533: ret = dp_monomial_hilbert_poincare_weight(b,x,w);
2534: } else
2535: ret = dp_monomial_hilbert_poincare(b,x);
2536: current->n = n;
2537: current->hn = (P)BDY(BDY(ret));
1.49 noro 2538: current->x = x;
1.56 noro 2539: current->w = w;
2540: }
2541:
2542: int comp_hn(P a, P b)
2543: {
2544: P s;
2545: DCP dc;
2546:
2547: subp(CO,a,b,&s);
1.57 noro 2548: if ( !s ) return -1;
1.56 noro 2549: else if ( OID(s) == 1 ) return 0;
2550: else {
2551: for ( dc = DC(s); NEXT(dc); dc = NEXT(dc) );
2552: return (int)ZTOS((Z)dc->d);
2553: }
1.49 noro 2554: }
2555:
1.56 noro 2556: void update_hpdata(HPDATA current,int nh)
1.49 noro 2557: {
2558: NODE data1,nd,t;
2559: DL new,dl;
2560: int len,i,n;
2561: Z dz;
2562: DL *p;
2563: VECT b,head;
2564: P tv,td,s,hn,hpoly;
2565: LIST list1;
2566:
2567: n = nd_nvar;
2568: new = ndltodl(n,nd_psh[nh]->dl);
2569: MKVECT(b,nh); p = (DL *)BDY(b);
2570: for ( i = 0; i < nh; i++ ) {
2571: p[i] = monomial_colon(ndltodl(n,nd_psh[i]->dl),new,n);
2572: }
2573: // compute HP(I:new)
1.56 noro 2574: if ( current->w )
2575: list1 = dp_monomial_hilbert_poincare_weight(b,current->x,current->w);
2576: else
2577: list1 = dp_monomial_hilbert_poincare(b,current->x);
1.49 noro 2578: data1 = BDY((LIST)list1);
2579: // HP(I+<new>) = H(I)-t^d*H(I:new), d=tdeg(new)
2580: makevar("t",&tv); UTOZ(new->td,dz);
2581: pwrp(CO,tv,dz,&td);
2582: mulp(CO,(P)ARG0(data1),td,&s);
2583: subp(CO,current->hn,s,&hn);
2584: current->hn = hn;
2585: }
2586:
2587: ND_pairs nd_remove_same_sugar( ND_pairs d, int sugar)
2588: {
2589: struct oND_pairs root;
2590: ND_pairs prev,cur;
2591:
2592: root.next = d;
2593: prev = &root; cur = d;
2594: while ( cur ) {
2595: if ( SG(cur) == sugar )
2596: prev->next = cur->next;
2597: else
2598: prev = cur;
2599: cur = cur->next;
2600: }
2601: return root.next;
2602: }
2603:
1.1 noro 2604: /* return value = 0 => input is not a GB */
2605:
2606: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2607: {
1.6 noro 2608: int i,nh,sugar,stat;
2609: NODE r,g,t;
2610: ND_pairs d;
2611: ND_pairs l;
2612: ND h,nf,s,head,nf1;
2613: NDV nfv;
2614: Z q;
2615: union oNDC dn,hc;
2616: int diag_count = 0;
1.41 noro 2617: int Nnfnz = 0,Nnfz = 0;
1.6 noro 2618: P cont;
2619: LIST list;
1.49 noro 2620: struct oHPDATA current_hpdata,final_hpdata;
2621: int final_hpvalue;
2622:
1.27 noro 2623: struct oEGT eg1,eg2,eg_update;
1.6 noro 2624:
1.27 noro 2625: init_eg(&eg_update);
1.11 noro 2626: Nnd_add = 0;
1.6 noro 2627: g = 0; d = 0;
2628: for ( i = 0; i < nd_psn; i++ ) {
2629: d = update_pairs(d,g,i,gensyz);
2630: g = update_base(g,i);
2631: }
2632: sugar = 0;
1.49 noro 2633: if ( nd_hpdata ) {
1.52 noro 2634: if ( DP_Print ) fprintf(asir_out,"Hilbert driven algorithm.\n");
1.49 noro 2635: setup_hpdata(&final_hpdata,¤t_hpdata);
2636: }
1.6 noro 2637: while ( d ) {
1.1 noro 2638: again:
1.6 noro 2639: l = nd_minp(d,&d);
2640: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2641: if ( SG(l) != sugar ) {
2642: if ( ishomo ) {
2643: diag_count = 0;
2644: stat = do_diagonalize(sugar,m);
1.1 noro 2645: if ( !stat ) {
1.6 noro 2646: NEXT(l) = d; d = l;
2647: d = nd_reconstruct(0,d);
2648: goto again;
1.1 noro 2649: }
1.6 noro 2650: }
2651: sugar = SG(l);
2652: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2653: }
2654: stat = nd_sp(m,0,l,&h);
2655: if ( !stat ) {
2656: NEXT(l) = d; d = l;
2657: d = nd_reconstruct(0,d);
2658: goto again;
2659: }
1.1 noro 2660: #if USE_GEOBUCKET
1.39 noro 2661: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf)
2662: :nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2663: #else
1.39 noro 2664: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2665: #endif
1.6 noro 2666: if ( !stat ) {
2667: NEXT(l) = d; d = l;
2668: d = nd_reconstruct(0,d);
2669: goto again;
2670: } else if ( nf ) {
1.41 noro 2671: Nnfnz++;
1.6 noro 2672: if ( checkonly || gensyz ) return 0;
1.1 noro 2673: if ( nd_newelim ) {
2674: if ( nd_module ) {
2675: if ( MPOS(HDL(nf)) > 1 ) return 0;
2676: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2677: }
1.6 noro 2678: if ( DP_Print ) { printf("+"); fflush(stdout); }
2679: hc = HCU(nf);
2680: nd_removecont(m,nf);
2681: if ( !m && nd_nalg ) {
2682: nd_monic(0,&nf);
2683: nd_removecont(m,nf);
2684: }
2685: if ( nd_gentrace ) {
2686: /* exact division */
1.1 noro 2687: cont = ndc_div(m,hc,HCU(nf));
2688: if ( m || !UNIQ(cont) ) {
1.6 noro 2689: t = mknode(4,NULLP,NULLP,NULLP,cont);
2690: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2691: nd_tracelist = t;
2692: }
2693: }
1.6 noro 2694: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2695: nh = ndv_newps(m,nfv,0);
1.6 noro 2696: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2697: diag_count = 0;
2698: stat = do_diagonalize(sugar,m);
2699: if ( !stat ) {
2700: NEXT(l) = d; d = l;
2701: d = nd_reconstruct(1,d);
2702: goto again;
1.1 noro 2703: }
1.6 noro 2704: }
1.27 noro 2705: get_eg(&eg1);
1.6 noro 2706: d = update_pairs(d,g,nh,0);
1.27 noro 2707: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2708: g = update_base(g,nh);
2709: FREENDP(l);
1.49 noro 2710: if ( nd_hpdata ) {
1.57 noro 2711: int dg,sugar0;
1.56 noro 2712:
2713: update_hpdata(¤t_hpdata,nh);
2714: dg = comp_hn(final_hpdata.hn,current_hpdata.hn);
1.57 noro 2715: if ( dg < 0 ) {
2716: fprintf(asir_out,"We found a gb\n");
2717: d = 0;
2718: }
2719: sugar0 = sugar;
2720: while ( d && dg > sugar0 ) {
1.59 noro 2721: if ( DP_Print ) { fprintf(asir_out,"[%d]",sugar0); fflush(asir_out); }
1.58 noro 2722: d = nd_remove_same_sugar(d,sugar0);
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.60 ! noro 2741: fprintf(asir_out,"\nnd_gb done. Nbase=%d,Nnd_add=%d,Npairs=%d, Nnfnz=%d,Nnfz=%d,",nd_psn,Nnd_add,Npairs,Nnfnz,Nnfz);
1.57 noro 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.60 ! noro 3196: printf("Nbase=%d,Nnfnz=%d,Nnfz=%d,Nnfsingular=%d\n",Nnfnz,Nnfz,Nnfs,nd_psn);
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: }
3522: sugar0 = sugar;
3523: while ( d && dg > sugar0 ) {
1.59 noro 3524: if ( DP_Print ) { fprintf(asir_out,"[%d]",sugar0); fflush(asir_out); }
1.58 noro 3525: d = nd_remove_same_sugar(d,sugar0);
1.57 noro 3526: sugar0++;
1.49 noro 3527: }
3528: }
1.6 noro 3529: } else {
1.57 noro 3530: if ( DP_Print ) { fprintf(asir_out,"*"); fflush(asir_out); }
1.6 noro 3531: }
3532: } else {
1.57 noro 3533: if ( DP_Print ) { fprintf(asir_out,"."); fflush(asir_out); }
1.1 noro 3534: }
1.6 noro 3535: FREENDP(l);
3536: }
3537: if ( nd_nalg ) {
3538: if ( DP_Print ) {
3539: print_eg("monic",&eg_monic);
3540: print_eg("invdalg",&eg_invdalg);
3541: print_eg("le",&eg_le);
1.1 noro 3542: }
1.6 noro 3543: }
1.1 noro 3544: conv_ilist(nd_demand,1,g,indp);
1.60 ! noro 3545: if ( DP_Print ) { fprintf(asir_out,"\nnd_gb_trace done. Nbase=%d\n",nd_psn); fflush(asir_out); }
1.6 noro 3546: return g;
1.1 noro 3547: }
3548:
3549: int ndv_compare(NDV *p1,NDV *p2)
3550: {
3551: return DL_COMPARE(HDL(*p1),HDL(*p2));
3552: }
3553:
3554: int ndv_compare_rev(NDV *p1,NDV *p2)
3555: {
3556: return -DL_COMPARE(HDL(*p1),HDL(*p2));
3557: }
3558:
3559: int ndvi_compare(NDVI p1,NDVI p2)
3560: {
3561: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
3562: }
3563:
3564: int ndvi_compare_rev(NDVI p1,NDVI p2)
3565: {
3566: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3567: }
3568:
3569: NODE ndv_reduceall(int m,NODE f)
3570: {
3571: int i,j,n,stat;
3572: ND nf,g,head;
3573: NODE t,a0,a;
3574: union oNDC dn;
3575: Q q,num,den;
3576: NODE node;
3577: LIST l;
3578: Z iq,jq;
3579: int *perm;
3580: union oNDC hc;
3581: P cont,cont1;
3582:
3583: if ( nd_nora ) return f;
3584: n = length(f);
1.24 noro 3585: ndv_setup(m,0,f,0,1,0);
1.1 noro 3586: perm = (int *)MALLOC(n*sizeof(int));
3587: if ( nd_gentrace ) {
3588: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3589: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3590: }
3591: for ( i = 0; i < n; ) {
3592: if ( nd_gentrace ) {
3593: /* Trace = [1,index,1,1] */
1.6 noro 3594: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3595: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3596: }
3597: g = ndvtond(m,nd_ps[i]);
3598: g = nd_separate_head(g,&head);
1.6 noro 3599: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3600: if ( !stat )
3601: nd_reconstruct(0,0);
3602: else {
3603: if ( DP_Print ) { printf("."); fflush(stdout); }
3604: ndv_free(nd_ps[i]);
3605: hc = HCU(nf); nd_removecont(m,nf);
3606: if ( nd_gentrace ) {
3607: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3608: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3609: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3610: }
1.6 noro 3611: /* exact division */
1.1 noro 3612: cont = ndc_div(m,hc,HCU(nf));
3613: finalize_tracelist(perm[i],cont);
3614: }
3615: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3616: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3617: i++;
3618: }
3619: }
3620: if ( DP_Print ) { printf("\n"); }
3621: for ( a0 = 0, i = 0; i < n; i++ ) {
3622: NEXTNODE(a0,a);
3623: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3624: else {
3625: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3626: BDY(a) = (pointer)nd_ps[j];
3627: }
3628: }
3629: NEXT(a) = 0;
3630: return a0;
3631: }
3632:
1.41 noro 3633: int ndplength(ND_pairs d)
3634: {
3635: int i;
3636: for ( i = 0; d; i++ ) d = NEXT(d);
3637: return i;
3638: }
3639:
1.1 noro 3640: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3641: {
3642: ND_pairs d1,nd,cur,head,prev,remove;
1.41 noro 3643: int len0;
1.1 noro 3644:
3645: if ( !g ) return d;
3646: /* for testing */
3647: if ( gensyz && nd_gensyz == 2 ) {
3648: d1 = nd_newpairs(g,t);
3649: if ( !d )
3650: return d1;
3651: else {
3652: nd = d;
3653: while ( NEXT(nd) ) nd = NEXT(nd);
3654: NEXT(nd) = d1;
3655: return d;
3656: }
3657: }
3658: d = crit_B(d,t);
3659: d1 = nd_newpairs(g,t);
1.41 noro 3660: len0 = ndplength(d1);
1.1 noro 3661: d1 = crit_M(d1);
3662: d1 = crit_F(d1);
1.41 noro 3663: NcriMF += len0-ndplength(d1);
1.1 noro 3664: if ( gensyz || do_weyl )
3665: head = d1;
3666: else {
3667: prev = 0; cur = head = d1;
3668: while ( cur ) {
3669: if ( crit_2( cur->i1,cur->i2 ) ) {
3670: remove = cur;
3671: if ( !prev ) head = cur = NEXT(cur);
3672: else cur = NEXT(prev) = NEXT(cur);
1.41 noro 3673: FREENDP(remove); Ncri2++;
1.1 noro 3674: } else {
3675: prev = cur; cur = NEXT(cur);
3676: }
3677: }
3678: }
3679: if ( !d )
3680: return head;
3681: else {
3682: nd = d;
3683: while ( NEXT(nd) ) nd = NEXT(nd);
3684: NEXT(nd) = head;
3685: return d;
3686: }
3687: }
3688:
1.24 noro 3689: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3690:
1.30 noro 3691: ND_pairs update_pairs_s( ND_pairs d, int t,NODE *syz)
1.24 noro 3692: {
3693: ND_pairs d1;
1.26 noro 3694: struct oEGT eg1,eg2,eg3;
1.24 noro 3695:
1.30 noro 3696: if ( !t ) return d;
1.26 noro 3697: get_eg(&eg1);
1.30 noro 3698: d1 = nd_newpairs_s(t,syz);
1.26 noro 3699: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3700: d = merge_pairs_s(d,d1);
1.26 noro 3701: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3702: return d;
3703: }
1.1 noro 3704:
1.47 noro 3705: int update_pairs_array_s( ND_pairs *d, int t,NODE *syz)
3706: {
3707: ND_pairs *d1;
3708: struct oEGT eg1,eg2,eg3;
3709: int i;
3710:
3711: if ( !t ) return 0;
3712: get_eg(&eg1);
3713: Nnewpair = 0;
3714: d1 = nd_newpairs_array_s(t,syz);
3715: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
3716: for ( i = 0; i < nd_nbase; i++ )
3717: d[i] = merge_pairs_s(d[i],d1[i]);
3718: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
3719: return Nnewpair;
3720: }
3721:
1.1 noro 3722: ND_pairs nd_newpairs( NODE g, int t )
3723: {
3724: NODE h;
3725: UINT *dl;
3726: int ts,s,i,t0,min,max;
3727: ND_pairs r,r0;
3728:
3729: dl = DL(nd_psh[t]);
3730: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3731: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3732: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3733: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3734: continue;
3735: if ( nd_gbblock ) {
3736: t0 = (long)BDY(h);
3737: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3738: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3739: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3740: break;
3741: }
3742: if ( nd_gbblock[i] >= 0 )
3743: continue;
3744: }
1.41 noro 3745: NEXTND_pairs(r0,r); Npairs++;
1.1 noro 3746: r->i1 = (long)BDY(h);
3747: r->i2 = t;
3748: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3749: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3750: SG(r) = MAX(s,ts) + TD(LCM(r));
3751: /* experimental */
3752: if ( nd_sugarweight )
3753: r->sugar2 = ndl_weight2(r->lcm);
3754: }
3755: if ( r0 ) NEXT(r) = 0;
3756: return r0;
3757: }
3758:
1.46 noro 3759: int sig_cmpdl_op(int n,DL d1,DL d2)
3760: {
3761: int e1,e2,i,j,l;
3762: int *t1,*t2;
3763: int len,head;
3764: struct order_pair *pair;
3765:
3766: len = nd_sba_modord->block_length;
3767: pair = nd_sba_modord->order_pair;
3768:
3769: head = 0;
3770: for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {
3771: l = pair[i].length;
3772: switch ( pair[i].order ) {
3773: case 0:
3774: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3775: e1 += t1[j];
3776: e2 += t2[j];
3777: }
3778: if ( e1 > e2 )
3779: return 1;
3780: else if ( e1 < e2 )
3781: return -1;
3782: else {
3783: for ( j = l - 1; j >= 0 && t1[j] == t2[j]; j-- );
3784: if ( j >= 0 )
3785: return t1[j] < t2[j] ? 1 : -1;
3786: }
3787: break;
3788: case 1:
3789: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3790: e1 += t1[j];
3791: e2 += t2[j];
3792: }
3793: if ( e1 > e2 )
3794: return 1;
3795: else if ( e1 < e2 )
3796: return -1;
3797: else {
3798: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3799: if ( j < l )
3800: return t1[j] > t2[j] ? 1 : -1;
3801: }
3802: break;
3803: case 2:
3804: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3805: if ( j < l )
3806: return t1[j] > t2[j] ? 1 : -1;
3807: break;
3808: default:
3809: error("sig_cmpdl_op : invalid order"); break;
3810: }
3811: t1 += l; t2 += l; head += l;
3812: }
3813: return 0;
3814: }
3815:
3816: int sig_cmpdl_mat(int n,DL d1,DL d2)
3817: {
3818: int *v,*t1,*t2;
3819: int s,i,j,len;
3820: int **matrix;
3821: static int *w;
3822: static int nvar = 0;
3823:
3824: if ( nvar != n ) {
3825: nvar = n; w = (int *)MALLOC(n*sizeof(int));
3826: }
3827: for ( i = 0, t1 = d1->d, t2 = d2->d; i < n; i++ )
3828: w[i] = t1[i]-t2[i];
3829: len = nd_sba_modord->row;
3830: matrix = nd_sba_modord->matrix;
3831: for ( j = 0; j < len; j++ ) {
3832: v = matrix[j];
3833: for ( i = 0, s = 0; i < n; i++ )
3834: s += v[i]*w[i];
3835: if ( s > 0 )
3836: return 1;
3837: else if ( s < 0 )
3838: return -1;
3839: }
3840: return 0;
3841: }
3842:
3843: struct comp_sig_spec *create_comp_sig_spec(VL current_vl,VL old_vl,Obj ord,Obj weight)
3844: {
3845: struct comp_sig_spec *spec;
3846: VL ovl,vl;
3847: V ov;
3848: int i,j,n,nvar,s;
3849: NODE node,t,tn;
3850: struct order_pair *l;
3851: MAT m;
3852: Obj **b;
3853: int **w;
3854: int *a;
3855:
3856: spec = (struct comp_sig_spec *)MALLOC(sizeof(struct comp_sig_spec));
3857: for ( i = 0, vl = current_vl; vl; vl = NEXT(vl), i++ );
3858: spec->n = nvar = i;
3859: if ( old_vl != 0 ) {
3860: spec->oldv = (int *)MALLOC(nvar*sizeof(int));
3861: for ( i = 0, ovl = old_vl; i < nvar; ovl = NEXT(ovl), i++ ) {
3862: ov = ovl->v;
3863: for ( j = 0, vl = current_vl; vl; vl = NEXT(vl), j++ )
3864: if ( ov == vl->v ) break;
3865: spec->oldv[i] = j;
3866: }
3867: } else
3868: spec->oldv = 0;
3869: if ( !ord || NUM(ord) ) {
3870: switch ( ZTOS((Z)ord) ) {
3871: case 0:
3872: spec->cmpdl = cmpdl_revgradlex; break;
3873: case 1:
3874: spec->cmpdl = cmpdl_gradlex; break;
3875: case 2:
3876: spec->cmpdl = cmpdl_lex; break;
3877: default:
3878: error("create_comp_sig_spec : invalid spec"); break;
3879: }
3880: } else if ( OID(ord) == O_LIST ) {
3881: node = BDY((LIST)ord);
3882: for ( n = 0, t = node; t; t = NEXT(t), n++ );
3883: l = (struct order_pair *)MALLOC_ATOMIC(n*sizeof(struct order_pair));
3884: for ( i = 0, t = node, s = 0; i < n; t = NEXT(t), i++ ) {
3885: tn = BDY((LIST)BDY(t)); l[i].order = ZTOS((Q)BDY(tn));
3886: tn = NEXT(tn); l[i].length = ZTOS((Q)BDY(tn));
3887: s += l[i].length;
3888: }
3889: if ( s != nvar )
3890: error("create_comp_sig_spec : invalid spec");
3891: spec->order_pair = l;
3892: spec->block_length = n;
3893: spec->cmpdl = sig_cmpdl_op;
3894: } else if ( OID(ord) == O_MAT ) {
3895: m = (MAT)ord; b = (Obj **)BDY(m);
3896: if ( m->col != nvar )
3897: error("create_comp_sig_spec : invalid spec");
3898: w = almat(m->row,m->col);
3899: for ( i = 0; i < m->row; i++ )
3900: for ( j = 0; j < m->col; j++ )
3901: w[i][j] = ZTOS((Q)b[i][j]);
3902: spec->row = m->row;
3903: spec->matrix = w;
3904: spec->cmpdl = sig_cmpdl_mat;
3905: } else
3906: error("create_comp_sig_spec : invalid spec");
3907: if ( weight != 0 ) {
3908: node = BDY((LIST)weight);
3909: a = (int *)MALLOC(nvar*sizeof(int));
3910: for ( i = 0; i < nvar; i++, node = NEXT(node) )
3911: a[i] = ZTOS((Z)BDY(node));
3912: spec->weight = a;
3913: }
3914: return spec;
3915: }
3916:
3917: #define SIG_MUL_WEIGHT(a,i) (weight?(a)*weight[i]:(a))
3918:
3919: int comp_sig_monomial(int n,DL d1,DL d2)
3920: {
3921: static DL m1,m2;
3922: static int nvar = 0;
3923: int *oldv,*weight;
3924: int i,w1,w2;
3925:
3926: if ( nvar != n ) {
3927: nvar = n; NEWDL(m1,nvar); NEWDL(m2,nvar);
3928: }
3929: if ( !nd_sba_modord )
3930: return (*cmpdl)(n,d1,d2);
1.55 noro 3931: else if ( !nd_sba_modord->weight && !nd_sba_modord->oldv ) {
3932: return (*nd_sba_modord->cmpdl)(n,d1,d2);
3933: } else {
1.46 noro 3934: weight = nd_sba_modord->weight;
3935: oldv = nd_sba_modord->oldv;
3936: if ( oldv ) {
3937: for ( i = 0; i < n; i++ ) {
3938: m1->d[i] = d1->d[oldv[i]]; m2->d[i] = d2->d[oldv[i]];
3939: }
3940: } else {
3941: for ( i = 0; i < n; i++ ) {
3942: m1->d[i] = d1->d[i]; m2->d[i] = d2->d[i];
3943: }
3944: }
3945: for ( i = 0, w1 = w2 = 0; i < n; i++ ) {
3946: w1 += SIG_MUL_WEIGHT(m1->d[i],i);
3947: w2 += SIG_MUL_WEIGHT(m2->d[i],i);
3948: }
3949: m1->td = w1; m2->td = w2;
3950: return (*nd_sba_modord->cmpdl)(n,m1,m2);
3951: }
3952: }
3953:
1.24 noro 3954: int comp_sig(SIG s1,SIG s2)
3955: {
1.38 noro 3956: if ( nd_sba_pot ) {
3957: if ( s1->pos > s2->pos ) return 1;
3958: else if ( s1->pos < s2->pos ) return -1;
1.55 noro 3959: else return comp_sig_monomial(nd_nvar,DL(s1),DL(s2));
1.38 noro 3960: } else {
3961: static DL m1,m2;
1.44 noro 3962: static int nvar = 0;
1.38 noro 3963: int ret;
3964:
3965: if ( nvar != nd_nvar ) {
3966: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
3967: }
1.47 noro 3968: if ( !nd_sba_modord )
1.55 noro 3969: ret = (*cmpdl)(nd_nvar,DL2(s1),DL2(s2));
1.47 noro 3970: else
1.55 noro 3971: ret = comp_sig_monomial(nd_nvar,DL2(s1),DL2(s2));
1.38 noro 3972: if ( ret != 0 ) return ret;
3973: else if ( s1->pos > s2->pos ) return 1;
3974: else if ( s1->pos < s2->pos ) return -1;
3975: else return 0;
1.24 noro 3976: }
3977: }
3978:
3979: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3980: {
3981: int ret,s1,s2;
3982: RHist p1,p2;
3983: static int wpd;
3984: static UINT *lcm;
3985:
3986: sp->i1 = i1;
3987: sp->i2 = i2;
3988: p1 = nd_psh[i1];
3989: p2 = nd_psh[i2];
3990: ndl_lcm(DL(p1),DL(p2),sp->lcm);
1.49 noro 3991: #if 0
1.24 noro 3992: s1 = SG(p1)-TD(DL(p1));
3993: s2 = SG(p2)-TD(DL(p2));
3994: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
1.49 noro 3995: #endif
1.24 noro 3996:
1.26 noro 3997: if ( wpd != nd_wpd ) {
1.24 noro 3998: wpd = nd_wpd;
3999: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
4000: }
4001: // DL(sig1) <- sp->lcm
4002: // DL(sig1) -= DL(p1)
4003: // DL(sig1) += DL(p1->sig)
1.27 noro 4004: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 4005: _ndltodl(lcm,DL(sig1));
4006: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
4007: sig1->pos = p1->sig->pos;
1.55 noro 4008: _adddl(nd_nvar,DL(sig1),nd_sba_hm[sig1->pos],DL2(sig1));
1.24 noro 4009:
4010: // DL(sig2) <- sp->lcm
4011: // DL(sig2) -= DL(p2)
4012: // DL(sig2) += DL(p2->sig)
1.27 noro 4013: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 4014: _ndltodl(lcm,DL(sig2));
4015: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
4016: sig2->pos = p2->sig->pos;
1.55 noro 4017: _adddl(nd_nvar,DL(sig2),nd_sba_hm[sig2->pos],DL2(sig2));
1.24 noro 4018:
4019: ret = comp_sig(sig1,sig2);
4020: if ( ret == 0 ) return 0;
4021: else if ( ret > 0 ) sp->sig = sig1;
4022: else sp->sig = sig2;
1.49 noro 4023:
4024: s1 = DL(sig1)->td+nd_sba_hm[p1->sig->pos]->td;
4025: s2 = DL(sig2)->td+nd_sba_hm[p2->sig->pos]->td;
4026: SG(sp) = MAX(s1,s2);
4027:
1.24 noro 4028: return 1;
4029: }
4030:
4031: SIG dup_sig(SIG sig)
4032: {
4033: SIG r;
4034:
4035: if ( !sig ) return 0;
4036: else {
4037: NEWSIG(r);
4038: _copydl(nd_nvar,DL(sig),DL(r));
1.55 noro 4039: _copydl(nd_nvar,DL2(sig),DL2(r));
1.24 noro 4040: r->pos = sig->pos;
4041: return r;
4042: }
4043: }
4044:
4045: void dup_ND_pairs(ND_pairs to,ND_pairs from)
4046: {
4047: to->i1 = from->i1;
4048: to->i2 = from->i2;
4049: to->sugar = from->sugar;
4050: to->sugar2 = from->sugar2;
4051: ndl_copy(from->lcm,to->lcm);
4052: to->sig = dup_sig(from->sig);
4053: }
4054:
4055: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
4056: {
4057: struct oND_pairs root;
4058: ND_pairs q1,q2,r0,r;
4059: int ret;
4060:
4061: r = &root;
4062: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
4063: ret = comp_sig(q1->sig,q2->sig);
4064: if ( ret < 0 ) {
4065: r->next = q1; r = q1; q1 = q1->next;
4066: } else if ( ret > 0 ) {
4067: r->next = q2; r = q2; q2 = q2->next;
4068: } else {
1.47 noro 4069: Nnewpair--;
1.24 noro 4070: ret = DL_COMPARE(q1->lcm,q2->lcm);
1.35 noro 4071: Nsamesig++;
1.24 noro 4072: if ( ret < 0 ) {
4073: r->next = q1; r = q1; q1 = q1->next;
4074: q2 = q2->next;
4075: } else {
4076: r->next = q2; r = q2; q2 = q2->next;
4077: q1 = q1->next;
4078: }
4079: }
4080: }
4081: if ( q1 ) {
4082: r->next = q1;
4083: } else {
4084: r->next = q2;
4085: }
4086: return root.next;
4087: }
4088:
4089: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
4090: {
4091: ND_pairs p,prev;
1.47 noro 4092: int ret=1;
1.24 noro 4093:
4094: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
4095: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
4096: break;
4097: }
4098: if ( ret == 0 ) {
4099: ret = DL_COMPARE(s->lcm,p->lcm);
4100: if ( ret < 0 ) {
4101: // replace p with s
4102: s->next = p->next;
4103: if ( prev == 0 ) {
4104: return s;
4105: } else {
4106: prev->next = s;
4107: return l;
4108: }
4109: } else
4110: return l;
4111: } else {
4112: // insert s between prev and p
1.47 noro 4113: Nnewpair++;
1.24 noro 4114: s->next = p;
4115: if ( prev == 0 ) {
4116: return s;
4117: } else {
4118: prev->next = s;
4119: return l;
4120: }
4121: }
4122: }
4123:
1.29 noro 4124: INLINE int __dl_redble(DL d1,DL d2,int nvar)
4125: {
4126: int i;
4127:
4128: if ( d1->td > d2->td )
4129: return 0;
4130: for ( i = nvar-1; i >= 0; i-- )
4131: if ( d1->d[i] > d2->d[i] )
4132: break;
4133: if ( i >= 0 )
4134: return 0;
4135: else
4136: return 1;
4137: }
4138:
1.30 noro 4139: ND_pairs nd_newpairs_s(int t, NODE *syz)
1.24 noro 4140: {
4141: NODE h,s;
4142: UINT *dl;
1.27 noro 4143: int ts,ret,i;
1.24 noro 4144: ND_pairs r,r0,_sp,sp;
1.29 noro 4145: SIG spsig,tsig;
1.44 noro 4146: static int nvar = 0;
1.29 noro 4147: static SIG _sig1,_sig2;
1.26 noro 4148: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 4149:
4150: NEWND_pairs(_sp);
1.29 noro 4151: if ( !_sig1 || nvar != nd_nvar ) {
4152: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
4153: }
1.24 noro 4154: r0 = 0;
1.27 noro 4155: for ( i = 0; i < t; i++ ) {
4156: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
1.24 noro 4157: if ( ret ) {
4158: spsig = _sp->sig;
1.29 noro 4159: for ( s = syz[spsig->pos]; s; s = s->next ) {
1.24 noro 4160: tsig = (SIG)s->body;
1.29 noro 4161: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
1.24 noro 4162: break;
4163: }
4164: if ( s == 0 ) {
4165: NEWND_pairs(sp);
4166: dup_ND_pairs(sp,_sp);
4167: r0 = insert_pair_s(r0,sp);
1.26 noro 4168: } else
4169: Nsyz++;
1.24 noro 4170: }
4171: }
4172: return r0;
4173: }
4174:
1.47 noro 4175: ND_pairs *nd_newpairs_array_s(int t, NODE *syz)
4176: {
4177: NODE h,s;
4178: UINT *dl;
4179: int ts,ret,i;
4180: ND_pairs r,r0,_sp,sp;
4181: ND_pairs *d;
4182: SIG spsig,tsig;
4183: static int nvar = 0;
4184: static SIG _sig1,_sig2;
4185: struct oEGT eg1,eg2,eg3,eg4;
4186:
4187: NEWND_pairs(_sp);
4188: if ( !_sig1 || nvar != nd_nvar ) {
4189: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
4190: }
4191: d = (ND_pairs *)MALLOC(nd_nbase*sizeof(ND_pairs));
4192: Nnewpair = 0;
4193: for ( i = 0; i < t; i++ ) {
4194: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
4195: if ( ret ) {
4196: spsig = _sp->sig;
4197: for ( s = syz[spsig->pos]; s; s = s->next ) {
4198: tsig = (SIG)s->body;
4199: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
4200: break;
4201: }
4202: if ( s == 0 ) {
4203: NEWND_pairs(sp);
4204: dup_ND_pairs(sp,_sp);
4205: d[spsig->pos] = insert_pair_s(d[spsig->pos],sp);
4206: } else
4207: Nsyz++;
4208: }
4209: }
4210: return d;
4211: }
4212:
1.1 noro 4213: /* ipair = [i1,i2],[i1,i2],... */
4214: ND_pairs nd_ipairtospair(NODE ipair)
4215: {
4216: int s1,s2;
4217: NODE tn,t;
4218: ND_pairs r,r0;
4219:
4220: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
4221: NEXTND_pairs(r0,r);
4222: tn = BDY((LIST)BDY(t));
1.6 noro 4223: r->i1 = ZTOS((Q)ARG0(tn));
4224: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 4225: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
4226: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
4227: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
4228: SG(r) = MAX(s1,s2) + TD(LCM(r));
4229: /* experimental */
4230: if ( nd_sugarweight )
4231: r->sugar2 = ndl_weight2(r->lcm);
4232: }
4233: if ( r0 ) NEXT(r) = 0;
4234: return r0;
4235: }
4236:
4237: /* kokokara */
4238:
4239: ND_pairs crit_B( ND_pairs d, int s )
4240: {
4241: ND_pairs cur,head,prev,remove;
4242: UINT *t,*tl,*lcm;
4243: int td,tdl;
4244:
4245: if ( !d ) return 0;
4246: t = DL(nd_psh[s]);
4247: prev = 0;
4248: head = cur = d;
4249: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
4250: while ( cur ) {
4251: tl = cur->lcm;
4252: if ( ndl_reducible(tl,t) ) {
4253: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
4254: if ( !ndl_equal(lcm,tl) ) {
4255: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
4256: if (!ndl_equal(lcm,tl)) {
4257: remove = cur;
4258: if ( !prev ) {
4259: head = cur = NEXT(cur);
4260: } else {
4261: cur = NEXT(prev) = NEXT(cur);
4262: }
1.41 noro 4263: FREENDP(remove); NcriB++;
1.1 noro 4264: } else {
4265: prev = cur; cur = NEXT(cur);
4266: }
4267: } else {
4268: prev = cur; cur = NEXT(cur);
4269: }
4270: } else {
4271: prev = cur; cur = NEXT(cur);
4272: }
4273: }
4274: return head;
4275: }
4276:
4277: ND_pairs crit_M( ND_pairs d1 )
4278: {
4279: ND_pairs e,d2,d3,dd,p;
4280: UINT *id,*jd;
4281:
4282: if ( !d1 ) return d1;
4283: for ( dd = 0, e = d1; e; e = d3 ) {
4284: if ( !(d2 = NEXT(e)) ) {
4285: NEXT(e) = dd;
4286: return e;
4287: }
4288: id = LCM(e);
4289: for ( d3 = 0; d2; d2 = p ) {
4290: p = NEXT(d2);
4291: jd = LCM(d2);
4292: if ( ndl_equal(jd,id) )
4293: ;
4294: else if ( TD(jd) > TD(id) )
4295: if ( ndl_reducible(jd,id) ) continue;
4296: else ;
4297: else if ( ndl_reducible(id,jd) ) goto delit;
4298: NEXT(d2) = d3;
4299: d3 = d2;
4300: }
4301: NEXT(e) = dd;
4302: dd = e;
4303: continue;
4304: /**/
4305: delit: NEXT(d2) = d3;
4306: d3 = d2;
4307: for ( ; p; p = d2 ) {
4308: d2 = NEXT(p);
4309: NEXT(p) = d3;
4310: d3 = p;
4311: }
4312: FREENDP(e);
4313: }
4314: return dd;
4315: }
4316:
4317: ND_pairs crit_F( ND_pairs d1 )
4318: {
4319: ND_pairs rest, head,remove;
4320: ND_pairs last, p, r, w;
4321: int s;
4322:
4323: if ( !d1 ) return d1;
4324: for ( head = last = 0, p = d1; NEXT(p); ) {
4325: r = w = equivalent_pairs(p,&rest);
4326: s = SG(r);
4327: w = NEXT(w);
4328: while ( w ) {
4329: if ( crit_2(w->i1,w->i2) ) {
4330: r = w;
4331: w = NEXT(w);
4332: while ( w ) {
4333: remove = w;
4334: w = NEXT(w);
4335: FREENDP(remove);
4336: }
4337: break;
4338: } else if ( SG(w) < s ) {
4339: FREENDP(r);
4340: r = w;
4341: s = SG(r);
4342: w = NEXT(w);
4343: } else {
4344: remove = w;
4345: w = NEXT(w);
4346: FREENDP(remove);
4347: }
4348: }
4349: if ( last ) NEXT(last) = r;
4350: else head = r;
4351: NEXT(last = r) = 0;
4352: p = rest;
4353: if ( !p ) return head;
4354: }
4355: if ( !last ) return p;
4356: NEXT(last) = p;
4357: return head;
4358: }
4359:
4360: int crit_2( int dp1, int dp2 )
4361: {
4362: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
4363: }
4364:
4365: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
4366: {
4367: ND_pairs w,p,r,s;
4368: UINT *d;
4369:
4370: w = d1;
4371: d = LCM(w);
4372: s = NEXT(w);
4373: NEXT(w) = 0;
4374: for ( r = 0; s; s = p ) {
4375: p = NEXT(s);
4376: if ( ndl_equal(d,LCM(s)) ) {
4377: NEXT(s) = w; w = s;
4378: } else {
4379: NEXT(s) = r; r = s;
4380: }
4381: }
4382: *prest = r;
4383: return w;
4384: }
4385:
4386: NODE update_base(NODE nd,int ndp)
4387: {
4388: UINT *dl, *dln;
4389: NODE last, p, head;
4390:
4391: dl = DL(nd_psh[ndp]);
4392: for ( head = last = 0, p = nd; p; ) {
4393: dln = DL(nd_psh[(long)BDY(p)]);
4394: if ( ndl_reducible( dln, dl ) ) {
4395: p = NEXT(p);
4396: if ( last ) NEXT(last) = p;
4397: } else {
4398: if ( !last ) head = p;
4399: p = NEXT(last = p);
4400: }
4401: }
4402: head = append_one(head,ndp);
4403: return head;
4404: }
4405:
4406: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
4407: {
4408: ND_pairs m,ml,p,l;
4409: UINT *lcm;
4410: int s,td,len,tlen,c,c1;
4411:
4412: if ( !(p = NEXT(m = d)) ) {
4413: *prest = p;
4414: NEXT(m) = 0;
4415: return m;
4416: }
4417: if ( !NoSugar ) {
4418: if ( nd_sugarweight ) {
4419: s = m->sugar2;
4420: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4421: if ( (p->sugar2 < s)
4422: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4423: ml = l; m = p; s = m->sugar2;
4424: }
4425: } else {
4426: s = SG(m);
4427: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4428: if ( (SG(p) < s)
4429: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4430: ml = l; m = p; s = SG(m);
4431: }
4432: }
4433: } else {
4434: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4435: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
4436: ml = l; m = p; s = SG(m);
4437: }
4438: }
4439: if ( !ml ) *prest = NEXT(m);
4440: else {
4441: NEXT(ml) = NEXT(m);
4442: *prest = d;
4443: }
4444: NEXT(m) = 0;
4445: return m;
4446: }
4447:
4448: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
4449: {
4450: int msugar,i;
4451: ND_pairs t,dm0,dm,dr0,dr;
4452:
4453: if ( nd_sugarweight ) {
4454: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
4455: if ( t->sugar2 < msugar ) msugar = t->sugar2;
4456: dm0 = 0; dr0 = 0;
4457: for ( i = 0, t = d; t; t = NEXT(t) )
4458: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
4459: if ( dm0 ) NEXT(dm) = t;
4460: else dm0 = t;
4461: dm = t;
4462: i++;
4463: } else {
4464: if ( dr0 ) NEXT(dr) = t;
4465: else dr0 = t;
4466: dr = t;
4467: }
4468: } else {
4469: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
4470: if ( SG(t) < msugar ) msugar = SG(t);
4471: dm0 = 0; dr0 = 0;
4472: for ( i = 0, t = d; t; t = NEXT(t) )
4473: if ( i < nd_f4_nsp && SG(t) == msugar ) {
4474: if ( dm0 ) NEXT(dm) = t;
4475: else dm0 = t;
4476: dm = t;
4477: i++;
4478: } else {
4479: if ( dr0 ) NEXT(dr) = t;
4480: else dr0 = t;
4481: dr = t;
4482: }
4483: }
4484: NEXT(dm) = 0;
4485: if ( dr0 ) NEXT(dr) = 0;
4486: *prest = dr0;
4487: return dm0;
4488: }
4489:
1.28 noro 4490: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
4491: {
4492: int msugar;
4493: ND_pairs t,last;
4494:
4495: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
4496: if ( SG(t) == msugar ) last = t;
4497: *prest = last->next;
4498: last->next = 0;
4499: return d;
4500: }
4501:
1.1 noro 4502: int nd_tdeg(NDV c)
4503: {
4504: int wmax = 0;
4505: int i,len;
4506: NMV a;
4507:
4508: len = LEN(c);
4509: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4510: wmax = MAX(TD(DL(a)),wmax);
4511: return wmax;
4512: }
4513:
1.24 noro 4514: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 4515: {
4516: int len;
4517: RHist r;
4518: NDV b;
4519: NODE tn;
4520: LIST l;
4521: Z iq;
4522:
4523: if ( nd_psn == nd_pslen ) {
4524: nd_pslen *= 2;
4525: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
4526: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
4527: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
4528: nd_bound = (UINT **)
4529: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
4530: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
4531: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
4532: }
4533: NEWRHist(r); nd_psh[nd_psn] = r;
4534: nd_ps[nd_psn] = a;
4535: if ( aq ) {
4536: nd_ps_trace[nd_psn] = aq;
4537: if ( !m ) {
4538: register_hcf(aq);
4539: } else if ( m == -2 ) {
4540: /* do nothing */
4541: } else
4542: error("ndv_newps : invalud modulus");
4543: nd_bound[nd_psn] = ndv_compute_bound(aq);
4544: #if 1
4545: SG(r) = SG(aq);
4546: #else
4547: SG(r) = nd_tdeg(aq);
4548: #endif
4549: ndl_copy(HDL(aq),DL(r));
1.24 noro 4550: r->sig = dup_sig(aq->sig);
1.1 noro 4551: } else {
4552: if ( !m ) register_hcf(a);
4553: nd_bound[nd_psn] = ndv_compute_bound(a);
4554: #if 1
4555: SG(r) = SG(a);
4556: #else
4557: SG(r) = nd_tdeg(a);
4558: #endif
4559: ndl_copy(HDL(a),DL(r));
1.24 noro 4560: r->sig = dup_sig(a->sig);
1.1 noro 4561: }
4562: if ( nd_demand ) {
4563: if ( aq ) {
4564: ndv_save(nd_ps_trace[nd_psn],nd_psn);
4565: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4566: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4567: nd_ps_trace[nd_psn] = 0;
4568: } else {
4569: ndv_save(nd_ps[nd_psn],nd_psn);
4570: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
4571: nd_ps[nd_psn] = 0;
4572: }
4573: }
4574: if ( nd_gentrace ) {
4575: /* reverse the tracelist and append it to alltracelist */
4576: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 4577: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 4578: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
4579: }
4580: return nd_psn++;
4581: }
4582:
1.46 noro 4583: // find LM wrt the specified modord
4584: void ndv_lm_modord(NDV p,DL d)
1.45 noro 4585: {
4586: NMV m;
4587: DL tmp;
4588: int len,i,ret;
4589:
4590: NEWDL(tmp,nd_nvar);
4591: m = BDY(p); len = LEN(p);
1.46 noro 4592: _ndltodl(DL(m),d); // printdl(d); printf("->");
1.45 noro 4593: for ( i = 1, NMV_ADV(m); i < len; i++, NMV_ADV(m) ) {
4594: _ndltodl(DL(m),tmp);
1.46 noro 4595: ret = comp_sig_monomial(nd_nvar,tmp,d);
1.45 noro 4596: if ( ret > 0 ) _copydl(nd_nvar,tmp,d);
4597: }
1.46 noro 4598: // printdl(d); printf("\n");
1.45 noro 4599: }
4600:
1.1 noro 4601: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
4602: /* return 1 if success, 0 if failure (HC(a mod p)) */
4603:
1.24 noro 4604: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 4605: {
1.6 noro 4606: int i,j,td,len,max;
4607: NODE s,s0,f0,tn;
4608: UINT *d;
4609: RHist r;
4610: NDVI w;
4611: NDV a,am;
4612: union oNDC hc;
4613: NODE node;
4614: P hcp;
4615: Z iq,jq;
4616: LIST l;
4617:
4618: nd_found = 0; nd_notfirst = 0; nd_create = 0;
4619: /* initialize the tracelist */
4620: nd_tracelist = 0;
4621:
4622: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
4623: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
4624: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
4625: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
4626: if ( !dont_sort ) {
4627: /* XXX heuristic */
1.26 noro 4628: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 4629: qsort(w,nd_psn,sizeof(struct oNDVI),
4630: (int (*)(const void *,const void *))ndvi_compare_rev);
4631: else
4632: qsort(w,nd_psn,sizeof(struct oNDVI),
4633: (int (*)(const void *,const void *))ndvi_compare);
4634: }
4635: nd_pslen = 2*nd_psn;
4636: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4637: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4638: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4639: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4640: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
4641: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
4642: nd_hcf = 0;
1.1 noro 4643:
1.6 noro 4644: if ( trace && nd_vc )
4645: makesubst(nd_vc,&nd_subst);
4646: else
4647: nd_subst = 0;
1.1 noro 4648:
1.6 noro 4649: if ( !nd_red )
4650: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
4651: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
4652: for ( i = 0; i < nd_psn; i++ ) {
4653: hc = HCU(w[i].p);
4654: if ( trace ) {
4655: if ( mod == -2 ) {
4656: /* over a large finite field */
4657: /* trace = small modulus */
4658: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
4659: ndv_mod(-2,a);
4660: if ( !dont_removecont) ndv_removecont(-2,a);
4661: am = nd_ps[i] = ndv_dup(trace,w[i].p);
4662: ndv_mod(trace,am);
4663: if ( DL_COMPARE(HDL(am),HDL(a)) )
4664: return 0;
4665: ndv_removecont(trace,am);
4666: } else {
4667: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
4668: if ( !dont_removecont) ndv_removecont(0,a);
4669: register_hcf(a);
4670: am = nd_ps[i] = ndv_dup(mod,a);
4671: ndv_mod(mod,am);
4672: if ( DL_COMPARE(HDL(am),HDL(a)) )
4673: return 0;
4674: ndv_removecont(mod,am);
4675: }
4676: } else {
4677: a = nd_ps[i] = ndv_dup(mod,w[i].p);
4678: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
4679: if ( !mod ) register_hcf(a);
1.1 noro 4680: }
1.6 noro 4681: if ( nd_gentrace ) {
4682: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
4683: /* exact division */
1.1 noro 4684: if ( !dont_removecont )
1.6 noro 4685: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
4686: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
4687: }
4688: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
4689: nd_bound[i] = ndv_compute_bound(a);
4690: nd_psh[i] = r;
4691: if ( nd_demand ) {
4692: if ( trace ) {
4693: ndv_save(nd_ps_trace[i],i);
4694: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4695: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4696: nd_ps_trace[i] = 0;
4697: } else {
4698: ndv_save(nd_ps[i],i);
4699: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
4700: nd_ps[i] = 0;
4701: }
1.1 noro 4702: }
1.6 noro 4703: }
1.24 noro 4704: if ( sba ) {
1.27 noro 4705: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 4706: // setup signatures
1.27 noro 4707: for ( i = 0; i < nd_psn; i++ ) {
4708: SIG sig;
1.24 noro 4709:
1.27 noro 4710: NEWSIG(sig); sig->pos = i;
4711: nd_ps[i]->sig = sig;
4712: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
4713: nd_psh[i]->sig = sig;
4714: if ( trace ) {
4715: nd_ps_trace[i]->sig = sig;
4716: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
4717: }
4718: NEWDL(nd_sba_hm[i],nd_nvar);
1.46 noro 4719: if ( nd_sba_modord )
4720: ndv_lm_modord(nd_ps[i],nd_sba_hm[i]);
1.45 noro 4721: else
4722: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
1.55 noro 4723: _adddl(nd_nvar,DL(sig),nd_sba_hm[i],DL2(sig));
1.27 noro 4724: }
1.29 noro 4725: nd_sba_pos = (NODE *)MALLOC(nd_psn*sizeof(NODE));
4726: for ( i = 0; i < nd_psn; i++ ) {
4727: j = nd_psh[i]->sig->pos;
4728: nd_sba_pos[j] = append_one(nd_sba_pos[j],i);
4729: }
1.24 noro 4730: }
1.6 noro 4731: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
4732: return 1;
1.1 noro 4733: }
4734:
4735: struct order_spec *append_block(struct order_spec *spec,
4736: int nv,int nalg,int ord);
4737:
4738: extern VECT current_dl_weight_vector_obj;
4739: static VECT prev_weight_vector_obj;
4740:
4741: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
4742: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
4743: {
4744: NODE alist,t,s,r0,r,arg;
4745: VL tv;
4746: P poly;
4747: DP d;
4748: Alg alpha,dp;
4749: DAlg inv,da,hc;
4750: MP m;
4751: int i,nvar,nalg,n;
4752: NumberField nf;
4753: LIST f1,f2;
4754: struct order_spec *current_spec;
4755: VECT obj,obj0;
4756: VECT tmp;
4757:
4758: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
4759: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
4760:
4761: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
4762: NEXTNODE(alist,t); MKV(tv->v,poly);
4763: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
4764: tv->v = tv->v->priv;
4765: }
4766: NEXT(t) = 0;
4767:
4768: /* simplification, making polynomials monic */
4769: setfield_dalg(alist);
4770: obj_algtodalg((Obj)f,(Obj *)&f1);
4771: for ( t = BDY(f); t; t = NEXT(t) ) {
4772: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
4773: hc = (DAlg)BDY(d)->c;
4774: if ( NID(hc) == N_DA ) {
4775: invdalg(hc,&inv);
4776: for ( m = BDY(d); m; m = NEXT(m) ) {
4777: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
4778: }
4779: }
4780: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
4781: }
4782: obj_dalgtoalg((Obj)f1,(Obj *)&f);
4783:
4784: /* append alg vars to the var list */
4785: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
4786: NEXT(tv) = av;
4787:
4788: /* append a block to ord */
4789: *ord1p = append_block(ord,nvar,nalg,2);
4790:
4791: /* create generator list */
4792: nf = get_numberfield();
4793: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
4794: MKAlg(nf->defpoly[i],dp);
4795: MKNODE(s,dp,t); t = s;
4796: }
4797: MKLIST(f1,t);
4798: *alistp = alist;
4799: algobjtorat((Obj)f1,(Obj *)f1p);
4800:
4801: /* creating a new weight vector */
4802: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
4803: n = nvar+nalg+1;
4804: MKVECT(obj,n);
4805: if ( obj0 && obj0->len == nvar )
4806: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
4807: else
4808: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
4809: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
4810: BDY(obj)[n-1] = (pointer)ONE;
4811: arg = mknode(1,obj);
4812: Pdp_set_weight(arg,&tmp);
4813: }
4814:
4815: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
4816: {
4817: NODE s,t,u0,u;
4818: P p;
4819: VL tv;
4820: Obj obj;
4821: VECT tmp;
4822: NODE arg;
4823:
4824: u0 = 0;
4825: for ( t = r; t; t = NEXT(t) ) {
4826: p = (P)BDY(t);
4827: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
4828: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
4829: }
4830: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
4831: NEXTNODE(u0,u);
4832: BDY(u) = (pointer)p;
4833: }
4834: }
4835: arg = mknode(1,prev_weight_vector_obj);
4836: Pdp_set_weight(arg,&tmp);
4837:
4838: return u0;
4839: }
4840:
4841: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
4842: {
4843: VL tv,fv,vv,vc,av;
4844: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4845: int e,max,nvar,i;
4846: NDV b;
4847: int ishomo,nalg,mrank,trank,wmax,len;
4848: NMV a;
4849: Alg alpha,dp;
4850: P p,zp;
4851: Q dmy;
4852: LIST f1,f2,zpl;
4853: Obj obj;
4854: NumberField nf;
4855: struct order_spec *ord1;
4856: NODE tr,tl1,tl2,tl3,tl4,nzlist;
4857: LIST l1,l2,l3,l4,l5;
4858: int j;
4859: Z jq,bpe,last_nonzero;
4860: int *perm;
4861: EPOS oepos;
4862: int obpe,oadv,ompos,cbpe;
1.15 noro 4863: VECT hvect;
1.1 noro 4864:
1.41 noro 4865: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 4866: nd_module = 0;
4867: if ( !m && Demand ) nd_demand = 1;
4868: else nd_demand = 0;
4869:
4870: if ( DP_Multiple )
4871: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4872: #if 0
4873: ndv_alloc = 0;
4874: #endif
4875: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 4876: parse_nd_option(vv,current_option);
1.1 noro 4877: if ( m && nd_vc )
4878: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4879: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4880: switch ( ord->id ) {
4881: case 1:
4882: if ( ord->nv != nvar )
4883: error("nd_{gr,f4} : invalid order specification");
4884: break;
4885: default:
4886: break;
4887: }
4888: nd_nalg = 0;
4889: av = 0;
4890: if ( !m ) {
4891: get_algtree((Obj)f,&av);
4892: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4893: nd_ntrans = nvar;
4894: nd_nalg = nalg;
4895: /* #i -> t#i */
4896: if ( nalg ) {
4897: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4898: ord = ord1;
4899: f = f1;
4900: }
4901: nvar += nalg;
4902: }
4903: nd_init_ord(ord);
4904: mrank = 0;
4905: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4906: for ( tv = vv; tv; tv = NEXT(tv) ) {
4907: if ( nd_module ) {
1.16 noro 4908: if ( OID(BDY(t)) == O_DPM ) {
4909: e = dpm_getdeg((DPM)BDY(t),&trank);
4910: max = MAX(e,max);
4911: mrank = MAX(mrank,trank);
4912: } else {
4913: s = BDY((LIST)BDY(t));
4914: trank = length(s);
4915: mrank = MAX(mrank,trank);
4916: for ( ; s; s = NEXT(s) ) {
4917: e = getdeg(tv->v,(P)BDY(s));
4918: max = MAX(e,max);
4919: }
1.1 noro 4920: }
4921: } else {
1.43 noro 4922: if ( OID(BDY(t)) == O_DP ) {
4923: e = dp_getdeg((DP)BDY(t));
4924: max = MAX(e,max);
4925: } else {
4926: e = getdeg(tv->v,(P)BDY(t));
4927: max = MAX(e,max);
4928: }
1.1 noro 4929: }
4930: }
4931: nd_setup_parameters(nvar,nd_nzlist?0:max);
4932: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4933: ishomo = 1;
4934: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4935: if ( nd_module ) {
1.16 noro 4936: if ( OID(BDY(t)) == O_DPM ) {
4937: Z cont;
4938: DPM zdpm;
4939:
4940: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4941: else zdpm = (DPM)BDY(t);
4942: b = (pointer)dpmtondv(m,zdpm);
4943: } else {
4944: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4945: else zpl = (LIST)BDY(t);
1.1 noro 4946: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4947: }
1.1 noro 4948: } else {
1.43 noro 4949: if ( OID(BDY(t)) == O_DP ) {
4950: DP zdp;
4951:
4952: if ( !m && !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
4953: else zdp = (DP)BDY(t);
4954: b = (pointer)dptondv(m,zdp);
4955: } else {
4956: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4957: else zp = (P)BDY(t);
4958: b = (pointer)ptondv(CO,vv,zp);
4959: }
1.1 noro 4960: }
4961: if ( ishomo )
4962: ishomo = ishomo && ndv_ishomo(b);
4963: if ( m ) ndv_mod(m,b);
4964: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4965: }
4966: if ( fd0 ) NEXT(fd) = 0;
4967:
4968: if ( !ishomo && homo ) {
4969: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4970: b = (NDV)BDY(t); len = LEN(b);
4971: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4972: wmax = MAX(TD(DL(a)),wmax);
4973: }
4974: homogenize_order(ord,nvar,&ord1);
4975: nd_init_ord(ord1);
4976: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4977: for ( t = fd0; t; t = NEXT(t) )
4978: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4979: }
4980:
1.24 noro 4981: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4982: if ( nd_gentrace ) {
4983: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4984: }
4985: if ( nd_splist ) {
4986: *rp = compute_splist();
4987: return;
4988: }
4989: if ( nd_check_splist ) {
4990: if ( f4 ) {
4991: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4992: else *rp = 0;
4993: } else {
4994: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4995: else *rp = 0;
4996: }
4997: return;
4998: }
4999: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
5000: if ( !x ) {
5001: *rp = 0; return;
5002: }
1.15 noro 5003: if ( nd_gentrace ) {
5004: MKVECT(hvect,nd_psn);
5005: for ( i = 0; i < nd_psn; i++ )
5006: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5007: }
1.1 noro 5008: if ( !ishomo && homo ) {
5009: /* dehomogenization */
5010: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5011: nd_init_ord(ord);
5012: nd_setup_parameters(nvar,0);
5013: }
5014: nd_demand = 0;
5015: if ( nd_module && nd_intersect ) {
5016: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 5017: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 5018: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
5019: }
5020: conv_ilist(nd_demand,0,x,0);
5021: goto FINAL;
5022: }
5023: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
5024: x = ndv_reducebase(x,perm);
5025: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5026: x = ndv_reduceall(m,x);
5027: cbpe = nd_bpe;
5028: if ( nd_gentrace && !f4 ) {
5029: tl2 = nd_alltracelist; nd_alltracelist = 0;
5030: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
5031: tl3 = nd_alltracelist; nd_alltracelist = 0;
5032: if ( nd_gensyz ) {
5033: nd_gb(m,0,1,1,0);
5034: tl4 = nd_alltracelist; nd_alltracelist = 0;
5035: } else tl4 = 0;
5036: }
5037: nd_bpe = cbpe;
5038: nd_setup_parameters(nd_nvar,0);
5039: FINAL:
5040: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 5041: NEXTNODE(r0,r);
5042: if ( nd_module ) {
5043: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
5044: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
5045: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
5046: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 5047: }
5048: if ( r0 ) NEXT(r) = 0;
5049: if ( !m && nd_nalg )
5050: r0 = postprocess_algcoef(av,alist,r0);
5051: MKLIST(*rp,r0);
5052: if ( nd_gentrace ) {
5053: if ( f4 ) {
1.6 noro 5054: STOZ(16,bpe);
5055: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 5056: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 5057: } else {
5058: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5059: tl3 = reverse_node(tl3);
5060: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5061: for ( t = tl2; t; t = NEXT(t) ) {
5062: /* s = [i,[*,j,*,*],...] */
5063: s = BDY((LIST)BDY(t));
1.6 noro 5064: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5065: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5066: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5067: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5068: }
5069: }
5070: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5071: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5072: }
5073: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5074: MKLIST(l5,tl4);
1.6 noro 5075: STOZ(nd_bpe,bpe);
1.15 noro 5076: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5077: }
5078: }
5079: #if 0
5080: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
5081: #endif
5082: }
5083:
1.28 noro 5084: NODE nd_sba_f4(int m,int **indp);
5085:
5086: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 5087: {
5088: VL tv,fv,vv,vc,av;
1.55 noro 5089: NODE fd,fd0,r,r0,t,x,s,xx,nd,nd1,syz;
1.24 noro 5090: int e,max,nvar,i;
5091: NDV b;
5092: int ishomo,nalg,wmax,len;
5093: NMV a;
5094: P p,zp;
5095: Q dmy;
5096: struct order_spec *ord1;
5097: int j;
5098: int *perm;
5099: EPOS oepos;
5100: int obpe,oadv,ompos,cbpe;
1.51 noro 5101: struct oEGT eg0,eg1,egconv,egintred;
1.55 noro 5102: LIST l1,redind;
5103: Z z;
1.24 noro 5104:
5105: nd_module = 0;
5106: nd_demand = 0;
1.35 noro 5107: Nsamesig = 0;
1.24 noro 5108: if ( DP_Multiple )
5109: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
5110: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5111: parse_nd_option(vv,current_option);
1.24 noro 5112: if ( m && nd_vc )
5113: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
5114: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5115: switch ( ord->id ) {
5116: case 1:
5117: if ( ord->nv != nvar )
5118: error("nd_sba : invalid order specification");
5119: break;
5120: default:
5121: break;
5122: }
5123: nd_nalg = 0;
5124: nd_init_ord(ord);
5125: // for SIG comparison
5126: initd(ord);
5127: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
5128: for ( tv = vv; tv; tv = NEXT(tv) ) {
1.43 noro 5129: if ( OID(BDY(t)) == O_DP ) {
5130: e = dp_getdeg((DP)BDY(t));
5131: max = MAX(e,max);
5132: } else {
5133: e = getdeg(tv->v,(P)BDY(t));
5134: max = MAX(e,max);
5135: }
1.24 noro 5136: }
5137: }
1.25 noro 5138: nd_setup_parameters(nvar,max);
1.24 noro 5139: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
5140: ishomo = 1;
5141: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
1.43 noro 5142: if ( OID(BDY(t)) == O_DP ) {
5143: DP zdp;
5144:
5145: if ( !m ) dp_ptozp((DP)BDY(t),&zdp);
5146: else zdp = (DP)BDY(t);
5147: b = (pointer)dptondv(m,zdp);
5148: } else {
5149: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
5150: else zp = (P)BDY(t);
5151: b = (pointer)ptondv(CO,vv,zp);
5152: }
1.24 noro 5153: if ( ishomo )
5154: ishomo = ishomo && ndv_ishomo(b);
5155: if ( m ) ndv_mod(m,b);
5156: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
5157: }
5158: if ( fd0 ) NEXT(fd) = 0;
5159:
5160: if ( !ishomo && homo ) {
5161: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
5162: b = (NDV)BDY(t); len = LEN(b);
5163: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
5164: wmax = MAX(TD(DL(a)),wmax);
5165: }
5166: homogenize_order(ord,nvar,&ord1);
5167: nd_init_ord(ord1);
1.42 noro 5168: // for SIG comparison
5169: initd(ord1);
1.24 noro 5170: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
5171: for ( t = fd0; t; t = NEXT(t) )
5172: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5173: }
5174:
1.39 noro 5175: ndv_setup(m,0,fd0,nd_sba_dontsort,0,1);
1.55 noro 5176: if ( nd_gentrace ) {
5177: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5178: }
1.44 noro 5179: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm,&syz);
1.24 noro 5180: if ( !x ) {
5181: *rp = 0; return;
5182: }
5183: if ( !ishomo && homo ) {
5184: /* dehomogenization */
5185: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5186: nd_init_ord(ord);
1.42 noro 5187: // for SIG comparison
5188: initd(ord);
1.24 noro 5189: nd_setup_parameters(nvar,0);
5190: }
5191: nd_demand = 0;
1.51 noro 5192: get_eg(&eg0);
1.24 noro 5193: x = ndv_reducebase(x,perm);
1.55 noro 5194: for ( nd = 0, i = length(x)-1; i >= 0; i-- ) {
5195: STOZ(perm[i],z); MKNODE(nd1,z,nd); nd = nd1;
5196: }
5197: MKLIST(redind,nd);
1.24 noro 5198: x = ndv_reduceall(m,x);
1.51 noro 5199: get_eg(&eg1); init_eg(&egintred); add_eg(&egintred,&eg0,&eg1);
1.24 noro 5200: nd_setup_parameters(nd_nvar,0);
1.29 noro 5201: get_eg(&eg0);
1.24 noro 5202: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
5203: NEXTNODE(r0,r);
5204: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
1.34 noro 5205: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.24 noro 5206: }
5207: if ( r0 ) NEXT(r) = 0;
1.44 noro 5208: if ( nd_sba_syz ) {
5209: LIST gb,hsyz;
5210:
5211: MKLIST(gb,r0);
5212: MKLIST(hsyz,syz);
5213: nd = mknode(2,gb,hsyz);
5214: MKLIST(*rp,nd);
1.55 noro 5215: } else if ( nd_gentrace ) {
5216: LIST gb,trace;
5217:
5218: MKLIST(trace,nd_alltracelist);
5219: MKLIST(gb,r0);
5220: nd = mknode(3,gb,redind,trace);
5221: MKLIST(*rp,nd);
1.44 noro 5222: } else
5223: MKLIST(*rp,r0);
1.29 noro 5224: get_eg(&eg1); init_eg(&egconv); add_eg(&egconv,&eg0,&eg1);
1.51 noro 5225: print_eg("intred",&egintred); fprintf(asir_out,"\n");
1.29 noro 5226: print_eg("conv",&egconv); fprintf(asir_out,"\n");
1.24 noro 5227: }
5228:
1.1 noro 5229: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
5230: {
5231: VL tv,fv,vv,vc,av;
5232: NODE fd,fd0,r,r0,t,x,s,xx,alist;
5233: int e,max,nvar,i;
5234: NDV b;
5235: int ishomo,nalg;
5236: Alg alpha,dp;
5237: P p,zp;
5238: Q dmy;
5239: LIST f1,f2;
5240: Obj obj;
5241: NumberField nf;
5242: struct order_spec *ord1;
5243: int *perm;
5244:
5245: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5246: parse_nd_option(vv,current_option);
1.1 noro 5247: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5248: switch ( ord->id ) {
5249: case 1:
5250: if ( ord->nv != nvar )
5251: error("nd_check : invalid order specification");
5252: break;
5253: default:
5254: break;
5255: }
5256: nd_nalg = 0;
5257: av = 0;
5258: if ( !m ) {
5259: get_algtree((Obj)f,&av);
5260: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
5261: nd_ntrans = nvar;
5262: nd_nalg = nalg;
5263: /* #i -> t#i */
5264: if ( nalg ) {
5265: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
5266: ord = ord1;
5267: f = f1;
5268: }
5269: nvar += nalg;
5270: }
5271: nd_init_ord(ord);
5272: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
5273: for ( tv = vv; tv; tv = NEXT(tv) ) {
5274: e = getdeg(tv->v,(P)BDY(t));
5275: max = MAX(e,max);
5276: }
5277: nd_setup_parameters(nvar,max);
5278: ishomo = 1;
5279: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5280: ptozp((P)BDY(t),1,&dmy,&zp);
5281: b = (pointer)ptondv(CO,vv,zp);
5282: if ( ishomo )
5283: ishomo = ishomo && ndv_ishomo(b);
5284: if ( m ) ndv_mod(m,b);
5285: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
5286: }
5287: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 5288: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 5289: for ( x = 0, i = 0; i < nd_psn; i++ )
5290: x = update_base(x,i);
5291: if ( do_check ) {
5292: x = nd_gb(m,ishomo,1,0,&perm);
5293: if ( !x ) {
5294: *rp = 0;
5295: return;
5296: }
5297: } else {
5298: #if 0
5299: /* bug ? */
5300: for ( t = x; t; t = NEXT(t) )
5301: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
5302: #else
5303: conv_ilist(0,0,x,&perm);
5304: #endif
5305: }
5306: x = ndv_reducebase(x,perm);
5307: x = ndv_reduceall(m,x);
5308: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
5309: NEXTNODE(r0,r);
5310: BDY(r) = ndvtop(m,CO,vv,BDY(t));
5311: }
5312: if ( r0 ) NEXT(r) = 0;
5313: if ( !m && nd_nalg )
5314: r0 = postprocess_algcoef(av,alist,r0);
5315: MKLIST(*rp,r0);
5316: }
5317:
5318: NDV recompute_trace(NODE trace,NDV *p,int m);
5319: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
5320:
5321: NDV recompute_trace(NODE ti,NDV *p,int mod)
5322: {
5323: int c,c1,c2,i;
5324: NM mul,m,tail;
5325: ND d,r,rm;
5326: NODE sj;
5327: NDV red;
5328: Obj mj;
5329:
5330: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
5331: CM(mul) = 1;
5332: tail = 0;
5333: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
5334: sj = BDY((LIST)BDY(ti));
5335: if ( ARG0(sj) ) {
1.6 noro 5336: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 5337: mj = (Obj)ARG2(sj);
5338: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
5339: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
5340: rm = ndv_mul_nm(mod,mul,red);
5341: if ( !r ) r = rm;
5342: else {
5343: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
5344: if ( d ) {
5345: NEXT(tail) = m; tail = m; LEN(d)++;
5346: } else {
5347: MKND(nd_nvar,m,1,d); tail = BDY(d);
5348: }
5349: }
5350: if ( !m ) return 0; /* failure */
5351: else {
5352: BDY(r) = m;
5353: if ( mod > 0 || mod == -1 ) {
5354: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
5355: DMAR(c1,c2,0,mod,c);
5356: nd_mul_c(mod,rm,c);
5357: } else {
5358: Z t,u;
5359:
5360: chsgnlf(HCZ(r),&t);
5361: divlf(t,HCZ(rm),&u);
5362: nd_mul_c_lf(rm,u);
5363: }
5364: r = nd_add(mod,r,rm);
5365: }
5366: }
5367: }
5368: }
5369: if ( tail ) NEXT(tail) = 0;
5370: d = nd_add(mod,d,r);
5371: nd_mul_c(mod,d,invm(HCM(d),mod));
5372: return ndtondv(mod,d);
5373: }
5374:
5375: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
5376: {
5377: VL tv,fv,vv,vc,av;
5378: NODE fd,fd0,r,r0,t,x,s,xx,alist;
5379: int e,max,nvar,i;
5380: NDV b;
5381: int ishomo,nalg;
5382: Alg alpha,dp;
5383: P p,zp;
5384: Q dmy;
5385: LIST f1,f2;
5386: Obj obj;
5387: NumberField nf;
5388: struct order_spec *ord1;
5389: NODE permtrace,intred,ind,perm,trace,ti;
5390: int len,n,j;
5391: NDV *db,*pb;
5392:
5393: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5394: parse_nd_option(vv,current_option);
1.1 noro 5395: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5396: switch ( ord->id ) {
5397: case 1:
5398: if ( ord->nv != nvar )
5399: error("nd_check : invalid order specification");
5400: break;
5401: default:
5402: break;
5403: }
5404: nd_init_ord(ord);
1.6 noro 5405: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 5406: nd_setup_parameters(nvar,0);
5407:
5408: len = length(BDY(f));
5409: db = (NDV *)MALLOC(len*sizeof(NDV *));
5410: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
5411: ptozp((P)BDY(t),1,&dmy,&zp);
5412: b = ptondv(CO,vv,zp);
5413: ndv_mod(m,b);
5414: ndv_mul_c(m,b,invm(HCM(b),m));
5415: db[i] = b;
5416: }
5417:
5418: permtrace = BDY((LIST)ARG2(BDY(tlist)));
5419: intred = BDY((LIST)ARG3(BDY(tlist)));
5420: ind = BDY((LIST)ARG4(BDY(tlist)));
5421: perm = BDY((LIST)ARG0(permtrace));
5422: trace = NEXT(permtrace);
5423:
5424: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 5425: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 5426: if ( j > i ) i = j;
5427: }
5428: n = i+1;
5429: pb = (NDV *)MALLOC(n*sizeof(NDV *));
5430: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
5431: ti = BDY((LIST)BDY(t));
1.6 noro 5432: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 5433: }
5434: for ( t = trace; t; t = NEXT(t) ) {
5435: ti = BDY((LIST)BDY(t));
1.6 noro 5436: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5437: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5438: if ( DP_Print ) {
5439: fprintf(asir_out,"."); fflush(asir_out);
5440: }
5441: }
5442: for ( t = intred; t; t = NEXT(t) ) {
5443: ti = BDY((LIST)BDY(t));
1.6 noro 5444: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5445: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5446: if ( DP_Print ) {
5447: fprintf(asir_out,"*"); fflush(asir_out);
5448: }
5449: }
5450: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
5451: NEXTNODE(r0,r);
1.6 noro 5452: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 5453: ndv_mul_c(m,b,invm(HCM(b),m));
5454: #if 0
1.6 noro 5455: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5456: #else
1.6 noro 5457: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5458: #endif
5459: }
5460: if ( r0 ) NEXT(r) = 0;
5461: MKLIST(*rp,r0);
5462: if ( DP_Print ) fprintf(asir_out,"\n");
5463: }
5464:
1.16 noro 5465: 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 5466: {
5467: VL tv,fv,vv,vc,av;
5468: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
5469: int m,nocheck,nvar,mindex,e,max;
5470: NDV c;
5471: NMV a;
5472: P p,zp;
5473: Q dmy;
5474: EPOS oepos;
5475: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
5476: Alg alpha,dp;
5477: P poly;
5478: LIST f1,f2,zpl;
5479: Obj obj;
5480: NumberField nf;
5481: struct order_spec *ord1;
5482: struct oEGT eg_check,eg0,eg1;
5483: NODE tr,tl1,tl2,tl3,tl4;
5484: LIST l1,l2,l3,l4,l5;
5485: int *perm;
5486: int j,ret;
5487: Z jq,bpe;
1.15 noro 5488: VECT hvect;
1.1 noro 5489:
1.41 noro 5490: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 5491: nd_module = 0;
5492: nd_lf = 0;
1.46 noro 5493: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
5494: parse_nd_option(vv,current_option);
1.1 noro 5495: if ( nd_lf ) {
5496: if ( f4 )
5497: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
5498: else
5499: error("nd_gr_trace is not implemented yet over a large finite field");
5500: return;
5501: }
5502: if ( DP_Multiple )
5503: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
5504:
5505: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5506: switch ( ord->id ) {
5507: case 1:
5508: if ( ord->nv != nvar )
5509: error("nd_gr_trace : invalid order specification");
5510: break;
5511: default:
5512: break;
5513: }
5514:
5515: get_algtree((Obj)f,&av);
5516: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
5517: nd_ntrans = nvar;
5518: nd_nalg = nalg;
5519: /* #i -> t#i */
5520: if ( nalg ) {
5521: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
5522: ord = ord1;
5523: f = f1;
5524: }
5525: nvar += nalg;
5526:
5527: nocheck = 0;
5528: mindex = 0;
5529:
5530: if ( Demand ) nd_demand = 1;
5531: else nd_demand = 0;
5532:
5533: /* setup modulus */
5534: if ( trace < 0 ) {
5535: trace = -trace;
5536: nocheck = 1;
5537: }
5538: m = trace > 1 ? trace : get_lprime(mindex);
5539: nd_init_ord(ord);
5540: mrank = 0;
5541: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
5542: for ( tv = vv; tv; tv = NEXT(tv) ) {
5543: if ( nd_module ) {
1.16 noro 5544: if ( OID(BDY(t)) == O_DPM ) {
5545: e = dpm_getdeg((DPM)BDY(t),&trank);
5546: max = MAX(e,max);
5547: mrank = MAX(mrank,trank);
5548: } else {
1.1 noro 5549: s = BDY((LIST)BDY(t));
5550: trank = length(s);
5551: mrank = MAX(mrank,trank);
5552: for ( ; s; s = NEXT(s) ) {
5553: e = getdeg(tv->v,(P)BDY(s));
5554: max = MAX(e,max);
5555: }
1.16 noro 5556: }
1.1 noro 5557: } else {
1.43 noro 5558: if ( OID(BDY(t)) == O_DP ) {
5559: e = dp_getdeg((DP)BDY(t));
5560: max = MAX(e,max);
5561: } else {
1.1 noro 5562: e = getdeg(tv->v,(P)BDY(t));
5563: max = MAX(e,max);
1.43 noro 5564: }
1.1 noro 5565: }
5566: }
5567: nd_setup_parameters(nvar,max);
5568: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
5569: ishomo = 1;
5570: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5571: if ( nd_module ) {
1.16 noro 5572: if ( OID(BDY(t)) == O_DPM ) {
5573: Z cont;
5574: DPM zdpm;
5575:
1.17 noro 5576: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 5577: else zdpm = (DPM)BDY(t);
5578: c = (pointer)dpmtondv(m,zdpm);
5579: } else {
5580: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
5581: else zpl = (LIST)BDY(t);
1.1 noro 5582: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 5583: }
1.1 noro 5584: } else {
1.43 noro 5585: if ( OID(BDY(t)) == O_DP ) {
5586: DP zdp;
5587:
5588: if ( !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
5589: else zdp = (DP)BDY(t);
5590: c = (pointer)dptondv(m,zdp);
5591: } else {
5592: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
5593: else zp = (P)BDY(t);
5594: c = (pointer)ptondv(CO,vv,zp);
5595: }
1.1 noro 5596: }
5597: if ( ishomo )
5598: ishomo = ishomo && ndv_ishomo(c);
5599: if ( c ) {
5600: NEXTNODE(in0,in); BDY(in) = (pointer)c;
5601: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
5602: }
5603: }
5604: if ( in0 ) NEXT(in) = 0;
5605: if ( fd0 ) NEXT(fd) = 0;
5606: if ( !ishomo && homo ) {
5607: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
5608: c = (NDV)BDY(t); len = LEN(c);
5609: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
5610: wmax = MAX(TD(DL(a)),wmax);
5611: }
5612: homogenize_order(ord,nvar,&ord1);
5613: nd_init_ord(ord1);
5614: nd_setup_parameters(nvar+1,wmax);
5615: for ( t = fd0; t; t = NEXT(t) )
5616: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5617: }
5618: if ( MaxDeg > 0 ) nocheck = 1;
5619: while ( 1 ) {
5620: tl1 = tl2 = tl3 = tl4 = 0;
5621: if ( Demand )
5622: nd_demand = 1;
1.24 noro 5623: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 5624: if ( nd_gentrace ) {
5625: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5626: }
5627: if ( ret )
5628: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
5629: if ( !ret || !cand ) {
5630: /* failure */
5631: if ( trace > 1 ) { *rp = 0; return; }
5632: else m = get_lprime(++mindex);
5633: continue;
5634: }
1.15 noro 5635: if ( nd_gentrace ) {
5636: MKVECT(hvect,nd_psn);
5637: for ( i = 0; i < nd_psn; i++ )
5638: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5639: }
1.1 noro 5640: if ( !ishomo && homo ) {
5641: /* dehomogenization */
5642: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5643: nd_init_ord(ord);
5644: nd_setup_parameters(nvar,0);
5645: }
5646: nd_demand = 0;
5647: cand = ndv_reducebase(cand,perm);
5648: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5649: cand = ndv_reduceall(0,cand);
5650: cbpe = nd_bpe;
5651: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
5652: get_eg(&eg0);
5653: if ( nocheck )
5654: break;
5655: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
5656: if ( nd_gentrace ) {
5657: tl3 = nd_alltracelist; nd_alltracelist = 0;
5658: } else tl3 = 0;
5659: /* gbcheck : cand is a GB of Id(cand) ? */
1.54 noro 5660: if ( nd_vc || nd_gentrace || nd_gensyz || do_weyl )
1.1 noro 5661: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
5662: else
5663: ret = nd_f4(0,1,0)!=0;
5664: if ( nd_gentrace && nd_gensyz ) {
5665: tl4 = nd_alltracelist; nd_alltracelist = 0;
5666: } else tl4 = 0;
5667: }
5668: if ( ret ) break;
5669: else if ( trace > 1 ) {
5670: /* failure */
5671: *rp = 0; return;
5672: } else {
5673: /* try the next modulus */
5674: m = get_lprime(++mindex);
5675: /* reset the parameters */
5676: if ( !ishomo && homo ) {
5677: nd_init_ord(ord1);
5678: nd_setup_parameters(nvar+1,wmax);
5679: } else {
5680: nd_init_ord(ord);
5681: nd_setup_parameters(nvar,max);
5682: }
5683: }
5684: }
5685: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
5686: if ( DP_Print )
1.6 noro 5687: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 5688: /* dp->p */
5689: nd_bpe = cbpe;
5690: nd_setup_parameters(nd_nvar,0);
5691: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 5692: if ( nd_module ) {
1.17 noro 5693: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 5694: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 5695: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
5696: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 5697: }
5698: if ( nd_nalg )
5699: cand = postprocess_algcoef(av,alist,cand);
5700: MKLIST(*rp,cand);
5701: if ( nd_gentrace ) {
5702: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5703: tl3 = reverse_node(tl3);
5704: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5705: for ( t = tl2; t; t = NEXT(t) ) {
5706: /* s = [i,[*,j,*,*],...] */
5707: s = BDY((LIST)BDY(t));
1.6 noro 5708: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5709: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5710: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5711: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5712: }
5713: }
5714: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5715: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5716: }
5717: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5718: MKLIST(l5,tl4);
1.6 noro 5719: STOZ(nd_bpe,bpe);
1.15 noro 5720: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5721: }
5722: }
5723:
5724: /* XXX : module element is not considered */
5725:
5726: void dltondl(int n,DL dl,UINT *r)
5727: {
5728: UINT *d;
5729: int i,j,l,s,ord_l;
5730: struct order_pair *op;
5731:
5732: d = (unsigned int *)dl->d;
5733: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
5734: if ( nd_blockmask ) {
5735: l = nd_blockmask->n;
5736: op = nd_blockmask->order_pair;
5737: for ( j = 0, s = 0; j < l; j++ ) {
5738: ord_l = op[j].length;
5739: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
5740: }
5741: TD(r) = ndl_weight(r);
5742: ndl_weight_mask(r);
5743: } else {
5744: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
5745: TD(r) = ndl_weight(r);
5746: }
5747: }
5748:
5749: DL ndltodl(int n,UINT *ndl)
5750: {
5751: DL dl;
5752: int *d;
5753: int i,j,l,s,ord_l;
5754: struct order_pair *op;
5755:
1.33 noro 5756: NEWDL_NOINIT(dl,n);
1.1 noro 5757: dl->td = TD(ndl);
5758: d = dl->d;
5759: if ( nd_blockmask ) {
5760: l = nd_blockmask->n;
5761: op = nd_blockmask->order_pair;
5762: for ( j = 0, s = 0; j < l; j++ ) {
5763: ord_l = op[j].length;
5764: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5765: }
5766: } else {
5767: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5768: }
5769: return dl;
5770: }
5771:
1.24 noro 5772: void _ndltodl(UINT *ndl,DL dl)
5773: {
5774: int *d;
5775: int i,j,l,s,ord_l,n;
5776: struct order_pair *op;
5777:
5778: n = nd_nvar;
5779: dl->td = TD(ndl);
5780: d = dl->d;
5781: if ( nd_blockmask ) {
5782: l = nd_blockmask->n;
5783: op = nd_blockmask->order_pair;
5784: for ( j = 0, s = 0; j < l; j++ ) {
5785: ord_l = op[j].length;
5786: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5787: }
5788: } else {
5789: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5790: }
5791: }
5792:
1.1 noro 5793: void nmtodp(int mod,NM m,DP *r)
5794: {
5795: DP dp;
5796: MP mr;
5797:
5798: NEWMP(mr);
5799: mr->dl = ndltodl(nd_nvar,DL(m));
5800: mr->c = (Obj)ndctop(mod,m->c);
5801: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5802: *r = dp;
5803: }
5804:
1.15 noro 5805: void ndltodp(UINT *d,DP *r)
5806: {
5807: DP dp;
5808: MP mr;
5809:
5810: NEWMP(mr);
5811: mr->dl = ndltodl(nd_nvar,d);
5812: mr->c = (Obj)ONE;
5813: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5814: *r = dp;
5815: }
5816:
1.1 noro 5817: void ndl_print(UINT *dl)
5818: {
5819: int n;
5820: int i,j,l,ord_l,s,s0;
5821: struct order_pair *op;
5822:
5823: n = nd_nvar;
5824: printf("<<");
5825: if ( nd_blockmask ) {
5826: l = nd_blockmask->n;
5827: op = nd_blockmask->order_pair;
5828: for ( j = 0, s = s0 = 0; j < l; j++ ) {
5829: ord_l = op[j].length;
5830: for ( i = 0; i < ord_l; i++, s++ )
5831: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
5832: }
5833: } else {
5834: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
5835: }
5836: printf(">>");
5837: if ( nd_module && MPOS(dl) )
5838: printf("*e%d",MPOS(dl));
5839: }
5840:
5841: void nd_print(ND p)
5842: {
5843: NM m;
5844:
5845: if ( !p )
5846: printf("0\n");
5847: else {
5848: for ( m = BDY(p); m; m = NEXT(m) ) {
5849: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 5850: else printf("+%ld*",CM(m));
1.1 noro 5851: ndl_print(DL(m));
5852: }
5853: printf("\n");
5854: }
5855: }
5856:
5857: void nd_print_q(ND p)
5858: {
5859: NM m;
5860:
5861: if ( !p )
5862: printf("0\n");
5863: else {
5864: for ( m = BDY(p); m; m = NEXT(m) ) {
5865: printf("+");
1.6 noro 5866: printexpr(CO,(Obj)CZ(m));
1.1 noro 5867: printf("*");
5868: ndl_print(DL(m));
5869: }
5870: printf("\n");
5871: }
5872: }
5873:
5874: void ndp_print(ND_pairs d)
5875: {
5876: ND_pairs t;
5877:
5878: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
5879: printf("\n");
5880: }
5881:
5882: void nd_removecont(int mod,ND p)
5883: {
5884: int i,n;
5885: Z *w;
5886: NM m;
5887: struct oVECT v;
5888:
5889: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
5890: else if ( mod == -2 ) {
5891: Z inv;
5892: divlf(ONE,HCZ(p),&inv);
5893: nd_mul_c_lf(p,inv);
5894: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
5895: else {
5896: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
5897: w = (Z *)MALLOC(n*sizeof(Q));
5898: v.len = n;
5899: v.body = (pointer *)w;
1.6 noro 5900: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5901: removecont_array((P *)w,n,1);
1.6 noro 5902: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5903: }
5904: }
5905:
5906: void nd_removecont2(ND p1,ND p2)
5907: {
5908: int i,n1,n2,n;
5909: Z *w;
5910: NM m;
5911: struct oVECT v;
5912:
5913: n1 = nd_length(p1);
5914: n2 = nd_length(p2);
5915: n = n1+n2;
5916: w = (Z *)MALLOC(n*sizeof(Q));
5917: v.len = n;
5918: v.body = (pointer *)w;
5919: i = 0;
5920: if ( p1 )
1.6 noro 5921: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5922: if ( p2 )
1.6 noro 5923: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5924: removecont_array((P *)w,n,1);
5925: i = 0;
5926: if ( p1 )
1.6 noro 5927: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5928: if ( p2 )
1.6 noro 5929: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5930: }
5931:
5932: void ndv_removecont(int mod,NDV p)
5933: {
5934: int i,len,all_p;
5935: Z *c;
5936: P *w;
5937: Z dvr,t;
5938: P g,cont,tp;
5939: NMV m;
5940:
5941: if ( mod == -1 )
5942: ndv_mul_c(mod,p,_invsf(HCM(p)));
5943: else if ( mod == -2 ) {
5944: Z inv;
5945: divlf(ONE,HCZ(p),&inv);
5946: ndv_mul_c_lf(p,inv);
5947: } else if ( mod )
5948: ndv_mul_c(mod,p,invm(HCM(p),mod));
5949: else {
5950: len = p->len;
5951: w = (P *)MALLOC(len*sizeof(P));
5952: c = (Z *)MALLOC(len*sizeof(Q));
5953: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5954: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5955: all_p = all_p && !NUM(w[i]);
5956: }
5957: if ( all_p ) {
5958: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5959: mulp(nd_vc,(P)dvr,g,&cont);
5960: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5961: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5962: }
5963: } else {
5964: sortbynm((Q *)c,len);
5965: qltozl((Q *)c,len,&dvr);
5966: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5967: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5968: }
5969: }
5970: }
5971: }
5972:
5973: /* koko */
5974:
5975: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5976: {
5977: int len,i,max;
5978: NMV m,mr0,mr,t;
5979:
5980: len = p->len;
1.14 noro 5981: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5982: max = MAX(max,TD(DL(m)));
5983: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5984: m = (NMV)((char *)mr0+(len-1)*oadv);
5985: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5986: t = (NMV)MALLOC(nmv_adv);
5987: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5988: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5989: CZ(mr) = CZ(m);
1.1 noro 5990: ndl_copy(DL(t),DL(mr));
5991: }
5992: NV(p)++;
5993: BDY(p) = mr0;
5994: }
5995:
5996: void ndv_dehomogenize(NDV p,struct order_spec *ord)
5997: {
5998: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
5999: int pos;
6000: Q *w;
6001: Q dvr,t;
6002: NMV m,r;
6003:
6004: len = p->len;
6005: newnvar = nd_nvar-1;
6006: newexporigin = nd_get_exporigin(ord);
6007: if ( nd_module ) newmpos = newexporigin-1;
6008: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
6009: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
6010: ndl_dehomogenize(DL(m));
6011: if ( newwpd != nd_wpd ) {
6012: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
6013: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 6014: CZ(r) = CZ(m);
1.1 noro 6015: if ( nd_module ) pos = MPOS(DL(m));
6016: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
6017: adj = nd_exporigin-newexporigin;
6018: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
6019: if ( nd_module ) {
6020: DL(r)[newmpos] = pos;
6021: }
6022: }
6023: }
6024: NV(p)--;
6025: }
6026:
6027: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
6028: {
6029: int i;
6030: P *tpl,*tpl1;
6031: NODE l;
6032: P h,gcd,t;
6033:
6034: tpl = (P *)MALLOC(m*sizeof(P));
6035: tpl1 = (P *)MALLOC(m*sizeof(P));
6036: bcopy(pl,tpl,m*sizeof(P));
6037: gcd = (P)ONE;
6038: for ( l = nd_hcf; l; l = NEXT(l) ) {
6039: h = (P)BDY(l);
6040: while ( 1 ) {
6041: for ( i = 0; i < m; i++ )
6042: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
6043: break;
6044: if ( i == m ) {
6045: bcopy(tpl1,tpl,m*sizeof(P));
6046: mulp(vl,gcd,h,&t); gcd = t;
6047: } else
6048: break;
6049: }
6050: }
6051: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
6052: if ( full ) {
6053: heu_nezgcdnpz(vl,tpl,m,&t);
6054: mulp(vl,gcd,t,pr);
6055: } else
6056: *pr = gcd;
6057: }
6058:
6059: void removecont_array(P *p,int n,int full)
6060: {
6061: int all_p,all_q,i;
6062: Z *c;
6063: P *w;
6064: P t,s;
6065:
6066: for ( all_q = 1, i = 0; i < n; i++ )
6067: all_q = all_q && NUM(p[i]);
6068: if ( all_q ) {
6069: removecont_array_q((Z *)p,n);
6070: } else {
6071: c = (Z *)MALLOC(n*sizeof(Z));
6072: w = (P *)MALLOC(n*sizeof(P));
6073: for ( i = 0; i < n; i++ ) {
6074: ptozp(p[i],1,(Q *)&c[i],&w[i]);
6075: }
6076: removecont_array_q(c,n);
6077: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
6078: for ( i = 0; i < n; i++ ) {
6079: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
6080: }
6081: }
6082: }
6083:
6084: /* c is an int array */
6085:
6086: void removecont_array_q(Z *c,int n)
6087: {
6088: struct oVECT v;
6089: Z d0,d1,a,u,u1,gcd;
6090: int i,j;
6091: Z *q,*r;
6092:
6093: q = (Z *)MALLOC(n*sizeof(Z));
6094: r = (Z *)MALLOC(n*sizeof(Z));
6095: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
6096: gcdvz_estimate(&v,&d0);
6097: for ( i = 0; i < n; i++ ) {
6098: divqrz(c[i],d0,&q[i],&r[i]);
6099: }
6100: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
6101: if ( i < n ) {
6102: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
6103: gcdvz(&v,&d1);
6104: gcdz(d0,d1,&gcd);
1.6 noro 6105: /* exact division */
6106: divsz(d0,gcd,&a);
1.1 noro 6107: for ( i = 0; i < n; i++ ) {
6108: mulz(a,q[i],&u);
6109: if ( r[i] ) {
1.6 noro 6110: /* exact division */
6111: divsz(r[i],gcd,&u1);
1.1 noro 6112: addz(u,u1,&q[i]);
6113: } else
6114: q[i] = u;
6115: }
6116: }
6117: for ( i = 0; i < n; i++ ) c[i] = q[i];
6118: }
6119:
1.4 noro 6120: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
6121:
6122: void mpz_removecont_array(mpz_t *c,int n)
6123: {
6124: mpz_t d0,a,u,u1,gcd;
6125: int i,j;
1.13 noro 6126: static mpz_t *q,*r;
6127: static int c_len = 0;
1.4 noro 6128:
6129: for ( i = 0; i < n; i++ )
6130: if ( mpz_sgn(c[i]) ) break;
6131: if ( i == n ) return;
6132: gcdv_mpz_estimate(d0,c,n);
1.13 noro 6133: if ( n > c_len ) {
6134: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
6135: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
6136: c_len = n;
6137: }
1.4 noro 6138: for ( i = 0; i < n; i++ ) {
6139: mpz_init(q[i]); mpz_init(r[i]);
6140: mpz_fdiv_qr(q[i],r[i],c[i],d0);
6141: }
6142: for ( i = 0; i < n; i++ )
6143: if ( mpz_sgn(r[i]) ) break;
6144: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
6145: if ( i < n ) {
6146: mpz_gcd(gcd,d0,r[i]);
6147: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
6148: mpz_div(a,d0,gcd);
6149: for ( i = 0; i < n; i++ ) {
6150: mpz_mul(u,a,q[i]);
6151: if ( mpz_sgn(r[i]) ) {
6152: mpz_div(u1,r[i],gcd);
6153: mpz_add(q[i],u,u1);
6154: } else
6155: mpz_set(q[i],u);
6156: }
6157: }
6158: for ( i = 0; i < n; i++ )
6159: mpz_set(c[i],q[i]);
6160: }
6161:
1.1 noro 6162: void nd_mul_c(int mod,ND p,int mul)
6163: {
6164: NM m;
6165: int c,c1;
6166:
6167: if ( !p ) return;
6168: if ( mul == 1 ) return;
6169: if ( mod == -1 )
6170: for ( m = BDY(p); m; m = NEXT(m) )
6171: CM(m) = _mulsf(CM(m),mul);
6172: else
6173: for ( m = BDY(p); m; m = NEXT(m) ) {
6174: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6175: }
6176: }
6177:
6178: void nd_mul_c_lf(ND p,Z mul)
6179: {
6180: NM m;
6181: Z c;
6182:
6183: if ( !p ) return;
6184: if ( UNIZ(mul) ) return;
6185: for ( m = BDY(p); m; m = NEXT(m) ) {
6186: mullf(CZ(m),mul,&c); CZ(m) = c;
6187: }
6188: }
6189:
6190: void nd_mul_c_q(ND p,P mul)
6191: {
6192: NM m;
6193: P c;
6194:
6195: if ( !p ) return;
6196: if ( UNIQ(mul) ) return;
6197: for ( m = BDY(p); m; m = NEXT(m) ) {
6198: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
6199: }
6200: }
6201:
6202: void nd_mul_c_p(VL vl,ND p,P mul)
6203: {
6204: NM m;
6205: P c;
6206:
6207: if ( !p ) return;
6208: for ( m = BDY(p); m; m = NEXT(m) ) {
6209: mulp(vl,CP(m),mul,&c); CP(m) = c;
6210: }
6211: }
6212:
6213: void nd_free(ND p)
6214: {
6215: NM t,s;
6216:
6217: if ( !p ) return;
6218: t = BDY(p);
6219: while ( t ) {
6220: s = NEXT(t);
6221: FREENM(t);
6222: t = s;
6223: }
6224: FREEND(p);
6225: }
6226:
6227: void ndv_free(NDV p)
6228: {
6229: GCFREE(BDY(p));
6230: }
6231:
6232: void nd_append_red(UINT *d,int i)
6233: {
6234: RHist m,m0;
6235: int h;
6236:
6237: NEWRHist(m);
6238: h = ndl_hash_value(d);
6239: m->index = i;
6240: ndl_copy(d,DL(m));
6241: NEXT(m) = nd_red[h];
6242: nd_red[h] = m;
6243: }
6244:
6245: UINT *ndv_compute_bound(NDV p)
6246: {
6247: UINT *d1,*d2,*t;
6248: UINT u;
6249: int i,j,k,l,len,ind;
6250: NMV m;
6251:
6252: if ( !p )
6253: return 0;
6254: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6255: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6256: len = LEN(p);
6257: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
6258: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
6259: ndl_max(DL(m),d1,d2);
6260: t = d1; d1 = d2; d2 = t;
6261: }
6262: l = nd_nvar+31;
6263: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
6264: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
6265: u = d1[i];
6266: k = (nd_epw-1)*nd_bpe;
6267: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
6268: t[ind] = (u>>k)&nd_mask0;
6269: }
6270: for ( ; ind < l; ind++ ) t[ind] = 0;
6271: return t;
6272: }
6273:
6274: UINT *nd_compute_bound(ND p)
6275: {
6276: UINT *d1,*d2,*t;
6277: UINT u;
6278: int i,j,k,l,len,ind;
6279: NM m;
6280:
6281: if ( !p )
6282: return 0;
6283: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6284: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6285: len = LEN(p);
6286: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
6287: for ( m = NEXT(m); m; m = NEXT(m) ) {
6288: ndl_lcm(DL(m),d1,d2);
6289: t = d1; d1 = d2; d2 = t;
6290: }
6291: l = nd_nvar+31;
6292: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
6293: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
6294: u = d1[i];
6295: k = (nd_epw-1)*nd_bpe;
6296: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
6297: t[ind] = (u>>k)&nd_mask0;
6298: }
6299: for ( ; ind < l; ind++ ) t[ind] = 0;
6300: return t;
6301: }
6302:
6303: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
6304: /* of a term. In this case we need additional 1 word. */
6305:
6306: int nd_get_exporigin(struct order_spec *ord)
6307: {
6308: switch ( ord->id ) {
1.21 noro 6309: case 0: case 2: case 256: case 258: case 300:
1.1 noro 6310: return 1+nd_module;
6311: case 1: case 257:
6312: /* block order */
6313: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
6314: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
6315: return ord->ord.block.length+1+nd_module;
6316: case 3: case 259:
6317: #if 0
6318: error("nd_get_exporigin : composite order is not supported yet.");
6319: #else
6320: return 1+nd_module;
6321: #endif
6322: default:
6323: error("nd_get_exporigin : ivalid argument.");
6324: return 0;
6325: }
6326: }
6327:
6328: void nd_setup_parameters(int nvar,int max) {
6329: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
6330: struct order_pair *op;
1.45 noro 6331: extern int CNVars;
1.1 noro 6332:
6333: nd_nvar = nvar;
1.45 noro 6334: CNVars = nvar;
1.1 noro 6335: if ( max ) {
6336: /* XXX */
6337: if ( do_weyl ) nd_bpe = 32;
6338: else if ( max < 2 ) nd_bpe = 1;
6339: else if ( max < 4 ) nd_bpe = 2;
6340: else if ( max < 8 ) nd_bpe = 3;
6341: else if ( max < 16 ) nd_bpe = 4;
6342: else if ( max < 32 ) nd_bpe = 5;
6343: else if ( max < 64 ) nd_bpe = 6;
6344: else if ( max < 256 ) nd_bpe = 8;
6345: else if ( max < 1024 ) nd_bpe = 10;
6346: else if ( max < 65536 ) nd_bpe = 16;
6347: else nd_bpe = 32;
6348: }
6349: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
6350: UINT t;
6351: int st;
6352: int *v;
6353: /* t = max(weights) */
6354: t = 0;
6355: if ( current_dl_weight_vector )
6356: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
6357: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
6358: if ( t < st ) t = st;
6359: }
6360: if ( nd_matrix )
6361: for ( i = 0; i < nd_matrix_len; i++ )
6362: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
6363: if ( (st=v[j]) < 0 ) st = -st;
6364: if ( t < st ) t = st;
6365: }
6366: /* i = bitsize of t */
6367: for ( i = 0; t; t >>=1, i++ );
6368: /* i += bitsize of nd_nvar */
6369: for ( t = nd_nvar; t; t >>=1, i++);
6370: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
6371: if ( (nd_bpe+i) >= 31 )
6372: error("nd_setup_parameters : too large weight");
6373: }
6374: nd_epw = (sizeof(UINT)*8)/nd_bpe;
6375: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
6376: nd_exporigin = nd_get_exporigin(nd_ord);
6377: wpd = nd_exporigin+elen;
6378: if ( nd_module )
6379: nd_mpos = nd_exporigin-1;
6380: else
6381: nd_mpos = -1;
6382: if ( wpd != nd_wpd ) {
6383: nd_free_private_storage();
6384: nd_wpd = wpd;
6385: }
6386: if ( nd_bpe < 32 ) {
6387: nd_mask0 = (1<<nd_bpe)-1;
6388: } else {
6389: nd_mask0 = 0xffffffff;
6390: }
6391: bzero(nd_mask,sizeof(nd_mask));
6392: nd_mask1 = 0;
6393: for ( i = 0; i < nd_epw; i++ ) {
6394: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
6395: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
6396: }
6397: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
6398: nd_epos = nd_create_epos(nd_ord);
6399: nd_blockmask = nd_create_blockmask(nd_ord);
6400: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
6401: }
6402:
6403: ND_pairs nd_reconstruct(int trace,ND_pairs d)
6404: {
6405: int i,obpe,oadv,h;
6406: static NM prev_nm_free_list;
6407: static ND_pairs prev_ndp_free_list;
6408: RHist mr0,mr;
6409: RHist r;
6410: RHist *old_red;
6411: ND_pairs s0,s,t;
6412: EPOS oepos;
6413:
6414: obpe = nd_bpe;
6415: oadv = nmv_adv;
6416: oepos = nd_epos;
6417: if ( obpe < 2 ) nd_bpe = 2;
6418: else if ( obpe < 3 ) nd_bpe = 3;
6419: else if ( obpe < 4 ) nd_bpe = 4;
6420: else if ( obpe < 5 ) nd_bpe = 5;
6421: else if ( obpe < 6 ) nd_bpe = 6;
6422: else if ( obpe < 8 ) nd_bpe = 8;
6423: else if ( obpe < 10 ) nd_bpe = 10;
6424: else if ( obpe < 16 ) nd_bpe = 16;
6425: else if ( obpe < 32 ) nd_bpe = 32;
6426: else error("nd_reconstruct : exponent too large");
6427:
6428: nd_setup_parameters(nd_nvar,0);
6429: prev_nm_free_list = _nm_free_list;
6430: prev_ndp_free_list = _ndp_free_list;
6431: _nm_free_list = 0;
6432: _ndp_free_list = 0;
6433: for ( i = nd_psn-1; i >= 0; i-- ) {
6434: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6435: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6436: }
6437: if ( trace )
6438: for ( i = nd_psn-1; i >= 0; i-- ) {
6439: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6440: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6441: }
6442: s0 = 0;
6443: for ( t = d; t; t = NEXT(t) ) {
6444: NEXTND_pairs(s0,s);
6445: s->i1 = t->i1;
6446: s->i2 = t->i2;
1.24 noro 6447: s->sig = t->sig;
1.1 noro 6448: SG(s) = SG(t);
6449: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6450: }
6451:
6452: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6453: for ( i = 0; i < REDTAB_LEN; i++ ) {
6454: old_red[i] = nd_red[i];
6455: nd_red[i] = 0;
6456: }
6457: for ( i = 0; i < REDTAB_LEN; i++ )
6458: for ( r = old_red[i]; r; r = NEXT(r) ) {
6459: NEWRHist(mr);
6460: mr->index = r->index;
6461: SG(mr) = SG(r);
6462: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6463: h = ndl_hash_value(DL(mr));
6464: NEXT(mr) = nd_red[h];
6465: nd_red[h] = mr;
1.24 noro 6466: mr->sig = r->sig;
1.1 noro 6467: }
6468: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6469: old_red = 0;
6470: for ( i = 0; i < nd_psn; i++ ) {
6471: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6472: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 6473: r->sig = nd_psh[i]->sig;
1.1 noro 6474: nd_psh[i] = r;
6475: }
6476: if ( s0 ) NEXT(s) = 0;
6477: prev_nm_free_list = 0;
6478: prev_ndp_free_list = 0;
6479: #if 0
6480: GC_gcollect();
6481: #endif
6482: return s0;
6483: }
6484:
1.30 noro 6485: void nd_reconstruct_s(int trace,ND_pairs *d)
6486: {
6487: int i,obpe,oadv,h;
6488: static NM prev_nm_free_list;
6489: static ND_pairs prev_ndp_free_list;
6490: RHist mr0,mr;
6491: RHist r;
6492: RHist *old_red;
6493: ND_pairs s0,s,t;
6494: EPOS oepos;
6495:
6496: obpe = nd_bpe;
6497: oadv = nmv_adv;
6498: oepos = nd_epos;
6499: if ( obpe < 2 ) nd_bpe = 2;
6500: else if ( obpe < 3 ) nd_bpe = 3;
6501: else if ( obpe < 4 ) nd_bpe = 4;
6502: else if ( obpe < 5 ) nd_bpe = 5;
6503: else if ( obpe < 6 ) nd_bpe = 6;
6504: else if ( obpe < 8 ) nd_bpe = 8;
6505: else if ( obpe < 10 ) nd_bpe = 10;
6506: else if ( obpe < 16 ) nd_bpe = 16;
6507: else if ( obpe < 32 ) nd_bpe = 32;
6508: else error("nd_reconstruct_s : exponent too large");
6509:
6510: nd_setup_parameters(nd_nvar,0);
6511: prev_nm_free_list = _nm_free_list;
6512: prev_ndp_free_list = _ndp_free_list;
6513: _nm_free_list = 0;
6514: _ndp_free_list = 0;
6515: for ( i = nd_psn-1; i >= 0; i-- ) {
6516: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6517: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6518: }
6519: if ( trace )
6520: for ( i = nd_psn-1; i >= 0; i-- ) {
6521: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6522: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6523: }
6524:
6525: for ( i = 0; i < nd_nbase; i++ ) {
6526: s0 = 0;
6527: for ( t = d[i]; t; t = NEXT(t) ) {
6528: NEXTND_pairs(s0,s);
6529: s->i1 = t->i1;
6530: s->i2 = t->i2;
6531: s->sig = t->sig;
6532: SG(s) = SG(t);
6533: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6534: }
1.47 noro 6535: if ( s0 ) NEXT(s) = 0;
1.30 noro 6536: d[i] = s0;
6537: }
6538:
6539: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6540: for ( i = 0; i < REDTAB_LEN; i++ ) {
6541: old_red[i] = nd_red[i];
6542: nd_red[i] = 0;
6543: }
6544: for ( i = 0; i < REDTAB_LEN; i++ )
6545: for ( r = old_red[i]; r; r = NEXT(r) ) {
6546: NEWRHist(mr);
6547: mr->index = r->index;
6548: SG(mr) = SG(r);
6549: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6550: h = ndl_hash_value(DL(mr));
6551: NEXT(mr) = nd_red[h];
6552: nd_red[h] = mr;
6553: mr->sig = r->sig;
6554: }
6555: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6556: old_red = 0;
6557: for ( i = 0; i < nd_psn; i++ ) {
6558: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6559: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
6560: r->sig = nd_psh[i]->sig;
6561: nd_psh[i] = r;
6562: }
6563: if ( s0 ) NEXT(s) = 0;
6564: prev_nm_free_list = 0;
6565: prev_ndp_free_list = 0;
6566: #if 0
6567: GC_gcollect();
6568: #endif
6569: }
6570:
1.1 noro 6571: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
6572: {
6573: int n,i,ei,oepw,omask0,j,s,ord_l,l;
6574: struct order_pair *op;
6575:
6576: n = nd_nvar;
6577: oepw = (sizeof(UINT)*8)/obpe;
6578: omask0 = (1<<obpe)-1;
6579: TD(r) = TD(d);
6580: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
6581: if ( nd_blockmask ) {
6582: l = nd_blockmask->n;
6583: op = nd_blockmask->order_pair;
6584: for ( i = 1; i < nd_exporigin; i++ )
6585: r[i] = d[i];
6586: for ( j = 0, s = 0; j < l; j++ ) {
6587: ord_l = op[j].length;
6588: for ( i = 0; i < ord_l; i++, s++ ) {
6589: ei = GET_EXP_OLD(d,s);
6590: PUT_EXP(r,s,ei);
6591: }
6592: }
6593: } else {
6594: for ( i = 0; i < n; i++ ) {
6595: ei = GET_EXP_OLD(d,i);
6596: PUT_EXP(r,i,ei);
6597: }
6598: }
6599: if ( nd_module ) MPOS(r) = MPOS(d);
6600: }
6601:
6602: ND nd_copy(ND p)
6603: {
6604: NM m,mr,mr0;
6605: int c,n;
6606: ND r;
6607:
6608: if ( !p )
6609: return 0;
6610: else {
6611: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
6612: NEXTNM(mr0,mr);
6613: CM(mr) = CM(m);
6614: ndl_copy(DL(m),DL(mr));
6615: }
6616: NEXT(mr) = 0;
6617: MKND(NV(p),mr0,LEN(p),r);
6618: SG(r) = SG(p);
6619: return r;
6620: }
6621: }
6622:
6623: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
6624: {
6625: NM m1,m2;
6626: NDV p1,p2;
6627: ND t1,t2;
6628: UINT *lcm;
6629: P gp,tp;
6630: Z g,t;
6631: Z iq;
6632: int td;
6633: LIST hist;
6634: NODE node;
6635: DP d;
6636:
6637: if ( !mod && nd_demand ) {
6638: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
6639: } else {
6640: if ( trace ) {
6641: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
6642: } else {
6643: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
6644: }
6645: }
6646: lcm = LCM(p);
6647: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
6648: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
6649: FREENM(m1); return 0;
6650: }
6651: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
6652: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
6653: FREENM(m1); FREENM(m2); return 0;
6654: }
6655:
6656: if ( mod == -1 ) {
6657: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
6658: } else if ( mod > 0 ) {
6659: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
6660: } else if ( mod == -2 ) {
6661: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
6662: } else if ( nd_vc ) {
6663: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
6664: divsp(nd_vc,HCP(p2),gp,&CP(m1));
6665: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
6666: } else {
1.6 noro 6667: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 6668: }
6669: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
6670: *rp = nd_add(mod,t1,t2);
6671: if ( nd_gentrace ) {
6672: /* nd_tracelist is initialized */
1.6 noro 6673: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6674: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 6675: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6676: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
6677: nd_tracelist = node;
6678: }
1.24 noro 6679: if ( *rp )
6680: (*rp)->sig = p->sig;
1.1 noro 6681: FREENM(m1); FREENM(m2);
6682: return 1;
6683: }
6684:
6685: void ndv_mul_c(int mod,NDV p,int mul)
6686: {
6687: NMV m;
6688: int c,c1,len,i;
6689:
6690: if ( !p ) return;
6691: len = LEN(p);
6692: if ( mod == -1 )
6693: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
6694: CM(m) = _mulsf(CM(m),mul);
6695: else
6696: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6697: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6698: }
6699: }
6700:
6701: void ndv_mul_c_lf(NDV p,Z mul)
6702: {
6703: NMV m;
6704: Z c;
6705: int len,i;
6706:
6707: if ( !p ) return;
6708: len = LEN(p);
6709: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6710: mullf(CZ(m),mul,&c); CZ(m) = c;
6711: }
6712: }
6713:
6714: /* for nd_det */
6715: void ndv_mul_c_q(NDV p,Z mul)
6716: {
6717: NMV m;
6718: Z c;
6719: int len,i;
6720:
6721: if ( !p ) return;
6722: len = LEN(p);
6723: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 6724: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 6725: }
6726: }
6727:
6728: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
6729: int n2,i,j,l,n,tlen;
6730: UINT *d0;
6731: NM *tab,*psum;
6732: ND s,r;
6733: NM t;
6734: NMV m1;
6735:
6736: if ( !p ) return 0;
6737: n = NV(p); n2 = n>>1;
6738: d0 = DL(m0);
6739: l = LEN(p);
6740: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
6741: tab = (NM *)MALLOC(tlen*sizeof(NM));
6742: psum = (NM *)MALLOC(tlen*sizeof(NM));
6743: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
6744: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
6745: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
6746: /* m0(NM) * m1(NMV) => tab(NM) */
6747: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
6748: for ( j = 0; j < tlen; j++ ) {
6749: if ( tab[j] ) {
6750: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
6751: }
6752: }
6753: }
6754: for ( i = tlen-1, r = 0; i >= 0; i-- )
6755: if ( psum[i] ) {
6756: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
6757: MKND(n,psum[i],j,s);
6758: r = nd_add(mod,r,s);
6759: }
6760: if ( r ) SG(r) = SG(p)+TD(d0);
6761: return r;
6762: }
6763:
6764: /* product of monomials */
6765: /* XXX block order is not handled correctly */
6766:
6767: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
6768: {
6769: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
6770: UINT *d0,*d1,*d,*dt,*ctab;
6771: Z *ctab_q;
6772: Z q,q1;
6773: UINT c0,c1,c;
6774: NM *p;
6775: NM m,t;
6776: int mpos;
6777:
6778: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
6779: if ( !m0 || !m1 ) return;
6780: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
6781: if ( nd_module )
6782: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
6783:
6784: NEWNM(m); d = DL(m);
6785: if ( mod ) {
6786: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
6787: } else if ( nd_vc )
6788: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
6789: else
1.6 noro 6790: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 6791: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
6792: homo = n&1 ? 1 : 0;
6793: if ( homo ) {
6794: /* offset of h-degree */
6795: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
6796: PUT_EXP(DL(m),n-1,h);
6797: TD(DL(m)) = h;
6798: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6799: }
6800: tab[0] = m;
6801: NEWNM(m); d = DL(m);
6802: for ( i = 0, curlen = 1; i < n2; i++ ) {
6803: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
6804: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
6805: /* xi^a*(Di^k*xi^l)*Di^b */
6806: a += l; b += k;
6807: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
6808: if ( !k || !l ) {
6809: for ( j = 0; j < curlen; j++ )
6810: if ( (t = tab[j]) != 0 ) {
6811: dt = DL(t);
6812: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
6813: if ( nd_blockmask ) ndl_weight_mask(dt);
6814: }
6815: curlen *= k+1;
6816: continue;
6817: }
6818: min = MIN(k,l);
6819: if ( mod ) {
6820: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
6821: mkwcm(k,l,mod,(int *)ctab);
6822: } else {
6823: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
6824: mkwc(k,l,ctab_q);
6825: }
6826: for ( j = min; j >= 0; j-- ) {
6827: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
6828: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
6829: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
6830: if ( homo ) {
6831: TD(d) = s;
6832: PUT_EXP(d,n-1,s-h);
6833: } else TD(d) = h;
6834: if ( nd_blockmask ) ndl_weight_mask(d);
6835: if ( mod ) c = ctab[j];
6836: else q = ctab_q[j];
6837: p = tab+curlen*j;
6838: if ( j == 0 ) {
6839: for ( u = 0; u < curlen; u++, p++ ) {
6840: if ( tab[u] ) {
6841: ndl_addto(DL(tab[u]),d);
6842: if ( mod ) {
6843: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
6844: } else if ( nd_vc )
6845: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
6846: else {
1.6 noro 6847: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 6848: }
6849: }
6850: }
6851: } else {
6852: for ( u = 0; u < curlen; u++, p++ ) {
6853: if ( tab[u] ) {
6854: NEWNM(t);
6855: ndl_add(DL(tab[u]),d,DL(t));
6856: if ( mod ) {
6857: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
6858: } else if ( nd_vc )
6859: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
6860: else
1.6 noro 6861: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 6862: *p = t;
6863: }
6864: }
6865: }
6866: }
6867: curlen *= k+1;
6868: }
6869: FREENM(m);
6870: if ( nd_module ) {
6871: mpos = MPOS(d1);
6872: for ( i = 0; i < tlen; i++ )
6873: if ( tab[i] ) {
6874: d = DL(tab[i]);
6875: MPOS(d) = mpos;
6876: TD(d) = ndl_weight(d);
6877: }
6878: }
6879: }
6880:
6881: ND ndv_mul_nm_symbolic(NM m0,NDV p)
6882: {
6883: NM mr,mr0;
6884: NMV m;
6885: UINT *d,*dt,*dm;
6886: int c,n,td,i,c1,c2,len;
6887: Q q;
6888: ND r;
6889:
6890: if ( !p ) return 0;
6891: else {
6892: n = NV(p); m = BDY(p);
6893: d = DL(m0);
6894: len = LEN(p);
6895: mr0 = 0;
6896: td = TD(d);
6897: c = CM(m0);
6898: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6899: NEXTNM(mr0,mr);
6900: CM(mr) = 1;
6901: ndl_add(DL(m),d,DL(mr));
6902: }
6903: NEXT(mr) = 0;
6904: MKND(NV(p),mr0,len,r);
6905: SG(r) = SG(p) + TD(d);
6906: return r;
6907: }
6908: }
6909:
6910: ND ndv_mul_nm(int mod,NM m0,NDV p)
6911: {
6912: NM mr,mr0;
6913: NMV m;
6914: UINT *d,*dt,*dm;
6915: int c,n,td,i,c1,c2,len;
6916: P q;
6917: ND r;
6918:
6919: if ( !p ) return 0;
6920: else if ( do_weyl ) {
6921: if ( mod < 0 ) {
6922: error("ndv_mul_nm : not implemented (weyl)");
6923: return 0;
6924: } else
6925: return weyl_ndv_mul_nm(mod,m0,p);
6926: } else {
6927: n = NV(p); m = BDY(p);
6928: d = DL(m0);
6929: len = LEN(p);
6930: mr0 = 0;
6931: td = TD(d);
6932: if ( mod == -1 ) {
6933: c = CM(m0);
6934: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6935: NEXTNM(mr0,mr);
6936: CM(mr) = _mulsf(CM(m),c);
6937: ndl_add(DL(m),d,DL(mr));
6938: }
6939: } else if ( mod == -2 ) {
6940: Z cl;
6941: cl = CZ(m0);
6942: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6943: NEXTNM(mr0,mr);
6944: mullf(CZ(m),cl,&CZ(mr));
6945: ndl_add(DL(m),d,DL(mr));
6946: }
6947: } else if ( mod ) {
6948: c = CM(m0);
6949: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6950: NEXTNM(mr0,mr);
6951: c1 = CM(m);
6952: DMAR(c1,c,0,mod,c2);
6953: CM(mr) = c2;
6954: ndl_add(DL(m),d,DL(mr));
6955: }
6956: } else {
6957: q = CP(m0);
6958: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6959: NEXTNM(mr0,mr);
6960: mulp(nd_vc,CP(m),q,&CP(mr));
6961: ndl_add(DL(m),d,DL(mr));
6962: }
6963: }
6964: NEXT(mr) = 0;
6965: MKND(NV(p),mr0,len,r);
6966: SG(r) = SG(p) + TD(d);
6967: return r;
6968: }
6969: }
6970:
6971: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
6972: {
6973: NM mq0,mq;
6974: NMV tm;
6975: Q q;
6976: int i,nv,sg,c,c1,c2,hindex;
6977: ND p,t,r;
6978:
6979: if ( bucket->m < 0 ) return 0;
6980: else {
6981: nv = NV(d);
6982: mq0 = 0;
6983: tm = (NMV)MALLOC(nmv_adv);
6984: while ( 1 ) {
6985: if ( mod > 0 || mod == -1 )
6986: hindex = head_pbucket(mod,bucket);
6987: else if ( mod == -2 )
6988: hindex = head_pbucket_lf(bucket);
6989: else
6990: hindex = head_pbucket_q(bucket);
6991: if ( hindex < 0 ) break;
6992: p = bucket->body[hindex];
6993: NEXTNM(mq0,mq);
6994: ndl_sub(HDL(p),HDL(d),DL(mq));
6995: ndl_copy(DL(mq),DL(tm));
6996: if ( mod ) {
6997: c1 = invm(HCM(d),mod); c2 = HCM(p);
6998: DMAR(c1,c2,0,mod,c); CM(mq) = c;
6999: CM(tm) = mod-c;
7000: } else {
1.6 noro 7001: divsz(HCZ(p),HCZ(d),&CZ(mq));
7002: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 7003: }
7004: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
7005: bucket->body[hindex] = nd_remove_head(p);
7006: t = nd_remove_head(t);
7007: add_pbucket(mod,bucket,t);
7008: }
7009: if ( !mq0 )
7010: r = 0;
7011: else {
7012: NEXT(mq) = 0;
7013: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
7014: MKND(nv,mq0,i,r);
7015: /* XXX */
7016: SG(r) = HTD(r);
7017: }
7018: return r;
7019: }
7020: }
7021:
7022: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
7023: {
7024: NMV m,mr,mr0,t;
7025: int len,i,k;
7026:
7027: if ( !p ) return;
7028: m = BDY(p); len = LEN(p);
7029: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
7030: m = (NMV)((char *)mr0+(len-1)*oadv);
7031: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
7032: t = (NMV)MALLOC(nmv_adv);
7033: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 7034: CZ(t) = CZ(m);
1.1 noro 7035: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
7036: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 7037: CZ(mr) = CZ(t);
1.1 noro 7038: ndl_copy(DL(t),DL(mr));
7039: }
7040: BDY(p) = mr0;
7041: }
7042:
7043: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
7044: {
7045: NMV m,mr,mr0;
7046: int len,i;
7047: NDV r;
7048:
7049: if ( !p ) return 0;
7050: m = BDY(p); len = LEN(p);
7051: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
7052: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
7053: ndl_zero(DL(mr));
7054: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 7055: CZ(mr) = CZ(m);
1.1 noro 7056: }
7057: MKNDV(NV(p),mr0,len,r);
7058: SG(r) = SG(p);
1.24 noro 7059: r->sig = p->sig;
1.1 noro 7060: return r;
7061: }
7062:
7063: /* duplicate p */
7064:
7065: NDV ndv_dup(int mod,NDV p)
7066: {
7067: NDV d;
7068: NMV t,m,m0;
7069: int i,len;
7070:
7071: if ( !p ) return 0;
7072: len = LEN(p);
7073: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
7074: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
7075: ndl_copy(DL(t),DL(m));
1.6 noro 7076: CZ(m) = CZ(t);
1.1 noro 7077: }
7078: MKNDV(NV(p),m0,len,d);
7079: SG(d) = SG(p);
7080: return d;
7081: }
7082:
7083: NDV ndv_symbolic(int mod,NDV p)
7084: {
7085: NDV d;
7086: NMV t,m,m0;
7087: int i,len;
7088:
7089: if ( !p ) return 0;
7090: len = LEN(p);
7091: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
7092: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
7093: ndl_copy(DL(t),DL(m));
1.6 noro 7094: CZ(m) = ONE;
1.1 noro 7095: }
7096: MKNDV(NV(p),m0,len,d);
7097: SG(d) = SG(p);
7098: return d;
7099: }
7100:
7101: ND nd_dup(ND p)
7102: {
7103: ND d;
7104: NM t,m,m0;
7105:
7106: if ( !p ) return 0;
7107: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
7108: NEXTNM(m0,m);
7109: ndl_copy(DL(t),DL(m));
1.6 noro 7110: CZ(m) = CZ(t);
1.1 noro 7111: }
7112: if ( m0 ) NEXT(m) = 0;
7113: MKND(NV(p),m0,LEN(p),d);
7114: SG(d) = SG(p);
7115: return d;
7116: }
7117:
7118: /* XXX if p->len == 0 then it represents 0 */
7119:
7120: void ndv_mod(int mod,NDV p)
7121: {
7122: NMV t,d;
7123: int r,s,u;
7124: int i,len,dlen;
7125: P cp;
7126: Z c;
7127: Obj gfs;
7128:
7129: if ( !p ) return;
7130: len = LEN(p);
7131: dlen = 0;
7132: if ( mod == -1 )
7133: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7134: simp_ff((Obj)CP(t),&gfs);
7135: if ( gfs ) {
7136: r = FTOIF(CONT((GFS)gfs));
7137: CM(d) = r;
7138: ndl_copy(DL(t),DL(d));
7139: NMV_ADV(d);
7140: dlen++;
7141: }
7142: }
7143: else if ( mod == -2 )
7144: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7145: simp_ff((Obj)CP(t),&gfs);
7146: if ( gfs ) {
7147: lmtolf((LM)gfs,&CZ(d));
7148: ndl_copy(DL(t),DL(d));
7149: NMV_ADV(d);
7150: dlen++;
7151: }
7152: }
7153: else
7154: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
7155: if ( nd_vc ) {
7156: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
7157: c = (Z)cp;
7158: } else
1.6 noro 7159: c = CZ(t);
1.1 noro 7160: r = remqi((Q)c,mod);
7161: if ( r ) {
7162: CM(d) = r;
7163: ndl_copy(DL(t),DL(d));
7164: NMV_ADV(d);
7165: dlen++;
7166: }
7167: }
7168: LEN(p) = dlen;
7169: }
7170:
7171: NDV ptondv(VL vl,VL dvl,P p)
7172: {
7173: ND nd;
7174:
7175: nd = ptond(vl,dvl,p);
7176: return ndtondv(0,nd);
7177: }
7178:
7179: void pltozpl(LIST l,Q *cont,LIST *pp)
7180: {
1.16 noro 7181: NODE nd,nd1;
7182: int n;
7183: P *pl;
7184: Q *cl;
7185: int i;
7186: P dmy;
7187: Z dvr,inv;
7188: LIST r;
7189:
7190: nd = BDY(l); n = length(nd);
7191: pl = (P *)MALLOC(n*sizeof(P));
7192: cl = (Q *)MALLOC(n*sizeof(Q));
7193: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
7194: ptozp((P)BDY(nd),1,&cl[i],&dmy);
7195: }
7196: qltozl(cl,n,&dvr);
7197: divz(ONE,dvr,&inv);
7198: nd = BDY(l);
7199: for ( i = 0; i < n; i++, nd = NEXT(nd) )
7200: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
7201: nd = 0;
7202: for ( i = n-1; i >= 0; i-- ) {
7203: MKNODE(nd1,pl[i],nd); nd = nd1;
7204: }
7205: MKLIST(r,nd);
7206: *pp = r;
1.1 noro 7207: }
7208:
7209: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
7210:
7211: NDV pltondv(VL vl,VL dvl,LIST p)
7212: {
7213: int i;
7214: NODE t;
7215: ND r,ri;
7216: NM m;
7217:
7218: if ( !nd_module ) error("pltond : module order must be set");
7219: r = 0;
7220: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
7221: ri = ptond(vl,dvl,(P)BDY(t));
7222: if ( ri )
7223: for ( m = BDY(ri); m; m = NEXT(m) ) {
7224: MPOS(DL(m)) = i;
7225: TD(DL(m)) = ndl_weight(DL(m));
7226: if ( nd_blockmask ) ndl_weight_mask(DL(m));
7227: }
7228: r = nd_add(0,r,ri);
7229: }
7230: return ndtondv(0,r);
7231: }
7232:
7233: ND ptond(VL vl,VL dvl,P p)
7234: {
7235: int n,i,j,k,e;
7236: VL tvl;
7237: V v;
7238: DCP dc;
7239: DCP *w;
7240: ND r,s,t,u;
7241: P x;
7242: int c;
7243: UINT *d;
7244: NM m,m0;
7245:
7246: if ( !p )
7247: return 0;
7248: else if ( NUM(p) ) {
7249: NEWNM(m);
7250: ndl_zero(DL(m));
1.48 noro 7251: if ( RATN(p) && !INT((Q)p) )
1.1 noro 7252: error("ptond : input must be integer-coefficient");
1.6 noro 7253: CZ(m) = (Z)p;
1.1 noro 7254: NEXT(m) = 0;
7255: MKND(nd_nvar,m,1,r);
7256: SG(r) = 0;
7257: return r;
7258: } else {
7259: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
7260: w = (DCP *)MALLOC(k*sizeof(DCP));
7261: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
7262: for ( i = 0, tvl = dvl, v = VR(p);
7263: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
7264: if ( !tvl ) {
7265: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
7266: t = ptond(vl,dvl,COEF(w[j]));
7267: pwrp(vl,x,DEG(w[j]),&p);
7268: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
7269: }
7270: return s;
7271: } else {
7272: NEWNM(m0); d = DL(m0);
7273: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 7274: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 7275: TD(d) = MUL_WEIGHT(e,i);
7276: if ( nd_blockmask) ndl_weight_mask(d);
7277: if ( nd_module ) MPOS(d) = 0;
7278: t = ptond(vl,dvl,COEF(w[j]));
7279: for ( m = BDY(t); m; m = NEXT(m) )
7280: ndl_addto(DL(m),d);
7281: SG(t) += TD(d);
7282: s = nd_add(0,s,t);
7283: }
7284: FREENM(m0);
7285: return s;
7286: }
7287: }
7288: }
7289:
7290: P ndvtop(int mod,VL vl,VL dvl,NDV p)
7291: {
7292: VL tvl;
7293: int len,n,j,i,e;
7294: NMV m;
7295: Z q;
7296: P c;
7297: UINT *d;
7298: P s,r,u,t,w;
7299: GFS gfs;
7300:
7301: if ( !p ) return 0;
7302: else {
7303: len = LEN(p);
7304: n = NV(p);
7305: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7306: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
7307: if ( mod == -1 ) {
7308: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7309: } else if ( mod == -2 ) {
7310: c = (P)CZ(m);
7311: } else if ( mod > 0 ) {
1.6 noro 7312: STOZ(CM(m),q); c = (P)q;
1.1 noro 7313: } else
7314: c = CP(m);
7315: d = DL(m);
7316: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7317: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7318: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7319: }
7320: addp(vl,s,t,&u); s = u;
7321: }
7322: return s;
7323: }
7324: }
7325:
7326: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
7327: {
7328: VL tvl;
7329: int len,n,j,i,e;
7330: NMV m;
7331: Z q;
7332: P c;
7333: UINT *d;
7334: P s,r,u,t,w;
7335: GFS gfs;
7336: P *a;
7337: LIST l;
7338: NODE nd,nd1;
7339:
7340: if ( !p ) return 0;
7341: else {
7342: a = (P *)MALLOC((rank+1)*sizeof(P));
7343: for ( i = 0; i <= rank; i++ ) a[i] = 0;
7344: len = LEN(p);
7345: n = NV(p);
7346: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7347: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
7348: if ( mod == -1 ) {
7349: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7350: } else if ( mod ) {
1.6 noro 7351: STOZ(CM(m),q); c = (P)q;
1.1 noro 7352: } else
7353: c = CP(m);
7354: d = DL(m);
7355: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7356: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7357: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7358: }
7359: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
7360: }
7361: nd = 0;
7362: for ( i = rank; i > 0; i-- ) {
7363: MKNODE(nd1,a[i],nd); nd = nd1;
7364: }
7365: MKLIST(l,nd);
7366: return l;
7367: }
7368: }
7369:
7370: NDV ndtondv(int mod,ND p)
7371: {
7372: NDV d;
7373: NMV m,m0;
7374: NM t;
7375: int i,len;
7376:
7377: if ( !p ) return 0;
7378: len = LEN(p);
7379: if ( mod > 0 || mod == -1 )
7380: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7381: else
7382: m0 = m = MALLOC(len*nmv_adv);
7383: #if 0
7384: ndv_alloc += nmv_adv*len;
7385: #endif
7386: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
7387: ndl_copy(DL(t),DL(m));
1.6 noro 7388: CZ(m) = CZ(t);
1.1 noro 7389: }
7390: MKNDV(NV(p),m0,len,d);
7391: SG(d) = SG(p);
1.24 noro 7392: d->sig = p->sig;
1.1 noro 7393: return d;
7394: }
7395:
1.16 noro 7396: static int dmm_comp_nv;
7397:
7398: int dmm_comp(DMM *a,DMM *b)
7399: {
7400: return -compdmm(dmm_comp_nv,*a,*b);
7401: }
7402:
7403: void dmm_sort_by_ord(DMM *a,int len,int nv)
7404: {
7405: dmm_comp_nv = nv;
7406: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
7407: }
7408:
7409: void dpm_sort(DPM p,DPM *rp)
7410: {
7411: DMM t,t1;
7412: int len,i,n;
7413: DMM *a;
7414: DPM d;
7415:
7416: if ( !p ) *rp = 0;
7417: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7418: a = (DMM *)MALLOC(len*sizeof(DMM));
7419: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7420: n = p->nv;
7421: dmm_sort_by_ord(a,len,n);
7422: t = 0;
7423: for ( i = len-1; i >= 0; i-- ) {
7424: NEWDMM(t1);
7425: t1->c = a[i]->c;
7426: t1->dl = a[i]->dl;
7427: t1->pos = a[i]->pos;
7428: t1->next = t;
7429: t = t1;
7430: }
7431: MKDPM(n,t,d);
7432: SG(d) = SG(p);
7433: *rp = d;
7434: }
7435:
1.18 noro 7436: int dpm_comp(DPM *a,DPM *b)
7437: {
1.22 noro 7438: return -compdpm(CO,*a,*b);
1.18 noro 7439: }
7440:
7441: NODE dpm_sort_list(NODE l)
7442: {
7443: int i,len;
7444: NODE t,t1;
7445: DPM *a;
7446:
7447: len = length(l);
7448: a = (DPM *)MALLOC(len*sizeof(DPM));
7449: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
7450: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
7451: t = 0;
7452: for ( i = len-1; i >= 0; i-- ) {
7453: MKNODE(t1,(pointer)a[i],t); t = t1;
7454: }
7455: return t;
7456: }
7457:
1.20 noro 7458: int nmv_comp(NMV a,NMV b)
7459: {
1.21 noro 7460: int t;
7461: t = DL_COMPARE(a->dl,b->dl);
7462: return -t;
1.20 noro 7463: }
7464:
1.43 noro 7465: NDV dptondv(int mod,DP p)
7466: {
7467: NDV d;
7468: NMV m,m0;
7469: MP t;
7470: MP *a;
7471: int i,len,n;
7472:
7473: if ( !p ) return 0;
7474: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7475: n = p->nv;
7476: if ( mod > 0 || mod == -1 )
7477: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7478: else
7479: m0 = m = MALLOC(len*nmv_adv);
7480: for ( i = 0, t = BDY(p); i < len; i++, NMV_ADV(m), t = NEXT(t) ) {
7481: dltondl(n,t->dl,DL(m));
7482: TD(DL(m)) = ndl_weight(DL(m));
7483: CZ(m) = (Z)t->c;
7484: }
7485: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
7486: MKNDV(NV(p),m0,len,d);
7487: SG(d) = SG(p);
7488: return d;
7489: }
7490:
1.16 noro 7491: NDV dpmtondv(int mod,DPM p)
7492: {
7493: NDV d;
7494: NMV m,m0;
7495: DMM t;
7496: DMM *a;
7497: int i,len,n;
7498:
7499: if ( !p ) return 0;
7500: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7501: a = (DMM *)MALLOC(len*sizeof(DMM));
7502: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7503: n = p->nv;
7504: dmm_sort_by_ord(a,len,n);
7505: if ( mod > 0 || mod == -1 )
7506: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7507: else
7508: m0 = m = MALLOC(len*nmv_adv);
7509: #if 0
7510: ndv_alloc += nmv_adv*len;
7511: #endif
7512: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
7513: dltondl(n,a[i]->dl,DL(m));
7514: MPOS(DL(m)) = a[i]->pos;
1.20 noro 7515: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 7516: CZ(m) = (Z)a[i]->c;
7517: }
1.20 noro 7518: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 7519: MKNDV(NV(p),m0,len,d);
7520: SG(d) = SG(p);
7521: return d;
7522: }
7523:
1.1 noro 7524: ND ndvtond(int mod,NDV p)
7525: {
7526: ND d;
7527: NM m,m0;
7528: NMV t;
7529: int i,len;
7530:
7531: if ( !p ) return 0;
7532: m0 = 0;
7533: len = p->len;
7534: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7535: NEXTNM(m0,m);
7536: ndl_copy(DL(t),DL(m));
1.6 noro 7537: CZ(m) = CZ(t);
1.1 noro 7538: }
7539: NEXT(m) = 0;
7540: MKND(NV(p),m0,len,d);
7541: SG(d) = SG(p);
1.28 noro 7542: d->sig = p->sig;
1.1 noro 7543: return d;
7544: }
7545:
7546: DP ndvtodp(int mod,NDV p)
7547: {
7548: MP m,m0;
7549: DP d;
7550: NMV t;
7551: int i,len;
7552:
7553: if ( !p ) return 0;
7554: m0 = 0;
7555: len = p->len;
7556: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7557: NEXTMP(m0,m);
7558: m->dl = ndltodl(nd_nvar,DL(t));
7559: m->c = (Obj)ndctop(mod,t->c);
7560: }
7561: NEXT(m) = 0;
7562: MKDP(nd_nvar,m0,d);
7563: SG(d) = SG(p);
7564: return d;
7565: }
7566:
1.44 noro 7567: DPM sigtodpm(SIG s)
7568: {
7569: DMM m;
7570: DPM d;
7571:
7572: NEWDMM(m);
7573: m->c = (Obj)ONE;
7574: m->dl = s->dl;
7575: m->pos = s->pos+1;
7576: m->next = 0;
7577: MKDPM(nd_nvar,m,d);
7578: SG(d) = s->dl->td;
7579: return d;
7580: }
7581:
1.16 noro 7582: DPM ndvtodpm(int mod,NDV p)
7583: {
7584: DMM m,m0;
7585: DPM d;
7586: NMV t;
7587: int i,len;
7588:
7589: if ( !p ) return 0;
7590: m0 = 0;
7591: len = p->len;
7592: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7593: NEXTDMM(m0,m);
7594: m->dl = ndltodl(nd_nvar,DL(t));
7595: m->c = (Obj)ndctop(mod,t->c);
7596: m->pos = MPOS(DL(t));
7597: }
7598: NEXT(m) = 0;
7599: MKDPM(nd_nvar,m0,d);
7600: SG(d) = SG(p);
7601: return d;
7602: }
7603:
7604:
1.1 noro 7605: DP ndtodp(int mod,ND p)
7606: {
7607: MP m,m0;
7608: DP d;
7609: NM t;
7610: int i,len;
7611:
7612: if ( !p ) return 0;
7613: m0 = 0;
7614: len = p->len;
7615: for ( t = BDY(p); t; t = NEXT(t) ) {
7616: NEXTMP(m0,m);
7617: m->dl = ndltodl(nd_nvar,DL(t));
7618: m->c = (Obj)ndctop(mod,t->c);
7619: }
7620: NEXT(m) = 0;
7621: MKDP(nd_nvar,m0,d);
7622: SG(d) = SG(p);
7623: return d;
7624: }
7625:
7626: void ndv_print(NDV p)
7627: {
7628: NMV m;
7629: int i,len;
7630:
7631: if ( !p ) printf("0\n");
7632: else {
7633: len = LEN(p);
7634: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7635: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 7636: else printf("+%ld*",CM(m));
1.1 noro 7637: ndl_print(DL(m));
7638: }
7639: printf("\n");
7640: }
7641: }
7642:
7643: void ndv_print_q(NDV p)
7644: {
7645: NMV m;
7646: int i,len;
7647:
7648: if ( !p ) printf("0\n");
7649: else {
7650: len = LEN(p);
7651: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7652: printf("+");
1.6 noro 7653: printexpr(CO,(Obj)CZ(m));
1.1 noro 7654: printf("*");
7655: ndl_print(DL(m));
7656: }
7657: printf("\n");
7658: }
7659: }
7660:
7661: NODE ndv_reducebase(NODE x,int *perm)
7662: {
7663: int len,i,j;
7664: NDVI w;
7665: NODE t,t0;
7666:
1.41 noro 7667: if ( nd_norb ) return x;
1.1 noro 7668: len = length(x);
7669: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
7670: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
7671: w[i].p = BDY(t); w[i].i = perm[i];
7672: }
7673: for ( i = 0; i < len; i++ ) {
7674: for ( j = 0; j < i; j++ ) {
7675: if ( w[i].p && w[j].p ) {
7676: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
7677: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
7678: }
7679: }
7680: }
7681: for ( i = j = 0, t0 = 0; i < len; i++ ) {
7682: if ( w[i].p ) {
7683: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
7684: perm[j++] = w[i].i;
7685: }
7686: }
7687: NEXT(t) = 0; x = t0;
7688: return x;
7689: }
7690:
7691: /* XXX incomplete */
7692:
1.21 noro 7693: extern DMMstack dmm_stack;
7694: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 7695:
1.1 noro 7696: void nd_init_ord(struct order_spec *ord)
7697: {
7698: nd_module = (ord->id >= 256);
7699: if ( nd_module ) {
7700: nd_dcomp = -1;
1.21 noro 7701: nd_module_ordtype = ord->module_ordtype;
1.1 noro 7702: nd_pot_nelim = ord->pot_nelim;
7703: nd_poly_weight_len = ord->nv;
7704: nd_poly_weight = ord->top_weight;
7705: nd_module_rank = ord->module_rank;
7706: nd_module_weight = ord->module_top_weight;
7707: }
7708: nd_matrix = 0;
7709: nd_matrix_len = 0;
7710: switch ( ord->id ) {
7711: case 0:
7712: switch ( ord->ord.simple ) {
7713: case 0:
7714: nd_dcomp = 1;
7715: nd_isrlex = 1;
7716: break;
7717: case 1:
7718: nd_dcomp = 1;
7719: nd_isrlex = 0;
7720: break;
7721: case 2:
7722: nd_dcomp = 0;
7723: nd_isrlex = 0;
7724: ndl_compare_function = ndl_lex_compare;
7725: break;
7726: case 11:
7727: /* XXX */
7728: nd_dcomp = 0;
7729: nd_isrlex = 1;
7730: ndl_compare_function = ndl_ww_lex_compare;
7731: break;
7732: default:
7733: error("nd_gr : unsupported order");
7734: }
7735: break;
7736: case 1:
7737: /* block order */
7738: /* XXX */
7739: nd_dcomp = -1;
7740: nd_isrlex = 0;
7741: ndl_compare_function = ndl_block_compare;
7742: break;
7743: case 2:
7744: /* matrix order */
7745: /* XXX */
7746: nd_dcomp = -1;
7747: nd_isrlex = 0;
7748: nd_matrix_len = ord->ord.matrix.row;
7749: nd_matrix = ord->ord.matrix.matrix;
7750: ndl_compare_function = ndl_matrix_compare;
7751: break;
7752: case 3:
7753: /* composite order */
7754: nd_dcomp = -1;
7755: nd_isrlex = 0;
7756: nd_worb_len = ord->ord.composite.length;
7757: nd_worb = ord->ord.composite.w_or_b;
7758: ndl_compare_function = ndl_composite_compare;
7759: break;
7760:
7761: /* module order */
7762: case 256:
7763: switch ( ord->ord.simple ) {
7764: case 0:
1.21 noro 7765: nd_dcomp = 0;
1.1 noro 7766: nd_isrlex = 1;
1.21 noro 7767: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 7768: break;
7769: case 1:
1.21 noro 7770: nd_dcomp = 0;
1.1 noro 7771: nd_isrlex = 0;
7772: ndl_compare_function = ndl_module_glex_compare;
7773: break;
7774: case 2:
1.21 noro 7775: nd_dcomp = 0;
1.1 noro 7776: nd_isrlex = 0;
1.21 noro 7777: ndl_compare_function = ndl_module_compare;
7778: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 7779: break;
7780: default:
1.21 noro 7781: error("nd_init_ord : unsupported order");
1.1 noro 7782: }
7783: break;
7784: case 257:
7785: /* block order */
7786: nd_isrlex = 0;
1.21 noro 7787: ndl_compare_function = ndl_module_compare;
7788: ndl_base_compare_function = ndl_block_compare;
1.1 noro 7789: break;
7790: case 258:
7791: /* matrix order */
7792: nd_isrlex = 0;
7793: nd_matrix_len = ord->ord.matrix.row;
7794: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 7795: ndl_compare_function = ndl_module_compare;
7796: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 7797: break;
7798: case 259:
7799: /* composite order */
7800: nd_isrlex = 0;
7801: nd_worb_len = ord->ord.composite.length;
7802: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 7803: ndl_compare_function = ndl_module_compare;
7804: ndl_base_compare_function = ndl_composite_compare;
7805: break;
7806: case 300:
7807: /* schreyer order */
7808: if ( ord->base->id != 256 )
7809: error("nd_init_ord : unsupported base order");
7810: ndl_compare_function = ndl_module_schreyer_compare;
7811: dmm_stack = ord->dmmstack;
7812: switch ( ord->base->ord.simple ) {
7813: case 0:
7814: nd_isrlex = 1;
7815: ndl_base_compare_function = ndl_glex_compare;
7816: dl_base_compare_function = cmpdl_revgradlex;
7817: break;
7818: case 1:
7819: nd_isrlex = 0;
7820: ndl_base_compare_function = ndl_glex_compare;
7821: dl_base_compare_function = cmpdl_gradlex;
7822: break;
7823: case 2:
7824: nd_isrlex = 0;
7825: ndl_base_compare_function = ndl_lex_compare;
7826: dl_base_compare_function = cmpdl_lex;
7827: break;
7828: default:
7829: error("nd_init_ord : unsupported order");
7830: }
1.1 noro 7831: break;
7832: }
7833: nd_ord = ord;
7834: }
7835:
7836: BlockMask nd_create_blockmask(struct order_spec *ord)
7837: {
7838: int n,i,j,s,l;
7839: UINT *t;
7840: BlockMask bm;
7841:
7842: /* we only create mask table for block order */
7843: if ( ord->id != 1 && ord->id != 257 )
7844: return 0;
7845: n = ord->ord.block.length;
7846: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
7847: bm->n = n;
7848: bm->order_pair = ord->ord.block.order_pair;
7849: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
7850: for ( i = 0, s = 0; i < n; i++ ) {
7851: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
7852: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
7853: l = bm->order_pair[i].length;
7854: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
7855: }
7856: return bm;
7857: }
7858:
7859: EPOS nd_create_epos(struct order_spec *ord)
7860: {
7861: int i,j,l,s,ord_l,ord_o;
7862: EPOS epos;
7863: struct order_pair *op;
7864:
7865: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
7866: switch ( ord->id ) {
1.21 noro 7867: case 0: case 256: case 300:
1.1 noro 7868: if ( nd_isrlex ) {
7869: for ( i = 0; i < nd_nvar; i++ ) {
7870: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
7871: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
7872: }
7873: } else {
7874: for ( i = 0; i < nd_nvar; i++ ) {
7875: epos[i].i = nd_exporigin + i/nd_epw;
7876: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7877: }
7878: }
7879: break;
7880: case 1: case 257:
7881: /* block order */
7882: l = ord->ord.block.length;
7883: op = ord->ord.block.order_pair;
7884: for ( j = 0, s = 0; j < l; j++ ) {
7885: ord_o = op[j].order;
7886: ord_l = op[j].length;
7887: if ( !ord_o )
7888: for ( i = 0; i < ord_l; i++ ) {
7889: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
7890: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
7891: }
7892: else
7893: for ( i = 0; i < ord_l; i++ ) {
7894: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
7895: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
7896: }
7897: s += ord_l;
7898: }
7899: break;
7900: case 2:
7901: /* matrix order */
7902: case 3:
7903: /* composite order */
7904: default:
7905: for ( i = 0; i < nd_nvar; i++ ) {
7906: epos[i].i = nd_exporigin + i/nd_epw;
7907: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7908: }
7909: break;
7910: }
7911: return epos;
7912: }
7913:
7914: /* external interface */
7915:
7916: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
7917: {
7918: NODE t,in0,in;
7919: ND ndf,nf;
7920: NDV ndvf;
7921: VL vv,tv;
7922: int stat,nvar,max,mrank;
7923: union oNDC dn;
7924: Q cont;
7925: P pp;
7926: LIST ppl;
7927:
7928: if ( !f ) {
7929: *rp = 0;
7930: return;
7931: }
7932: pltovl(v,&vv);
7933: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
7934:
7935: /* max=65536 implies nd_bpe=32 */
7936: max = 65536;
7937:
7938: nd_module = 0;
7939: /* nd_module will be set if ord is a module ordering */
7940: nd_init_ord(ord);
7941: nd_setup_parameters(nvar,max);
7942: if ( nd_module && OID(f) != O_LIST )
7943: error("nd_nf_p : the first argument must be a list");
7944: if ( nd_module ) mrank = length(BDY((LIST)f));
7945: /* conversion to ndv */
7946: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
7947: NEXTNODE(in0,in);
7948: if ( nd_module ) {
7949: if ( !BDY(t) || OID(BDY(t)) != O_LIST
7950: || length(BDY((LIST)BDY(t))) != mrank )
7951: error("nd_nf_p : inconsistent basis element");
7952: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
7953: else ppl = (LIST)BDY(t);
7954: BDY(in) = (pointer)pltondv(CO,vv,ppl);
7955: } else {
7956: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
7957: else pp = (P)BDY(t);
7958: BDY(in) = (pointer)ptondv(CO,vv,pp);
7959: }
7960: if ( m ) ndv_mod(m,(NDV)BDY(in));
7961: }
7962: if ( in0 ) NEXT(in) = 0;
7963:
7964: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
7965: else ndvf = ptondv(CO,vv,(P)f);
7966: if ( m ) ndv_mod(m,ndvf);
7967: ndf = (pointer)ndvtond(m,ndvf);
7968:
7969: /* dont sort, dont removecont */
1.24 noro 7970: ndv_setup(m,0,in0,1,1,0);
1.1 noro 7971: nd_scale=2;
1.6 noro 7972: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 7973: if ( !stat )
7974: error("nd_nf_p : exponent too large");
7975: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
7976: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
7977: }
7978:
7979: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
7980: {
7981: NM m;
7982: UINT *t,*s;
7983: int i;
7984:
7985: for ( i = 0; i < n; i++ ) r[i] = 0;
7986: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7987: t = DL(m);
7988: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7989: r[i] = CM(m);
7990: }
7991: for ( i = 0; !r[i]; i++ );
7992: return i;
7993: }
7994:
7995: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
7996: {
7997: NM m;
7998: UINT *t,*s;
7999: int i;
8000:
8001: for ( i = 0; i < n; i++ ) r[i] = 0;
8002: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
8003: t = DL(m);
8004: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 8005: r[i] = CZ(m);
1.1 noro 8006: }
8007: for ( i = 0; !r[i]; i++ );
8008: return i;
8009: }
8010:
8011: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
8012: {
8013: NM m;
8014: UINT *t,*s;
8015: int i;
8016:
8017: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
8018: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
8019: t = DL(m);
8020: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
8021: mpz_set(r[i],BDY(CZ(m)));
8022: }
8023: for ( i = 0; !mpz_sgn(r[i]); i++ );
8024: return i;
8025: }
8026:
8027: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
8028: {
8029: NM m;
8030: unsigned long *v;
8031: int i,j,h,size;
8032: UINT *s,*t;
8033:
8034: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
8035: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
8036: bzero(v,size);
8037: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
8038: t = DL(m);
8039: h = ndl_hash_value(t);
8040: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
8041: v[i/BLEN] |= 1L <<(i%BLEN);
8042: }
8043: return v;
8044: }
8045:
8046: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
8047: {
8048: NMV mr;
8049: UINT *d,*t,*s;
8050: int i,j,len,h,head;
8051:
8052: d = DL(m);
8053: len = LEN(p);
8054: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8055: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
8056: ndl_add(d,DL(mr),t);
8057: h = ndl_hash_value(t);
8058: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
8059: if ( j == 0 ) head = i;
8060: v[i/BLEN] |= 1L <<(i%BLEN);
8061: }
8062: return head;
8063: }
8064:
8065: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
8066: {
8067: NM m;
8068: NMV mr;
8069: UINT *d,*t,*s;
8070: NDV p;
8071: int i,j,len;
8072: Z *r;
8073:
8074: m = pair->mul;
8075: d = DL(m);
8076: p = nd_ps[pair->index];
8077: len = LEN(p);
8078: r = (Z *)CALLOC(n,sizeof(Q));
8079: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8080: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
8081: ndl_add(d,DL(mr),t);
8082: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 8083: r[i] = CZ(mr);
1.1 noro 8084: }
8085: return r;
8086: }
8087:
1.11 noro 8088: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 8089: {
8090: NM m;
8091: NMV mr;
1.11 noro 8092: UINT *d,*t,*s,*u;
1.1 noro 8093: NDV p;
8094: unsigned char *ivc;
8095: unsigned short *ivs;
8096: UINT *v,*ivi,*s0v;
1.11 noro 8097: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 8098: IndArray r;
8099:
8100: m = pair->mul;
8101: d = DL(m);
8102: if ( trace )
8103: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
8104: else
8105: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
8106:
8107: len = LEN(p);
8108: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
8109: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 8110: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
8111: ndl_add(d,DL(mr),t);
8112: st = prev;
8113: ed = n;
8114: while ( ed > st ) {
8115: md = (st+ed)/2;
8116: u = s0+md*nd_wpd;
8117: c = DL_COMPARE(u,t);
8118: if ( c == 0 ) break;
8119: else if ( c > 0 ) st = md;
8120: else ed = md;
8121: }
8122: prev = v[j] = md;
1.1 noro 8123: }
8124: r = (IndArray)MALLOC(sizeof(struct oIndArray));
8125: r->head = v[0];
8126: diff = 0;
8127: for ( i = 1; i < len; i++ ) {
8128: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
8129: }
8130: if ( diff < 256 ) {
8131: r->width = 1;
8132: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
8133: r->index.c = ivc;
8134: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
8135: } else if ( diff < 65536 ) {
8136: r->width = 2;
8137: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
8138: r->index.s = ivs;
8139: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
8140: } else {
8141: r->width = 4;
8142: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
8143: r->index.i = ivi;
8144: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
8145: }
8146: return r;
8147: }
8148:
8149: int compress_array(Z *svect,Z *cvect,int n)
8150: {
8151: int i,j;
8152:
8153: for ( i = j = 0; i < n; i++ )
8154: if ( svect[i] ) cvect[j++] = svect[i];
8155: return j;
8156: }
8157:
8158: void expand_array(Z *svect,Z *cvect,int n)
8159: {
8160: int i,j;
8161:
8162: for ( i = j = 0; j < n; i++ )
8163: if ( svect[i] ) svect[i] = cvect[j++];
8164: }
8165:
1.8 noro 8166: #if 0
1.1 noro 8167: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8168: {
8169: int i,j,k,len,pos,prev,nz;
8170: Z cs,mcs,c1,c2,cr,gcd,t;
8171: IndArray ivect;
8172: unsigned char *ivc;
8173: unsigned short *ivs;
8174: unsigned int *ivi;
8175: NDV redv;
8176: NMV mr;
8177: NODE rp;
8178: int maxrs;
8179: double hmag;
8180: Z *cvect;
1.3 noro 8181: int l;
1.1 noro 8182:
8183: maxrs = 0;
8184: for ( i = 0; i < col && !svect[i]; i++ );
8185: if ( i == col ) return maxrs;
8186: hmag = p_mag((P)svect[i])*nd_scale;
8187: cvect = (Z *)MALLOC(col*sizeof(Q));
8188: for ( i = 0; i < nred; i++ ) {
8189: ivect = imat[i];
8190: k = ivect->head;
8191: if ( svect[k] ) {
8192: maxrs = MAX(maxrs,rp0[i]->sugar);
8193: redv = nd_demand?ndv_load(rp0[i]->index)
8194: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
8195: len = LEN(redv); mr = BDY(redv);
1.6 noro 8196: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 8197: chsgnz(cs,&mcs);
8198: if ( !UNIQ(cr) ) {
8199: for ( j = 0; j < col; j++ ) {
8200: mulz(svect[j],cr,&c1); svect[j] = c1;
8201: }
8202: }
8203: svect[k] = 0; prev = k;
8204: switch ( ivect->width ) {
8205: case 1:
8206: ivc = ivect->index.c;
8207: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8208: pos = prev+ivc[j]; prev = pos;
1.6 noro 8209: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8210: }
8211: break;
8212: case 2:
8213: ivs = ivect->index.s;
8214: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8215: pos = prev+ivs[j]; prev = pos;
1.6 noro 8216: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8217: }
8218: break;
8219: case 4:
8220: ivi = ivect->index.i;
8221: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8222: pos = prev+ivi[j]; prev = pos;
1.6 noro 8223: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 8224: }
8225: break;
8226: }
8227: for ( j = k+1; j < col && !svect[j]; j++ );
8228: if ( j == col ) break;
8229: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
8230: nz = compress_array(svect,cvect,col);
8231: removecont_array((P *)cvect,nz,1);
8232: expand_array(svect,cvect,nz);
8233: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
8234: }
8235: }
8236: }
8237: nz = compress_array(svect,cvect,col);
8238: removecont_array((P *)cvect,nz,1);
8239: expand_array(svect,cvect,nz);
8240: if ( DP_Print ) {
8241: fprintf(asir_out,"-"); fflush(asir_out);
8242: }
8243: return maxrs;
8244: }
1.4 noro 8245: #else
1.9 noro 8246:
1.4 noro 8247: /* direct mpz version */
8248: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8249: {
8250: int i,j,k,len,pos,prev;
8251: mpz_t cs,cr,gcd;
8252: IndArray ivect;
8253: unsigned char *ivc;
8254: unsigned short *ivs;
8255: unsigned int *ivi;
8256: NDV redv;
8257: NMV mr;
8258: NODE rp;
8259: int maxrs;
8260: double hmag;
8261: int l;
1.13 noro 8262: static mpz_t *svect;
8263: static int svect_len=0;
1.4 noro 8264:
8265: maxrs = 0;
8266: for ( i = 0; i < col && !svect0[i]; i++ );
8267: if ( i == col ) return maxrs;
8268: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 8269: if ( col > svect_len ) {
8270: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
8271: svect_len = col;
8272: }
1.4 noro 8273: for ( i = 0; i < col; i++ ) {
8274: mpz_init(svect[i]);
8275: if ( svect0[i] )
8276: mpz_set(svect[i],BDY(svect0[i]));
8277: else
8278: mpz_set_ui(svect[i],0);
8279: }
8280: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
8281: for ( i = 0; i < nred; i++ ) {
8282: ivect = imat[i];
8283: k = ivect->head;
8284: if ( mpz_sgn(svect[k]) ) {
8285: maxrs = MAX(maxrs,rp0[i]->sugar);
8286: redv = nd_demand?ndv_load(rp0[i]->index)
8287: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
8288: len = LEN(redv); mr = BDY(redv);
1.6 noro 8289: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 8290: mpz_div(cs,svect[k],gcd);
1.6 noro 8291: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 8292: mpz_neg(cs,cs);
1.9 noro 8293: if ( MUNIMPZ(cr) )
8294: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
8295: else if ( !UNIMPZ(cr) )
8296: for ( j = 0; j < col; j++ ) {
8297: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
8298: }
1.4 noro 8299: mpz_set_ui(svect[k],0);
8300: prev = k;
8301: switch ( ivect->width ) {
8302: case 1:
8303: ivc = ivect->index.c;
8304: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8305: pos = prev+ivc[j]; prev = pos;
1.6 noro 8306: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8307: }
8308: break;
8309: case 2:
8310: ivs = ivect->index.s;
8311: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8312: pos = prev+ivs[j]; prev = pos;
1.6 noro 8313: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8314: }
8315: break;
8316: case 4:
8317: ivi = ivect->index.i;
8318: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8319: pos = prev+ivi[j]; prev = pos;
1.6 noro 8320: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8321: }
8322: break;
8323: }
8324: for ( j = k+1; j < col && !svect[j]; j++ );
8325: if ( j == col ) break;
8326: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
8327: mpz_removecont_array(svect,col);
8328: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
8329: }
8330: }
8331: }
8332: mpz_removecont_array(svect,col);
8333: if ( DP_Print ) {
8334: fprintf(asir_out,"-"); fflush(asir_out);
8335: }
8336: for ( i = 0; i < col; i++ )
8337: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
8338: else svect0[i] = 0;
8339: return maxrs;
8340: }
8341: #endif
1.1 noro 8342:
1.40 noro 8343: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.1 noro 8344: {
8345: int i,j,k,len,pos,prev;
8346: UINT c,c1,c2,c3,up,lo,dmy;
8347: IndArray ivect;
8348: unsigned char *ivc;
8349: unsigned short *ivs;
8350: unsigned int *ivi;
8351: NDV redv;
8352: NMV mr;
8353: NODE rp;
8354: int maxrs;
8355:
8356: maxrs = 0;
8357: for ( i = 0; i < nred; i++ ) {
8358: ivect = imat[i];
8359: k = ivect->head; svect[k] %= m;
1.40 noro 8360: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.1 noro 8361: maxrs = MAX(maxrs,rp0[i]->sugar);
8362: c = m-c; redv = nd_ps[rp0[i]->index];
8363: len = LEN(redv); mr = BDY(redv);
8364: svect[k] = 0; prev = k;
8365: switch ( ivect->width ) {
8366: case 1:
8367: ivc = ivect->index.c;
8368: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8369: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.40 noro 8370: if ( c1 ) {
8371: c2 = svect[pos];
1.1 noro 8372: DMA(c1,c,c2,up,lo);
8373: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8374: } else svect[pos] = lo;
1.40 noro 8375: }
1.1 noro 8376: }
8377: break;
8378: case 2:
8379: ivs = ivect->index.s;
8380: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8381: pos = prev+ivs[j]; c1 = CM(mr);
8382: prev = pos;
1.40 noro 8383: if ( c1 ) {
8384: c2 = svect[pos];
1.1 noro 8385: DMA(c1,c,c2,up,lo);
8386: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8387: } else svect[pos] = lo;
1.40 noro 8388: }
1.1 noro 8389: }
8390: break;
8391: case 4:
8392: ivi = ivect->index.i;
8393: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8394: pos = prev+ivi[j]; c1 = CM(mr);
8395: prev = pos;
1.40 noro 8396: if ( c1 ) {
8397: c2 = svect[pos];
1.1 noro 8398: DMA(c1,c,c2,up,lo);
8399: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8400: } else svect[pos] = lo;
1.40 noro 8401: }
1.1 noro 8402: }
8403: break;
8404: }
8405: }
8406: }
8407: for ( i = 0; i < col; i++ )
8408: if ( svect[i] >= (UINT)m ) svect[i] %= m;
8409: return maxrs;
8410: }
8411:
8412: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8413: {
8414: int i,j,k,len,pos,prev;
8415: UINT c,c1,c2,c3,up,lo,dmy;
8416: IndArray ivect;
8417: unsigned char *ivc;
8418: unsigned short *ivs;
8419: unsigned int *ivi;
8420: NDV redv;
8421: NMV mr;
8422: NODE rp;
8423: int maxrs;
8424:
8425: maxrs = 0;
8426: for ( i = 0; i < nred; i++ ) {
8427: ivect = imat[i];
8428: k = ivect->head;
8429: if ( (c = svect[k]) != 0 ) {
8430: maxrs = MAX(maxrs,rp0[i]->sugar);
8431: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
8432: len = LEN(redv); mr = BDY(redv);
8433: svect[k] = 0; prev = k;
8434: switch ( ivect->width ) {
8435: case 1:
8436: ivc = ivect->index.c;
8437: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8438: pos = prev+ivc[j]; prev = pos;
8439: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8440: }
8441: break;
8442: case 2:
8443: ivs = ivect->index.s;
8444: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8445: pos = prev+ivs[j]; prev = pos;
8446: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8447: }
8448: break;
8449: case 4:
8450: ivi = ivect->index.i;
8451: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8452: pos = prev+ivi[j]; prev = pos;
8453: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8454: }
8455: break;
8456: }
8457: }
8458: }
8459: return maxrs;
8460: }
8461:
8462: ND nd_add_lf(ND p1,ND p2)
8463: {
8464: int n,c,can;
8465: ND r;
8466: NM m1,m2,mr0,mr,s;
8467: Z t;
8468:
8469: if ( !p1 ) return p2;
8470: else if ( !p2 ) return p1;
8471: else {
8472: can = 0;
8473: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
8474: c = DL_COMPARE(DL(m1),DL(m2));
8475: switch ( c ) {
8476: case 0:
8477: addlf(CZ(m1),CZ(m2),&t);
8478: s = m1; m1 = NEXT(m1);
8479: if ( t ) {
8480: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
8481: } else {
8482: can += 2; FREENM(s);
8483: }
8484: s = m2; m2 = NEXT(m2); FREENM(s);
8485: break;
8486: case 1:
8487: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
8488: break;
8489: case -1:
8490: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
8491: break;
8492: }
8493: }
8494: if ( !mr0 )
8495: if ( m1 ) mr0 = m1;
8496: else if ( m2 ) mr0 = m2;
8497: else return 0;
8498: else if ( m1 ) NEXT(mr) = m1;
8499: else if ( m2 ) NEXT(mr) = m2;
8500: else NEXT(mr) = 0;
8501: BDY(p1) = mr0;
8502: SG(p1) = MAX(SG(p1),SG(p2));
8503: LEN(p1) = LEN(p1)+LEN(p2)-can;
8504: FREEND(p2);
8505: return p1;
8506: }
8507: }
8508:
8509: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8510: {
8511: int i,j,k,len,pos,prev;
8512: mpz_t c,mc,c1;
8513: IndArray ivect;
8514: unsigned char *ivc;
8515: unsigned short *ivs;
8516: unsigned int *ivi;
8517: NDV redv;
8518: NMV mr;
8519: NODE rp;
8520: int maxrs;
8521:
8522: maxrs = 0;
8523: lf_lazy = 1;
8524: for ( i = 0; i < nred; i++ ) {
8525: ivect = imat[i];
8526: k = ivect->head;
8527: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
8528: if ( mpz_sgn(svect[k]) ) {
8529: maxrs = MAX(maxrs,rp0[i]->sugar);
8530: mpz_neg(svect[k],svect[k]);
8531: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
8532: len = LEN(redv); mr = BDY(redv);
8533: prev = k;
8534: switch ( ivect->width ) {
8535: case 1:
8536: ivc = ivect->index.c;
8537: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8538: pos = prev+ivc[j]; prev = pos;
8539: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8540: }
8541: break;
8542: case 2:
8543: ivs = ivect->index.s;
8544: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8545: pos = prev+ivs[j]; prev = pos;
8546: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8547: }
8548: break;
8549: case 4:
8550: ivi = ivect->index.i;
8551: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8552: pos = prev+ivi[j]; prev = pos;
8553: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8554: }
8555: break;
8556: }
8557: mpz_set_ui(svect[k],0);
8558: }
8559: }
8560: lf_lazy=0;
8561: for ( i = 0; i < col; i++ ) {
8562: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
8563: }
8564: return maxrs;
8565: }
8566:
8567: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
8568: {
8569: int i,j,k,l,rank,s;
8570: mpz_t a,a1,inv;
8571: mpz_t *t,*pivot,*pk;
8572: mpz_t **mat;
8573: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
8574: int size,size1;
8575:
8576: mpz_init(inv);
8577: mpz_init(a);
8578: mat = (mpz_t **)mat0;
8579: size = 0;
8580: for ( rank = 0, j = 0; j < col; j++ ) {
8581: for ( i = rank; i < row; i++ ) {
8582: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
8583: }
8584: for ( i = rank; i < row; i++ )
8585: if ( mpz_sgn(mat[i][j]) )
8586: break;
8587: if ( i == row ) {
8588: colstat[j] = 0;
8589: continue;
8590: } else
8591: colstat[j] = 1;
8592: if ( i != rank ) {
8593: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8594: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8595: }
8596: pivot = mat[rank];
8597: s = sugar[rank];
8598: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
8599: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8600: if ( mpz_sgn(*pk) ) {
8601: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
8602: }
8603: for ( i = rank+1; i < row; i++ ) {
8604: t = mat[i];
8605: if ( mpz_sgn(t[j]) ) {
8606: sugar[i] = MAX(sugar[i],s);
8607: mpz_neg(a,t[j]);
8608: red_by_vect_lf(t+j,pivot+j,a,col-j);
8609: }
8610: }
8611: rank++;
8612: }
8613: for ( j = col-1, l = rank-1; j >= 0; j-- )
8614: if ( colstat[j] ) {
8615: pivot = mat[l];
8616: s = sugar[l];
8617: for ( k = j; k < col; k++ )
8618: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
8619: for ( i = 0; i < l; i++ ) {
8620: t = mat[i];
8621: if ( mpz_sgn(t[j]) ) {
8622: sugar[i] = MAX(sugar[i],s);
8623: mpz_neg(a,t[j]);
8624: red_by_vect_lf(t+j,pivot+j,a,col-j);
8625: }
8626: }
8627: l--;
8628: }
8629: for ( j = 0, l = 0; l < rank; j++ )
8630: if ( colstat[j] ) {
8631: t = mat[l];
8632: for ( k = j; k < col; k++ ) {
8633: mpz_mod(t[k],t[k],BDY(current_mod_lf));
8634: }
8635: l++;
8636: }
8637: return rank;
8638: }
8639:
8640:
8641: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
8642: {
8643: int j,k,len;
8644: UINT *p;
8645: UINT c;
8646: NDV r;
8647: NMV mr0,mr;
8648:
8649: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8650: if ( !len ) return 0;
8651: else {
8652: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8653: #if 0
8654: ndv_alloc += nmv_adv*len;
8655: #endif
8656: mr = mr0;
8657: p = s0vect;
8658: for ( j = k = 0; j < col; j++, p += nd_wpd )
8659: if ( !rhead[j] ) {
8660: if ( (c = vect[k++]) != 0 ) {
8661: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8662: }
8663: }
8664: MKNDV(nd_nvar,mr0,len,r);
8665: return r;
8666: }
8667: }
8668:
1.40 noro 8669: NDV vect_to_ndv_s(UINT *vect,int col,UINT *s0vect)
8670: {
8671: int j,k,len;
8672: UINT *p;
8673: UINT c;
8674: NDV r;
8675: NMV mr0,mr;
8676:
8677: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8678: if ( !len ) return 0;
8679: else {
8680: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8681: mr = mr0;
8682: p = s0vect;
8683: for ( j = k = 0; j < col; j++, p += nd_wpd )
8684: if ( (c = vect[k++]) != 0 ) {
8685: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8686: }
8687: MKNDV(nd_nvar,mr0,len,r);
8688: return r;
8689: }
8690: }
8691:
1.1 noro 8692: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
8693: {
8694: int j,k,len;
8695: UINT *p;
8696: NDV r;
8697: NMV mr0,mr;
8698:
8699: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
8700: if ( !len ) return 0;
8701: else {
8702: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8703: mr = mr0;
8704: p = s0vect;
8705: for ( j = 0; j < col; j++, p += nd_wpd )
8706: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
8707: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
8708: }
8709: MKNDV(nd_nvar,mr0,len,r);
8710: return r;
8711: }
8712: }
8713:
8714: /* for preprocessed vector */
8715:
8716: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
8717: {
1.6 noro 8718: int j,k,len;
8719: UINT *p;
8720: Z c;
8721: NDV r;
8722: NMV mr0,mr;
1.1 noro 8723:
1.6 noro 8724: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8725: if ( !len ) return 0;
8726: else {
8727: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 8728: #if 0
1.6 noro 8729: ndv_alloc += nmv_adv*len;
1.1 noro 8730: #endif
1.6 noro 8731: mr = mr0;
8732: p = s0vect;
8733: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
8734: if ( !rhead[j] ) {
8735: if ( (c = vect[k++]) != 0 ) {
8736: if ( !INT(c) )
8737: error("vect_to_ndv_q : components must be integers");
8738: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
8739: }
8740: }
1.1 noro 8741: }
1.6 noro 8742: MKNDV(nd_nvar,mr0,len,r);
8743: return r;
8744: }
1.1 noro 8745: }
8746:
8747: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
8748: {
8749: int j,k,len;
8750: UINT *p;
8751: mpz_t c;
8752: NDV r;
8753: NMV mr0,mr;
8754:
8755: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
8756: if ( !len ) return 0;
8757: else {
8758: mr0 = (NMV)MALLOC(nmv_adv*len);
8759: #if 0
8760: ndv_alloc += nmv_adv*len;
8761: #endif
8762: mr = mr0;
8763: p = s0vect;
8764: for ( j = k = 0; j < col; j++, p += nd_wpd )
8765: if ( !rhead[j] ) {
8766: c[0] = vect[k++][0];
8767: if ( mpz_sgn(c) ) {
8768: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
8769: }
8770: }
8771: MKNDV(nd_nvar,mr0,len,r);
8772: return r;
8773: }
8774: }
8775:
8776: /* for plain vector */
8777:
8778: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
8779: {
8780: int j,k,len;
8781: UINT *p;
8782: Z c;
8783: NDV r;
8784: NMV mr0,mr;
8785:
8786: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8787: if ( !len ) return 0;
8788: else {
8789: mr0 = (NMV)MALLOC(nmv_adv*len);
8790: #if 0
8791: ndv_alloc += nmv_adv*len;
8792: #endif
8793: mr = mr0;
8794: p = s0vect;
8795: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
8796: if ( (c = vect[k]) != 0 ) {
8797: if ( !INT(c) )
1.6 noro 8798: error("plain_vect_to_ndv_q : components must be integers");
8799: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 8800: }
8801: MKNDV(nd_nvar,mr0,len,r);
8802: return r;
8803: }
8804: }
8805:
8806: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
8807: {
8808: ND_pairs t;
8809: NODE sp0,sp;
8810: int stat;
8811: ND spol;
8812:
8813: for ( t = l; t; t = NEXT(t) ) {
8814: stat = nd_sp(m,trace,t,&spol);
8815: if ( !stat ) return 0;
8816: if ( spol ) {
8817: add_pbucket_symbolic(bucket,spol);
8818: }
8819: }
8820: return 1;
8821: }
8822:
8823: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
8824: {
8825: NODE rp0,rp;
8826: NM mul,head,s0,s;
8827: int index,col,i,sugar;
8828: RHist h;
8829: UINT *s0v,*p;
8830: NM_ind_pair pair;
8831: ND red;
8832: NDV *ps;
8833:
8834: s0 = 0; rp0 = 0; col = 0;
8835: if ( nd_demand )
8836: ps = trace?nd_ps_trace_sym:nd_ps_sym;
8837: else
8838: ps = trace?nd_ps_trace:nd_ps;
8839: while ( 1 ) {
8840: head = remove_head_pbucket_symbolic(bucket);
8841: if ( !head ) break;
8842: if ( !s0 ) s0 = head;
8843: else NEXT(s) = head;
8844: s = head;
8845: index = ndl_find_reducer(DL(head));
8846: if ( index >= 0 ) {
8847: h = nd_psh[index];
8848: NEWNM(mul);
8849: ndl_sub(DL(head),DL(h),DL(mul));
8850: if ( ndl_check_bound2(index,DL(mul)) )
8851: return 0;
8852: sugar = TD(DL(mul))+SG(ps[index]);
1.28 noro 8853: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 8854: red = ndv_mul_nm_symbolic(mul,ps[index]);
8855: add_pbucket_symbolic(bucket,nd_remove_head(red));
8856: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
8857: }
8858: col++;
8859: }
8860: if ( rp0 ) NEXT(rp) = 0;
8861: NEXT(s) = 0;
8862: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
8863: for ( i = 0, p = s0v, s = s0; i < col;
8864: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
8865: *s0vect = s0v;
8866: *r = rp0;
8867: return col;
8868: }
8869:
8870: void print_ndp(ND_pairs l)
8871: {
8872: ND_pairs t;
8873:
8874: for ( t = l; t; t = NEXT(t) )
8875: printf("[%d,%d] ",t->i1,t->i2);
8876: printf("\n");
8877: }
8878:
8879: NODE nd_f4(int m,int checkonly,int **indp)
8880: {
8881: int i,nh,stat,index,f4red;
8882: NODE r,g,tn0,tn,node;
8883: ND_pairs d,l,t,ll0,ll,lh;
8884: LIST l0,l1;
8885: ND spol,red;
8886: NDV nf,redv;
8887: NM s0,s;
8888: NODE rp0,srp0,nflist,nzlist,nzlist_t;
8889: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
8890: UINT c;
8891: UINT **spmat;
8892: UINT *s0vect,*svect,*p,*v;
8893: int *colstat;
8894: IndArray *imat;
8895: int *rhead;
8896: int spcol,sprow;
8897: int sugar,sugarh;
8898: PGeoBucket bucket;
8899: struct oEGT eg0,eg1,eg_f4;
8900: Z i1,i2,sugarq;
1.12 noro 8901:
8902: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 8903: #if 0
8904: ndv_alloc = 0;
8905: #endif
1.11 noro 8906: Nf4_red=0;
1.1 noro 8907: g = 0; d = 0;
8908: for ( i = 0; i < nd_psn; i++ ) {
8909: d = update_pairs(d,g,i,0);
8910: g = update_base(g,i);
8911: }
8912: nzlist = 0;
8913: nzlist_t = nd_nzlist;
8914: f4red = 1;
8915: nd_last_nonzero = 0;
8916: while ( d ) {
8917: get_eg(&eg0);
8918: l = nd_minsugarp(d,&d);
8919: sugar = nd_sugarweight?l->sugar2:SG(l);
8920: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8921: if ( nzlist_t ) {
8922: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 8923: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 8924: tn = BDY((LIST)ARG1(node));
8925: if ( !tn ) {
8926: nzlist_t = NEXT(nzlist_t);
8927: continue;
8928: }
8929: /* tn = [[i1,i2],...] */
8930: lh = nd_ipairtospair(tn);
8931: }
8932: bucket = create_pbucket();
8933: stat = nd_sp_f4(m,0,l,bucket);
8934: if ( !stat ) {
8935: for ( t = l; NEXT(t); t = NEXT(t) );
8936: NEXT(t) = d; d = l;
8937: d = nd_reconstruct(0,d);
8938: continue;
8939: }
8940: if ( bucket->m < 0 ) continue;
8941: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8942: if ( !col ) {
8943: for ( t = l; NEXT(t); t = NEXT(t) );
8944: NEXT(t) = d; d = l;
8945: d = nd_reconstruct(0,d);
8946: continue;
8947: }
1.12 noro 8948: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 8949: if ( DP_Print )
1.6 noro 8950: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 8951: sugar,eg_f4.exectime);
1.1 noro 8952: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
8953: if ( checkonly && nflist ) return 0;
8954: /* adding new bases */
8955: if ( nflist ) nd_last_nonzero = f4red;
8956: for ( r = nflist; r; r = NEXT(r) ) {
8957: nf = (NDV)BDY(r);
1.38 noro 8958: if ( nd_f4_td ) SG(nf) = nd_tdeg(nf);
1.1 noro 8959: ndv_removecont(m,nf);
8960: if ( !m && nd_nalg ) {
8961: ND nf1;
8962:
8963: nf1 = ndvtond(m,nf);
8964: nd_monic(0,&nf1);
8965: nd_removecont(m,nf1);
8966: nf = ndtondv(m,nf1);
8967: }
1.24 noro 8968: nh = ndv_newps(m,nf,0);
1.1 noro 8969: d = update_pairs(d,g,nh,0);
8970: g = update_base(g,nh);
8971: }
8972: if ( DP_Print ) {
8973: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
8974: }
8975: if ( nd_gentrace ) {
8976: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
8977: NEXTNODE(tn0,tn);
1.6 noro 8978: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 8979: node = mknode(2,i1,i2); MKLIST(l0,node);
8980: BDY(tn) = l0;
8981: }
8982: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 8983: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 8984: MKNODE(node,l1,nzlist); nzlist = node;
8985: }
8986: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
8987: f4red++;
8988: if ( nd_f4red && f4red > nd_f4red ) break;
8989: if ( nd_rank0 && !nflist ) break;
8990: }
8991: if ( nd_gentrace ) {
8992: MKLIST(l0,reverse_node(nzlist));
8993: MKNODE(nd_alltracelist,l0,0);
8994: }
8995: #if 0
8996: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8997: #endif
1.12 noro 8998: if ( DP_Print ) {
8999: fprintf(asir_out,"number of red=%d,",Nf4_red);
9000: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
9001: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
1.41 noro 9002: fprintf(asir_out,"number of removed pairs=%d\n,",NcriB+NcriMF+Ncri2);
1.12 noro 9003: }
1.1 noro 9004: conv_ilist(nd_demand,0,g,indp);
9005: return g;
9006: }
9007:
9008: NODE nd_f4_trace(int m,int **indp)
9009: {
9010: int i,nh,stat,index;
9011: NODE r,g;
9012: ND_pairs d,l,l0,t;
9013: ND spol,red;
9014: NDV nf,redv,nfqv,nfv;
9015: NM s0,s;
9016: NODE rp0,srp0,nflist;
9017: int nsp,nred,col,rank,len,k,j,a;
9018: UINT c;
9019: UINT **spmat;
9020: UINT *s0vect,*svect,*p,*v;
9021: int *colstat;
9022: IndArray *imat;
9023: int *rhead;
9024: int spcol,sprow;
9025: int sugar;
9026: PGeoBucket bucket;
9027: struct oEGT eg0,eg1,eg_f4;
9028:
9029: g = 0; d = 0;
9030: for ( i = 0; i < nd_psn; i++ ) {
9031: d = update_pairs(d,g,i,0);
9032: g = update_base(g,i);
9033: }
9034: while ( d ) {
9035: get_eg(&eg0);
9036: l = nd_minsugarp(d,&d);
9037: sugar = SG(l);
9038: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
9039: bucket = create_pbucket();
9040: stat = nd_sp_f4(m,0,l,bucket);
9041: if ( !stat ) {
9042: for ( t = l; NEXT(t); t = NEXT(t) );
9043: NEXT(t) = d; d = l;
9044: d = nd_reconstruct(1,d);
9045: continue;
9046: }
9047: if ( bucket->m < 0 ) continue;
9048: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
9049: if ( !col ) {
9050: for ( t = l; NEXT(t); t = NEXT(t) );
9051: NEXT(t) = d; d = l;
9052: d = nd_reconstruct(1,d);
9053: continue;
9054: }
9055: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
9056: if ( DP_Print )
1.3 noro 9057: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 9058: sugar,eg_f4.exectime);
1.1 noro 9059: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
9060: if ( !l0 ) continue;
9061: l = l0;
9062:
9063: /* over Q */
9064: bucket = create_pbucket();
9065: stat = nd_sp_f4(0,1,l,bucket);
9066: if ( !stat ) {
9067: for ( t = l; NEXT(t); t = NEXT(t) );
9068: NEXT(t) = d; d = l;
9069: d = nd_reconstruct(1,d);
9070: continue;
9071: }
9072: if ( bucket->m < 0 ) continue;
9073: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
9074: if ( !col ) {
9075: for ( t = l; NEXT(t); t = NEXT(t) );
9076: NEXT(t) = d; d = l;
9077: d = nd_reconstruct(1,d);
9078: continue;
9079: }
9080: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
9081: /* adding new bases */
9082: for ( r = nflist; r; r = NEXT(r) ) {
9083: nfqv = (NDV)BDY(r);
9084: ndv_removecont(0,nfqv);
1.6 noro 9085: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 9086: if ( nd_nalg ) {
9087: ND nf1;
9088:
9089: nf1 = ndvtond(m,nfqv);
9090: nd_monic(0,&nf1);
9091: nd_removecont(0,nf1);
9092: nfqv = ndtondv(0,nf1); nd_free(nf1);
9093: }
9094: nfv = ndv_dup(0,nfqv);
9095: ndv_mod(m,nfv);
9096: ndv_removecont(m,nfv);
1.24 noro 9097: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 9098: d = update_pairs(d,g,nh,0);
9099: g = update_base(g,nh);
9100: }
9101: }
9102: #if 0
9103: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
9104: #endif
9105: conv_ilist(nd_demand,1,g,indp);
9106: return g;
9107: }
9108:
9109: int rref(matrix mat,int *sugar)
9110: {
9111: int row,col,i,j,k,l,s,wcol,wj;
9112: unsigned long bj;
9113: unsigned long **a;
9114: unsigned long *ai,*ak,*as,*t;
9115: int *pivot;
9116:
9117: row = mat->row;
9118: col = mat->col;
9119: a = mat->a;
9120: wcol = (col+BLEN-1)/BLEN;
9121: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
9122: i = 0;
9123: for ( j = 0; j < col; j++ ) {
9124: wj = j/BLEN; bj = 1L<<(j%BLEN);
9125: for ( k = i; k < row; k++ )
9126: if ( a[k][wj] & bj ) break;
9127: if ( k == row ) continue;
9128: pivot[i] = j;
9129: if ( k != i ) {
9130: t = a[i]; a[i] = a[k]; a[k] = t;
9131: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
9132: }
9133: ai = a[i];
9134: for ( k = i+1; k < row; k++ ) {
9135: ak = a[k];
9136: if ( ak[wj] & bj ) {
9137: for ( l = wj; l < wcol; l++ )
9138: ak[l] ^= ai[l];
9139: sugar[k] = MAX(sugar[k],sugar[i]);
9140: }
9141: }
9142: i++;
9143: }
9144: for ( k = i-1; k >= 0; k-- ) {
9145: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
9146: ak = a[k];
9147: for ( s = 0; s < k; s++ ) {
9148: as = a[s];
9149: if ( as[wj] & bj ) {
9150: for ( l = wj; l < wcol; l++ )
9151: as[l] ^= ak[l];
9152: sugar[s] = MAX(sugar[s],sugar[k]);
9153: }
9154: }
9155: }
9156: return i;
9157: }
9158:
9159: void print_matrix(matrix mat)
9160: {
9161: int row,col,i,j;
9162: unsigned long *ai;
9163:
9164: row = mat->row;
9165: col = mat->col;
9166: printf("%d x %d\n",row,col);
9167: for ( i = 0; i < row; i++ ) {
9168: ai = mat->a[i];
9169: for ( j = 0; j < col; j++ ) {
9170: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
9171: else putchar('0');
9172: }
9173: putchar('\n');
9174: }
9175: }
9176:
9177: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
9178:
9179: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
9180: {
9181: int row,col,wcol,wj,i,j;
9182: unsigned long bj;
9183: unsigned long *ai;
9184: unsigned long **a;
9185: int len;
9186: int *pos;
9187:
9188: row = mat->row;
9189: col = mat->col;
9190: wcol = (col+BLEN-1)/BLEN;
9191: pos = (int *)MALLOC(wcol*sizeof(int));
9192: bzero(pos,wcol*sizeof(int));
9193: for ( i = j = 0; i < wcol; i++ )
9194: if ( v[i] ) pos[j++] = i;;
9195: len = j;
9196: wj = rhead/BLEN;
9197: bj = 1L<<rhead%BLEN;
9198: a = mat->a;
9199: for ( i = 0; i < row; i++ ) {
9200: ai = a[i];
9201: if ( ai[wj]&bj ) {
9202: for ( j = 0; j < len; j++ )
9203: ai[pos[j]] ^= v[pos[j]];
9204: sugar[i] = MAX(sugar[i],rsugar);
9205: }
9206: }
9207: }
9208:
9209: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
9210: {
9211: int nsp,nred,i,i0,k,rank,row;
9212: NODE r0,rp;
9213: ND_pairs sp;
9214: ND spol;
9215: NM_ind_pair rt;
9216: int *s0hash;
9217: UINT *s;
9218: int *pivot,*sugar,*head;
9219: matrix mat;
9220: NM m;
9221: NODE r;
9222: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
9223: int rhead,rsugar,size;
9224: unsigned long *v;
9225:
9226: get_eg(&eg0);
9227: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
9228: nred = length(rp0);
9229: mat = alloc_matrix(nsp,col);
9230: s0hash = (int *)MALLOC(col*sizeof(int));
9231: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
9232: s0hash[i] = ndl_hash_value(s);
9233:
9234: sugar = (int *)MALLOC(nsp*sizeof(int));
9235: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
9236: nd_sp(2,0,sp,&spol);
9237: if ( spol ) {
9238: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
9239: sugar[i] = SG(spol);
9240: i++;
9241: }
9242: }
9243: mat->row = i;
9244: if ( DP_Print ) {
9245: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
9246: }
9247: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
9248: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
9249: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
9250: rt = (NM_ind_pair)BDY(rp);
9251: bzero(v,size);
9252: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
9253: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
9254: red_by_vect_2(mat,sugar,v,rhead,rsugar);
9255: }
9256:
9257: get_eg(&eg1);
9258: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
9259: rank = rref(mat,sugar);
9260:
9261: for ( i = 0, r0 = 0; i < rank; i++ ) {
9262: NEXTNODE(r0,r);
9263: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
9264: SG((NDV)BDY(r)) = sugar[i];
9265: }
9266: if ( r0 ) NEXT(r) = 0;
9267: get_eg(&eg2);
9268: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
9269: if ( DP_Print ) {
9270: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 9271: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 9272: fflush(asir_out);
9273: }
9274: return r0;
9275: }
9276:
9277:
9278: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
9279: {
9280: IndArray *imat;
1.11 noro 9281: int nsp,nred,i,start;
1.1 noro 9282: int *rhead;
9283: NODE r0,rp;
9284: ND_pairs sp;
9285: NM_ind_pair *rvect;
9286: UINT *s;
9287: int *s0hash;
1.11 noro 9288: struct oEGT eg0,eg1,eg_conv;
1.1 noro 9289:
9290: if ( m == 2 && nd_rref2 )
9291: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
9292:
9293: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
9294: nred = length(rp0);
9295: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
9296: rhead = (int *)MALLOC(col*sizeof(int));
9297: for ( i = 0; i < col; i++ ) rhead[i] = 0;
9298:
9299: /* construction of index arrays */
1.11 noro 9300: get_eg(&eg0);
1.1 noro 9301: if ( DP_Print ) {
1.11 noro 9302: fprintf(asir_out,"%dx%d,",nsp+nred,col);
9303: fflush(asir_out);
1.1 noro 9304: }
9305: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 9306: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 9307: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 9308: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 9309: rhead[imat[i]->head] = 1;
1.11 noro 9310: start = imat[i]->head;
9311: }
1.12 noro 9312: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 9313: if ( DP_Print ) {
9314: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
9315: fflush(asir_out);
1.1 noro 9316: }
9317: if ( m > 0 )
1.7 noro 9318: #if SIZEOF_LONG==8
1.1 noro 9319: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9320: #else
9321: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9322: #endif
9323: else if ( m == -1 )
9324: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9325: else if ( m == -2 )
9326: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9327: else
9328: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9329: return r0;
9330: }
9331:
9332: /* for Fp, 2<=p<2^16 */
9333:
9334: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9335: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9336: {
9337: int spcol,sprow,a;
9338: int i,j,k,l,rank;
9339: NODE r0,r;
9340: ND_pairs sp;
9341: ND spol;
9342: UINT **spmat;
9343: UINT *svect,*v;
9344: int *colstat;
9345: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9346: int maxrs;
9347: int *spsugar;
9348: ND_pairs *spactive;
9349:
9350: spcol = col-nred;
9351: get_eg(&eg0);
9352: /* elimination (1st step) */
9353: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9354: svect = (UINT *)MALLOC(col*sizeof(UINT));
9355: spsugar = (int *)MALLOC(nsp*sizeof(int));
9356: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9357: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9358: nd_sp(m,0,sp,&spol);
9359: if ( !spol ) continue;
9360: nd_to_vect(m,s0vect,col,spol,svect);
9361: if ( m == -1 )
9362: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9363: else
1.40 noro 9364: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,0);
1.1 noro 9365: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9366: if ( i < col ) {
9367: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9368: for ( j = k = 0; j < col; j++ )
9369: if ( !rhead[j] ) v[k++] = svect[j];
9370: spsugar[sprow] = MAX(maxrs,SG(spol));
9371: if ( nz )
9372: spactive[sprow] = sp;
9373: sprow++;
9374: }
9375: nd_free(spol);
9376: }
9377: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9378: if ( DP_Print ) {
1.5 noro 9379: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9380: fflush(asir_out);
9381: }
9382: /* free index arrays */
9383: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9384:
9385: /* elimination (2nd step) */
9386: colstat = (int *)MALLOC(spcol*sizeof(int));
9387: if ( m == -1 )
9388: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9389: else
9390: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
9391: r0 = 0;
9392: for ( i = 0; i < rank; i++ ) {
9393: NEXTNODE(r0,r); BDY(r) =
9394: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9395: SG((NDV)BDY(r)) = spsugar[i];
9396: GCFREE(spmat[i]);
9397: }
9398: if ( r0 ) NEXT(r) = 0;
9399:
9400: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9401: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9402: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9403: if ( DP_Print ) {
1.5 noro 9404: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9405: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9406: nsp,nred,sprow,spcol,rank);
1.5 noro 9407: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9408: }
9409: if ( nz ) {
9410: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9411: if ( rank > 0 ) {
9412: NEXT(spactive[rank-1]) = 0;
9413: *nz = spactive[0];
9414: } else
9415: *nz = 0;
9416: }
9417: return r0;
9418: }
9419:
1.40 noro 9420: NODE nd_f4_red_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9421: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
9422: {
9423: int spcol,sprow,a;
9424: int i,j,k,l,rank;
9425: NODE r0,r;
9426: ND_pairs sp;
9427: ND spol;
9428: UINT **spmat;
9429: UINT *svect,*cvect;
9430: UINT *v;
9431: int *colstat;
9432: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9433: int maxrs;
9434: int *spsugar;
9435: ND_pairs *spactive;
9436: SIG *spsig;
9437:
9438: get_eg(&eg0);
9439: /* elimination (1st step) */
9440: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9441: spsugar = (int *)MALLOC(nsp*sizeof(int));
9442: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
9443: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9444: nd_sp(m,0,sp,&spol);
9445: if ( !spol ) {
9446: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9447: continue;
9448: }
9449: svect = (UINT *)MALLOC(col*sizeof(UINT));
9450: nd_to_vect(m,s0vect,col,spol,svect);
9451: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,spol->sig);
9452: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9453: if ( i < col ) {
9454: spmat[sprow] = svect;
9455: spsugar[sprow] = MAX(maxrs,SG(spol));
9456: spsig[sprow] = sp->sig;
9457: sprow++;
9458: } else {
9459: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9460: }
9461: nd_free(spol);
9462: }
9463: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
9464: if ( DP_Print ) {
9465: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
9466: fflush(asir_out);
9467: }
9468: /* free index arrays */
9469: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9470:
9471: /* elimination (2nd step) */
9472: colstat = (int *)MALLOC(col*sizeof(int));
9473: rank = nd_gauss_elim_mod_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
9474: r0 = 0;
9475: for ( i = 0; i < sprow; i++ ) {
9476: if ( spsugar[i] >= 0 ) {
9477: NEXTNODE(r0,r);
9478: BDY(r) = vect_to_ndv_s(spmat[i],col,s0vect);
9479: SG((NDV)BDY(r)) = spsugar[i];
9480: ((NDV)BDY(r))->sig = spsig[i];
9481: } else
9482: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
9483: GCFREE(spmat[i]);
9484: }
9485: if ( r0 ) NEXT(r) = 0;
9486: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
9487: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9488: if ( DP_Print ) {
9489: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
9490: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9491: nsp,nred,sprow,col,rank);
9492: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
9493: }
9494: return r0;
9495: }
9496:
1.1 noro 9497:
9498: /* for small finite fields */
9499:
9500: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9501: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9502: {
9503: int spcol,sprow,a;
9504: int i,j,k,l,rank;
9505: NODE r0,r;
9506: ND_pairs sp;
9507: ND spol;
9508: UINT **spmat;
9509: UINT *svect,*v;
9510: int *colstat;
9511: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9512: int maxrs;
9513: int *spsugar;
9514: ND_pairs *spactive;
9515:
9516: spcol = col-nred;
9517: get_eg(&eg0);
9518: /* elimination (1st step) */
9519: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9520: svect = (UINT *)MALLOC(col*sizeof(UINT));
9521: spsugar = (int *)MALLOC(nsp*sizeof(int));
9522: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9523: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9524: nd_sp(m,0,sp,&spol);
9525: if ( !spol ) continue;
9526: nd_to_vect(m,s0vect,col,spol,svect);
9527: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9528: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9529: if ( i < col ) {
9530: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9531: for ( j = k = 0; j < col; j++ )
9532: if ( !rhead[j] ) v[k++] = svect[j];
9533: spsugar[sprow] = MAX(maxrs,SG(spol));
9534: if ( nz )
9535: spactive[sprow] = sp;
9536: sprow++;
9537: }
9538: nd_free(spol);
9539: }
9540: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9541: if ( DP_Print ) {
1.5 noro 9542: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9543: fflush(asir_out);
9544: }
9545: /* free index arrays */
9546: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9547:
9548: /* elimination (2nd step) */
9549: colstat = (int *)MALLOC(spcol*sizeof(int));
9550: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9551: r0 = 0;
9552: for ( i = 0; i < rank; i++ ) {
9553: NEXTNODE(r0,r); BDY(r) =
9554: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9555: SG((NDV)BDY(r)) = spsugar[i];
9556: GCFREE(spmat[i]);
9557: }
9558: if ( r0 ) NEXT(r) = 0;
9559:
9560: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9561: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9562: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9563: if ( DP_Print ) {
1.5 noro 9564: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9565: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9566: nsp,nred,sprow,spcol,rank);
1.5 noro 9567: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9568: }
9569: if ( nz ) {
9570: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9571: if ( rank > 0 ) {
9572: NEXT(spactive[rank-1]) = 0;
9573: *nz = spactive[0];
9574: } else
9575: *nz = 0;
9576: }
9577: return r0;
9578: }
9579:
9580: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9581: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9582: {
9583: int spcol,sprow,a;
9584: int i,j,k,l,rank;
9585: NODE r0,r;
9586: ND_pairs sp;
9587: ND spol;
9588: mpz_t **spmat;
9589: mpz_t *svect,*v;
9590: int *colstat;
9591: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9592: int maxrs;
9593: int *spsugar;
9594: pointer *w;
9595:
9596: spcol = col-nred;
9597: get_eg(&eg0);
9598: /* elimination (1st step) */
9599: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
9600: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
9601: spsugar = (int *)MALLOC(nsp*sizeof(int));
9602: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9603: nd_sp(m,trace,sp,&spol);
9604: if ( !spol ) continue;
9605: nd_to_vect_lf(s0vect,col,spol,svect);
9606: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
9607: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
9608: if ( i < col ) {
9609: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
9610: for ( j = k = 0; j < col; j++ )
9611: if ( !rhead[j] ) v[k++][0] = svect[j][0];
9612: spsugar[sprow] = MAX(maxrs,SG(spol));
9613: sprow++;
9614: }
9615: /* nd_free(spol); */
9616: }
9617: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9618: if ( DP_Print ) {
1.5 noro 9619: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9620: fflush(asir_out);
9621: }
9622: /* free index arrays */
9623: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9624:
9625: /* elimination (2nd step) */
9626: colstat = (int *)MALLOC(spcol*sizeof(int));
9627: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
9628: w = (pointer *)MALLOC(rank*sizeof(pointer));
9629: for ( i = 0; i < rank; i++ ) {
9630: #if 0
9631: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9632: SG((NDV)w[rank-i-1]) = spsugar[i];
9633: #else
9634: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9635: SG((NDV)w[i]) = spsugar[i];
9636: #endif
9637: /* GCFREE(spmat[i]); */
9638:
9639: }
9640: #if 0
9641: qsort(w,rank,sizeof(NDV),
9642: (int (*)(const void *,const void *))ndv_compare);
9643: #endif
9644: r0 = 0;
9645: for ( i = 0; i < rank; i++ ) {
9646: NEXTNODE(r0,r); BDY(r) = w[i];
9647: }
9648: if ( r0 ) NEXT(r) = 0;
9649:
9650: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9651: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9652: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9653: if ( DP_Print ) {
1.5 noro 9654: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9655: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9656: nsp,nred,sprow,spcol,rank);
1.5 noro 9657: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9658: }
9659: return r0;
9660: }
9661:
9662: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9663: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9664: {
9665: int spcol,sprow,a;
9666: int i,j,k,l,rank;
9667: NODE r0,r;
9668: ND_pairs sp;
9669: ND spol;
9670: Z **spmat;
9671: Z *svect,*v;
9672: int *colstat;
9673: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9674: int maxrs;
9675: int *spsugar;
9676: pointer *w;
9677:
9678: spcol = col-nred;
9679: get_eg(&eg0);
9680: /* elimination (1st step) */
9681: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
9682: svect = (Z *)MALLOC(col*sizeof(Q));
9683: spsugar = (int *)MALLOC(nsp*sizeof(int));
9684: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9685: nd_sp(0,trace,sp,&spol);
9686: if ( !spol ) continue;
9687: nd_to_vect_q(s0vect,col,spol,svect);
9688: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
9689: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9690: if ( i < col ) {
9691: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
9692: for ( j = k = 0; j < col; j++ )
9693: if ( !rhead[j] ) v[k++] = svect[j];
9694: spsugar[sprow] = MAX(maxrs,SG(spol));
9695: sprow++;
9696: }
9697: /* nd_free(spol); */
9698: }
9699: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9700: if ( DP_Print ) {
1.5 noro 9701: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9702: fflush(asir_out);
9703: }
9704: /* free index arrays */
9705: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9706:
9707: /* elimination (2nd step) */
9708: colstat = (int *)MALLOC(spcol*sizeof(int));
9709: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
9710: w = (pointer *)MALLOC(rank*sizeof(pointer));
9711: for ( i = 0; i < rank; i++ ) {
9712: #if 0
9713: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9714: SG((NDV)w[rank-i-1]) = spsugar[i];
9715: #else
9716: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9717: SG((NDV)w[i]) = spsugar[i];
9718: #endif
9719: /* GCFREE(spmat[i]); */
9720: }
9721: #if 0
9722: qsort(w,rank,sizeof(NDV),
9723: (int (*)(const void *,const void *))ndv_compare);
9724: #endif
9725: r0 = 0;
9726: for ( i = 0; i < rank; i++ ) {
9727: NEXTNODE(r0,r); BDY(r) = w[i];
9728: }
9729: if ( r0 ) NEXT(r) = 0;
9730:
9731: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9732: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9733: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9734: if ( DP_Print ) {
1.5 noro 9735: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9736: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9737: nsp,nred,sprow,spcol,rank);
1.5 noro 9738: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9739: }
9740: return r0;
9741: }
9742:
9743: FILE *nd_write,*nd_read;
9744:
9745: void nd_send_int(int a) {
9746: write_int(nd_write,(unsigned int *)&a);
9747: }
9748:
9749: void nd_send_intarray(int *p,int len) {
9750: write_intarray(nd_write,(unsigned int *)p,len);
9751: }
9752:
9753: int nd_recv_int() {
9754: int a;
9755:
9756: read_int(nd_read,(unsigned int *)&a);
9757: return a;
9758: }
9759:
9760: void nd_recv_intarray(int *p,int len) {
9761: read_intarray(nd_read,(unsigned int *)p,len);
9762: }
9763:
9764: void nd_send_ndv(NDV p) {
9765: int len,i;
9766: NMV m;
9767:
9768: if ( !p ) nd_send_int(0);
9769: else {
9770: len = LEN(p);
9771: nd_send_int(len);
9772: m = BDY(p);
9773: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9774: nd_send_int(CM(m));
9775: nd_send_intarray((int *)DL(m),nd_wpd);
9776: }
9777: }
9778: }
9779:
9780: void nd_send_nd(ND p) {
9781: int len,i;
9782: NM m;
9783:
9784: if ( !p ) nd_send_int(0);
9785: else {
9786: len = LEN(p);
9787: nd_send_int(len);
9788: m = BDY(p);
9789: for ( i = 0; i < len; i++, m = NEXT(m) ) {
9790: nd_send_int(CM(m));
9791: nd_send_intarray((int *)DL(m),nd_wpd);
9792: }
9793: }
9794: }
9795:
9796: NDV nd_recv_ndv()
9797: {
9798: int len,i;
9799: NMV m,m0;
9800: NDV r;
9801:
9802: len = nd_recv_int();
9803: if ( !len ) return 0;
9804: else {
9805: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
9806: #if 0
9807: ndv_alloc += len*nmv_adv;
9808: #endif
9809: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9810: CM(m) = nd_recv_int();
9811: nd_recv_intarray((int *)DL(m),nd_wpd);
9812: }
9813: MKNDV(nd_nvar,m0,len,r);
9814: return r;
9815: }
9816: }
9817:
9818: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
9819: {
9820: int i,j,t,c,rank,inv;
9821: int *ci,*ri;
9822: Z dn;
9823: MAT m,nm;
9824:
9825: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
9826: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
9827: for ( i = 0; i < row; i++ )
9828: for ( j = 0; j < col; j++ )
9829: mat0[i][j] = 0;
9830: c = col-rank;
9831: for ( i = 0; i < rank; i++ ) {
9832: mat0[i][ri[i]] = dn;
9833: for ( j = 0; j < c; j++ )
9834: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
9835: }
9836: return rank;
9837: }
9838:
9839: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
9840: {
9841: int i,j,k,l,inv,a,rank,s;
9842: unsigned int *t,*pivot,*pk;
9843: unsigned int **mat;
9844: ND_pairs pair;
9845:
9846: mat = (unsigned int **)mat0;
9847: for ( rank = 0, j = 0; j < col; j++ ) {
9848: for ( i = rank; i < row; i++ )
9849: mat[i][j] %= md;
9850: for ( i = rank; i < row; i++ )
9851: if ( mat[i][j] )
9852: break;
9853: if ( i == row ) {
9854: colstat[j] = 0;
9855: continue;
9856: } else
9857: colstat[j] = 1;
9858: if ( i != rank ) {
9859: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9860: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9861: if ( spactive ) {
9862: pair = spactive[i]; spactive[i] = spactive[rank];
9863: spactive[rank] = pair;
9864: }
9865: }
9866: pivot = mat[rank];
9867: s = sugar[rank];
9868: inv = invm(pivot[j],md);
9869: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9870: if ( *pk ) {
9871: if ( *pk >= (unsigned int)md )
9872: *pk %= md;
9873: DMAR(*pk,inv,0,md,*pk)
9874: }
9875: for ( i = rank+1; i < row; i++ ) {
9876: t = mat[i];
9877: if ( (a = t[j]) != 0 ) {
9878: sugar[i] = MAX(sugar[i],s);
9879: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9880: }
9881: }
9882: rank++;
9883: }
9884: for ( j = col-1, l = rank-1; j >= 0; j-- )
9885: if ( colstat[j] ) {
9886: pivot = mat[l];
9887: s = sugar[l];
9888: for ( i = 0; i < l; i++ ) {
9889: t = mat[i];
9890: t[j] %= md;
9891: if ( (a = t[j]) != 0 ) {
9892: sugar[i] = MAX(sugar[i],s);
9893: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9894: }
9895: }
9896: l--;
9897: }
9898: for ( j = 0, l = 0; l < rank; j++ )
9899: if ( colstat[j] ) {
9900: t = mat[l];
9901: for ( k = j; k < col; k++ )
9902: if ( t[k] >= (unsigned int)md )
9903: t[k] %= md;
9904: l++;
9905: }
9906: return rank;
9907: }
9908:
1.40 noro 9909: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
9910: {
9911: int i,j,k,l,rank,s,imin;
9912: UINT inv;
9913: UINT a;
9914: UINT *t,*pivot,*pk;
9915: UINT *ck;
9916: UINT *ct;
9917: ND_pairs pair;
9918: SIG sg;
9919: int *used;
9920:
9921: used = (int *)MALLOC(row*sizeof(int));
9922: for ( j = 0; j < col; j++ ) {
9923: for ( i = 0; i < row; i++ )
9924: a = mat[i][j] %= md;
9925: for ( i = 0; i < row; i++ )
9926: if ( !used[i] && mat[i][j] ) break;
9927: if ( i == row ) {
9928: colstat[j] = 0;
9929: continue;
9930: } else {
9931: colstat[j] = 1;
9932: used[i] = 1;
9933: }
9934: /* column j is normalized */
9935: s = sugar[i];
9936: inv = invm(mat[i][j],md);
9937: /* normalize pivot row */
9938: for ( k = j, pk = mat[i]+j; k < col; k++, pk++, ck++ ) {
9939: DMAR(*pk,inv,0,md,*pk);
9940: }
9941: for ( k = i+1; k < row; k++ ) {
9942: if ( (a = mat[k][j]) != 0 ) {
9943: sugar[k] = MAX(sugar[k],s);
9944: red_by_vect(md,mat[k]+j,mat[i]+j,(int)(md-a),col-j);
9945: Nf4_red++;
9946: }
9947: }
9948: }
9949: rank = 0;
9950: for ( i = 0; i < row; i++ ) {
9951: for ( j = 0; j < col; j++ )
9952: if ( mat[i][j] ) break;
9953: if ( j == col ) sugar[i] = -1;
9954: else rank++;
9955: }
9956: return rank;
9957: }
9958:
1.1 noro 9959:
1.7 noro 9960: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 9961: {
1.7 noro 9962: int i,j,k,l,inv,a,rank,s;
9963: unsigned int *t,*pivot,*pk;
9964: unsigned int **mat;
9965:
9966: mat = (unsigned int **)mat0;
9967: for ( rank = 0, j = 0; j < col; j++ ) {
9968: for ( i = rank; i < row; i++ )
9969: if ( mat[i][j] )
9970: break;
9971: if ( i == row ) {
9972: colstat[j] = 0;
9973: continue;
9974: } else
9975: colstat[j] = 1;
9976: if ( i != rank ) {
9977: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9978: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9979: }
9980: pivot = mat[rank];
9981: s = sugar[rank];
9982: inv = _invsf(pivot[j]);
9983: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9984: if ( *pk )
9985: *pk = _mulsf(*pk,inv);
9986: for ( i = rank+1; i < row; i++ ) {
9987: t = mat[i];
9988: if ( (a = t[j]) != 0 ) {
9989: sugar[i] = MAX(sugar[i],s);
9990: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9991: }
9992: }
9993: rank++;
9994: }
9995: for ( j = col-1, l = rank-1; j >= 0; j-- )
9996: if ( colstat[j] ) {
9997: pivot = mat[l];
9998: s = sugar[l];
9999: for ( i = 0; i < l; i++ ) {
10000: t = mat[i];
10001: if ( (a = t[j]) != 0 ) {
10002: sugar[i] = MAX(sugar[i],s);
10003: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
10004: }
10005: }
10006: l--;
10007: }
10008: return rank;
10009: }
1.1 noro 10010:
1.7 noro 10011: int ndv_ishomo(NDV p)
10012: {
10013: NMV m;
10014: int len,h;
1.1 noro 10015:
10016: if ( !p ) return 1;
10017: len = LEN(p);
10018: m = BDY(p);
10019: h = TD(DL(m));
10020: NMV_ADV(m);
10021: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 10022: if ( TD(DL(m)) != h ) {
10023: return 0;
10024: }
1.1 noro 10025: return 1;
10026: }
10027:
10028: void ndv_save(NDV p,int index)
10029: {
10030: FILE *s;
10031: char name[BUFSIZ];
10032: short id;
10033: int nv,sugar,len,n,i,td,e,j;
10034: NMV m;
10035: unsigned int *dl;
10036: int mpos;
10037:
10038: sprintf(name,"%s/%d",Demand,index);
10039: s = fopen(name,"w");
10040: savevl(s,0);
10041: if ( !p ) {
10042: saveobj(s,0);
10043: return;
10044: }
10045: id = O_DP;
10046: nv = NV(p);
10047: sugar = SG(p);
10048: len = LEN(p);
10049: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
10050: write_int(s,(unsigned int *)&len);
10051:
10052: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 10053: saveobj(s,(Obj)CZ(m));
1.1 noro 10054: dl = DL(m);
10055: td = TD(dl);
10056: write_int(s,(unsigned int *)&td);
10057: for ( j = 0; j < nv; j++ ) {
10058: e = GET_EXP(dl,j);
10059: write_int(s,(unsigned int *)&e);
10060: }
10061: if ( nd_module ) {
10062: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
10063: }
10064: }
10065: fclose(s);
10066: }
10067:
10068: void nd_save_mod(ND p,int index)
10069: {
10070: FILE *s;
10071: char name[BUFSIZ];
10072: int nv,sugar,len,c;
10073: NM m;
10074:
10075: sprintf(name,"%s/%d",Demand,index);
10076: s = fopen(name,"w");
10077: if ( !p ) {
10078: len = 0;
10079: write_int(s,(unsigned int *)&len);
10080: fclose(s);
10081: return;
10082: }
10083: nv = NV(p);
10084: sugar = SG(p);
10085: len = LEN(p);
10086: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
10087: for ( m = BDY(p); m; m = NEXT(m) ) {
10088: c = CM(m); write_int(s,(unsigned int *)&c);
10089: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
10090: }
10091: fclose(s);
10092: }
10093:
10094: NDV ndv_load(int index)
10095: {
10096: FILE *s;
10097: char name[BUFSIZ];
10098: short id;
10099: int nv,sugar,len,n,i,td,e,j;
10100: NDV d;
10101: NMV m0,m;
10102: unsigned int *dl;
10103: Obj obj;
10104: int mpos;
10105:
10106: sprintf(name,"%s/%d",Demand,index);
10107: s = fopen(name,"r");
10108: if ( !s ) return 0;
10109:
10110: skipvl(s);
10111: read_short(s,(unsigned short *)&id);
10112: if ( !id ) return 0;
10113: read_int(s,(unsigned int *)&nv);
10114: read_int(s,(unsigned int *)&sugar);
10115: read_int(s,(unsigned int *)&len);
10116:
10117: m0 = m = MALLOC(len*nmv_adv);
10118: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 10119: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 10120: dl = DL(m);
10121: ndl_zero(dl);
10122: read_int(s,(unsigned int *)&td); TD(dl) = td;
10123: for ( j = 0; j < nv; j++ ) {
10124: read_int(s,(unsigned int *)&e);
10125: PUT_EXP(dl,j,e);
10126: }
10127: if ( nd_module ) {
10128: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
10129: }
10130: if ( nd_blockmask ) ndl_weight_mask(dl);
10131: }
10132: fclose(s);
10133: MKNDV(nv,m0,len,d);
10134: SG(d) = sugar;
10135: return d;
10136: }
10137:
10138: ND nd_load_mod(int index)
10139: {
10140: FILE *s;
10141: char name[BUFSIZ];
10142: int nv,sugar,len,i,c;
10143: ND d;
10144: NM m0,m;
10145:
10146: sprintf(name,"%s/%d",Demand,index);
10147: s = fopen(name,"r");
10148: /* if the file does not exist, it means p[index]=0 */
10149: if ( !s ) return 0;
10150:
10151: read_int(s,(unsigned int *)&nv);
10152: if ( !nv ) { fclose(s); return 0; }
10153:
10154: read_int(s,(unsigned int *)&sugar);
10155: read_int(s,(unsigned int *)&len);
10156: for ( m0 = 0, i = 0; i < len; i++ ) {
10157: NEXTNM(m0,m);
10158: read_int(s,(unsigned int *)&c); CM(m) = c;
10159: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
10160: }
10161: NEXT(m) = 0;
10162: MKND(nv,m0,len,d);
10163: SG(d) = sugar;
10164: fclose(s);
10165: return d;
10166: }
10167:
10168: void nd_det(int mod,MAT f,P *rp)
10169: {
10170: VL fv,tv;
10171: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
10172: pointer **m;
10173: P **w;
10174: P mp,r;
10175: NDV **dm;
10176: NDV *t,*mi,*mj;
10177: NDV d,s,mij,mjj;
10178: ND u;
10179: NMV nmv;
10180: UINT *bound;
10181: PGeoBucket bucket;
10182: struct order_spec *ord;
10183: Z dq,dt,ds;
10184: Z mone;
10185: Z gn,qn,dn0,nm,dn;
10186:
10187: create_order_spec(0,0,&ord);
10188: nd_init_ord(ord);
10189: get_vars((Obj)f,&fv);
10190: if ( f->row != f->col )
10191: error("nd_det : non-square matrix");
10192: n = f->row;
10193: m = f->body;
10194: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
10195:
10196: if ( !nvar ) {
10197: if ( !mod )
10198: detp(CO,(P **)m,n,rp);
10199: else {
10200: w = (P **)almat_pointer(n,n);
10201: for ( i = 0; i < n; i++ )
10202: for ( j = 0; j < n; j++ )
10203: ptomp(mod,(P)m[i][j],&w[i][j]);
10204: detmp(CO,mod,w,n,&mp);
10205: mptop(mp,rp);
10206: }
10207: return;
10208: }
10209:
10210: if ( !mod ) {
10211: w = (P **)almat_pointer(n,n);
10212: dq = ONE;
10213: for ( i = 0; i < n; i++ ) {
10214: dn0 = ONE;
10215: for ( j = 0; j < n; j++ ) {
10216: if ( !m[i][j] ) continue;
10217: lgp(m[i][j],&nm,&dn);
1.6 noro 10218: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 10219: }
10220: if ( !UNIZ(dn0) ) {
10221: ds = dn0;
10222: for ( j = 0; j < n; j++ )
10223: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
10224: mulz(dq,ds,&dt); dq = dt;
10225: } else
10226: for ( j = 0; j < n; j++ )
10227: w[i][j] = (P)m[i][j];
10228: }
10229: m = (pointer **)w;
10230: }
10231:
10232: for ( i = 0, max = 1; i < n; i++ )
10233: for ( j = 0; j < n; j++ )
10234: for ( tv = fv; tv; tv = NEXT(tv) ) {
10235: e = getdeg(tv->v,(P)m[i][j]);
10236: max = MAX(e,max);
10237: }
10238: nd_setup_parameters(nvar,max);
10239: dm = (NDV **)almat_pointer(n,n);
10240: for ( i = 0, max = 1; i < n; i++ )
10241: for ( j = 0; j < n; j++ ) {
10242: dm[i][j] = ptondv(CO,fv,m[i][j]);
10243: if ( mod ) ndv_mod(mod,dm[i][j]);
10244: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
10245: }
10246: d = ptondv(CO,fv,(P)ONE);
10247: if ( mod ) ndv_mod(mod,d);
10248: chsgnz(ONE,&mone);
10249: for ( j = 0, sgn = 1; j < n; j++ ) {
10250: if ( DP_Print ) {
10251: fprintf(asir_out,".");
10252: }
10253: for ( i = j; i < n && !dm[i][j]; i++ );
10254: if ( i == n ) {
10255: *rp = 0;
10256: return;
10257: }
10258: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
10259: for ( k = j; k < n; k++ )
10260: for ( l = j; l < n; l++ )
10261: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
10262: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
10263: }
10264: if ( k0 != j ) {
10265: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
10266: sgn = -sgn;
10267: }
10268: if ( l0 != j ) {
10269: for ( k = j; k < n; k++ ) {
10270: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
10271: }
10272: sgn = -sgn;
10273: }
10274: bound = nd_det_compute_bound(dm,n,j);
10275: for ( k = 0; k < nd_nvar; k++ )
10276: if ( bound[k]*2 > nd_mask0 ) break;
10277: if ( k < nd_nvar )
10278: nd_det_reconstruct(dm,n,j,d);
10279:
10280: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
10281: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
10282: mi = dm[i]; mij = mi[j];
10283: if ( mod )
10284: ndv_mul_c(mod,mij,mod-1);
10285: else
10286: ndv_mul_c_q(mij,mone);
10287: for ( k = j+1; k < n; k++ ) {
10288: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
10289: bucket = create_pbucket();
10290: if ( mi[k] ) {
10291: nmv = BDY(mjj); len = LEN(mjj);
10292: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10293: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
10294: add_pbucket(mod,bucket,u);
10295: }
10296: }
10297: if ( mj[k] && mij ) {
10298: nmv = BDY(mij); len = LEN(mij);
10299: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10300: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
10301: add_pbucket(mod,bucket,u);
10302: }
10303: }
10304: u = nd_quo(mod,bucket,d);
10305: mi[k] = ndtondv(mod,u);
10306: }
10307: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
10308: }
10309: d = mjj;
10310: }
10311: if ( DP_Print ) {
10312: fprintf(asir_out,"\n");
10313: }
10314: if ( sgn < 0 ) {
10315: if ( mod )
10316: ndv_mul_c(mod,d,mod-1);
10317: else
10318: ndv_mul_c_q(d,mone);
10319: }
10320: r = ndvtop(mod,CO,fv,d);
10321: if ( !mod && !UNIQ(dq) )
10322: divsp(CO,r,(P)dq,rp);
10323: else
10324: *rp = r;
10325: }
10326:
10327: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
10328: {
10329: NM mr,mr0;
10330: NM tnm;
10331: NMV m;
10332: UINT *d0,*dt,*dm;
10333: int c,n,td,i,c1,c2,len;
10334: Z q;
10335: ND r;
10336:
10337: if ( !p ) return 0;
10338: else {
10339: n = NV(p); m = BDY(p); len = LEN(p);
10340: d0 = DL(m0);
10341: td = TD(d);
10342: mr0 = 0;
10343: NEWNM(tnm);
10344: if ( mod ) {
10345: c = CM(m0);
10346: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10347: ndl_add(DL(m),d0,DL(tnm));
10348: if ( ndl_reducible(DL(tnm),d) ) {
10349: NEXTNM(mr0,mr);
10350: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
10351: ndl_copy(DL(tnm),DL(mr));
10352: }
10353: }
10354: } else {
1.6 noro 10355: q = CZ(m0);
1.1 noro 10356: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10357: ndl_add(DL(m),d0,DL(tnm));
10358: if ( ndl_reducible(DL(tnm),d) ) {
10359: NEXTNM(mr0,mr);
1.6 noro 10360: mulz(CZ(m),q,&CZ(mr));
1.1 noro 10361: ndl_copy(DL(tnm),DL(mr));
10362: }
10363: }
10364: }
10365: if ( !mr0 )
10366: return 0;
10367: else {
10368: NEXT(mr) = 0;
10369: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10370: MKND(NV(p),mr0,len,r);
10371: SG(r) = SG(p) + TD(d0);
10372: return r;
10373: }
10374: }
10375: }
10376:
10377: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
10378: {
10379: int i,obpe,oadv,h,k,l;
10380: static NM prev_nm_free_list;
10381: EPOS oepos;
10382:
10383: obpe = nd_bpe;
10384: oadv = nmv_adv;
10385: oepos = nd_epos;
10386: if ( obpe < 2 ) nd_bpe = 2;
10387: else if ( obpe < 3 ) nd_bpe = 3;
10388: else if ( obpe < 4 ) nd_bpe = 4;
10389: else if ( obpe < 5 ) nd_bpe = 5;
10390: else if ( obpe < 6 ) nd_bpe = 6;
10391: else if ( obpe < 8 ) nd_bpe = 8;
10392: else if ( obpe < 10 ) nd_bpe = 10;
10393: else if ( obpe < 16 ) nd_bpe = 16;
10394: else if ( obpe < 32 ) nd_bpe = 32;
10395: else error("nd_det_reconstruct : exponent too large");
10396:
10397: nd_setup_parameters(nd_nvar,0);
10398: prev_nm_free_list = _nm_free_list;
10399: _nm_free_list = 0;
10400: for ( k = j; k < n; k++ )
10401: for (l = j; l < n; l++ )
10402: ndv_realloc(dm[k][l],obpe,oadv,oepos);
10403: ndv_realloc(d,obpe,oadv,oepos);
10404: prev_nm_free_list = 0;
10405: #if 0
10406: GC_gcollect();
10407: #endif
10408: }
10409:
10410: /* returns a UINT array containing degree bounds */
10411:
10412: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
10413: {
10414: UINT *d0,*d1,*d,*t,*r;
10415: int k,l,i;
10416:
10417: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
10418: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
10419: for ( k = j; k < n; k++ )
10420: for ( l = j; l < n; l++ )
10421: if ( dm[k][l] ) {
10422: d = ndv_compute_bound(dm[k][l]);
10423: for ( i = 0; i < nd_nvar; i++ )
10424: d0[i] = MAX(d0[i],d[i]);
10425: }
10426: return d0;
10427: }
10428:
10429: DL nd_separate_d(UINT *d,UINT *trans)
10430: {
10431: int n,td,i,e,j;
10432: DL a;
10433:
10434: ndl_zero(trans);
10435: td = 0;
10436: for ( i = 0; i < nd_ntrans; i++ ) {
10437: e = GET_EXP(d,i);
10438: PUT_EXP(trans,i,e);
10439: td += MUL_WEIGHT(e,i);
10440: }
10441: if ( nd_ntrans+nd_nalg < nd_nvar ) {
10442: /* homogenized */
10443: i = nd_nvar-1;
10444: e = GET_EXP(d,i);
10445: PUT_EXP(trans,i,e);
10446: td += MUL_WEIGHT(e,i);
10447: }
10448: TD(trans) = td;
10449: if ( nd_blockmask) ndl_weight_mask(trans);
10450: NEWDL(a,nd_nalg);
10451: td = 0;
10452: for ( i = 0; i < nd_nalg; i++ ) {
10453: j = nd_ntrans+i;
10454: e = GET_EXP(d,j);
10455: a->d[i] = e;
10456: td += e;
10457: }
10458: a->td = td;
10459: return a;
10460: }
10461:
10462: int nd_monic(int mod,ND *p)
10463: {
10464: UINT *trans,*t;
10465: DL alg;
10466: MP mp0,mp;
10467: NM m,m0,m1,ma0,ma,mb,mr0,mr;
10468: ND r;
10469: DL dl;
10470: DP nm;
10471: NDV ndv;
10472: DAlg inv,cd;
10473: ND s,c;
10474: Z l,mul;
10475: Z ln;
10476: int n,ntrans,i,e,td,is_lc,len;
10477: NumberField nf;
10478: struct oEGT eg0,eg1;
10479:
10480: if ( !(nf = get_numberfield()) )
10481: error("nd_monic : current_numberfield is not set");
10482:
10483: /* Q coef -> DAlg coef */
10484: NEWNM(ma0); ma = ma0;
10485: m = BDY(*p);
10486: is_lc = 1;
10487: while ( 1 ) {
10488: NEWMP(mp0); mp = mp0;
1.6 noro 10489: mp->c = (Obj)CZ(m);
1.1 noro 10490: mp->dl = nd_separate_d(DL(m),DL(ma));
10491: NEWNM(mb);
10492: for ( m = NEXT(m); m; m = NEXT(m) ) {
10493: alg = nd_separate_d(DL(m),DL(mb));
10494: if ( !ndl_equal(DL(ma),DL(mb)) )
10495: break;
1.6 noro 10496: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 10497: }
10498: NEXT(mp) = 0;
10499: MKDP(nd_nalg,mp0,nm);
10500: MKDAlg(nm,ONE,cd);
10501: if ( is_lc == 1 ) {
10502: /* if the lc is a rational number, we have nothing to do */
10503: if ( !mp0->dl->td )
10504: return 1;
10505:
10506: get_eg(&eg0);
10507: invdalg(cd,&inv);
10508: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
10509: /* check the validity of inv */
10510: if ( mod && !remqi((Q)inv->dn,mod) )
10511: return 0;
10512: CA(ma) = nf->one;
10513: is_lc = 0;
10514: ln = ONE;
10515: } else {
10516: muldalg(cd,inv,&CA(ma));
10517: lcmz(ln,CA(ma)->dn,&ln);
10518: }
10519: if ( m ) {
10520: NEXT(ma) = mb; ma = mb;
10521: } else {
10522: NEXT(ma) = 0;
10523: break;
10524: }
10525: }
10526: /* l = lcm(denoms) */
10527: l = ln;
10528: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 10529: divsz(l,CA(m)->dn,&mul);
1.1 noro 10530: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
10531: NEXTNM(mr0,mr);
1.6 noro 10532: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 10533: dl = mp->dl;
10534: td = TD(DL(m));
10535: ndl_copy(DL(m),DL(mr));
10536: for ( i = 0; i < nd_nalg; i++ ) {
10537: e = dl->d[i];
10538: PUT_EXP(DL(mr),i+nd_ntrans,e);
10539: td += MUL_WEIGHT(e,i+nd_ntrans);
10540: }
10541: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
10542: TD(DL(mr)) = td;
10543: if ( nd_blockmask) ndl_weight_mask(DL(mr));
10544: }
10545: }
10546: NEXT(mr) = 0;
10547: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10548: MKND(NV(*p),mr0,len,r);
10549: /* XXX */
10550: SG(r) = SG(*p);
10551: nd_free(*p);
10552: *p = r;
10553: return 1;
10554: }
10555:
10556: NODE reverse_node(NODE n)
10557: {
10558: NODE t,t1;
10559:
10560: for ( t = 0; n; n = NEXT(n) ) {
10561: MKNODE(t1,BDY(n),t); t = t1;
10562: }
10563: return t;
10564: }
10565:
10566: P ndc_div(int mod,union oNDC a,union oNDC b)
10567: {
10568: union oNDC c;
10569: int inv,t;
10570:
10571: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 10572: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 10573: else if ( mod ) {
10574: inv = invm(b.m,mod);
10575: DMAR(a.m,inv,0,mod,t); c.m = t;
10576: } else if ( nd_vc )
10577: divsp(nd_vc,a.p,b.p,&c.p);
10578: else
10579: divsz(a.z,b.z,&c.z);
10580: return ndctop(mod,c);
10581: }
10582:
10583: P ndctop(int mod,union oNDC c)
10584: {
10585: Z q;
10586: int e;
10587: GFS gfs;
10588:
10589: if ( mod == -1 ) {
10590: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
10591: } else if ( mod == -2 ) {
1.10 noro 10592: q = c.z; return (P)q;
1.1 noro 10593: } else if ( mod > 0 ) {
1.6 noro 10594: STOZ(c.m,q); return (P)q;
1.1 noro 10595: } else
10596: return (P)c.p;
10597: }
10598:
10599: /* [0,0,0,cont] = p -> p/cont */
10600:
10601: void finalize_tracelist(int i,P cont)
10602: {
10603: LIST l;
10604: NODE node;
10605: Z iq;
10606:
10607: if ( !UNIQ(cont) ) {
10608: node = mknode(4,NULLP,NULLP,NULLP,cont);
10609: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
10610: nd_tracelist = node;
10611: }
1.6 noro 10612: STOZ(i,iq);
1.1 noro 10613: nd_tracelist = reverse_node(nd_tracelist);
10614: MKLIST(l,nd_tracelist);
10615: node = mknode(2,iq,l); MKLIST(l,node);
10616: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
10617: nd_alltracelist = node; nd_tracelist = 0;
10618: }
10619:
10620: void conv_ilist(int demand,int trace,NODE g,int **indp)
10621: {
10622: int n,i,j;
10623: int *ind;
10624: NODE t;
10625:
10626: n = length(g);
10627: ind = (int *)MALLOC(n*sizeof(int));
10628: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
10629: j = (long)BDY(t); ind[i] = j;
10630: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
10631: }
10632: if ( indp ) *indp = ind;
10633: }
10634:
1.30 noro 10635: NODE conv_ilist_s(int demand,int trace,int **indp)
10636: {
10637: int n,i,j;
10638: int *ind;
10639: NODE g0,g;
10640:
10641: n = nd_psn;
10642: ind = (int *)MALLOC(n*sizeof(int));
10643: g0 = 0;
10644: for ( i = 0; i < n; i++ ) {
10645: ind[i] = i;
10646: NEXTNODE(g0,g);
10647: BDY(g) = (pointer)(demand?ndv_load(i):(trace?nd_ps_trace[i]:nd_ps[i]));
10648: }
10649: if ( g0 ) NEXT(g) = 0;
10650: if ( indp ) *indp = ind;
10651: return g0;
10652: }
10653:
1.46 noro 10654: void parse_nd_option(VL vl,NODE opt)
1.1 noro 10655: {
1.38 noro 10656: NODE t,p,u;
1.1 noro 10657: int i,s,n;
1.38 noro 10658: char *key;
10659: Obj value;
1.46 noro 10660: VL oldvl;
1.1 noro 10661:
1.41 noro 10662: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_norb = 0; nd_gbblock = 0;
1.1 noro 10663: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
10664: nd_splist = 0; nd_check_splist = 0;
1.38 noro 10665: nd_sugarweight = 0; nd_f4red =0; nd_rank0 = 0;
10666: nd_f4_td = 0; nd_sba_f4step = 2; nd_sba_pot = 0; nd_sba_largelcm = 0;
1.41 noro 10667: nd_sba_dontsort = 0; nd_top = 0; nd_sba_redundant_check = 0;
1.46 noro 10668: nd_sba_syz = 0; nd_sba_modord = 0; nd_sba_inputisgb = 0;
1.49 noro 10669: nd_hpdata = 0;
1.39 noro 10670:
1.38 noro 10671: for ( t = opt; t; t = NEXT(t) ) {
10672: p = BDY((LIST)BDY(t));
10673: key = BDY((STRING)BDY(p));
10674: value = (Obj)BDY(NEXT(p));
10675: if ( !strcmp(key,"gentrace") )
10676: nd_gentrace = value?1:0;
10677: else if ( !strcmp(key,"gensyz") )
10678: nd_gensyz = value?1:0;
10679: else if ( !strcmp(key,"nora") )
10680: nd_nora = value?1:0;
1.41 noro 10681: else if ( !strcmp(key,"norb") )
10682: nd_norb = value?1:0;
1.38 noro 10683: else if ( !strcmp(key,"gbblock") ) {
10684: if ( value && OID(value) == O_LIST ) {
1.1 noro 10685: u = BDY((LIST)value);
1.38 noro 10686: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
1.1 noro 10687: for ( i = 0; u; u = NEXT(u) ) {
10688: p = BDY((LIST)BDY(u));
1.6 noro 10689: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
10690: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 10691: }
10692: nd_gbblock[i] = -1;
1.38 noro 10693: } else
10694: nd_gbblock = 0;
1.1 noro 10695: } else if ( !strcmp(key,"newelim") )
10696: nd_newelim = value?1:0;
10697: else if ( !strcmp(key,"intersect") )
10698: nd_intersect = value?1:0;
1.17 noro 10699: else if ( !strcmp(key,"syzgen") )
10700: nd_intersect = ZTOS((Q)value);
1.1 noro 10701: else if ( !strcmp(key,"lf") )
10702: nd_lf = value?1:0;
10703: else if ( !strcmp(key,"trace") ) {
1.38 noro 10704: if ( value ) {
10705: u = BDY((LIST)value);
10706: nd_nzlist = BDY((LIST)ARG2(u));
10707: nd_bpe = ZTOS((Q)ARG3(u));
10708: }
1.1 noro 10709: } else if ( !strcmp(key,"f4red") ) {
1.38 noro 10710: nd_f4red = ZTOS((Q)value);
1.1 noro 10711: } else if ( !strcmp(key,"rank0") ) {
1.38 noro 10712: nd_rank0 = value?1:0;
1.1 noro 10713: } else if ( !strcmp(key,"splist") ) {
1.38 noro 10714: nd_splist = value?1:0;
1.1 noro 10715: } else if ( !strcmp(key,"check_splist") ) {
10716: nd_check_splist = BDY((LIST)value);
1.49 noro 10717: } else if ( !strcmp(key,"hpdata") ) {
1.50 noro 10718: if ( value )
10719: nd_hpdata = BDY((LIST)value);
1.1 noro 10720: } else if ( !strcmp(key,"sugarweight") ) {
10721: u = BDY((LIST)value);
1.38 noro 10722: n = length(u);
10723: nd_sugarweight = MALLOC(n*sizeof(int));
1.1 noro 10724: for ( i = 0; i < n; i++, u = NEXT(u) )
1.38 noro 10725: nd_sugarweight[i] = ZTOS((Q)BDY(u));
10726: } else if ( !strcmp(key,"f4_td") ) {
10727: nd_f4_td = value?1:0;
10728: } else if ( !strcmp(key,"sba_f4step") ) {
10729: nd_sba_f4step = value?ZTOS((Q)value):0;
10730: } else if ( !strcmp(key,"sba_pot") ) {
1.44 noro 10731: nd_sba_pot = ZTOS((Q)value);
1.38 noro 10732: } else if ( !strcmp(key,"sba_largelcm") ) {
10733: nd_sba_largelcm = value?1:0;
1.39 noro 10734: } else if ( !strcmp(key,"sba_dontsort") ) {
10735: nd_sba_dontsort = value?1:0;
1.44 noro 10736: } else if ( !strcmp(key,"sba_syz") ) {
10737: nd_sba_syz = value?1:0;
1.46 noro 10738: } else if ( !strcmp(key,"sba_modord") ) {
10739: // value=[vlist,ordspec,weight]
10740: u = BDY((LIST)value);
10741: pltovl((LIST)ARG0(u),&oldvl);
10742: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10743: } else if ( !strcmp(key,"sba_gbinput") ) {
10744: nd_sba_inputisgb = value?1:0;
10745: if ( nd_sba_inputisgb != 0 ) {
10746: // value=[vlist,ordspec,weight]
10747: u = BDY((LIST)value);
10748: pltovl((LIST)ARG0(u),&oldvl);
10749: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10750: }
1.41 noro 10751: } else if ( !strcmp(key,"sba_redundant_check") ) {
10752: nd_sba_redundant_check = value?1:0;
1.39 noro 10753: } else if ( !strcmp(key,"top") ) {
10754: nd_top = value?1:0;
1.1 noro 10755: }
1.38 noro 10756: }
1.44 noro 10757: if ( nd_sba_syz ) nd_sba_dontsort = 1;
1.1 noro 10758: }
10759:
10760: ND mdptond(DP d);
10761: ND nd_mul_nm(int mod,NM m0,ND p);
10762: ND nd_mul_nm_lf(NM m0,ND p);
10763: ND *btog(NODE ti,ND **p,int nb,int mod);
10764: ND btog_one(NODE ti,ND *p,int nb,int mod);
10765: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
10766: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
10767:
10768: /* d:monomial */
10769: ND mdptond(DP d)
10770: {
10771: NM m;
10772: ND r;
10773:
10774: if ( OID(d) == 1 )
10775: r = ptond(CO,CO,(P)d);
10776: else {
10777: NEWNM(m);
10778: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 10779: CZ(m) = (Z)BDY(d)->c;
1.1 noro 10780: NEXT(m) = 0;
10781: MKND(NV(d),m,1,r);
10782: }
10783: return r;
10784: }
10785:
10786: ND nd_mul_nm(int mod,NM m0,ND p)
10787: {
10788: UINT *d0;
10789: int c0,c1,c;
10790: NM tm,mr,mr0;
10791: ND r;
10792:
10793: if ( !p ) return 0;
10794: d0 = DL(m0);
10795: c0 = CM(m0);
10796: mr0 = 0;
10797: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10798: NEXTNM(mr0,mr);
10799: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
10800: ndl_add(d0,DL(tm),DL(mr));
10801: }
10802: NEXT(mr) = 0;
10803: MKND(NV(p),mr0,LEN(p),r);
10804: return r;
10805: }
10806:
10807: ND nd_mul_nm_lf(NM m0,ND p)
10808: {
10809: UINT *d0;
10810: Z c0,c1,c;
10811: NM tm,mr,mr0;
10812: ND r;
10813:
10814: if ( !p ) return 0;
10815: d0 = DL(m0);
10816: c0 = CZ(m0);
10817: mr0 = 0;
10818: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10819: NEXTNM(mr0,mr);
10820: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
10821: ndl_add(d0,DL(tm),DL(mr));
10822: }
10823: NEXT(mr) = 0;
10824: MKND(NV(p),mr0,LEN(p),r);
10825: return r;
10826: }
10827:
10828: ND *btog(NODE ti,ND **p,int nb,int mod)
10829: {
10830: PGeoBucket *r;
10831: int i,ci;
10832: NODE t,s;
10833: ND m,tp;
10834: ND *pi,*rd;
10835: P c;
10836:
10837: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10838: for ( i = 0; i < nb; i++ )
10839: r[i] = create_pbucket();
10840: for ( t = ti; t; t = NEXT(t) ) {
10841: s = BDY((LIST)BDY(t));
10842: if ( ARG0(s) ) {
10843: m = mdptond((DP)ARG2(s));
1.6 noro 10844: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10845: if ( (ci = ((MQ)c)->cont) != 0 ) {
10846: HCM(m) = ci;
1.6 noro 10847: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10848: for ( i = 0; i < nb; i++ ) {
10849: tp = nd_mul_nm(mod,BDY(m),pi[i]);
10850: add_pbucket(mod,r[i],tp);
10851: }
10852: }
10853: ci = 1;
10854: } else {
10855: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10856: ci = invm(ci,mod);
10857: }
10858: }
10859: rd = (ND *)MALLOC(nb*sizeof(ND));
10860: for ( i = 0; i < nb; i++ )
10861: rd[i] = normalize_pbucket(mod,r[i]);
10862: if ( ci != 1 )
10863: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
10864: return rd;
10865: }
10866:
10867: /* YYY */
10868: ND *btog_lf(NODE ti,ND **p,int nb)
10869: {
10870: PGeoBucket *r;
10871: int i;
10872: NODE t,s;
10873: ND m,tp;
10874: ND *pi,*rd;
10875: LM lm;
10876: Z lf,c;
10877:
10878: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10879: for ( i = 0; i < nb; i++ )
10880: r[i] = create_pbucket();
10881: for ( t = ti; t; t = NEXT(t) ) {
10882: s = BDY((LIST)BDY(t));
10883: if ( ARG0(s) ) {
10884: m = mdptond((DP)ARG2(s));
1.6 noro 10885: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 10886: if ( lm ) {
10887: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 10888: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10889: for ( i = 0; i < nb; i++ ) {
10890: tp = nd_mul_nm_lf(BDY(m),pi[i]);
10891: add_pbucket(-2,r[i],tp);
10892: }
10893: }
10894: c = ONE;
10895: } else {
10896: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
10897: }
10898: }
10899: rd = (ND *)MALLOC(nb*sizeof(ND));
10900: for ( i = 0; i < nb; i++ )
10901: rd[i] = normalize_pbucket(-2,r[i]);
10902: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
10903: return rd;
10904: }
10905:
10906: ND btog_one(NODE ti,ND *p,int nb,int mod)
10907: {
10908: PGeoBucket r;
10909: int i,ci,j;
10910: NODE t,s;
10911: ND m,tp;
10912: ND pi,rd;
10913: P c;
10914:
10915: r = create_pbucket();
10916: for ( t = ti; t; t = NEXT(t) ) {
10917: s = BDY((LIST)BDY(t));
10918: if ( ARG0(s) ) {
10919: m = mdptond((DP)ARG2(s));
1.6 noro 10920: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10921: if ( (ci = ((MQ)c)->cont) != 0 ) {
10922: HCM(m) = ci;
1.6 noro 10923: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 10924: if ( !pi ) {
10925: pi = nd_load_mod(j);
10926: tp = nd_mul_nm(mod,BDY(m),pi);
10927: nd_free(pi);
10928: add_pbucket(mod,r,tp);
10929: } else {
10930: tp = nd_mul_nm(mod,BDY(m),pi);
10931: add_pbucket(mod,r,tp);
10932: }
10933: }
10934: ci = 1;
10935: } else {
10936: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10937: ci = invm(ci,mod);
10938: }
10939: }
10940: rd = normalize_pbucket(mod,r);
10941: free_pbucket(r);
10942: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
10943: return rd;
10944: }
10945:
10946: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
10947:
10948: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
10949: {
10950: int i,j,n,m,nb,pi0,pi1,nvar;
10951: VL fv,tv,vv;
10952: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10953: ND **p;
10954: ND *c;
10955: ND u;
10956: P inv;
10957: MAT mat;
10958:
10959: if ( mod == -2 )
10960: return nd_btog_lf(f,v,ord,tlist,rp);
10961:
10962: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10963: parse_nd_option(vv,current_option);
1.1 noro 10964: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10965: switch ( ord->id ) {
10966: case 1:
10967: if ( ord->nv != nvar )
10968: error("nd_check : invalid order specification");
10969: break;
10970: default:
10971: break;
10972: }
10973: nd_init_ord(ord);
10974: #if 0
1.6 noro 10975: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10976: #else
10977: nd_bpe = 32;
10978: #endif
10979: nd_setup_parameters(nvar,0);
10980: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10981: intred = BDY((LIST)ARG3(BDY(tlist)));
10982: ind = BDY((LIST)ARG4(BDY(tlist)));
10983: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10984: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10985: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10986: if ( j > i ) i = j;
10987: }
10988: n = i+1;
10989: nb = length(BDY(f));
10990: p = (ND **)MALLOC(n*sizeof(ND *));
10991: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10992: pi = BDY((LIST)BDY(t));
1.6 noro 10993: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10994: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10995: ptomp(mod,(P)ARG2(pi),&inv);
10996: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10997: u = ptond(CO,vv,(P)ONE);
10998: HCM(u) = ((MQ)inv)->cont;
10999: c[pi1] = u;
11000: }
11001: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11002: printf("%d ",i); fflush(stdout);
11003: ti = BDY((LIST)BDY(t));
1.6 noro 11004: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11005: }
11006: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11007: printf("%d ",i); fflush(stdout);
11008: ti = BDY((LIST)BDY(t));
1.6 noro 11009: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11010: }
11011: m = length(ind);
11012: MKMAT(mat,nb,m);
11013: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 11014: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 11015: BDY(mat)[i][j] = ndtodp(mod,c[i]);
11016: return mat;
11017: }
11018:
11019: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
11020: {
11021: int i,j,n,m,nb,pi0,pi1,nvar;
11022: VL fv,tv,vv;
11023: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
11024: ND **p;
11025: ND *c;
11026: ND u;
11027: MAT mat;
11028: LM lm;
11029: Z lf,inv;
11030:
11031: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11032: parse_nd_option(vv,current_option);
1.1 noro 11033: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11034: switch ( ord->id ) {
11035: case 1:
11036: if ( ord->nv != nvar )
11037: error("nd_check : invalid order specification");
11038: break;
11039: default:
11040: break;
11041: }
11042: nd_init_ord(ord);
11043: #if 0
1.6 noro 11044: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 11045: #else
11046: nd_bpe = 32;
11047: #endif
11048: nd_setup_parameters(nvar,0);
11049: permtrace = BDY((LIST)ARG2(BDY(tlist)));
11050: intred = BDY((LIST)ARG3(BDY(tlist)));
11051: ind = BDY((LIST)ARG4(BDY(tlist)));
11052: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
11053: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 11054: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 11055: if ( j > i ) i = j;
11056: }
11057: n = i+1;
11058: nb = length(BDY(f));
11059: p = (ND **)MALLOC(n*sizeof(ND *));
11060: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
11061: pi = BDY((LIST)BDY(t));
1.6 noro 11062: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 11063: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
11064: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
11065: u = ptond(CO,vv,(P)ONE);
11066: HCZ(u) = inv;
11067: c[pi1] = u;
11068: }
11069: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11070: printf("%d ",i); fflush(stdout);
11071: ti = BDY((LIST)BDY(t));
1.6 noro 11072: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 11073: }
11074: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11075: printf("%d ",i); fflush(stdout);
11076: ti = BDY((LIST)BDY(t));
1.6 noro 11077: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 11078: }
11079: m = length(ind);
11080: MKMAT(mat,nb,m);
11081: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 11082: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 11083: BDY(mat)[i][j] = ndtodp(-2,c[i]);
11084: return mat;
11085: }
11086:
11087: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
11088: LIST tlist,int pos,MAT *rp)
11089: {
11090: int i,j,n,m,nb,pi0,pi1,nvar;
11091: VL fv,tv,vv;
11092: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
11093: ND *p;
11094: ND *c;
11095: ND u;
11096: P inv;
11097: VECT vect;
11098:
11099: if ( mod == -2 )
11100: error("nd_btog_one : not implemented yet for a large finite field");
11101:
11102: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11103: parse_nd_option(vv,current_option);
1.1 noro 11104: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11105: switch ( ord->id ) {
11106: case 1:
11107: if ( ord->nv != nvar )
11108: error("nd_check : invalid order specification");
11109: break;
11110: default:
11111: break;
11112: }
11113: nd_init_ord(ord);
11114: #if 0
1.6 noro 11115: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 11116: #else
11117: nd_bpe = 32;
11118: #endif
11119: nd_setup_parameters(nvar,0);
11120: permtrace = BDY((LIST)ARG2(BDY(tlist)));
11121: intred = BDY((LIST)ARG3(BDY(tlist)));
11122: ind = BDY((LIST)ARG4(BDY(tlist)));
11123: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
11124: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 11125: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 11126: if ( j > i ) i = j;
11127: }
11128: n = i+1;
11129: nb = length(BDY(f));
11130: p = (ND *)MALLOC(n*sizeof(ND *));
11131: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
11132: pi = BDY((LIST)BDY(t));
1.6 noro 11133: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 11134: if ( pi1 == pos ) {
11135: ptomp(mod,(P)ARG2(pi),&inv);
11136: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
11137: u = ptond(CO,vv,(P)ONE);
11138: HCM(u) = ((MQ)inv)->cont;
11139: p[pi0] = u;
11140: }
11141: }
11142: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
11143: printf("%d ",i); fflush(stdout);
11144: ti = BDY((LIST)BDY(t));
1.6 noro 11145: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11146: if ( Demand ) {
11147: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
11148: }
11149: }
11150: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
11151: printf("%d ",i); fflush(stdout);
11152: ti = BDY((LIST)BDY(t));
1.6 noro 11153: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 11154: if ( Demand ) {
11155: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
11156: }
11157: }
11158: m = length(ind);
11159: MKVECT(vect,m);
11160: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 11161: u = p[ZTOS((Q)BDY(t))];
1.1 noro 11162: if ( !u ) {
1.6 noro 11163: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 11164: BDY(vect)[j] = ndtodp(mod,u);
11165: nd_free(u);
11166: } else
11167: BDY(vect)[j] = ndtodp(mod,u);
11168: }
11169: return vect;
11170: }
11171:
11172: void ndv_print_lf(NDV p)
11173: {
11174: NMV m;
11175: int i,len;
11176:
11177: if ( !p ) printf("0\n");
11178: else {
11179: len = LEN(p);
11180: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
11181: printf("+");
11182: mpz_out_str(asir_out,10,BDY(CZ(m)));
11183: printf("*");
11184: ndl_print(DL(m));
11185: }
11186: printf("\n");
11187: }
11188: }
11189:
11190: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
11191: {
11192: VL tv,fv,vv,vc,av;
11193: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
11194: int m,nocheck,nvar,mindex,e,max;
11195: NDV c;
11196: NMV a;
11197: P p,zp;
11198: Q dmy;
11199: EPOS oepos;
11200: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
11201: Alg alpha,dp;
11202: P poly;
11203: LIST f1,f2,zpl;
11204: Obj obj;
11205: NumberField nf;
11206: struct order_spec *ord1;
11207: struct oEGT eg_check,eg0,eg1;
11208: NODE tr,tl1,tl2,tl3,tl4;
11209: LIST l1,l2,l3,l4,l5;
11210: int *perm;
11211: int j,ret;
11212: NODE retn;
11213: Q jq,bpe;
11214:
11215: nd_module = 0;
11216: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 11217: parse_nd_option(vv,current_option);
1.1 noro 11218: if ( nd_vc )
11219: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
11220: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
11221: switch ( ord->id ) {
11222: case 1:
11223: if ( ord->nv != nvar )
11224: error("nd_f4_lf_trace : invalid order specification");
11225: break;
11226: default:
11227: break;
11228: }
11229:
11230: nd_ntrans = nvar;
11231: nd_nalg = 0;
11232:
11233: nocheck = 0;
11234: mindex = 0;
11235:
11236: /* do not use on-demand load/save */
11237: nd_demand = 0;
11238: m = trace > 1 ? trace : get_lprime(mindex);
11239: nd_init_ord(ord);
11240: mrank = 0;
11241: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
11242: for ( tv = vv; tv; tv = NEXT(tv) ) {
11243: if ( nd_module ) {
11244: s = BDY((LIST)BDY(t));
11245: trank = length(s);
11246: mrank = MAX(mrank,trank);
11247: for ( ; s; s = NEXT(s) ) {
11248: e = getdeg(tv->v,(P)BDY(s));
11249: max = MAX(e,max);
11250: }
11251: } else {
11252: e = getdeg(tv->v,(P)BDY(t));
11253: max = MAX(e,max);
11254: }
11255: }
11256: nd_setup_parameters(nvar,max);
11257: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
11258: ishomo = 1;
11259: /* XXX */
11260: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
11261: if ( nd_module ) {
11262: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
11263: } else {
11264: c = (pointer)ptondv(CO,vv,(P)BDY(t));
11265: }
11266: if ( ishomo )
11267: ishomo = ishomo && ndv_ishomo(c);
11268: if ( c ) {
11269: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
11270: ndv_mod(-2,c);
11271: NEXTNODE(in0,in); BDY(in) = (pointer)c;
11272: }
11273: }
11274: if ( in0 ) NEXT(in) = 0;
11275: if ( fd0 ) NEXT(fd) = 0;
11276: if ( !ishomo && homo ) {
11277: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
11278: c = (NDV)BDY(t); len = LEN(c);
11279: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
11280: wmax = MAX(TD(DL(a)),wmax);
11281: }
11282: homogenize_order(ord,nvar,&ord1);
11283: nd_init_ord(ord1);
11284: nd_setup_parameters(nvar+1,wmax);
11285: for ( t = fd0; t; t = NEXT(t) )
11286: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
11287: }
11288: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 11289: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 11290: if ( ret )
11291: cand = nd_f4_lf_trace_main(m,&perm);
11292: if ( !ret || !cand ) {
11293: *rp = 0; return;
11294: }
11295: if ( !ishomo && homo ) {
11296: /* dehomogenization */
11297: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
11298: nd_init_ord(ord);
11299: nd_setup_parameters(nvar,0);
11300: }
11301: cand = ndv_reducebase(cand,perm);
11302: cand = ndv_reduceall(-2,cand);
11303: cbpe = nd_bpe;
11304: get_eg(&eg0);
11305: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
11306: /* gbcheck : cand is a GB of Id(cand) ? */
11307: retn = nd_f4(-2,0,0);
11308: }
11309: if ( !retn ) {
11310: /* failure */
11311: *rp = 0; return;
11312: }
11313: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
11314: if ( DP_Print )
1.5 noro 11315: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 11316: /* dp->p */
11317: nd_bpe = cbpe;
11318: nd_setup_parameters(nd_nvar,0);
11319: for ( r = cand; r; r = NEXT(r) ) {
11320: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
11321: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
11322: }
11323: MKLIST(*rp,cand);
11324: }
11325:
11326: NODE nd_f4_lf_trace_main(int m,int **indp)
11327: {
11328: int i,nh,stat,index;
11329: NODE r,rm,g;
11330: ND_pairs d,l,l0,t;
11331: ND spol,red;
11332: NDV nf,redv,nfqv,nfv;
11333: NM s0,s;
11334: NODE rp0,srp0,nflist,nflist_lf;
11335: int nsp,nred,col,rank,len,k,j,a;
11336: UINT c;
11337: UINT **spmat;
11338: UINT *s0vect,*svect,*p,*v;
11339: int *colstat;
11340: IndArray *imat;
11341: int *rhead;
11342: int spcol,sprow;
11343: int sugar;
11344: PGeoBucket bucket;
11345: struct oEGT eg0,eg1,eg_f4;
11346:
11347: g = 0; d = 0;
11348: for ( i = 0; i < nd_psn; i++ ) {
11349: d = update_pairs(d,g,i,0);
11350: g = update_base(g,i);
11351: }
11352: while ( d ) {
11353: get_eg(&eg0);
11354: l = nd_minsugarp(d,&d);
11355: sugar = SG(l);
11356: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
11357: bucket = create_pbucket();
11358: stat = nd_sp_f4(m,0,l,bucket);
11359: if ( !stat ) {
11360: for ( t = l; NEXT(t); t = NEXT(t) );
11361: NEXT(t) = d; d = l;
11362: d = nd_reconstruct(1,d);
11363: continue;
11364: }
11365: if ( bucket->m < 0 ) continue;
11366: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
11367: if ( !col ) {
11368: for ( t = l; NEXT(t); t = NEXT(t) );
11369: NEXT(t) = d; d = l;
11370: d = nd_reconstruct(1,d);
11371: continue;
11372: }
11373: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
11374: if ( DP_Print )
1.5 noro 11375: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 11376: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
11377: if ( !l0 ) continue;
11378: l = l0;
11379:
11380: /* over LF */
11381: bucket = create_pbucket();
11382: stat = nd_sp_f4(-2,1,l,bucket);
11383: if ( !stat ) {
11384: for ( t = l; NEXT(t); t = NEXT(t) );
11385: NEXT(t) = d; d = l;
11386: d = nd_reconstruct(1,d);
11387: continue;
11388: }
11389: if ( bucket->m < 0 ) continue;
11390: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
11391: if ( !col ) {
11392: for ( t = l; NEXT(t); t = NEXT(t) );
11393: NEXT(t) = d; d = l;
11394: d = nd_reconstruct(1,d);
11395: continue;
11396: }
11397: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
11398: /* adding new bases */
11399: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
11400: nfv = (NDV)BDY(rm);
11401: nfqv = (NDV)BDY(r);
11402: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
11403: ndv_removecont(m,nfv);
11404: ndv_removecont(-2,nfqv);
1.24 noro 11405: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 11406: d = update_pairs(d,g,nh,0);
11407: g = update_base(g,nh);
11408: }
11409: if ( r || rm ) return 0;
11410: }
11411: conv_ilist(nd_demand,1,g,indp);
11412: return g;
11413: }
11414:
1.7 noro 11415: #if SIZEOF_LONG==8
11416:
11417: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
11418: {
11419: int j,k,len;
11420: UINT *p;
11421: UINT c;
11422: NDV r;
11423: NMV mr0,mr;
11424:
11425: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
11426: if ( !len ) return 0;
11427: else {
11428: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11429: #if 0
11430: ndv_alloc += nmv_adv*len;
11431: #endif
11432: mr = mr0;
11433: p = s0vect;
11434: for ( j = k = 0; j < col; j++, p += nd_wpd )
11435: if ( !rhead[j] ) {
11436: if ( (c = (UINT)vect[k++]) != 0 ) {
11437: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11438: }
11439: }
11440: MKNDV(nd_nvar,mr0,len,r);
11441: return r;
11442: }
11443: }
11444:
1.28 noro 11445: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
11446: {
11447: int j,k,len;
11448: UINT *p;
11449: UINT c;
11450: NDV r;
11451: NMV mr0,mr;
11452:
11453: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
11454: if ( !len ) return 0;
11455: else {
11456: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11457: mr = mr0;
11458: p = s0vect;
11459: for ( j = k = 0; j < col; j++, p += nd_wpd )
11460: if ( (c = (UINT)vect[k++]) != 0 ) {
11461: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11462: }
11463: MKNDV(nd_nvar,mr0,len,r);
11464: return r;
11465: }
11466: }
11467:
1.7 noro 11468: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
11469: {
11470: NM m;
1.11 noro 11471: UINT *t,*s,*u;
11472: int i,st,ed,md,prev,c;
1.7 noro 11473:
11474: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 11475: prev = 0;
11476: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
11477: t = DL(m);
11478: st = prev;
11479: ed = n;
11480: while ( ed > st ) {
11481: md = (st+ed)/2;
11482: u = s0+md*nd_wpd;
11483: c = DL_COMPARE(u,t);
11484: if ( c == 0 ) break;
11485: else if ( c > 0 ) st = md;
11486: else ed = md;
11487: }
11488: r[md] = (mp_limb_t)CM(m);
11489: prev = md;
1.7 noro 11490: }
11491: for ( i = 0; !r[i]; i++ );
11492: return i;
11493: }
11494:
11495: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
11496:
1.28 noro 11497: 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 11498: {
11499: int i,j,k,len,pos,prev;
11500: mp_limb_t a,c,c1,c2;
11501: IndArray ivect;
11502: unsigned char *ivc;
11503: unsigned short *ivs;
11504: unsigned int *ivi;
11505: NDV redv;
11506: NMV mr;
11507: NODE rp;
11508: int maxrs;
11509:
11510: for ( i = 0; i < col; i++ ) cvect[i] = 0;
11511: maxrs = 0;
11512: for ( i = 0; i < nred; i++ ) {
11513: ivect = imat[i];
11514: k = ivect->head;
11515: a = svect[k]; c = cvect[k];
11516: MOD128(a,c,m);
11517: svect[k] = a; cvect[k] = 0;
1.28 noro 11518: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 11519: Nf4_red++;
1.7 noro 11520: maxrs = MAX(maxrs,rp0[i]->sugar);
11521: c = m-c; redv = nd_ps[rp0[i]->index];
11522: len = LEN(redv); mr = BDY(redv);
11523: svect[k] = 0; prev = k;
11524: switch ( ivect->width ) {
11525: case 1:
11526: ivc = ivect->index.c;
11527: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11528: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 11529: c2 = svect[pos]+c1*c;
11530: if ( c2 < svect[pos] ) cvect[pos]++;
11531: svect[pos] = c2;
1.7 noro 11532: }
11533: break;
11534: case 2:
11535: ivs = ivect->index.s;
11536: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11537: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 11538: c2 = svect[pos]+c1*c;
11539: if ( c2 < svect[pos] ) cvect[pos]++;
11540: svect[pos] = c2;
1.7 noro 11541: }
11542: break;
11543: case 4:
11544: ivi = ivect->index.i;
11545: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11546: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 11547: c2 = svect[pos]+c1*c;
11548: if ( c2 < svect[pos] ) cvect[pos]++;
11549: svect[pos] = c2;
1.7 noro 11550: }
11551: break;
11552: }
11553: }
11554: }
11555: for ( i = 0; i < col; i++ ) {
11556: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
11557: }
11558: return maxrs;
11559: }
11560:
11561: /* for Fp, 2^15=<p<2^29 */
11562:
11563: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11564: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
11565: {
11566: int spcol,sprow,a;
11567: int i,j,k,l,rank;
11568: NODE r0,r;
11569: ND_pairs sp;
11570: ND spol;
11571: mp_limb_t **spmat;
11572: mp_limb_t *svect,*cvect;
11573: mp_limb_t *v;
11574: int *colstat;
11575: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11576: int maxrs;
11577: int *spsugar;
11578: ND_pairs *spactive;
11579:
11580: spcol = col-nred;
11581: get_eg(&eg0);
11582: /* elimination (1st step) */
11583: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11584: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11585: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11586: spsugar = (int *)MALLOC(nsp*sizeof(int));
11587: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
11588: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11589: nd_sp(m,0,sp,&spol);
11590: if ( !spol ) continue;
11591: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 noro 11592: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 11593: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11594: if ( i < col ) {
11595: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
11596: for ( j = k = 0; j < col; j++ )
11597: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
11598: spsugar[sprow] = MAX(maxrs,SG(spol));
11599: if ( nz )
11600: spactive[sprow] = sp;
11601: sprow++;
11602: }
11603: nd_free(spol);
11604: }
1.12 noro 11605: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 11606: if ( DP_Print ) {
11607: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11608: fflush(asir_out);
11609: }
11610: /* free index arrays */
11611: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11612:
11613: /* elimination (2nd step) */
11614: colstat = (int *)MALLOC(spcol*sizeof(int));
11615: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
11616: r0 = 0;
11617: for ( i = 0; i < rank; i++ ) {
11618: NEXTNODE(r0,r); BDY(r) =
11619: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
11620: SG((NDV)BDY(r)) = spsugar[i];
11621: GCFREE(spmat[i]);
11622: }
11623: if ( r0 ) NEXT(r) = 0;
11624:
11625: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 11626: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 11627: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11628: if ( DP_Print ) {
11629: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11630: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11631: nsp,nred,sprow,spcol,rank);
11632: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11633: }
11634: if ( nz ) {
11635: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
11636: if ( rank > 0 ) {
11637: NEXT(spactive[rank-1]) = 0;
11638: *nz = spactive[0];
11639: } else
11640: *nz = 0;
11641: }
11642: return r0;
11643: }
11644:
11645: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
11646: {
11647: int i,j,k,l,rank,s;
11648: mp_limb_t inv;
11649: mp_limb_t a;
11650: UINT c;
11651: mp_limb_t *t,*pivot,*pk;
11652: UINT *ck;
11653: UINT **cmat;
11654: UINT *ct;
11655: ND_pairs pair;
11656:
11657: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11658: for ( i = 0; i < row; i++ ) {
11659: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11660: bzero(cmat[i],col*sizeof(UINT));
11661: }
11662:
11663: for ( rank = 0, j = 0; j < col; j++ ) {
11664: for ( i = rank; i < row; i++ ) {
11665: a = mat[i][j]; c = cmat[i][j];
11666: MOD128(a,c,md);
11667: mat[i][j] = a; cmat[i][j] = 0;
11668: }
11669: for ( i = rank; i < row; i++ )
11670: if ( mat[i][j] )
11671: break;
11672: if ( i == row ) {
11673: colstat[j] = 0;
11674: continue;
11675: } else
11676: colstat[j] = 1;
11677: if ( i != rank ) {
11678: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
11679: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
11680: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
11681: if ( spactive ) {
11682: pair = spactive[i]; spactive[i] = spactive[rank];
11683: spactive[rank] = pair;
11684: }
11685: }
11686: /* column j is normalized */
11687: s = sugar[rank];
11688: inv = invm((UINT)mat[rank][j],md);
11689: /* normalize pivot row */
11690: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
11691: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11692: }
11693: for ( i = rank+1; i < row; i++ ) {
11694: if ( (a = mat[i][j]) != 0 ) {
11695: sugar[i] = MAX(sugar[i],s);
11696: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 11697: Nf4_red++;
1.7 noro 11698: }
11699: }
11700: rank++;
11701: }
11702: for ( j = col-1, l = rank-1; j >= 0; j-- )
11703: if ( colstat[j] ) {
11704: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
11705: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
11706: }
11707: s = sugar[l];
11708: for ( i = 0; i < l; i++ ) {
11709: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
11710: if ( a ) {
11711: sugar[i] = MAX(sugar[i],s);
11712: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 11713: Nf4_red++;
1.7 noro 11714: }
11715: }
11716: l--;
11717: }
11718: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11719: GCFREE(cmat);
11720: return rank;
11721: }
11722:
1.28 noro 11723: 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)
11724: {
11725: int i,j,k,l,rank,s,imin;
11726: mp_limb_t inv;
11727: mp_limb_t a;
11728: UINT c;
11729: mp_limb_t *t,*pivot,*pk;
11730: UINT *ck;
11731: UINT **cmat;
11732: UINT *ct;
11733: ND_pairs pair;
11734: SIG sg;
1.31 noro 11735: int *used;
1.28 noro 11736:
1.31 noro 11737: used = (int *)MALLOC(row*sizeof(int));
1.28 noro 11738: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11739: for ( i = 0; i < row; i++ ) {
11740: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11741: bzero(cmat[i],col*sizeof(UINT));
11742: }
11743:
1.31 noro 11744: for ( j = 0; j < col; j++ ) {
11745: for ( i = 0; i < row; i++ ) {
1.28 noro 11746: a = mat[i][j]; c = cmat[i][j];
11747: MOD128(a,c,md);
11748: mat[i][j] = a; cmat[i][j] = 0;
11749: }
1.31 noro 11750: for ( i = 0; i < row; i++ )
11751: if ( !used[i] && mat[i][j] ) break;
11752: if ( i == row ) {
1.28 noro 11753: colstat[j] = 0;
11754: continue;
1.31 noro 11755: } else {
1.28 noro 11756: colstat[j] = 1;
1.31 noro 11757: used[i] = 1;
1.28 noro 11758: }
11759: /* column j is normalized */
1.31 noro 11760: s = sugar[i];
11761: inv = invm((UINT)mat[i][j],md);
1.28 noro 11762: /* normalize pivot row */
1.31 noro 11763: for ( k = j, pk = mat[i]+j, ck = cmat[i]+j; k < col; k++, pk++, ck++ ) {
1.28 noro 11764: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11765: }
1.31 noro 11766: for ( k = i+1; k < row; k++ ) {
11767: if ( (a = mat[k][j]) != 0 ) {
11768: sugar[k] = MAX(sugar[k],s);
11769: red_by_vect64(md,mat[k]+j,cmat[k]+j,mat[i]+j,(int)(md-a),col-j);
1.28 noro 11770: Nf4_red++;
11771: }
11772: }
11773: }
1.31 noro 11774: rank = 0;
11775: for ( i = 0; i < row; i++ ) {
11776: for ( j = 0; j < col; j++ )
11777: if ( mat[i][j] ) break;
11778: if ( j == col ) sugar[i] = -1;
11779: else rank++;
11780: }
1.28 noro 11781: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11782: GCFREE(cmat);
11783: return rank;
11784: }
11785:
11786: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11787: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
11788: {
11789: int spcol,sprow,a;
11790: int i,j,k,l,rank;
11791: NODE r0,r;
11792: ND_pairs sp;
11793: ND spol;
11794: mp_limb_t **spmat;
11795: mp_limb_t *svect,*cvect;
11796: mp_limb_t *v;
11797: int *colstat;
11798: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11799: int maxrs;
11800: int *spsugar;
11801: ND_pairs *spactive;
11802: SIG *spsig;
11803:
11804: get_eg(&eg0);
11805: /* elimination (1st step) */
11806: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11807: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11808: spsugar = (int *)MALLOC(nsp*sizeof(int));
11809: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
11810: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11811: nd_sp(m,0,sp,&spol);
11812: if ( !spol ) {
1.29 noro 11813: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11814: continue;
11815: }
11816: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11817: nd_to_vect64(m,s0vect,col,spol,svect);
11818: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
11819: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11820: if ( i < col ) {
11821: spmat[sprow] = svect;
11822: spsugar[sprow] = MAX(maxrs,SG(spol));
11823: spsig[sprow] = sp->sig;
11824: sprow++;
11825: } else {
1.29 noro 11826: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11827: }
11828: nd_free(spol);
11829: }
11830: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
11831: if ( DP_Print ) {
11832: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11833: fflush(asir_out);
11834: }
11835: /* free index arrays */
11836: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11837:
11838: /* elimination (2nd step) */
11839: colstat = (int *)MALLOC(col*sizeof(int));
11840: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
11841: r0 = 0;
1.31 noro 11842: for ( i = 0; i < sprow; i++ ) {
11843: if ( spsugar[i] >= 0 ) {
11844: NEXTNODE(r0,r);
11845: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
11846: SG((NDV)BDY(r)) = spsugar[i];
11847: ((NDV)BDY(r))->sig = spsig[i];
11848: } else
11849: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
1.28 noro 11850: GCFREE(spmat[i]);
11851: }
11852: if ( r0 ) NEXT(r) = 0;
11853: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
11854: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11855: if ( DP_Print ) {
11856: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11857: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11858: nsp,nred,sprow,col,rank);
11859: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11860: }
11861: return r0;
11862: }
1.40 noro 11863: #endif
1.28 noro 11864:
11865: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
11866: {
11867: IndArray *imat;
11868: int nsp,nred,i,start;
11869: int *rhead;
11870: NODE r0,rp;
11871: ND_pairs sp;
11872: NM_ind_pair *rvect;
11873: UINT *s;
11874: int *s0hash;
11875: struct oEGT eg0,eg1,eg_conv;
11876:
11877: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
11878: nred = length(rp0);
11879: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
11880: rhead = (int *)MALLOC(col*sizeof(int));
11881: for ( i = 0; i < col; i++ ) rhead[i] = 0;
11882:
11883: /* construction of index arrays */
11884: get_eg(&eg0);
11885: if ( DP_Print ) {
11886: fprintf(asir_out,"%dx%d,",nsp+nred,col);
11887: fflush(asir_out);
11888: }
11889: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
11890: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
11891: rvect[i] = (NM_ind_pair)BDY(rp);
11892: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
11893: rhead[imat[i]->head] = 1;
11894: start = imat[i]->head;
11895: }
11896: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
11897: if ( DP_Print ) {
11898: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
11899: fflush(asir_out);
11900: }
11901: if ( m > 0 )
1.40 noro 11902: #if SIZEOF_LONG==8
1.28 noro 11903: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
1.40 noro 11904: #else
11905: r0 = nd_f4_red_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
11906: #endif
1.28 noro 11907: else
11908: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
11909: error("nd_f4_red_q_main_s : not implemented yet");
11910: return r0;
11911: }
11912:
11913: INLINE int ndl_find_reducer_minsig(UINT *dg)
11914: {
11915: RHist r;
11916: int i,singular,ret,d,k,imin;
11917: SIG t;
11918: static int wpd,nvar;
11919: static SIG quo,quomin;
11920: static UINT *tmp;
11921:
11922: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
11923: if ( wpd != nd_wpd ) {
11924: wpd = nd_wpd;
11925: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
11926: }
11927: #if 0
11928: d = ndl_hash_value(dg);
11929: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
11930: if ( ndl_equal(dg,DL(r)) ) {
11931: return r->index;
11932: }
11933: }
11934: #endif
11935: imin = -1;
11936: for ( i = 0; i < nd_psn; i++ ) {
11937: r = nd_psh[i];
11938: if ( ndl_reducible(dg,DL(r)) ) {
11939: ndl_sub(dg,DL(r),tmp);
11940: _ndltodl(tmp,DL(quo));
11941: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
11942: quo->pos = nd_psh[i]->sig->pos;
1.55 noro 11943: _adddl(nd_nvar,DL(quo),nd_sba_hm[quo->pos],DL2(quo));
1.28 noro 11944: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
11945: t = quo; quo = quomin; quomin = t;
11946: imin = i;
11947: }
11948: }
11949: }
11950: if ( imin == -1 ) return nd_psn;
11951: else {
11952: #if 0
11953: nd_append_red(dg,i);
11954: #endif
11955: return imin;
11956: }
11957: }
11958:
11959: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
11960: {
11961: NODE rp0,rp;
11962: NM mul,head,s0,s;
11963: int index,col,i,sugar;
11964: RHist h;
11965: UINT *s0v,*p;
11966: NM_ind_pair pair;
11967: ND red;
11968: NDV *ps;
11969: SIG sig;
11970:
11971: s0 = 0; rp0 = 0; col = 0;
11972: if ( nd_demand )
11973: ps = trace?nd_ps_trace_sym:nd_ps_sym;
11974: else
11975: ps = trace?nd_ps_trace:nd_ps;
11976: while ( 1 ) {
11977: head = remove_head_pbucket_symbolic(bucket);
11978: if ( !head ) break;
11979: if ( !s0 ) s0 = head;
11980: else NEXT(s) = head;
11981: s = head;
11982: index = ndl_find_reducer_minsig(DL(head));
11983: if ( index >= 0 && index < nd_psn ) {
11984: h = nd_psh[index];
11985: NEWNM(mul);
11986: ndl_sub(DL(head),DL(h),DL(mul));
11987: if ( ndl_check_bound2(index,DL(mul)) )
11988: return 0;
11989: sugar = TD(DL(mul))+SG(ps[index]);
11990: NEWSIG(sig);
11991: _ndltodl(DL(mul),DL(sig));
11992: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
11993: sig->pos = nd_psh[index]->sig->pos;
1.55 noro 11994: _adddl(nd_nvar,DL(sig),nd_sba_hm[sig->pos],DL2(sig));
1.28 noro 11995: MKNM_ind_pair(pair,mul,index,sugar,sig);
11996: red = ndv_mul_nm_symbolic(mul,ps[index]);
11997: add_pbucket_symbolic(bucket,nd_remove_head(red));
11998: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
11999: }
12000: col++;
12001: }
12002: if ( rp0 ) NEXT(rp) = 0;
12003: NEXT(s) = 0;
12004: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
12005: for ( i = 0, p = s0v, s = s0; i < col;
12006: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
12007: *s0vect = s0v;
12008: *r = rp0;
12009:
12010: return col;
12011: }
12012:
12013: NODE nd_sba_f4(int m,int **indp)
12014: {
1.34 noro 12015: int i,nh,stat,index,f4red,f4step;
1.33 noro 12016: int col,rank,len,k,j,a,sugar,nbase,psugar,ms;
12017: NODE r,g,rp0,nflist;
1.41 noro 12018: ND_pairs d,l,t,l1;
1.33 noro 12019: ND h,nf;
12020: NDV nfv;
12021: union oNDC hc;
12022: UINT *s0vect;
1.28 noro 12023: UINT c;
12024: PGeoBucket bucket;
1.33 noro 12025: NODE *syzlist;
12026: SIG sig;
1.28 noro 12027: struct oEGT eg0,eg1,eg_f4;
1.33 noro 12028: struct oEGT eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.28 noro 12029:
12030: Nf4_red=0;
1.30 noro 12031: d = 0;
1.29 noro 12032: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.28 noro 12033: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 12034: d = update_pairs_s(d,i,syzlist);
1.28 noro 12035: }
1.30 noro 12036: nd_nbase = nd_psn;
1.28 noro 12037: f4red = 1;
1.33 noro 12038: psugar = 0;
1.34 noro 12039: f4step = 0;
1.28 noro 12040: while ( d ) {
1.33 noro 12041: for ( t = d, ms = SG(d); t; t = NEXT(t) )
12042: if ( SG(t) < ms ) ms = SG(t);
1.38 noro 12043: if ( ms == psugar && f4step >= nd_sba_f4step ) {
1.33 noro 12044: again:
12045: l = d; d = d->next;
1.41 noro 12046: #if 0
1.33 noro 12047: if ( small_lcm(l) ) {
12048: if ( DP_Print ) fprintf(asir_out,"M");
12049: continue;
12050: }
12051: sig = l->sig;
12052: stat = nd_sp(m,0,l,&h);
1.41 noro 12053: #else
12054: l1 = find_smallest_lcm(l);
12055: if ( l1 == 0 ) {
12056: if ( DP_Print ) fprintf(asir_out,"M");
12057: continue;
12058: }
12059: sig = l1->sig;
12060: stat = nd_sp(m,0,l1,&h);
12061: #endif
1.33 noro 12062: if ( !stat ) {
12063: NEXT(l) = d; d = l;
12064: d = nd_reconstruct(0,d);
12065: goto again;
12066: }
12067: get_eg(&eg1);
12068: #if USE_GEOBUCKET
1.39 noro 12069: 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 12070: #else
1.39 noro 12071: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 12072: #endif
12073: get_eg(&eg2);
12074: if ( !stat ) {
12075: NEXT(l) = d; d = l;
12076: d = nd_reconstruct(0,d);
12077: goto again;
12078: } else if ( stat == -1 ) {
12079: if ( DP_Print ) { printf("S"); fflush(stdout); }
12080: FREENDP(l);
12081: } else if ( nf ) {
12082: if ( DP_Print ) { printf("+"); fflush(stdout); }
12083: add_eg(&eg_nf,&eg1,&eg2);
12084: hc = HCU(nf);
12085: nd_removecont(m,nf);
12086: nfv = ndtondv(m,nf); nd_free(nf);
12087: nh = ndv_newps(m,nfv,0);
12088:
1.30 noro 12089: d = update_pairs_s(d,nh,syzlist);
12090: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.33 noro 12091: FREENDP(l);
1.28 noro 12092: } else {
1.33 noro 12093: add_eg(&eg_nfzero,&eg1,&eg2);
12094: // syzygy
12095: get_eg(&eg1);
12096: d = remove_spair_s(d,sig);
12097: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 12098: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.33 noro 12099: if ( DP_Print ) { printf("."); fflush(stdout); }
12100: FREENDP(l);
12101: }
12102: } else {
1.34 noro 12103: if ( ms != psugar ) f4step = 1;
12104: else f4step++;
1.33 noro 12105: again2:
12106: psugar = ms;
12107: l = nd_minsugarp_s(d,&d);
12108: sugar = nd_sugarweight?d->sugar2:SG(d);
12109: bucket = create_pbucket();
12110: stat = nd_sp_f4(m,0,l,bucket);
12111: if ( !stat ) {
12112: for ( t = l; NEXT(t); t = NEXT(t) );
12113: NEXT(t) = d; d = l;
12114: d = nd_reconstruct(0,d);
12115: goto again2;
12116: }
12117: if ( bucket->m < 0 ) continue;
12118: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
12119: if ( !col ) {
1.37 noro 12120: for ( t = l; NEXT(t); t = NEXT(t) )
12121: ;
12122: NEXT(t) = d; d = l;
1.33 noro 12123: d = nd_reconstruct(0,d);
12124: goto again2;
12125: }
1.34 noro 12126: if ( DP_Print ) fprintf(asir_out,"\nsugar=%d,",psugar);
1.33 noro 12127: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,syzlist);
12128: /* adding new bases */
12129: for ( r = nflist; r; r = NEXT(r) ) {
12130: nfv = (NDV)BDY(r);
1.38 noro 12131: if ( nd_f4_td ) SG(nfv) = nd_tdeg(nfv);
1.33 noro 12132: ndv_removecont(m,nfv);
12133: nh = ndv_newps(m,nfv,0);
12134: d = update_pairs_s(d,nh,syzlist);
12135: nd_sba_pos[nfv->sig->pos] = append_one(nd_sba_pos[nfv->sig->pos],nh);
12136: }
12137: for ( i = 0; i < nd_nbase; i++ )
12138: for ( r = syzlist[i]; r; r = NEXT(r) )
12139: d = remove_spair_s(d,(SIG)BDY(r));
12140: d = remove_large_lcm(d);
12141: if ( DP_Print ) {
1.34 noro 12142: fprintf(asir_out,"f4red=%d,gblen=%d",f4red,nd_psn); fflush(asir_out);
1.33 noro 12143: }
12144: f4red++;
1.28 noro 12145: }
12146: }
12147: if ( DP_Print ) {
1.34 noro 12148: fprintf(asir_out,"\nnumber of red=%d,",Nf4_red);
1.28 noro 12149: }
1.30 noro 12150: g = conv_ilist_s(nd_demand,0,indp);
1.28 noro 12151: return g;
12152: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>