Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.47
1.47 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.46 2021/01/25 00:39:52 noro Exp $ */
1.1 noro 2:
3: #include "nd.h"
4:
1.45 noro 5: void print_siglist(NODE l);
6:
1.47 ! noro 7: int Nnd_add,Nf4_red,NcriB,NcriMF,Ncri2,Npairs,Nnewpair;
1.12 noro 8: struct oEGT eg_search,f4_symb,f4_conv,f4_elim1,f4_elim2;
1.1 noro 9:
10: int diag_period = 6;
11: int weight_check = 1;
12: int (*ndl_compare_function)(UINT *a1,UINT *a2);
1.21 noro 13: /* for general module order */
1.19 noro 14: int (*ndl_base_compare_function)(UINT *a1,UINT *a2);
1.21 noro 15: int (*dl_base_compare_function)(int nv,DL a,DL b);
16: int nd_base_ordtype;
1.1 noro 17: int nd_dcomp;
18: int nd_rref2;
19: NM _nm_free_list;
20: ND _nd_free_list;
21: ND_pairs _ndp_free_list;
22: NODE nd_hcf;
1.35 noro 23: int Nsyz,Nsamesig;
1.1 noro 24:
25: Obj nd_top_weight;
26:
27: static NODE nd_subst;
28: static VL nd_vc;
29: static int nd_ntrans;
30: static int nd_nalg;
31: #if 0
32: static int ndv_alloc;
33: #endif
34: #if 1
35: static int nd_f4_nsp=0x7fffffff;
36: #else
37: static int nd_f4_nsp=50;
38: #endif
39: static double nd_scale=2;
40: static UINT **nd_bound;
41: static struct order_spec *nd_ord;
42: static EPOS nd_epos;
43: static BlockMask nd_blockmask;
44: static int nd_nvar;
45: static int nd_isrlex;
46: static int nd_epw,nd_bpe,nd_wpd,nd_exporigin;
47: static UINT nd_mask[32];
48: static UINT nd_mask0,nd_mask1;
49:
50: static NDV *nd_ps;
51: static NDV *nd_ps_trace;
52: static NDV *nd_ps_sym;
53: static NDV *nd_ps_trace_sym;
54: static RHist *nd_psh;
1.30 noro 55: static int nd_psn,nd_pslen,nd_nbase;
1.1 noro 56: static RHist *nd_red;
57: static int *nd_work_vector;
58: static int **nd_matrix;
59: static int nd_matrix_len;
60: static struct weight_or_block *nd_worb;
61: static int nd_worb_len;
62: static int nd_found,nd_create,nd_notfirst;
63: static int nmv_adv;
64: static int nd_demand;
1.21 noro 65: static int nd_module,nd_module_ordtype,nd_mpos,nd_pot_nelim;
1.1 noro 66: static int nd_module_rank,nd_poly_weight_len;
67: static int *nd_poly_weight,*nd_module_weight;
68: static NODE nd_tracelist;
69: static NODE nd_alltracelist;
1.41 noro 70: static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect,nd_lf,nd_norb;
71: static int nd_f4_td,nd_sba_f4step,nd_sba_pot,nd_sba_largelcm,nd_sba_dontsort,nd_sba_redundant_check;
1.46 noro 72: static int nd_top,nd_sba_syz,nd_sba_inputisgb;
1.1 noro 73: static int *nd_gbblock;
74: static NODE nd_nzlist,nd_check_splist;
75: static int nd_splist;
76: static int *nd_sugarweight;
77: static int nd_f4red,nd_rank0,nd_last_nonzero;
1.27 noro 78: static DL *nd_sba_hm;
1.29 noro 79: static NODE *nd_sba_pos;
1.1 noro 80:
1.46 noro 81: struct comp_sig_spec {
82: int n;
83: // current_i <-> oldv[i]
84: int *oldv;
85: int *weight;
86: struct order_pair *order_pair;
87: int block_length;
88: int **matrix;
89: int row;
90: int (*cmpdl)(int n,DL d1,DL d2);
91: };
92:
93: struct comp_sig_spec *nd_sba_modord;
94:
1.1 noro 95: NumberField get_numberfield();
96: UINT *nd_det_compute_bound(NDV **dm,int n,int j);
97: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d);
98: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr);
99: int nd_monic(int m,ND *p);
100: NDV plain_vect_to_ndv_q(Z *mat,int col,UINT *s0vect);
101: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank);
102: NDV pltondv(VL vl,VL dvl,LIST p);
103: void pltozpl(LIST l,Q *cont,LIST *pp);
104: void ndl_max(UINT *d1,unsigned *d2,UINT *d);
105: void nmtodp(int mod,NM m,DP *r);
1.15 noro 106: void ndltodp(UINT *d,DP *r);
1.1 noro 107: NODE reverse_node(NODE n);
108: P ndc_div(int mod,union oNDC a,union oNDC b);
109: P ndctop(int mod,union oNDC c);
110: void finalize_tracelist(int i,P cont);
111: void conv_ilist(int demand,int trace,NODE g,int **indp);
1.46 noro 112: void parse_nd_option(VL vl,NODE opt);
1.1 noro 113: void dltondl(int n,DL dl,UINT *r);
114: DP ndvtodp(int mod,NDV p);
115: DP ndtodp(int mod,ND p);
1.16 noro 116: DPM ndvtodpm(int mod,NDV p);
1.43 noro 117: NDV dptondv(int mod,DP p);
1.16 noro 118: NDV dpmtondv(int mod,DPM p);
1.43 noro 119: int dp_getdeg(DP p);
1.16 noro 120: int dpm_getdeg(DPM p,int *rank);
121: void dpm_ptozp(DPM p,Z *cont,DPM *r);
122: int compdmm(int nv,DMM a,DMM b);
1.44 noro 123: DPM sigtodpm(SIG s);
124: SIG dup_sig(SIG sig);
1.1 noro 125:
126: void Pdp_set_weight(NODE,VECT *);
127: void Pox_cmo_rpc(NODE,Obj *);
128:
129: ND nd_add_lf(ND p1,ND p2);
130: void nd_mul_c_lf(ND p,Z mul);
131: void ndv_mul_c_lf(NDV p,Z mul);
132: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
133: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
134: NODE nd_f4_red_mod64_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_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
137: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred);
138: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat);
1.40 noro 139: 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 140: NODE nd_f4_lf_trace_main(int m,int **indp);
141: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp);
142:
143: extern int lf_lazy;
144: extern Z current_mod_lf;
145:
146: extern int Denominator,DP_Multiple,MaxDeg;
147:
148: #define BLEN (8*sizeof(unsigned long))
149:
150: typedef struct matrix {
151: int row,col;
152: unsigned long **a;
153: } *matrix;
154:
155:
156: void nd_free_private_storage()
157: {
158: _nm_free_list = 0;
159: _ndp_free_list = 0;
160: #if 0
161: GC_gcollect();
162: #endif
163: }
164:
165: void _NM_alloc()
166: {
167: NM p;
168: int i;
169:
170: for ( i = 0; i < 1024; i++ ) {
171: p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
172: p->next = _nm_free_list; _nm_free_list = p;
173: }
174: }
175:
176: matrix alloc_matrix(int row,int col)
177: {
178: unsigned long **a;
179: int i,len,blen;
180: matrix mat;
181:
182: mat = (matrix)MALLOC(sizeof(struct matrix));
183: mat->row = row;
184: mat->col = col;
185: mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *));
186: return mat;
187: }
188:
189:
190: void _ND_alloc()
191: {
192: ND p;
193: int i;
194:
195: for ( i = 0; i < 1024; i++ ) {
196: p = (ND)MALLOC(sizeof(struct oND));
197: p->body = (NM)_nd_free_list; _nd_free_list = p;
198: }
199: }
200:
201: void _NDP_alloc()
202: {
203: ND_pairs p;
204: int i;
205:
206: for ( i = 0; i < 1024; i++ ) {
207: p = (ND_pairs)MALLOC(sizeof(struct oND_pairs)
208: +(nd_wpd-1)*sizeof(UINT));
209: p->next = _ndp_free_list; _ndp_free_list = p;
210: }
211: }
212:
213: INLINE int nd_length(ND p)
214: {
215: NM m;
216: int i;
217:
218: if ( !p )
219: return 0;
220: else {
221: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
222: return i;
223: }
224: }
225:
226: extern int dp_negative_weight;
227:
228: INLINE int ndl_reducible(UINT *d1,UINT *d2)
229: {
230: UINT u1,u2;
231: int i,j;
232:
233: if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
234:
235: if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0;
236: #if USE_UNROLL
237: switch ( nd_bpe ) {
238: case 3:
239: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
240: u1 = d1[i]; u2 = d2[i];
241: if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
242: if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
243: if ( (u1& 0xe00000) < (u2& 0xe00000) ) return 0;
244: if ( (u1& 0x1c0000) < (u2& 0x1c0000) ) return 0;
245: if ( (u1& 0x38000) < (u2& 0x38000) ) return 0;
246: if ( (u1& 0x7000) < (u2& 0x7000) ) return 0;
247: if ( (u1& 0xe00) < (u2& 0xe00) ) return 0;
248: if ( (u1& 0x1c0) < (u2& 0x1c0) ) return 0;
249: if ( (u1& 0x38) < (u2& 0x38) ) return 0;
250: if ( (u1& 0x7) < (u2& 0x7) ) return 0;
251: }
252: return 1;
253: break;
254: case 4:
255: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
256: u1 = d1[i]; u2 = d2[i];
257: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
258: if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
259: if ( (u1& 0xf00000) < (u2& 0xf00000) ) return 0;
260: if ( (u1& 0xf0000) < (u2& 0xf0000) ) return 0;
261: if ( (u1& 0xf000) < (u2& 0xf000) ) return 0;
262: if ( (u1& 0xf00) < (u2& 0xf00) ) return 0;
263: if ( (u1& 0xf0) < (u2& 0xf0) ) return 0;
264: if ( (u1& 0xf) < (u2& 0xf) ) return 0;
265: }
266: return 1;
267: break;
268: case 6:
269: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
270: u1 = d1[i]; u2 = d2[i];
271: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
272: if ( (u1& 0xfc0000) < (u2& 0xfc0000) ) return 0;
273: if ( (u1& 0x3f000) < (u2& 0x3f000) ) return 0;
274: if ( (u1& 0xfc0) < (u2& 0xfc0) ) return 0;
275: if ( (u1& 0x3f) < (u2& 0x3f) ) return 0;
276: }
277: return 1;
278: break;
279: case 8:
280: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
281: u1 = d1[i]; u2 = d2[i];
282: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
283: if ( (u1& 0xff0000) < (u2& 0xff0000) ) return 0;
284: if ( (u1& 0xff00) < (u2& 0xff00) ) return 0;
285: if ( (u1& 0xff) < (u2& 0xff) ) return 0;
286: }
287: return 1;
288: break;
289: case 16:
290: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
291: u1 = d1[i]; u2 = d2[i];
292: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
293: if ( (u1& 0xffff) < (u2& 0xffff) ) return 0;
294: }
295: return 1;
296: break;
297: case 32:
298: for ( i = nd_exporigin; i < nd_wpd; i++ )
299: if ( d1[i] < d2[i] ) return 0;
300: return 1;
301: break;
302: default:
303: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
304: u1 = d1[i]; u2 = d2[i];
305: for ( j = 0; j < nd_epw; j++ )
306: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
307: }
308: return 1;
309: }
310: #else
311: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
312: u1 = d1[i]; u2 = d2[i];
313: for ( j = 0; j < nd_epw; j++ )
314: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
315: }
316: return 1;
317: #endif
318: }
319:
320: /*
321: * If the current order is a block order,
322: * then the last block is length 1 and contains
323: * the homo variable. Otherwise, the original
324: * order is either 0 or 2.
325: */
326:
327: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int ompos,int weight)
328: {
329: int w,i,e,n,omask0;
330:
331: omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
332: n = nd_nvar-1;
333: ndl_zero(r);
334: for ( i = 0; i < n; i++ ) {
335: e = GET_EXP_OLD(d,i);
336: PUT_EXP(r,i,e);
337: }
338: w = TD(d);
339: PUT_EXP(r,nd_nvar-1,weight-w);
340: if ( nd_module ) MPOS(r) = d[ompos];
341: TD(r) = weight;
342: if ( nd_blockmask ) ndl_weight_mask(r);
343: }
344:
345: void ndl_dehomogenize(UINT *d)
346: {
347: UINT mask;
348: UINT h;
349: int i,bits;
350:
351: if ( nd_blockmask ) {
352: h = GET_EXP(d,nd_nvar-1);
353: XOR_EXP(d,nd_nvar-1,h);
354: TD(d) -= h;
355: ndl_weight_mask(d);
356: } else {
357: if ( nd_isrlex ) {
358: if ( nd_bpe == 32 ) {
359: h = d[nd_exporigin];
360: for ( i = nd_exporigin+1; i < nd_wpd; i++ )
361: d[i-1] = d[i];
362: d[i-1] = 0;
363: TD(d) -= h;
364: } else {
365: bits = nd_epw*nd_bpe;
366: mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
367: h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
368: for ( i = nd_exporigin; i < nd_wpd; i++ )
369: d[i] = ((d[i]<<nd_bpe)&mask)
370: |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
371: TD(d) -= h;
372: }
373: } else {
374: h = GET_EXP(d,nd_nvar-1);
375: XOR_EXP(d,nd_nvar-1,h);
376: TD(d) -= h;
377: }
378: }
379: }
380:
381: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
382: {
383: UINT t1,t2,u,u1,u2;
384: int i,j,l;
385:
386: if ( nd_module && (MPOS(d1) != MPOS(d2)) )
387: error("ndl_lcm : inconsistent monomials");
388: #if USE_UNROLL
389: switch ( nd_bpe ) {
390: case 3:
391: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
392: u1 = d1[i]; u2 = d2[i];
393: t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
394: t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
395: t1 = (u1& 0xe00000); t2 = (u2& 0xe00000); u |= t1>t2?t1:t2;
396: t1 = (u1& 0x1c0000); t2 = (u2& 0x1c0000); u |= t1>t2?t1:t2;
397: t1 = (u1& 0x38000); t2 = (u2& 0x38000); u |= t1>t2?t1:t2;
398: t1 = (u1& 0x7000); t2 = (u2& 0x7000); u |= t1>t2?t1:t2;
399: t1 = (u1& 0xe00); t2 = (u2& 0xe00); u |= t1>t2?t1:t2;
400: t1 = (u1& 0x1c0); t2 = (u2& 0x1c0); u |= t1>t2?t1:t2;
401: t1 = (u1& 0x38); t2 = (u2& 0x38); u |= t1>t2?t1:t2;
402: t1 = (u1& 0x7); t2 = (u2& 0x7); u |= t1>t2?t1:t2;
403: d[i] = u;
404: }
405: break;
406: case 4:
407: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
408: u1 = d1[i]; u2 = d2[i];
409: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
410: t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
411: t1 = (u1& 0xf00000); t2 = (u2& 0xf00000); u |= t1>t2?t1:t2;
412: t1 = (u1& 0xf0000); t2 = (u2& 0xf0000); u |= t1>t2?t1:t2;
413: t1 = (u1& 0xf000); t2 = (u2& 0xf000); u |= t1>t2?t1:t2;
414: t1 = (u1& 0xf00); t2 = (u2& 0xf00); u |= t1>t2?t1:t2;
415: t1 = (u1& 0xf0); t2 = (u2& 0xf0); u |= t1>t2?t1:t2;
416: t1 = (u1& 0xf); t2 = (u2& 0xf); u |= t1>t2?t1:t2;
417: d[i] = u;
418: }
419: break;
420: case 6:
421: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
422: u1 = d1[i]; u2 = d2[i];
423: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
424: t1 = (u1& 0xfc0000); t2 = (u2& 0xfc0000); u |= t1>t2?t1:t2;
425: t1 = (u1& 0x3f000); t2 = (u2& 0x3f000); u |= t1>t2?t1:t2;
426: t1 = (u1& 0xfc0); t2 = (u2& 0xfc0); u |= t1>t2?t1:t2;
427: t1 = (u1& 0x3f); t2 = (u2& 0x3f); u |= t1>t2?t1:t2;
428: d[i] = u;
429: }
430: break;
431: case 8:
432: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
433: u1 = d1[i]; u2 = d2[i];
434: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
435: t1 = (u1& 0xff0000); t2 = (u2& 0xff0000); u |= t1>t2?t1:t2;
436: t1 = (u1& 0xff00); t2 = (u2& 0xff00); u |= t1>t2?t1:t2;
437: t1 = (u1& 0xff); t2 = (u2& 0xff); u |= t1>t2?t1:t2;
438: d[i] = u;
439: }
440: break;
441: case 16:
442: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
443: u1 = d1[i]; u2 = d2[i];
444: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
445: t1 = (u1& 0xffff); t2 = (u2& 0xffff); u |= t1>t2?t1:t2;
446: d[i] = u;
447: }
448: break;
449: case 32:
450: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
451: u1 = d1[i]; u2 = d2[i];
452: d[i] = u1>u2?u1:u2;
453: }
454: break;
455: default:
456: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
457: u1 = d1[i]; u2 = d2[i];
458: for ( j = 0, u = 0; j < nd_epw; j++ ) {
459: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
460: }
461: d[i] = u;
462: }
463: break;
464: }
465: #else
466: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
467: u1 = d1[i]; u2 = d2[i];
468: for ( j = 0, u = 0; j < nd_epw; j++ ) {
469: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
470: }
471: d[i] = u;
472: }
473: #endif
474: if ( nd_module ) MPOS(d) = MPOS(d1);
475: TD(d) = ndl_weight(d);
476: if ( nd_blockmask ) ndl_weight_mask(d);
477: }
478:
479: void ndl_max(UINT *d1,unsigned *d2,UINT *d)
480: {
481: UINT t1,t2,u,u1,u2;
482: int i,j,l;
483:
484: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
485: u1 = d1[i]; u2 = d2[i];
486: for ( j = 0, u = 0; j < nd_epw; j++ ) {
487: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
488: }
489: d[i] = u;
490: }
491: }
492:
493: int ndl_weight(UINT *d)
494: {
495: UINT t,u;
496: int i,j;
497:
498: if ( current_dl_weight_vector )
499: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
500: u = GET_EXP(d,i);
501: t += MUL_WEIGHT(u,i);
502: }
503: else
504: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
505: u = d[i];
506: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
507: t += (u&nd_mask0);
508: }
1.20 noro 509: if ( nd_module && nd_module_rank && MPOS(d) )
510: t += nd_module_weight[MPOS(d)-1];
511: for ( i = nd_exporigin; i < nd_wpd; i++ )
512: if ( d[i] && !t )
513: printf("afo\n");
1.1 noro 514: return t;
515: }
516:
517: /* for sugarweight */
518:
519: int ndl_weight2(UINT *d)
520: {
521: int t,u;
522: int i,j;
523:
524: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
525: u = GET_EXP(d,i);
526: t += nd_sugarweight[i]*u;
527: }
1.20 noro 528: if ( nd_module && nd_module_rank && MPOS(d) )
529: t += nd_module_weight[MPOS(d)-1];
1.1 noro 530: return t;
531: }
532:
533: void ndl_weight_mask(UINT *d)
534: {
535: UINT t,u;
536: UINT *mask;
537: int i,j,k,l;
538:
539: l = nd_blockmask->n;
540: for ( k = 0; k < l; k++ ) {
541: mask = nd_blockmask->mask[k];
542: if ( current_dl_weight_vector )
543: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
544: u = GET_EXP_MASK(d,i,mask);
545: t += MUL_WEIGHT(u,i);
546: }
547: else
548: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
549: u = d[i]&mask[i];
550: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
551: t += (u&nd_mask0);
552: }
553: d[k+1] = t;
554: }
555: }
556:
1.21 noro 557: int ndl_glex_compare(UINT *d1,UINT *d2)
558: {
559: if ( TD(d1) > TD(d2) ) return 1;
560: else if ( TD(d1) < TD(d2) ) return -1;
561: else return ndl_lex_compare(d1,d2);
562: }
563:
1.1 noro 564: int ndl_lex_compare(UINT *d1,UINT *d2)
565: {
566: int i;
567:
568: d1 += nd_exporigin;
569: d2 += nd_exporigin;
570: for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
571: if ( *d1 > *d2 )
572: return nd_isrlex ? -1 : 1;
573: else if ( *d1 < *d2 )
574: return nd_isrlex ? 1 : -1;
575: return 0;
576: }
577:
578: int ndl_block_compare(UINT *d1,UINT *d2)
579: {
580: int i,l,j,ord_o,ord_l;
581: struct order_pair *op;
582: UINT t1,t2,m;
583: UINT *mask;
584:
585: l = nd_blockmask->n;
586: op = nd_blockmask->order_pair;
587: for ( j = 0; j < l; j++ ) {
588: mask = nd_blockmask->mask[j];
589: ord_o = op[j].order;
590: if ( ord_o < 2 ) {
591: if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
592: else if ( t1 < t2 ) return -1;
593: }
594: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
595: m = mask[i];
596: t1 = d1[i]&m;
597: t2 = d2[i]&m;
598: if ( t1 > t2 )
599: return !ord_o ? -1 : 1;
600: else if ( t1 < t2 )
601: return !ord_o ? 1 : -1;
602: }
603: }
604: return 0;
605: }
606:
607: int ndl_matrix_compare(UINT *d1,UINT *d2)
608: {
609: int i,j,s,row;
610: int *v;
611: Z **mat;
612: Z *w;
613: Z t1;
614: Z t,t2;
615:
1.6 noro 616: for ( j = 0; j < nd_nvar; j++ )
617: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
1.1 noro 618: if ( nd_top_weight ) {
619: if ( OID(nd_top_weight) == O_VECT ) {
1.6 noro 620: mat = (Z **)&BDY((VECT)nd_top_weight);
621: row = 1;
1.1 noro 622: } else {
623: mat = (Z **)BDY((MAT)nd_top_weight);
1.6 noro 624: row = ((MAT)nd_top_weight)->row;
1.1 noro 625: }
626: for ( i = 0; i < row; i++ ) {
1.6 noro 627: w = mat[i];
1.1 noro 628: for ( j = 0, t = 0; j < nd_nvar; j++ ) {
1.6 noro 629: STOZ(nd_work_vector[j],t1);
1.1 noro 630: mulz(w[j],t1,&t2);
631: addz(t,t2,&t1);
632: t = t1;
633: }
1.6 noro 634: if ( t ) {
635: s = sgnz(t);
1.1 noro 636: if ( s > 0 ) return 1;
637: else if ( s < 0 ) return -1;
1.6 noro 638: }
1.1 noro 639: }
1.6 noro 640: }
641: for ( i = 0; i < nd_matrix_len; i++ ) {
642: v = nd_matrix[i];
643: for ( j = 0, s = 0; j < nd_nvar; j++ )
644: s += v[j]*nd_work_vector[j];
645: if ( s > 0 ) return 1;
646: else if ( s < 0 ) return -1;
647: }
1.1 noro 648: if ( !ndl_equal(d1,d2) )
1.6 noro 649: error("ndl_matrix_compare : invalid matrix");
650: return 0;
1.1 noro 651: }
652:
653: int ndl_composite_compare(UINT *d1,UINT *d2)
654: {
655: int i,j,s,start,end,len,o;
656: int *v;
657: struct sparse_weight *sw;
658:
659: for ( j = 0; j < nd_nvar; j++ )
660: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
661: for ( i = 0; i < nd_worb_len; i++ ) {
662: len = nd_worb[i].length;
663: switch ( nd_worb[i].type ) {
664: case IS_DENSE_WEIGHT:
665: v = nd_worb[i].body.dense_weight;
666: for ( j = 0, s = 0; j < len; j++ )
667: s += v[j]*nd_work_vector[j];
668: if ( s > 0 ) return 1;
669: else if ( s < 0 ) return -1;
670: break;
671: case IS_SPARSE_WEIGHT:
672: sw = nd_worb[i].body.sparse_weight;
673: for ( j = 0, s = 0; j < len; j++ )
674: s += sw[j].value*nd_work_vector[sw[j].pos];
675: if ( s > 0 ) return 1;
676: else if ( s < 0 ) return -1;
677: break;
678: case IS_BLOCK:
679: o = nd_worb[i].body.block.order;
680: start = nd_worb[i].body.block.start;
681: switch ( o ) {
682: case 0:
683: end = start+len;
684: for ( j = start, s = 0; j < end; j++ )
685: s += MUL_WEIGHT(nd_work_vector[j],j);
686: if ( s > 0 ) return 1;
687: else if ( s < 0 ) return -1;
688: for ( j = end-1; j >= start; j-- )
689: if ( nd_work_vector[j] < 0 ) return 1;
690: else if ( nd_work_vector[j] > 0 ) return -1;
691: break;
692: case 1:
693: end = start+len;
694: for ( j = start, s = 0; j < end; j++ )
695: s += MUL_WEIGHT(nd_work_vector[j],j);
696: if ( s > 0 ) return 1;
697: else if ( s < 0 ) return -1;
698: for ( j = start; j < end; j++ )
699: if ( nd_work_vector[j] > 0 ) return 1;
700: else if ( nd_work_vector[j] < 0 ) return -1;
701: break;
702: case 2:
703: end = start+len;
704: for ( j = start; j < end; j++ )
705: if ( nd_work_vector[j] > 0 ) return 1;
706: else if ( nd_work_vector[j] < 0 ) return -1;
707: break;
708: }
709: break;
710: }
711: }
712: return 0;
713: }
714:
715: /* TDH -> WW -> TD-> RL */
716:
717: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
718: {
719: int i,m,e1,e2;
720:
721: if ( TD(d1) > TD(d2) ) return 1;
722: else if ( TD(d1) < TD(d2) ) return -1;
723: m = nd_nvar>>1;
724: for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
725: e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
726: e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
727: }
728: if ( e1 > e2 ) return 1;
729: else if ( e1 < e2 ) return -1;
730: return ndl_lex_compare(d1,d2);
731: }
732:
1.21 noro 733: // common function for module glex and grlex comparison
734: int ndl_module_glex_compare(UINT *d1,UINT *d2)
1.1 noro 735: {
1.21 noro 736: int c;
1.1 noro 737:
1.21 noro 738: switch ( nd_module_ordtype ) {
739: case 0:
740: if ( TD(d1) > TD(d2) ) return 1;
741: else if ( TD(d1) < TD(d2) ) return -1;
742: else if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
743: else if ( MPOS(d1) < MPOS(d2) ) return 1;
744: else if ( MPOS(d1) > MPOS(d2) ) return -1;
745: else return 0;
746: break;
1.1 noro 747:
1.21 noro 748: case 1:
1.19 noro 749: if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) {
750: if ( TD(d1) > TD(d2) ) return 1;
751: else if ( TD(d1) < TD(d2) ) return -1;
752: if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
753: if ( MPOS(d1) < MPOS(d2) ) return 1;
754: else if ( MPOS(d1) > MPOS(d2) ) return -1;
755: }
756: if ( MPOS(d1) < MPOS(d2) ) return 1;
757: else if ( MPOS(d1) > MPOS(d2) ) return -1;
1.21 noro 758: else if ( TD(d1) > TD(d2) ) return 1;
759: else if ( TD(d1) < TD(d2) ) return -1;
760: else return ndl_lex_compare(d1,d2);
761: break;
1.1 noro 762:
1.21 noro 763: case 2: // weight -> POT
764: if ( TD(d1) > TD(d2) ) return 1;
765: else if ( TD(d1) < TD(d2) ) return -1;
766: else if ( MPOS(d1) < MPOS(d2) ) return 1;
767: else if ( MPOS(d1) > MPOS(d2) ) return -1;
768: else return ndl_lex_compare(d1,d2);
769: break;
1.1 noro 770:
1.21 noro 771: default:
772: error("ndl_module_glex_compare : invalid module_ordtype");
1.28 noro 773: return 0;
1.21 noro 774: }
1.1 noro 775: }
776:
1.21 noro 777: // common for module comparison
778: int ndl_module_compare(UINT *d1,UINT *d2)
1.1 noro 779: {
1.21 noro 780: int c;
1.1 noro 781:
1.21 noro 782: switch ( nd_module_ordtype ) {
783: case 0:
1.23 noro 784: if ( (c = (*ndl_base_compare_function)(d1,d2)) != 0 ) return c;
1.21 noro 785: else if ( MPOS(d1) > MPOS(d2) ) return -1;
786: else if ( MPOS(d1) < MPOS(d2) ) return 1;
787: else return 0;
788: break;
1.1 noro 789:
1.21 noro 790: case 1:
791: if ( MPOS(d1) < MPOS(d2) ) return 1;
792: else if ( MPOS(d1) > MPOS(d2) ) return -1;
793: else return (*ndl_base_compare_function)(d1,d2);
794: break;
1.1 noro 795:
1.21 noro 796: case 2: // weight -> POT
797: if ( TD(d1) > TD(d2) ) return 1;
798: else if ( TD(d1) < TD(d2) ) return -1;
799: else if ( MPOS(d1) < MPOS(d2) ) return 1;
800: else if ( MPOS(d1) > MPOS(d2) ) return -1;
801: else return (*ndl_base_compare_function)(d1,d2);
802: break;
1.1 noro 803:
1.21 noro 804: default:
805: error("ndl_module_compare : invalid module_ordtype");
1.28 noro 806: return 0;
1.21 noro 807: }
1.1 noro 808: }
809:
1.21 noro 810: extern DMMstack dmm_stack;
811: void _addtodl(int n,DL d1,DL d2);
1.31 noro 812: void _adddl(int n,DL d1,DL d2,DL d3);
1.21 noro 813: int _eqdl(int n,DL d1,DL d2);
814:
815: int ndl_module_schreyer_compare(UINT *m1,UINT *m2)
816: {
1.44 noro 817: int pos1,pos2,t,j,retpot;
1.21 noro 818: DMM *in;
819: DMMstack s;
820: static DL d1=0;
821: static DL d2=0;
822: static int dlen=0;
1.44 noro 823: extern int ReversePOT;
1.21 noro 824:
1.44 noro 825: if ( ReversePOT ) retpot = -1;
826: else retpot = 1;
1.21 noro 827: pos1 = MPOS(m1); pos2 = MPOS(m2);
828: if ( pos1 == pos2 ) return (*ndl_base_compare_function)(m1,m2);
829: if ( nd_nvar > dlen ) {
830: NEWDL(d1,nd_nvar);
831: NEWDL(d2,nd_nvar);
832: dlen = nd_nvar;
833: }
834: d1->td = TD(m1);
835: for ( j = 0; j < nd_nvar; j++ ) d1->d[j] = GET_EXP(m1,j);
836: d2->td = TD(m2);
837: for ( j = 0; j < nd_nvar; j++ ) d2->d[j] = GET_EXP(m2,j);
838: for ( s = dmm_stack; s; s = NEXT(s) ) {
839: in = s->in;
840: _addtodl(nd_nvar,in[pos1]->dl,d1);
841: _addtodl(nd_nvar,in[pos2]->dl,d2);
842: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(nd_nvar,d1,d2)) {
1.44 noro 843: if ( pos1 < pos2 ) return retpot;
844: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 845: else return 0;
846: }
847: pos1 = in[pos1]->pos;
848: pos2 = in[pos2]->pos;
849: if ( pos1 == pos2 ) return (*dl_base_compare_function)(nd_nvar,d1,d2);
850: }
851: // comparison by the bottom order
852: LAST:
853: switch ( nd_base_ordtype ) {
854: case 0:
855: t = (*dl_base_compare_function)(nd_nvar,d1,d2);
856: if ( t ) return t;
1.44 noro 857: else if ( pos1 < pos2 ) return retpot;
858: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 859: else return 0;
860: break;
861: case 1:
1.44 noro 862: if ( pos1 < pos2 ) return retpot;
863: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 864: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
865: break;
866: case 2:
867: if ( d1->td > d2->td ) return 1;
868: else if ( d1->td < d2->td ) return -1;
1.44 noro 869: else if ( pos1 < pos2 ) return retpot;
870: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 871: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
872: break;
873: default:
874: error("ndl_schreyer_compare : invalid base ordtype");
1.28 noro 875: return 0;
1.21 noro 876: }
1.1 noro 877: }
878:
879: INLINE int ndl_equal(UINT *d1,UINT *d2)
880: {
881: int i;
882:
883: switch ( nd_wpd ) {
884: case 2:
885: if ( TD(d2) != TD(d1) ) return 0;
886: if ( d2[1] != d1[1] ) return 0;
887: return 1;
888: break;
889: case 3:
890: if ( TD(d2) != TD(d1) ) return 0;
891: if ( d2[1] != d1[1] ) return 0;
892: if ( d2[2] != d1[2] ) return 0;
893: return 1;
894: break;
895: default:
896: for ( i = 0; i < nd_wpd; i++ )
897: if ( *d1++ != *d2++ ) return 0;
898: return 1;
899: break;
900: }
901: }
902:
903: INLINE void ndl_copy(UINT *d1,UINT *d2)
904: {
905: int i;
906:
907: switch ( nd_wpd ) {
908: case 2:
909: TD(d2) = TD(d1);
910: d2[1] = d1[1];
911: break;
912: case 3:
913: TD(d2) = TD(d1);
914: d2[1] = d1[1];
915: d2[2] = d1[2];
916: break;
917: default:
918: for ( i = 0; i < nd_wpd; i++ )
919: d2[i] = d1[i];
920: break;
921: }
922: }
923:
924: INLINE void ndl_zero(UINT *d)
925: {
926: int i;
927: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
928: }
929:
930: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
931: {
932: int i;
933:
934: if ( nd_module ) {
935: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
936: error("ndl_add : invalid operation");
937: }
938: #if 1
939: switch ( nd_wpd ) {
940: case 2:
941: TD(d) = TD(d1)+TD(d2);
942: d[1] = d1[1]+d2[1];
943: break;
944: case 3:
945: TD(d) = TD(d1)+TD(d2);
946: d[1] = d1[1]+d2[1];
947: d[2] = d1[2]+d2[2];
948: break;
949: default:
950: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
951: break;
952: }
953: #else
954: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
955: #endif
956: }
957:
958: /* d1 += d2 */
959: INLINE void ndl_addto(UINT *d1,UINT *d2)
960: {
961: int i;
962:
963: if ( nd_module ) {
964: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
965: error("ndl_addto : invalid operation");
966: }
967: #if 1
968: switch ( nd_wpd ) {
969: case 2:
970: TD(d1) += TD(d2);
971: d1[1] += d2[1];
972: break;
973: case 3:
974: TD(d1) += TD(d2);
975: d1[1] += d2[1];
976: d1[2] += d2[2];
977: break;
978: default:
979: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
980: break;
981: }
982: #else
983: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
984: #endif
985: }
986:
987: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
988: {
989: int i;
990:
991: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
992: }
993:
994: int ndl_disjoint(UINT *d1,UINT *d2)
995: {
996: UINT t1,t2,u,u1,u2;
997: int i,j;
998:
999: if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
1000: #if USE_UNROLL
1001: switch ( nd_bpe ) {
1002: case 3:
1003: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1004: u1 = d1[i]; u2 = d2[i];
1005: t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
1006: t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
1007: t1 = u1& 0xe00000; t2 = u2& 0xe00000; if ( t1&&t2 ) return 0;
1008: t1 = u1& 0x1c0000; t2 = u2& 0x1c0000; if ( t1&&t2 ) return 0;
1009: t1 = u1& 0x38000; t2 = u2& 0x38000; if ( t1&&t2 ) return 0;
1010: t1 = u1& 0x7000; t2 = u2& 0x7000; if ( t1&&t2 ) return 0;
1011: t1 = u1& 0xe00; t2 = u2& 0xe00; if ( t1&&t2 ) return 0;
1012: t1 = u1& 0x1c0; t2 = u2& 0x1c0; if ( t1&&t2 ) return 0;
1013: t1 = u1& 0x38; t2 = u2& 0x38; if ( t1&&t2 ) return 0;
1014: t1 = u1& 0x7; t2 = u2& 0x7; if ( t1&&t2 ) return 0;
1015: }
1016: return 1;
1017: break;
1018: case 4:
1019: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1020: u1 = d1[i]; u2 = d2[i];
1021: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
1022: t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
1023: t1 = u1& 0xf00000; t2 = u2& 0xf00000; if ( t1&&t2 ) return 0;
1024: t1 = u1& 0xf0000; t2 = u2& 0xf0000; if ( t1&&t2 ) return 0;
1025: t1 = u1& 0xf000; t2 = u2& 0xf000; if ( t1&&t2 ) return 0;
1026: t1 = u1& 0xf00; t2 = u2& 0xf00; if ( t1&&t2 ) return 0;
1027: t1 = u1& 0xf0; t2 = u2& 0xf0; if ( t1&&t2 ) return 0;
1028: t1 = u1& 0xf; t2 = u2& 0xf; if ( t1&&t2 ) return 0;
1029: }
1030: return 1;
1031: break;
1032: case 6:
1033: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1034: u1 = d1[i]; u2 = d2[i];
1035: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1036: t1 = u1& 0xfc0000; t2 = u2& 0xfc0000; if ( t1&&t2 ) return 0;
1037: t1 = u1& 0x3f000; t2 = u2& 0x3f000; if ( t1&&t2 ) return 0;
1038: t1 = u1& 0xfc0; t2 = u2& 0xfc0; if ( t1&&t2 ) return 0;
1039: t1 = u1& 0x3f; t2 = u2& 0x3f; if ( t1&&t2 ) return 0;
1040: }
1041: return 1;
1042: break;
1043: case 8:
1044: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1045: u1 = d1[i]; u2 = d2[i];
1046: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1047: t1 = u1& 0xff0000; t2 = u2& 0xff0000; if ( t1&&t2 ) return 0;
1048: t1 = u1& 0xff00; t2 = u2& 0xff00; if ( t1&&t2 ) return 0;
1049: t1 = u1& 0xff; t2 = u2& 0xff; if ( t1&&t2 ) return 0;
1050: }
1051: return 1;
1052: break;
1053: case 16:
1054: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1055: u1 = d1[i]; u2 = d2[i];
1056: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1057: t1 = u1& 0xffff; t2 = u2& 0xffff; if ( t1&&t2 ) return 0;
1058: }
1059: return 1;
1060: break;
1061: case 32:
1062: for ( i = nd_exporigin; i < nd_wpd; i++ )
1063: if ( d1[i] && d2[i] ) return 0;
1064: return 1;
1065: break;
1066: default:
1067: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1068: u1 = d1[i]; u2 = d2[i];
1069: for ( j = 0; j < nd_epw; j++ ) {
1070: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1071: u1 >>= nd_bpe; u2 >>= nd_bpe;
1072: }
1073: }
1074: return 1;
1075: break;
1076: }
1077: #else
1078: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1079: u1 = d1[i]; u2 = d2[i];
1080: for ( j = 0; j < nd_epw; j++ ) {
1081: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1082: u1 >>= nd_bpe; u2 >>= nd_bpe;
1083: }
1084: }
1085: return 1;
1086: #endif
1087: }
1088:
1089: int ndl_check_bound(UINT *d1,UINT *d2)
1090: {
1091: UINT u2;
1092: int i,j,ind,k;
1093:
1094: ind = 0;
1095: #if USE_UNROLL
1096: switch ( nd_bpe ) {
1097: case 3:
1098: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1099: u2 = d2[i];
1100: if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
1101: if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
1102: if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
1103: if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
1104: if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
1105: if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
1106: if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
1107: if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
1108: if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
1109: if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
1110: }
1111: return 0;
1112: break;
1113: case 4:
1114: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1115: u2 = d2[i];
1116: if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
1117: if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
1118: if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
1119: if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
1120: if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
1121: if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
1122: if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
1123: if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
1124: }
1125: return 0;
1126: break;
1127: case 6:
1128: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1129: u2 = d2[i];
1130: if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
1131: if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
1132: if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
1133: if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
1134: if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
1135: }
1136: return 0;
1137: break;
1138: case 8:
1139: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1140: u2 = d2[i];
1141: if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
1142: if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
1143: if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
1144: if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
1145: }
1146: return 0;
1147: break;
1148: case 16:
1149: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1150: u2 = d2[i];
1151: if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
1152: if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
1153: }
1154: return 0;
1155: break;
1156: case 32:
1157: for ( i = nd_exporigin; i < nd_wpd; i++ )
1158: if ( d1[i]+d2[i]<d1[i] ) return 1;
1159: return 0;
1160: break;
1161: default:
1162: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1163: u2 = d2[i];
1164: k = (nd_epw-1)*nd_bpe;
1165: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1166: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1167: }
1168: return 0;
1169: break;
1170: }
1171: #else
1172: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1173: u2 = d2[i];
1174: k = (nd_epw-1)*nd_bpe;
1175: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1176: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1177: }
1178: return 0;
1179: #endif
1180: }
1181:
1182: int ndl_check_bound2(int index,UINT *d2)
1183: {
1184: return ndl_check_bound(nd_bound[index],d2);
1185: }
1186:
1187: INLINE int ndl_hash_value(UINT *d)
1188: {
1189: int i;
1.11 noro 1190: UINT r;
1.1 noro 1191:
1192: r = 0;
1193: for ( i = 0; i < nd_wpd; i++ )
1.12 noro 1194: r = (r*1511+d[i]);
1.11 noro 1195: r %= REDTAB_LEN;
1.1 noro 1196: return r;
1197: }
1198:
1199: INLINE int ndl_find_reducer(UINT *dg)
1200: {
1201: RHist r;
1202: int d,k,i;
1203:
1204: d = ndl_hash_value(dg);
1205: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1206: if ( ndl_equal(dg,DL(r)) ) {
1207: if ( k > 0 ) nd_notfirst++;
1208: nd_found++;
1209: return r->index;
1210: }
1211: }
1212: if ( Reverse )
1213: for ( i = nd_psn-1; i >= 0; i-- ) {
1214: r = nd_psh[i];
1215: if ( ndl_reducible(dg,DL(r)) ) {
1216: nd_create++;
1217: nd_append_red(dg,i);
1218: return i;
1219: }
1220: }
1221: else
1222: for ( i = 0; i < nd_psn; i++ ) {
1223: r = nd_psh[i];
1224: if ( ndl_reducible(dg,DL(r)) ) {
1225: nd_create++;
1226: nd_append_red(dg,i);
1227: return i;
1228: }
1229: }
1230: return -1;
1231: }
1232:
1.41 noro 1233: INLINE int ndl_find_reducer_nonsig(UINT *dg)
1234: {
1235: RHist r;
1236: int i;
1237:
1238: for ( i = 0; i < nd_psn; i++ ) {
1239: r = nd_psh[i];
1240: if ( ndl_reducible(dg,DL(r)) ) return i;
1241: }
1242: return -1;
1243: }
1244:
1.24 noro 1245: // ret=0,...,nd_psn-1 => reducer found
1246: // ret=nd_psn => reducer not found
1247: // ret=-1 => singular top reducible
1248:
1249: int comp_sig(SIG s1,SIG s2);
1250: void _ndltodl(UINT *ndl,DL dl);
1251:
1252: void print_sig(SIG s)
1253: {
1254: int i;
1255:
1256: fprintf(asir_out,"<<");
1257: for ( i = 0; i < nd_nvar; i++ ) {
1258: fprintf(asir_out,"%d",s->dl->d[i]);
1259: if ( i != nd_nvar-1 ) fprintf(asir_out,",");
1260: }
1261: fprintf(asir_out,">>*e%d",s->pos);
1262: }
1263:
1.45 noro 1264: void print_siglist(NODE l)
1265: {
1266: for ( ; l; l = NEXT(l) )
1267: print_sig((SIG)l->body);
1268: }
1269:
1270:
1.35 noro 1271: // assuming increasing order wrt signature
1272:
1.24 noro 1273: INLINE int ndl_find_reducer_s(UINT *dg,SIG sig)
1274: {
1275: RHist r;
1.27 noro 1276: int i,singular,ret,d,k;
1.26 noro 1277: static int wpd,nvar;
1.24 noro 1278: static SIG quo;
1279: static UINT *tmp;
1280:
1.26 noro 1281: if ( !quo || nvar != nd_nvar ) NEWSIG(quo);
1282: if ( wpd != nd_wpd ) {
1.24 noro 1283: wpd = nd_wpd;
1284: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
1285: }
1.27 noro 1286: d = ndl_hash_value(dg);
1.35 noro 1287: #if 1
1.27 noro 1288: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1289: if ( ndl_equal(dg,DL(r)) ) {
1290: return r->index;
1291: }
1292: }
1.35 noro 1293: #endif
1.24 noro 1294: singular = 0;
1295: for ( i = 0; i < nd_psn; i++ ) {
1296: r = nd_psh[i];
1297: if ( ndl_reducible(dg,DL(r)) ) {
1.27 noro 1298: ndl_sub(dg,DL(r),tmp);
1.24 noro 1299: _ndltodl(tmp,DL(quo));
1300: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
1301: quo->pos = nd_psh[i]->sig->pos;
1302: ret = comp_sig(sig,quo);
1303: if ( ret > 0 ) { singular = 0; break; }
1.38 noro 1304: if ( ret == 0 ) { /* fprintf(asir_out,"s"); fflush(asir_out); */ singular = 1; }
1.24 noro 1305: }
1306: }
1307: if ( singular ) return -1;
1.27 noro 1308: else if ( i < nd_psn )
1309: nd_append_red(dg,i);
1310: return i;
1.24 noro 1311: }
1312:
1.1 noro 1313: ND nd_merge(ND p1,ND p2)
1314: {
1315: int n,c;
1316: int t,can,td1,td2;
1317: ND r;
1318: NM m1,m2,mr0,mr,s;
1319:
1320: if ( !p1 ) return p2;
1321: else if ( !p2 ) return p1;
1322: else {
1323: can = 0;
1324: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1325: c = DL_COMPARE(DL(m1),DL(m2));
1326: switch ( c ) {
1327: case 0:
1328: s = m1; m1 = NEXT(m1);
1329: can++; NEXTNM2(mr0,mr,s);
1330: s = m2; m2 = NEXT(m2); FREENM(s);
1331: break;
1332: case 1:
1333: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1334: break;
1335: case -1:
1336: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1337: break;
1338: }
1339: }
1340: if ( !mr0 )
1341: if ( m1 ) mr0 = m1;
1342: else if ( m2 ) mr0 = m2;
1343: else return 0;
1344: else if ( m1 ) NEXT(mr) = m1;
1345: else if ( m2 ) NEXT(mr) = m2;
1346: else NEXT(mr) = 0;
1347: BDY(p1) = mr0;
1348: SG(p1) = MAX(SG(p1),SG(p2));
1349: LEN(p1) = LEN(p1)+LEN(p2)-can;
1350: FREEND(p2);
1351: return p1;
1352: }
1353: }
1354:
1355: ND nd_add(int mod,ND p1,ND p2)
1356: {
1357: int n,c;
1358: int t,can,td1,td2;
1359: ND r;
1360: NM m1,m2,mr0,mr,s;
1361:
1.11 noro 1362: Nnd_add++;
1.1 noro 1363: if ( !p1 ) return p2;
1364: else if ( !p2 ) return p1;
1365: else if ( mod == -1 ) return nd_add_sf(p1,p2);
1366: else if ( mod == -2 ) return nd_add_lf(p1,p2);
1367: else if ( !mod ) return nd_add_q(p1,p2);
1368: else {
1369: can = 0;
1370: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1371: c = DL_COMPARE(DL(m1),DL(m2));
1372: switch ( c ) {
1373: case 0:
1374: t = ((CM(m1))+(CM(m2))) - mod;
1375: if ( t < 0 ) t += mod;
1376: s = m1; m1 = NEXT(m1);
1377: if ( t ) {
1378: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1379: } else {
1380: can += 2; FREENM(s);
1381: }
1382: s = m2; m2 = NEXT(m2); FREENM(s);
1383: break;
1384: case 1:
1385: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1386: break;
1387: case -1:
1388: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1389: break;
1390: }
1391: }
1392: if ( !mr0 )
1393: if ( m1 ) mr0 = m1;
1394: else if ( m2 ) mr0 = m2;
1395: else return 0;
1396: else if ( m1 ) NEXT(mr) = m1;
1397: else if ( m2 ) NEXT(mr) = m2;
1398: else NEXT(mr) = 0;
1399: BDY(p1) = mr0;
1400: SG(p1) = MAX(SG(p1),SG(p2));
1401: LEN(p1) = LEN(p1)+LEN(p2)-can;
1402: FREEND(p2);
1403: return p1;
1404: }
1405: }
1406:
1407: /* XXX on opteron, the inlined manipulation of destructive additon of
1408: * two NM seems to make gcc optimizer get confused, so the part is
1409: * done in a function.
1410: */
1411:
1412: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1413: {
1414: NM s;
1415: P t;
1416: int can;
1417:
1418: addp(nd_vc,CP(*m1),CP(*m2),&t);
1419: s = *m1; *m1 = NEXT(*m1);
1420: if ( t ) {
1421: can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
1422: } else {
1423: can = 2; FREENM(s);
1424: }
1425: s = *m2; *m2 = NEXT(*m2); FREENM(s);
1426: return can;
1427: }
1428:
1429: ND nd_add_q(ND p1,ND p2)
1430: {
1431: int n,c,can;
1432: ND r;
1433: NM m1,m2,mr0,mr,s;
1434: P t;
1435:
1436: if ( !p1 ) return p2;
1437: else if ( !p2 ) return p1;
1438: else {
1439: can = 0;
1440: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1441: c = DL_COMPARE(DL(m1),DL(m2));
1442: switch ( c ) {
1443: case 0:
1444: #if defined(__x86_64__)
1445: can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1446: #else
1447: addp(nd_vc,CP(m1),CP(m2),&t);
1448: s = m1; m1 = NEXT(m1);
1449: if ( t ) {
1450: can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
1451: } else {
1452: can += 2; FREENM(s);
1453: }
1454: s = m2; m2 = NEXT(m2); FREENM(s);
1455: #endif
1456: break;
1457: case 1:
1458: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1459: break;
1460: case -1:
1461: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1462: break;
1463: }
1464: }
1465: if ( !mr0 )
1466: if ( m1 ) mr0 = m1;
1467: else if ( m2 ) mr0 = m2;
1468: else return 0;
1469: else if ( m1 ) NEXT(mr) = m1;
1470: else if ( m2 ) NEXT(mr) = m2;
1471: else NEXT(mr) = 0;
1472: BDY(p1) = mr0;
1473: SG(p1) = MAX(SG(p1),SG(p2));
1474: LEN(p1) = LEN(p1)+LEN(p2)-can;
1475: FREEND(p2);
1476: return p1;
1477: }
1478: }
1479:
1480: ND nd_add_sf(ND p1,ND p2)
1481: {
1482: int n,c,can;
1483: ND r;
1484: NM m1,m2,mr0,mr,s;
1485: int t;
1486:
1487: if ( !p1 ) return p2;
1488: else if ( !p2 ) return p1;
1489: else {
1490: can = 0;
1491: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1492: c = DL_COMPARE(DL(m1),DL(m2));
1493: switch ( c ) {
1494: case 0:
1495: t = _addsf(CM(m1),CM(m2));
1496: s = m1; m1 = NEXT(m1);
1497: if ( t ) {
1498: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1499: } else {
1500: can += 2; FREENM(s);
1501: }
1502: s = m2; m2 = NEXT(m2); FREENM(s);
1503: break;
1504: case 1:
1505: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1506: break;
1507: case -1:
1508: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1509: break;
1510: }
1511: }
1512: if ( !mr0 )
1513: if ( m1 ) mr0 = m1;
1514: else if ( m2 ) mr0 = m2;
1515: else return 0;
1516: else if ( m1 ) NEXT(mr) = m1;
1517: else if ( m2 ) NEXT(mr) = m2;
1518: else NEXT(mr) = 0;
1519: BDY(p1) = mr0;
1520: SG(p1) = MAX(SG(p1),SG(p2));
1521: LEN(p1) = LEN(p1)+LEN(p2)-can;
1522: FREEND(p2);
1523: return p1;
1524: }
1525: }
1526:
1527:
1528: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn,Obj *divp)
1529: {
1530: int c,c1,c2;
1531: Z cg,cred,gcd,tq;
1532: P cgp,credp,gcdp;
1533: Obj tr,tr1;
1534:
1535: if ( mod == -1 ) {
1536: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1537: *divp = (Obj)ONE;
1538: } else if ( mod == -2 ) {
1539: Z inv,t;
1540: divlf(ONE,HCZ(p),&inv);
1541: chsgnlf(HCZ(g),&t);
1542: mullf(inv,t,&CZ(mul));
1543: *divp = (Obj)ONE;
1544: } else if ( mod ) {
1545: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1546: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1547: *divp = (Obj)ONE;
1548: } else if ( nd_vc ) {
1549: ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
1550: divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
1551: chsgnp(cgp,&CP(mul));
1552: nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
1553: if ( dn ) {
1554: mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
1555: reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
1556: }
1557: *divp = (Obj)credp;
1558: } else {
1.6 noro 1559: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1560: chsgnz(cg,&CZ(mul));
1.1 noro 1561: nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
1562: if ( dn ) {
1563: mulz(dn->z,cred,&tq); dn->z = tq;
1564: }
1565: *divp = (Obj)cred;
1566: }
1567: return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1568: }
1569:
1570: /* ret=1 : success, ret=0 : overflow */
1.6 noro 1571: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1.1 noro 1572: {
1573: NM m,mrd,tail;
1574: NM mul;
1575: int n,sugar,psugar,sugar0,stat,index;
1576: int c,c1,c2,dummy;
1577: RHist h;
1578: NDV p,red;
1579: Q cg,cred,gcd,tq,qq;
1580: Z iq;
1581: DP dmul;
1582: NODE node;
1583: LIST hist;
1584: double hmag;
1585: P tp,tp1;
1586: Obj tr,tr1,div;
1587: union oNDC hg;
1588: P cont;
1589:
1590: if ( !g ) {
1591: *rp = d;
1592: return 1;
1593: }
1594: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1595:
1596: sugar0 = sugar = SG(g);
1597: n = NV(g);
1598: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1599: if ( d )
1600: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1601: for ( ; g; ) {
1602: index = ndl_find_reducer(HDL(g));
1603: if ( index >= 0 ) {
1604: h = nd_psh[index];
1605: ndl_sub(HDL(g),DL(h),DL(mul));
1606: if ( ndl_check_bound2(index,DL(mul)) ) {
1607: nd_free(g); nd_free(d);
1608: return 0;
1609: }
1610: p = nd_demand ? ndv_load(index) : ps[index];
1611: /* d+g -> div*(d+g)+mul*p */
1.6 noro 1612: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1.1 noro 1613: if ( nd_gentrace ) {
1614: /* Trace=[div,index,mul,ONE] */
1.6 noro 1615: STOZ(index,iq);
1.1 noro 1616: nmtodp(mod,mul,&dmul);
1617: node = mknode(4,div,iq,dmul,ONE);
1618: }
1619: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1620: if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) {
1621: hg = HCU(g);
1622: nd_removecont2(d,g);
1.6 noro 1623: if ( nd_gentrace ) {
1.1 noro 1624: /* overwrite cont : Trace=[div,index,mul,cont] */
1.6 noro 1625: /* exact division */
1.1 noro 1626: cont = ndc_div(mod,hg,HCU(g));
1627: if ( nd_gentrace && !UNIQ(cont) ) ARG3(node) = (pointer)cont;
1628: }
1629: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1630: }
1631: MKLIST(hist,node);
1632: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1633: } else if ( !full ) {
1634: *rp = g;
1635: return 1;
1636: } else {
1637: m = BDY(g);
1638: if ( NEXT(m) ) {
1639: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1640: } else {
1641: FREEND(g); g = 0;
1642: }
1643: if ( d ) {
1644: NEXT(tail)=m; tail=m; LEN(d)++;
1645: } else {
1646: MKND(n,m,1,d); tail = BDY(d);
1647: }
1648: }
1649: }
1650: if ( d ) SG(d) = sugar;
1651: *rp = d;
1652: return 1;
1653: }
1654:
1.24 noro 1655: // ret=1 => success
1656: // ret=0 => overflow
1657: // ret=-1 => singular top reducible
1658:
1659: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1660: {
1661: NM m,mrd,tail;
1662: NM mul;
1663: int n,sugar,psugar,sugar0,stat,index;
1664: int c,c1,c2,dummy;
1665: RHist h;
1666: NDV p,red;
1667: Q cg,cred,gcd,tq,qq;
1668: Z iq;
1669: DP dmul;
1670: NODE node;
1671: LIST hist;
1672: double hmag;
1673: P tp,tp1;
1674: Obj tr,tr1,div;
1675: union oNDC hg;
1676: P cont;
1677: SIG sig;
1678:
1679: if ( !g ) {
1680: *rp = d;
1681: return 1;
1682: }
1683: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1684:
1685: sugar0 = sugar = SG(g);
1686: n = NV(g);
1687: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1688: if ( d )
1689: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1690: sig = g->sig;
1691: for ( ; g; ) {
1692: index = ndl_find_reducer_s(HDL(g),sig);
1693: if ( index >= 0 && index < nd_psn ) {
1694: // reducer found
1695: h = nd_psh[index];
1696: ndl_sub(HDL(g),DL(h),DL(mul));
1697: if ( ndl_check_bound2(index,DL(mul)) ) {
1698: nd_free(g); nd_free(d);
1699: return 0;
1700: }
1701: p = ps[index];
1702: /* d+g -> div*(d+g)+mul*p */
1703: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1704: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1705: if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
1706: hg = HCU(g);
1707: nd_removecont2(d,g);
1708: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1709: }
1710: } else if ( index == -1 ) {
1711: // singular top reducible
1712: return -1;
1713: } else if ( !full ) {
1714: *rp = g;
1715: g->sig = sig;
1716: return 1;
1717: } else {
1718: m = BDY(g);
1719: if ( NEXT(m) ) {
1720: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1721: } else {
1722: FREEND(g); g = 0;
1723: }
1724: if ( d ) {
1725: NEXT(tail)=m; tail=m; LEN(d)++;
1726: } else {
1727: MKND(n,m,1,d); tail = BDY(d);
1728: }
1729: }
1730: }
1731: if ( d ) {
1732: SG(d) = sugar;
1733: d->sig = sig;
1734: }
1735: *rp = d;
1736: return 1;
1737: }
1738:
1.1 noro 1739: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1740: {
1741: int hindex,index;
1742: NDV p;
1743: ND u,d,red;
1744: NODE l;
1745: NM mul,m,mrd,tail;
1746: int sugar,psugar,n,h_reducible;
1747: PGeoBucket bucket;
1748: int c,c1,c2;
1749: Z cg,cred,gcd,zzz;
1750: RHist h;
1751: double hmag,gmag;
1752: int count = 0;
1753: int hcount = 0;
1754:
1755: if ( !g ) {
1756: *rp = 0;
1757: return 1;
1758: }
1759: sugar = SG(g);
1760: n = NV(g);
1.6 noro 1761: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1762: bucket = create_pbucket();
1763: add_pbucket(mod,bucket,g);
1764: d = 0;
1765: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1766: while ( 1 ) {
1767: if ( mod > 0 || mod == -1 )
1768: hindex = head_pbucket(mod,bucket);
1769: else if ( mod == -2 )
1770: hindex = head_pbucket_lf(bucket);
1771: else
1772: hindex = head_pbucket_q(bucket);
1773: if ( hindex < 0 ) {
1774: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1775: if ( d ) SG(d) = sugar;
1776: *rp = d;
1777: return 1;
1778: }
1779: g = bucket->body[hindex];
1780: index = ndl_find_reducer(HDL(g));
1781: if ( index >= 0 ) {
1782: count++;
1783: if ( !d ) hcount++;
1784: h = nd_psh[index];
1785: ndl_sub(HDL(g),DL(h),DL(mul));
1786: if ( ndl_check_bound2(index,DL(mul)) ) {
1787: nd_free(d);
1788: free_pbucket(bucket);
1789: *rp = 0;
1790: return 0;
1791: }
1792: p = ps[index];
1793: if ( mod == -1 )
1794: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1795: else if ( mod == -2 ) {
1796: Z inv,t;
1797: divlf(ONE,HCZ(p),&inv);
1798: chsgnlf(HCZ(g),&t);
1799: mullf(inv,t,&CZ(mul));
1800: } else if ( mod ) {
1801: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1802: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1803: } else {
1.6 noro 1804: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1805: chsgnz(cg,&CZ(mul));
1.1 noro 1806: nd_mul_c_q(d,(P)cred);
1807: mulq_pbucket(bucket,cred);
1808: g = bucket->body[hindex];
1.6 noro 1809: gmag = (double)p_mag((P)HCZ(g));
1.1 noro 1810: }
1811: red = ndv_mul_nm(mod,mul,p);
1812: bucket->body[hindex] = nd_remove_head(g);
1813: red = nd_remove_head(red);
1814: add_pbucket(mod,bucket,red);
1815: psugar = SG(p)+TD(DL(mul));
1816: sugar = MAX(sugar,psugar);
1817: if ( !mod && hmag && (gmag > hmag) ) {
1818: g = normalize_pbucket(mod,bucket);
1819: if ( !g ) {
1820: if ( d ) SG(d) = sugar;
1821: *rp = d;
1822: return 1;
1823: }
1824: nd_removecont2(d,g);
1.6 noro 1825: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1826: add_pbucket(mod,bucket,g);
1827: }
1828: } else if ( !full ) {
1829: g = normalize_pbucket(mod,bucket);
1830: if ( g ) SG(g) = sugar;
1831: *rp = g;
1832: return 1;
1833: } else {
1834: m = BDY(g);
1835: if ( NEXT(m) ) {
1836: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1837: } else {
1838: FREEND(g); g = 0;
1839: }
1840: bucket->body[hindex] = g;
1841: NEXT(m) = 0;
1842: if ( d ) {
1843: NEXT(tail)=m; tail=m; LEN(d)++;
1844: } else {
1845: MKND(n,m,1,d); tail = BDY(d);
1846: }
1847: }
1848: }
1849: }
1850:
1.25 noro 1851: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *rp)
1852: {
1853: int hindex,index;
1854: NDV p;
1855: ND u,d,red;
1856: NODE l;
1857: NM mul,m,mrd,tail;
1858: int sugar,psugar,n,h_reducible;
1859: PGeoBucket bucket;
1860: int c,c1,c2;
1861: Z cg,cred,gcd,zzz;
1862: RHist h;
1863: double hmag,gmag;
1864: int count = 0;
1865: int hcount = 0;
1866: SIG sig;
1867:
1868: if ( !g ) {
1869: *rp = 0;
1870: return 1;
1871: }
1872: sugar = SG(g);
1873: n = NV(g);
1874: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1875: bucket = create_pbucket();
1876: add_pbucket(mod,bucket,g);
1877: d = 0;
1878: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1879: sig = g->sig;
1880: while ( 1 ) {
1881: if ( mod > 0 || mod == -1 )
1882: hindex = head_pbucket(mod,bucket);
1883: else if ( mod == -2 )
1884: hindex = head_pbucket_lf(bucket);
1885: else
1886: hindex = head_pbucket_q(bucket);
1887: if ( hindex < 0 ) {
1888: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1889: if ( d ) {
1890: SG(d) = sugar;
1891: d->sig = sig;
1892: }
1893: *rp = d;
1894: return 1;
1895: }
1896: g = bucket->body[hindex];
1897: index = ndl_find_reducer_s(HDL(g),sig);
1898: if ( index >= 0 && index < nd_psn ) {
1899: count++;
1900: if ( !d ) hcount++;
1901: h = nd_psh[index];
1902: ndl_sub(HDL(g),DL(h),DL(mul));
1903: if ( ndl_check_bound2(index,DL(mul)) ) {
1904: nd_free(d);
1905: free_pbucket(bucket);
1906: *rp = 0;
1907: return 0;
1908: }
1909: p = ps[index];
1910: if ( mod == -1 )
1911: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1912: else if ( mod == -2 ) {
1913: Z inv,t;
1914: divlf(ONE,HCZ(p),&inv);
1915: chsgnlf(HCZ(g),&t);
1916: mullf(inv,t,&CZ(mul));
1917: } else if ( mod ) {
1918: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1919: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1920: } else {
1921: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1922: chsgnz(cg,&CZ(mul));
1923: nd_mul_c_q(d,(P)cred);
1924: mulq_pbucket(bucket,cred);
1925: g = bucket->body[hindex];
1926: gmag = (double)p_mag((P)HCZ(g));
1927: }
1928: red = ndv_mul_nm(mod,mul,p);
1929: bucket->body[hindex] = nd_remove_head(g);
1930: red = nd_remove_head(red);
1931: add_pbucket(mod,bucket,red);
1932: psugar = SG(p)+TD(DL(mul));
1933: sugar = MAX(sugar,psugar);
1934: if ( !mod && hmag && (gmag > hmag) ) {
1935: g = normalize_pbucket(mod,bucket);
1936: if ( !g ) {
1937: if ( d ) {
1938: SG(d) = sugar;
1939: d->sig = sig;
1940: }
1941: *rp = d;
1942: return 1;
1943: }
1944: nd_removecont2(d,g);
1945: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1946: add_pbucket(mod,bucket,g);
1947: }
1948: } else if ( index == -1 ) {
1949: // singular top reducible
1950: return -1;
1951: } else if ( !full ) {
1952: g = normalize_pbucket(mod,bucket);
1953: if ( g ) {
1954: SG(g) = sugar;
1955: g->sig = sig;
1956: }
1957: *rp = g;
1958: return 1;
1959: } else {
1960: m = BDY(g);
1961: if ( NEXT(m) ) {
1962: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1963: } else {
1964: FREEND(g); g = 0;
1965: }
1966: bucket->body[hindex] = g;
1967: NEXT(m) = 0;
1968: if ( d ) {
1969: NEXT(tail)=m; tail=m; LEN(d)++;
1970: } else {
1971: MKND(n,m,1,d); tail = BDY(d);
1972: }
1973: }
1974: }
1975: }
1976:
1.1 noro 1977: /* input : list of NDV, cand : list of NDV */
1978:
1979: int ndv_check_membership(int m,NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1980: {
1981: int n,i,stat;
1982: ND nf,d;
1983: NDV r;
1984: NODE t,s;
1985: union oNDC dn;
1986: Z q;
1987: LIST list;
1988:
1.24 noro 1989: ndv_setup(m,0,cand,nd_gentrace?1:0,1,0);
1.1 noro 1990: n = length(cand);
1991:
1992: if ( nd_gentrace ) { nd_alltracelist = 0; nd_tracelist = 0; }
1993: /* membercheck : list is a subset of Id(cand) ? */
1994: for ( t = input, i = 0; t; t = NEXT(t), i++ ) {
1995: again:
1996: nd_tracelist = 0;
1997: if ( nd_bpe > obpe )
1998: r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
1999: else
2000: r = (NDV)BDY(t);
2001: #if 0
2002: // moved to nd_f4_lf_trace()
2003: if ( m == -2 ) ndv_mod(m,r);
2004: #endif
2005: d = ndvtond(m,r);
1.6 noro 2006: stat = nd_nf(m,0,d,nd_ps,0,&nf);
1.1 noro 2007: if ( !stat ) {
2008: nd_reconstruct(0,0);
2009: goto again;
2010: } else if ( nf ) return 0;
2011: if ( nd_gentrace ) {
2012: nd_tracelist = reverse_node(nd_tracelist);
2013: MKLIST(list,nd_tracelist);
1.6 noro 2014: STOZ(i,q); s = mknode(2,q,list); MKLIST(list,s);
1.1 noro 2015: MKNODE(s,list,nd_alltracelist);
2016: nd_alltracelist = s; nd_tracelist = 0;
2017: }
2018: if ( DP_Print ) { printf("."); fflush(stdout); }
2019: }
2020: if ( DP_Print ) { printf("\n"); }
2021: return 1;
2022: }
2023:
2024: ND nd_remove_head(ND p)
2025: {
2026: NM m;
2027:
2028: m = BDY(p);
2029: if ( !NEXT(m) ) {
2030: FREEND(p); p = 0;
2031: } else {
2032: BDY(p) = NEXT(m); LEN(p)--;
2033: }
2034: FREENM(m);
2035: return p;
2036: }
2037:
2038: ND nd_separate_head(ND p,ND *head)
2039: {
2040: NM m,m0;
2041: ND r;
2042:
2043: m = BDY(p);
2044: if ( !NEXT(m) ) {
2045: *head = p; p = 0;
2046: } else {
2047: m0 = m;
2048: BDY(p) = NEXT(m); LEN(p)--;
2049: NEXT(m0) = 0;
2050: MKND(NV(p),m0,1,r);
2051: *head = r;
2052: }
2053: return p;
2054: }
2055:
2056: PGeoBucket create_pbucket()
2057: {
2058: PGeoBucket g;
2059:
2060: g = CALLOC(1,sizeof(struct oPGeoBucket));
2061: g->m = -1;
2062: return g;
2063: }
2064:
2065: void free_pbucket(PGeoBucket b) {
2066: int i;
2067:
2068: for ( i = 0; i <= b->m; i++ )
2069: if ( b->body[i] ) {
2070: nd_free(b->body[i]);
2071: b->body[i] = 0;
2072: }
2073: GCFREE(b);
2074: }
2075:
1.39 noro 2076: #if 0
1.1 noro 2077: void add_pbucket_symbolic(PGeoBucket g,ND d)
2078: {
2079: int l,i,k,m;
2080:
2081: if ( !d )
2082: return;
2083: l = LEN(d);
2084: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2085: /* 2^(k-1) < l <= 2^k (=m) */
2086: d = nd_merge(g->body[k],d);
2087: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2088: g->body[k] = 0;
2089: d = nd_merge(g->body[k+1],d);
2090: }
2091: g->body[k] = d;
2092: g->m = MAX(g->m,k);
2093: }
1.39 noro 2094: #else
2095: void add_pbucket_symbolic(PGeoBucket g,ND d)
2096: {
2097: int l,i,k,m,m0;
2098:
2099: if ( !d )
2100: return;
2101: m0 = g->m;
2102: while ( 1 ) {
2103: l = LEN(d);
2104: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2105: /* 2^(k-1) < l <= 2^k (=m) */
2106: if ( g->body[k] == 0 ) {
2107: g->body[k] = d;
2108: m0 = MAX(k,m0);
2109: break;
2110: } else {
2111: d = nd_merge(g->body[k],d);
2112: g->body[k] = 0;
2113: }
2114: }
2115: g->m = m0;
2116: }
2117: #endif
1.1 noro 2118:
1.39 noro 2119: #if 0
1.1 noro 2120: void add_pbucket(int mod,PGeoBucket g,ND d)
2121: {
2122: int l,i,k,m;
2123:
2124: if ( !d )
2125: return;
2126: l = LEN(d);
2127: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2128: /* 2^(k-1) < l <= 2^k (=m) */
2129: d = nd_add(mod,g->body[k],d);
2130: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2131: g->body[k] = 0;
2132: d = nd_add(mod,g->body[k+1],d);
2133: }
2134: g->body[k] = d;
2135: g->m = MAX(g->m,k);
2136: }
1.39 noro 2137: #else
2138: void add_pbucket(int mod,PGeoBucket g,ND d)
2139: {
2140: int l,i,k,m,m0;
2141:
2142: m0 = g->m;
2143: while ( d != 0 ) {
2144: l = LEN(d);
2145: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2146: /* 2^(k-1) < l <= 2^k (=m) */
2147: if ( g->body[k] == 0 ) {
2148: g->body[k] = d;
2149: m0 = MAX(k,m0);
2150: break;
2151: } else {
2152: d = nd_add(mod,g->body[k],d);
2153: g->body[k] = 0;
2154: }
2155: }
2156: g->m = m0;
2157: }
2158: #endif
1.1 noro 2159:
2160: void mulq_pbucket(PGeoBucket g,Z c)
2161: {
2162: int k;
2163:
2164: for ( k = 0; k <= g->m; k++ )
2165: nd_mul_c_q(g->body[k],(P)c);
2166: }
2167:
2168: NM remove_head_pbucket_symbolic(PGeoBucket g)
2169: {
2170: int j,i,k,c;
2171: NM head;
2172:
2173: k = g->m;
2174: j = -1;
2175: for ( i = 0; i <= k; i++ ) {
2176: if ( !g->body[i] ) continue;
2177: if ( j < 0 ) j = i;
2178: else {
2179: c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
2180: if ( c > 0 )
2181: j = i;
2182: else if ( c == 0 )
2183: g->body[i] = nd_remove_head(g->body[i]);
2184: }
2185: }
2186: if ( j < 0 ) return 0;
2187: else {
2188: head = BDY(g->body[j]);
2189: if ( !NEXT(head) ) {
2190: FREEND(g->body[j]);
2191: g->body[j] = 0;
2192: } else {
2193: BDY(g->body[j]) = NEXT(head);
2194: LEN(g->body[j])--;
2195: }
2196: return head;
2197: }
2198: }
2199:
2200: int head_pbucket(int mod,PGeoBucket g)
2201: {
2202: int j,i,c,k,nv,sum;
2203: UINT *di,*dj;
2204: ND gi,gj;
2205:
2206: k = g->m;
2207: while ( 1 ) {
2208: j = -1;
2209: for ( i = 0; i <= k; i++ ) {
2210: if ( !(gi = g->body[i]) )
2211: continue;
2212: if ( j < 0 ) {
2213: j = i;
2214: gj = g->body[j];
2215: dj = HDL(gj);
2216: sum = HCM(gj);
2217: } else {
2218: c = DL_COMPARE(HDL(gi),dj);
2219: if ( c > 0 ) {
2220: if ( sum ) HCM(gj) = sum;
2221: else g->body[j] = nd_remove_head(gj);
2222: j = i;
2223: gj = g->body[j];
2224: dj = HDL(gj);
2225: sum = HCM(gj);
2226: } else if ( c == 0 ) {
2227: if ( mod == -1 )
2228: sum = _addsf(sum,HCM(gi));
2229: else {
2230: sum = sum+HCM(gi)-mod;
2231: if ( sum < 0 ) sum += mod;
2232: }
2233: g->body[i] = nd_remove_head(gi);
2234: }
2235: }
2236: }
2237: if ( j < 0 ) return -1;
2238: else if ( sum ) {
2239: HCM(gj) = sum;
2240: return j;
2241: } else
2242: g->body[j] = nd_remove_head(gj);
2243: }
2244: }
2245:
2246: int head_pbucket_q(PGeoBucket g)
2247: {
2248: int j,i,c,k,nv;
2249: Z sum,t;
2250: ND gi,gj;
2251:
2252: k = g->m;
2253: while ( 1 ) {
2254: j = -1;
2255: for ( i = 0; i <= k; i++ ) {
2256: if ( !(gi = g->body[i]) ) continue;
2257: if ( j < 0 ) {
2258: j = i;
2259: gj = g->body[j];
1.6 noro 2260: sum = HCZ(gj);
1.1 noro 2261: } else {
2262: nv = NV(gi);
2263: c = DL_COMPARE(HDL(gi),HDL(gj));
2264: if ( c > 0 ) {
1.6 noro 2265: if ( sum ) HCZ(gj) = sum;
1.1 noro 2266: else g->body[j] = nd_remove_head(gj);
2267: j = i;
2268: gj = g->body[j];
1.6 noro 2269: sum = HCZ(gj);
1.1 noro 2270: } else if ( c == 0 ) {
1.6 noro 2271: addz(sum,HCZ(gi),&t);
1.1 noro 2272: sum = t;
2273: g->body[i] = nd_remove_head(gi);
2274: }
2275: }
2276: }
2277: if ( j < 0 ) return -1;
2278: else if ( sum ) {
1.6 noro 2279: HCZ(gj) = sum;
1.1 noro 2280: return j;
2281: } else
2282: g->body[j] = nd_remove_head(gj);
2283: }
2284: }
2285:
2286: int head_pbucket_lf(PGeoBucket g)
2287: {
2288: int j,i,c,k,nv;
2289: Z sum,t;
2290: ND gi,gj;
2291:
2292: k = g->m;
2293: while ( 1 ) {
2294: j = -1;
2295: for ( i = 0; i <= k; i++ ) {
2296: if ( !(gi = g->body[i]) ) continue;
2297: if ( j < 0 ) {
2298: j = i;
2299: gj = g->body[j];
2300: sum = HCZ(gj);
2301: } else {
2302: nv = NV(gi);
2303: c = DL_COMPARE(HDL(gi),HDL(gj));
2304: if ( c > 0 ) {
2305: if ( sum ) HCZ(gj) = sum;
2306: else g->body[j] = nd_remove_head(gj);
2307: j = i;
2308: gj = g->body[j];
2309: sum = HCZ(gj);
2310: } else if ( c == 0 ) {
2311: addlf(sum,HCZ(gi),&t);
2312: sum = t;
2313: g->body[i] = nd_remove_head(gi);
2314: }
2315: }
2316: }
2317: if ( j < 0 ) return -1;
2318: else if ( sum ) {
2319: HCZ(gj) = sum;
2320: return j;
2321: } else
2322: g->body[j] = nd_remove_head(gj);
2323: }
2324: }
2325:
2326: ND normalize_pbucket(int mod,PGeoBucket g)
2327: {
2328: int i;
2329: ND r,t;
2330:
2331: r = 0;
2332: for ( i = 0; i <= g->m; i++ ) {
2333: r = nd_add(mod,r,g->body[i]);
2334: g->body[i] = 0;
2335: }
2336: g->m = -1;
2337: return r;
2338: }
2339:
2340: #if 0
2341: void register_hcf(NDV p)
2342: {
2343: DCP dc,t;
2344: P hc,h;
2345: int c;
2346: NODE l,l1,prev;
2347:
2348: hc = p->body->c.p;
2349: if ( !nd_vc || NUM(hc) ) return;
2350: fctrp(nd_vc,hc,&dc);
2351: for ( t = dc; t; t = NEXT(t) ) {
2352: h = t->c;
2353: if ( NUM(h) ) continue;
2354: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2355: c = compp(nd_vc,h,(P)BDY(l));
2356: if ( c >= 0 ) break;
2357: }
2358: if ( !l || c > 0 ) {
2359: MKNODE(l1,h,l);
2360: if ( !prev )
2361: nd_hcf = l1;
2362: else
2363: NEXT(prev) = l1;
2364: }
2365: }
2366: }
2367: #else
2368: void register_hcf(NDV p)
2369: {
2370: DCP dc,t;
2371: P hc,h,q;
2372: Q dmy;
2373: int c;
2374: NODE l,l1,prev;
2375:
2376: hc = p->body->c.p;
2377: if ( NUM(hc) ) return;
2378: ptozp(hc,1,&dmy,&h);
2379: #if 1
2380: for ( l = nd_hcf; l; l = NEXT(l) ) {
2381: while ( 1 ) {
2382: if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
2383: else break;
2384: }
2385: }
2386: if ( NUM(h) ) return;
2387: #endif
2388: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2389: c = compp(nd_vc,h,(P)BDY(l));
2390: if ( c >= 0 ) break;
2391: }
2392: if ( !l || c > 0 ) {
2393: MKNODE(l1,h,l);
2394: if ( !prev )
2395: nd_hcf = l1;
2396: else
2397: NEXT(prev) = l1;
2398: }
2399: }
2400: #endif
2401:
2402: int do_diagonalize(int sugar,int m)
2403: {
1.6 noro 2404: int i,nh,stat;
2405: NODE r,g,t;
2406: ND h,nf,s,head;
2407: NDV nfv;
2408: Q q;
2409: P nm,nmp,dn,mnp,dnp,cont,cont1;
2410: union oNDC hc;
2411: NODE node;
2412: LIST l;
2413: Z iq;
1.1 noro 2414:
1.6 noro 2415: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2416: if ( nd_gentrace ) {
2417: /* Trace = [1,index,1,1] */
2418: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2419: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2420: }
2421: if ( nd_demand )
2422: nfv = ndv_load(i);
2423: else
2424: nfv = nd_ps[i];
2425: s = ndvtond(m,nfv);
2426: s = nd_separate_head(s,&head);
2427: stat = nd_nf(m,head,s,nd_ps,1,&nf);
2428: if ( !stat ) return 0;
2429: ndv_free(nfv);
2430: hc = HCU(nf); nd_removecont(m,nf);
2431: /* exact division */
2432: cont = ndc_div(m,hc,HCU(nf));
1.1 noro 2433: if ( nd_gentrace ) finalize_tracelist(i,cont);
1.6 noro 2434: nfv = ndtondv(m,nf);
2435: nd_free(nf);
2436: nd_bound[i] = ndv_compute_bound(nfv);
2437: if ( !m ) register_hcf(nfv);
2438: if ( nd_demand ) {
2439: ndv_save(nfv,i);
2440: ndv_free(nfv);
2441: } else
2442: nd_ps[i] = nfv;
2443: }
2444: return 1;
1.1 noro 2445: }
2446:
2447: LIST compute_splist()
2448: {
2449: NODE g,tn0,tn,node;
2450: LIST l0;
2451: ND_pairs d,t;
2452: int i;
2453: Z i1,i2;
2454:
2455: g = 0; d = 0;
2456: for ( i = 0; i < nd_psn; i++ ) {
2457: d = update_pairs(d,g,i,0);
2458: g = update_base(g,i);
2459: }
2460: for ( t = d, tn0 = 0; t; t = NEXT(t) ) {
2461: NEXTNODE(tn0,tn);
1.6 noro 2462: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 2463: node = mknode(2,i1,i2); MKLIST(l0,node);
2464: BDY(tn) = l0;
2465: }
2466: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
2467: return l0;
2468: }
2469:
2470: /* return value = 0 => input is not a GB */
2471:
2472: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2473: {
1.6 noro 2474: int i,nh,sugar,stat;
2475: NODE r,g,t;
2476: ND_pairs d;
2477: ND_pairs l;
2478: ND h,nf,s,head,nf1;
2479: NDV nfv;
2480: Z q;
2481: union oNDC dn,hc;
2482: int diag_count = 0;
1.41 noro 2483: int Nnfnz = 0,Nnfz = 0;
1.6 noro 2484: P cont;
2485: LIST list;
1.27 noro 2486: struct oEGT eg1,eg2,eg_update;
1.6 noro 2487:
1.27 noro 2488: init_eg(&eg_update);
1.11 noro 2489: Nnd_add = 0;
1.6 noro 2490: g = 0; d = 0;
2491: for ( i = 0; i < nd_psn; i++ ) {
2492: d = update_pairs(d,g,i,gensyz);
2493: g = update_base(g,i);
2494: }
2495: sugar = 0;
2496: while ( d ) {
1.1 noro 2497: again:
1.6 noro 2498: l = nd_minp(d,&d);
2499: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2500: if ( SG(l) != sugar ) {
2501: if ( ishomo ) {
2502: diag_count = 0;
2503: stat = do_diagonalize(sugar,m);
1.1 noro 2504: if ( !stat ) {
1.6 noro 2505: NEXT(l) = d; d = l;
2506: d = nd_reconstruct(0,d);
2507: goto again;
1.1 noro 2508: }
1.6 noro 2509: }
2510: sugar = SG(l);
2511: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2512: }
2513: stat = nd_sp(m,0,l,&h);
2514: if ( !stat ) {
2515: NEXT(l) = d; d = l;
2516: d = nd_reconstruct(0,d);
2517: goto again;
2518: }
1.1 noro 2519: #if USE_GEOBUCKET
1.39 noro 2520: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf)
2521: :nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2522: #else
1.39 noro 2523: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2524: #endif
1.6 noro 2525: if ( !stat ) {
2526: NEXT(l) = d; d = l;
2527: d = nd_reconstruct(0,d);
2528: goto again;
2529: } else if ( nf ) {
1.41 noro 2530: Nnfnz++;
1.6 noro 2531: if ( checkonly || gensyz ) return 0;
1.1 noro 2532: if ( nd_newelim ) {
2533: if ( nd_module ) {
2534: if ( MPOS(HDL(nf)) > 1 ) return 0;
2535: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2536: }
1.6 noro 2537: if ( DP_Print ) { printf("+"); fflush(stdout); }
2538: hc = HCU(nf);
2539: nd_removecont(m,nf);
2540: if ( !m && nd_nalg ) {
2541: nd_monic(0,&nf);
2542: nd_removecont(m,nf);
2543: }
2544: if ( nd_gentrace ) {
2545: /* exact division */
1.1 noro 2546: cont = ndc_div(m,hc,HCU(nf));
2547: if ( m || !UNIQ(cont) ) {
1.6 noro 2548: t = mknode(4,NULLP,NULLP,NULLP,cont);
2549: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2550: nd_tracelist = t;
2551: }
2552: }
1.6 noro 2553: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2554: nh = ndv_newps(m,nfv,0);
1.6 noro 2555: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2556: diag_count = 0;
2557: stat = do_diagonalize(sugar,m);
2558: if ( !stat ) {
2559: NEXT(l) = d; d = l;
2560: d = nd_reconstruct(1,d);
2561: goto again;
1.1 noro 2562: }
1.6 noro 2563: }
1.27 noro 2564: get_eg(&eg1);
1.6 noro 2565: d = update_pairs(d,g,nh,0);
1.27 noro 2566: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2567: g = update_base(g,nh);
2568: FREENDP(l);
1.41 noro 2569: } else {
2570: Nnfz++;
2571: if ( nd_gentrace && gensyz ) {
2572: nd_tracelist = reverse_node(nd_tracelist);
2573: MKLIST(list,nd_tracelist);
2574: STOZ(-1,q); t = mknode(2,q,list); MKLIST(list,t);
2575: MKNODE(t,list,nd_alltracelist);
2576: nd_alltracelist = t; nd_tracelist = 0;
2577: }
2578: if ( DP_Print ) { printf("."); fflush(stdout); }
2579: FREENDP(l);
2580: }
1.36 noro 2581: }
2582: conv_ilist(nd_demand,0,g,indp);
1.41 noro 2583: if ( !checkonly && DP_Print ) {
2584: printf("\nnd_gb done. Nnd_add=%d,Npairs=%d, Nnfnz=%d,Nnfz=%d,",Nnd_add,Npairs,Nnfnz,Nnfz);
2585: printf("Nremoved=%d\n",NcriB+NcriMF+Ncri2);
2586: fflush(asir_out);
2587: }
2588: if ( DP_Print ) {
2589: print_eg("update",&eg_update); fprintf(asir_out,"\n");
2590: }
1.36 noro 2591: return g;
1.1 noro 2592: }
2593:
1.30 noro 2594: ND_pairs update_pairs_s(ND_pairs d,int t,NODE *syz);
1.47 ! noro 2595: int update_pairs_array_s(ND_pairs *d,int t,NODE *syz);
1.30 noro 2596: ND_pairs nd_newpairs_s(int t ,NODE *syz);
1.47 ! noro 2597: ND_pairs *nd_newpairs_array_s(int t ,NODE *syz);
1.24 noro 2598:
2599: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *nf);
2600: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *nf);
2601:
2602: void _copydl(int n,DL d1,DL d2);
2603: void _subfromdl(int n,DL d1,DL d2);
2604: extern int (*cmpdl)(int n,DL d1,DL d2);
2605:
2606: NODE insert_sig(NODE l,SIG s)
2607: {
2608: int pos;
2609: DL sig;
2610: struct oNODE root;
2611: NODE p,prev,r;
2612: SIG t;
2613:
2614: pos = s->pos; sig = DL(s);
2615: root.next = l; prev = &root;
2616: for ( p = l; p; p = p->next ) {
2617: t = (SIG)p->body;
2618: if ( t->pos == pos ) {
2619: if ( _dl_redble(DL(t),sig,nd_nvar) )
2620: return root.next;
2621: else if ( _dl_redble(sig,DL(t),nd_nvar) )
2622: // remove p
2623: prev->next = p->next;
1.45 noro 2624: else
2625: prev = p;
1.24 noro 2626: } else
2627: prev = p;
2628: }
1.27 noro 2629: NEWNODE(r); r->body = (pointer)s; r->next = 0;
2630: for ( p = &root; p->next; p = p->next );
2631: p->next = r;
2632: // r->next = root.next;
2633: // return r;
2634: return root.next;
1.24 noro 2635: }
2636:
2637: ND_pairs remove_spair_s(ND_pairs d,SIG sig)
2638: {
2639: struct oND_pairs root;
2640: ND_pairs prev,p;
2641: SIG spsig;
2642:
2643: root.next = d;
2644: prev = &root; p = d;
2645: while ( p ) {
2646: spsig = p->sig;
1.26 noro 2647: if ( sig->pos == spsig->pos && _dl_redble(DL(sig),DL(spsig),nd_nvar) ) {
1.24 noro 2648: // remove p
2649: prev->next = p->next;
1.26 noro 2650: Nsyz++;
2651: } else
1.24 noro 2652: prev = p;
2653: p = p->next;
2654: }
2655: return (ND_pairs)root.next;
2656: }
2657:
1.29 noro 2658: int _dl_redble_ext(DL,DL,DL,int);
2659:
1.28 noro 2660: int small_lcm(ND_pairs l)
2661: {
2662: SIG sig;
2663: int i;
1.29 noro 2664: NODE t;
1.28 noro 2665: static DL lcm,mul,quo;
1.44 noro 2666: static int nvar = 0;
1.28 noro 2667:
1.38 noro 2668: if ( nd_sba_largelcm ) return 0;
1.28 noro 2669: if ( nvar < nd_nvar ) {
2670: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(quo,nvar); NEWDL(mul,nvar);
2671: }
2672: sig = l->sig;
2673: _ndltodl(l->lcm,lcm);
1.29 noro 2674: #if 0
1.28 noro 2675: for ( i = 0; i < nd_psn; i++ ) {
2676: if ( sig->pos == nd_psh[i]->sig->pos &&
1.29 noro 2677: _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
1.28 noro 2678: _ndltodl(DL(nd_psh[i]),mul);
2679: _addtodl(nd_nvar,quo,mul);
2680: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2681: break;
2682: }
2683: }
2684: if ( i < nd_psn ) return 1;
2685: else return 0;
1.29 noro 2686: #else
2687: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2688: i = (long)BDY(t);
2689: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2690: _ndltodl(DL(nd_psh[i]),mul);
2691: _addtodl(nd_nvar,quo,mul);
2692: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2693: break;
2694: }
2695: }
2696: if ( t ) return 1;
2697: else return 0;
2698: #endif
1.28 noro 2699: }
2700:
1.41 noro 2701: ND_pairs find_smallest_lcm(ND_pairs l)
2702: {
2703: SIG sig;
2704: int i,minindex;
2705: NODE t;
2706: ND_pairs r;
2707: struct oSIG sig1;
2708: static DL mul,quo,minlm;
1.44 noro 2709: static int nvar = 0;
1.41 noro 2710:
2711: if ( nvar < nd_nvar ) {
2712: nvar = nd_nvar;
2713: NEWDL(quo,nvar); NEWDL(mul,nvar);
2714: NEWDL(minlm,nvar);
2715: }
2716: sig = l->sig;
2717: // find mg s.t. m*s(g)=sig and m*lm(g) is minimal
2718: _ndltodl(l->lcm,minlm); minindex = -1;
2719: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2720: i = (long)BDY(t);
2721: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2722: _ndltodl(DL(nd_psh[i]),mul);
2723: _addtodl(nd_nvar,quo,mul);
2724: if ( (*cmpdl)(nd_nvar,minlm,mul) > 0 ) {
2725: minindex = i;
1.47 ! noro 2726: break;
1.41 noro 2727: _copydl(nd_nvar,mul,minlm);
2728: }
2729: }
2730: }
2731: // l->lcm is minimal; return l itself
2732: if ( minindex < 0 ) return l;
1.47 ! noro 2733: else return 0;
1.41 noro 2734: for ( i = 0; i < nd_psn; i++ ) {
2735: if ( i == minindex ) continue;
2736: _ndltodl(DL(nd_psh[i]),mul);
2737: if ( _dl_redble_ext(mul,minlm,quo,nd_nvar) ) {
2738: _addtodl(nd_nvar,nd_ps[i]->sig->dl,quo);
2739: sig1.pos = nd_ps[i]->sig->pos;
2740: sig1.dl = quo;
2741: if ( comp_sig(sig,&sig1) > 0 ) {
2742: // printf("X");
2743: NEWND_pairs(r);
2744: r->sig = sig;
2745: r->i1 = minindex;
2746: r->i2 = i;
2747: dltondl(nd_nvar,minlm,r->lcm);
2748: r->next = 0;
2749: return r;
2750: }
2751: }
2752: }
2753: // there is no suitable spair
2754: return 0;
2755: }
2756:
1.28 noro 2757: ND_pairs remove_large_lcm(ND_pairs d)
2758: {
2759: struct oND_pairs root;
2760: ND_pairs prev,p;
2761:
2762: root.next = d;
2763: prev = &root; p = d;
2764: while ( p ) {
1.41 noro 2765: #if 0
1.28 noro 2766: if ( small_lcm(p) ) {
2767: // remove p
2768: prev->next = p->next;
2769: } else
1.41 noro 2770: #else
2771: if ( find_smallest_lcm(p) == 0 ) {
2772: // remove p
2773: prev->next = p->next;
2774: } else
2775: #endif
1.28 noro 2776: prev = p;
2777: p = p->next;
2778: }
2779: return (ND_pairs)root.next;
2780: }
2781:
1.26 noro 2782: struct oEGT eg_create,eg_newpairs,eg_merge;
2783:
1.30 noro 2784: NODE conv_ilist_s(int demand,int trace,int **indp);
2785:
1.44 noro 2786: // S(fj*ei-fi*ej)
2787:
1.45 noro 2788: void _subdl(int,DL,DL,DL);
2789:
1.44 noro 2790: SIG trivial_sig(int i,int j)
2791: {
1.45 noro 2792: static DL lcm;
1.44 noro 2793: static struct oSIG sigi,sigj;
2794: static int nvar = 0;
2795: SIG sig;
2796:
2797: if ( nvar != nd_nvar ) {
1.45 noro 2798: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(sigi.dl,nvar); NEWDL(sigj.dl,nvar);
2799: }
1.46 noro 2800: if ( nd_sba_inputisgb != 0 ) {
1.45 noro 2801: lcm_of_DL(nd_nvar,nd_sba_hm[i],nd_sba_hm[j],lcm);
2802: sigi.pos = i; _subdl(nd_nvar,lcm,nd_sba_hm[i],sigi.dl);
2803: sigj.pos = j; _subdl(nd_nvar,lcm,nd_sba_hm[j],sigj.dl);
2804: if ( comp_sig(&sigi,&sigj) > 0 ) sig = dup_sig(&sigi);
2805: else sig = dup_sig(&sigj);
2806: } else {
2807: sigi.pos = i; _copydl(nd_nvar,nd_sba_hm[j],sigi.dl);
2808: sigj.pos = j; _copydl(nd_nvar,nd_sba_hm[i],sigj.dl);
2809: if ( comp_sig(&sigi,&sigj) > 0 ) sig = dup_sig(&sigi);
2810: else sig = dup_sig(&sigj);
1.44 noro 2811: }
2812: return sig;
2813: }
2814:
1.47 ! noro 2815: int nd_minsig(ND_pairs *d)
! 2816: {
! 2817: int min,i,ret;
! 2818:
! 2819: min = -1;
! 2820: for ( i = 0; i < nd_nbase; i++ ) {
! 2821: if ( d[i] != 0 ) {
! 2822: if ( min < 0 ) min = i;
! 2823: else {
! 2824: ret = comp_sig(d[i]->sig,d[min]->sig);
! 2825: if ( ret < 0 ) min = i;
! 2826: }
! 2827: }
! 2828: }
! 2829: return min;
! 2830: }
! 2831:
! 2832: int dlength(ND_pairs d)
! 2833: {
! 2834: int i;
! 2835: for ( i = 0; d; d = d->next, i++ );
! 2836: return i;
! 2837: }
! 2838:
1.44 noro 2839: NODE nd_sba_buch(int m,int ishomo,int **indp,NODE *syzp)
1.24 noro 2840: {
1.39 noro 2841: int i,j,nh,sugar,stat,pos;
1.30 noro 2842: NODE r,t,g;
1.47 ! noro 2843: ND_pairs *d;
1.41 noro 2844: ND_pairs l,l1;
1.24 noro 2845: ND h,nf,s,head,nf1;
2846: NDV nfv;
2847: Z q;
2848: union oNDC dn,hc;
2849: P cont;
2850: LIST list;
2851: SIG sig;
1.29 noro 2852: NODE *syzlist;
1.47 ! noro 2853: int ngen,ind;
1.41 noro 2854: int Nnominimal,Nredundant;
1.28 noro 2855: DL lcm,quo,mul;
1.47 ! noro 2856: struct oEGT eg1,eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero,eg_minsig,eg_smallest;
! 2857: int Nnfs=0,Nnfz=0,Nnfnz=0,dlen,nsyz;
1.24 noro 2858:
1.27 noro 2859: init_eg(&eg_remove);
1.29 noro 2860: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.47 ! noro 2861: d = (ND_pairs *)MALLOC(nd_psn*sizeof(ND_pairs));
! 2862: nd_nbase = nd_psn;
1.26 noro 2863: Nsyz = 0;
1.24 noro 2864: Nnd_add = 0;
1.41 noro 2865: Nnominimal = 0;
1.26 noro 2866: Nredundant = 0;
1.44 noro 2867: ngen = nd_psn;
1.29 noro 2868: for ( i = 0; i < nd_psn; i++ )
2869: for ( j = i+1; j < nd_psn; j++ ) {
1.44 noro 2870: sig = trivial_sig(i,j);
1.29 noro 2871: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
2872: }
1.47 ! noro 2873: dlen = 0;
1.41 noro 2874: for ( i = 0; i < nd_psn; i++ ) {
1.47 ! noro 2875: dlen += update_pairs_array_s(d,i,syzlist);
1.41 noro 2876: }
1.24 noro 2877: sugar = 0;
1.39 noro 2878: pos = 0;
1.26 noro 2879: NEWDL(lcm,nd_nvar); NEWDL(quo,nd_nvar); NEWDL(mul,nd_nvar);
2880: init_eg(&eg_create);
2881: init_eg(&eg_merge);
1.47 ! noro 2882: init_eg(&eg_minsig);
! 2883: init_eg(&eg_smallest);
1.29 noro 2884: init_eg(&eg_large);
1.31 noro 2885: init_eg(&eg_nf);
2886: init_eg(&eg_nfzero);
1.47 ! noro 2887: while ( 1 ) {
! 2888: if ( DP_Print && dlen%100 == 0 ) fprintf(asir_out,"(%d)",dlen);
! 2889: again :
! 2890: get_eg(&eg1);
! 2891: ind = nd_minsig(d);
! 2892: get_eg(&eg2); add_eg(&eg_minsig,&eg1,&eg2);
! 2893: if ( ind < 0 ) break;
! 2894: l = d[ind];
! 2895: // printf("(%d,%d)",l->i1,l->i2); print_sig(l->sig); printf("\n");
! 2896: get_eg(&eg1);
1.41 noro 2897: l1 = find_smallest_lcm(l);
1.47 ! noro 2898: get_eg(&eg2); add_eg(&eg_smallest,&eg1,&eg2);
1.41 noro 2899: if ( l1 == 0 ) {
1.47 ! noro 2900: d[ind] = d[ind]->next; dlen--;
1.41 noro 2901: if ( DP_Print ) fprintf(asir_out,"M");
2902: Nnominimal++;
2903: continue;
2904: }
2905: if ( SG(l1) != sugar ) {
2906: sugar = SG(l1);
2907: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2908: }
2909: sig = l1->sig;
2910: if ( DP_Print && nd_sba_pot ) {
2911: if ( sig->pos != pos ) {
2912: fprintf(asir_out,"[%d]",sig->pos);
2913: pos = sig->pos;
2914: }
2915: }
2916: stat = nd_sp(m,0,l1,&h);
1.24 noro 2917: if ( !stat ) {
1.47 ! noro 2918: nd_reconstruct_s(0,d);
1.24 noro 2919: goto again;
2920: }
1.31 noro 2921: get_eg(&eg1);
1.25 noro 2922: #if USE_GEOBUCKET
1.39 noro 2923: 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.24 noro 2924: #else
1.39 noro 2925: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.24 noro 2926: #endif
1.31 noro 2927: get_eg(&eg2);
1.24 noro 2928: if ( !stat ) {
1.47 ! noro 2929: nd_reconstruct_s(0,d);
1.24 noro 2930: goto again;
2931: } else if ( stat == -1 ) {
1.47 ! noro 2932: d[ind] = d[ind]->next; dlen--;
1.41 noro 2933: Nnfs++;
1.24 noro 2934: if ( DP_Print ) { printf("S"); fflush(stdout); }
2935: } else if ( nf ) {
1.47 ! noro 2936: d[ind] = d[ind]->next; dlen--;
1.41 noro 2937: Nnfnz++;
2938: if ( DP_Print ) {
2939: if ( nd_sba_redundant_check ) {
2940: if ( ndl_find_reducer_nonsig(HDL(nf)) >= 0 ) {
2941: Nredundant++;
2942: printf("R");
2943: } else
2944: printf("+");
2945: } else
2946: printf("+");
2947: fflush(stdout);
2948: }
1.31 noro 2949: add_eg(&eg_nf,&eg1,&eg2);
1.24 noro 2950: hc = HCU(nf);
2951: nd_removecont(m,nf);
2952: nfv = ndtondv(m,nf); nd_free(nf);
2953: nh = ndv_newps(m,nfv,0);
1.26 noro 2954:
1.47 ! noro 2955: dlen += update_pairs_array_s(d,nh,syzlist);
1.29 noro 2956: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.24 noro 2957: } else {
1.47 ! noro 2958: d[ind] = d[ind]->next; dlen--;
1.41 noro 2959: Nnfz++;
1.31 noro 2960: add_eg(&eg_nfzero,&eg1,&eg2);
1.24 noro 2961: // syzygy
1.27 noro 2962: get_eg(&eg1);
1.47 ! noro 2963: nsyz = Nsyz;
! 2964: d[sig->pos] = remove_spair_s(d[sig->pos],sig);
! 2965: dlen -= Nsyz-nsyz;
1.27 noro 2966: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 2967: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.24 noro 2968: if ( DP_Print ) { printf("."); fflush(stdout); }
2969: }
2970: }
1.30 noro 2971: g = conv_ilist_s(nd_demand,0,indp);
1.26 noro 2972: if ( DP_Print ) {
1.47 ! noro 2973: printf("\ndlen=%d,nd_sba done. nd_add=%d,Nsyz=%d,Nsamesig=%d,Nnominimal=%d\n",dlen,Nnd_add,Nsyz,Nsamesig,Nnominimal);
1.41 noro 2974: printf("Nnfnz=%d,Nnfz=%d,Nnfsingular=%d\n",Nnfnz,Nnfz,Nnfs);
2975: fflush(stdout);
2976: if ( nd_sba_redundant_check )
2977: printf("Nredundant=%d\n",Nredundant);
1.26 noro 2978: fflush(stdout);
2979: print_eg("create",&eg_create);
2980: print_eg("merge",&eg_merge);
1.47 ! noro 2981: print_eg("minsig",&eg_minsig);
! 2982: print_eg("smallest",&eg_smallest);
! 2983: print_eg("remove",&eg_remove);
! 2984: print_eg("nf",&eg_nf);
! 2985: print_eg("nfzero",&eg_nfzero);
! 2986: printf("\n");
! 2987: }
! 2988: if ( nd_sba_syz ) {
1.27 noro 2989: print_eg("remove",&eg_remove);
1.31 noro 2990: print_eg("nf",&eg_nf);
2991: print_eg("nfzero",&eg_nfzero);
1.27 noro 2992: printf("\n");
1.26 noro 2993: }
1.44 noro 2994: if ( nd_sba_syz ) {
2995: NODE hsyz,tsyz,prev;
2996:
2997: hsyz = 0;
2998: for ( i = 0; i < ngen; i++ ) {
2999: tsyz = syzlist[i];
3000: for ( prev = 0; tsyz != 0; prev = tsyz, tsyz = NEXT(tsyz))
3001: BDY(tsyz) = (pointer)sigtodpm((SIG)BDY(tsyz));
3002: if ( prev != 0 ) {
3003: prev->next = hsyz; hsyz = syzlist[i];
3004: }
3005: }
3006: *syzp = hsyz;
3007: } else *syzp = 0;
1.24 noro 3008: return g;
3009: }
3010:
1.1 noro 3011: /* splist = [[i1,i2],...] */
3012:
3013: int check_splist(int m,NODE splist)
3014: {
3015: NODE t,p;
3016: ND_pairs d,r,l;
3017: int stat;
3018: ND h,nf;
3019:
3020: for ( d = 0, t = splist; t; t = NEXT(t) ) {
3021: p = BDY((LIST)BDY(t));
1.6 noro 3022: NEXTND_pairs(d,r);
3023: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
3024: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 3025: SG(r) = TD(LCM(r)); /* XXX */
3026: }
3027: if ( d ) NEXT(r) = 0;
3028:
1.6 noro 3029: while ( d ) {
1.1 noro 3030: again:
1.6 noro 3031: l = nd_minp(d,&d);
3032: stat = nd_sp(m,0,l,&h);
3033: if ( !stat ) {
3034: NEXT(l) = d; d = l;
3035: d = nd_reconstruct(0,d);
3036: goto again;
3037: }
1.39 noro 3038: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.6 noro 3039: if ( !stat ) {
3040: NEXT(l) = d; d = l;
3041: d = nd_reconstruct(0,d);
3042: goto again;
3043: } else if ( nf ) return 0;
1.1 noro 3044: if ( DP_Print) { printf("."); fflush(stdout); }
1.6 noro 3045: }
1.1 noro 3046: if ( DP_Print) { printf("done.\n"); fflush(stdout); }
3047: return 1;
3048: }
3049:
3050: int check_splist_f4(int m,NODE splist)
3051: {
3052: UINT *s0vect;
1.6 noro 3053: PGeoBucket bucket;
1.1 noro 3054: NODE p,rp0,t;
3055: ND_pairs d,r,l,ll;
3056: int col,stat;
3057:
3058: for ( d = 0, t = splist; t; t = NEXT(t) ) {
3059: p = BDY((LIST)BDY(t));
1.6 noro 3060: NEXTND_pairs(d,r);
3061: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
3062: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 3063: SG(r) = TD(LCM(r)); /* XXX */
3064: }
3065: if ( d ) NEXT(r) = 0;
3066:
1.6 noro 3067: while ( d ) {
3068: l = nd_minsugarp(d,&d);
3069: bucket = create_pbucket();
3070: stat = nd_sp_f4(m,0,l,bucket);
3071: if ( !stat ) {
3072: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3073: NEXT(ll) = d; d = l;
3074: d = nd_reconstruct(0,d);
3075: continue;
3076: }
3077: if ( bucket->m < 0 ) continue;
3078: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
3079: if ( !col ) {
3080: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3081: NEXT(ll) = d; d = l;
3082: d = nd_reconstruct(0,d);
3083: continue;
1.1 noro 3084: }
1.6 noro 3085: if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0;
3086: }
3087: return 1;
1.1 noro 3088: }
3089:
3090: int do_diagonalize_trace(int sugar,int m)
3091: {
1.6 noro 3092: int i,nh,stat;
3093: NODE r,g,t;
3094: ND h,nf,nfq,s,head;
3095: NDV nfv,nfqv;
3096: Q q,den,num;
3097: union oNDC hc;
3098: NODE node;
3099: LIST l;
3100: Z iq;
3101: P cont,cont1;
1.1 noro 3102:
1.6 noro 3103: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
3104: if ( nd_gentrace ) {
3105: /* Trace = [1,index,1,1] */
3106: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
3107: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3108: }
3109: /* for nd_ps */
3110: s = ndvtond(m,nd_ps[i]);
3111: s = nd_separate_head(s,&head);
3112: stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
3113: if ( !stat ) return 0;
3114: nf = nd_add(m,head,nf);
3115: ndv_free(nd_ps[i]);
3116: nd_ps[i] = ndtondv(m,nf);
3117: nd_free(nf);
3118:
3119: /* for nd_ps_trace */
3120: if ( nd_demand )
3121: nfv = ndv_load(i);
3122: else
3123: nfv = nd_ps_trace[i];
3124: s = ndvtond(0,nfv);
3125: s = nd_separate_head(s,&head);
3126: stat = nd_nf(0,head,s,nd_ps_trace,1,&nf);
3127: if ( !stat ) return 0;
3128: ndv_free(nfv);
3129: hc = HCU(nf); nd_removecont(0,nf);
3130: /* exact division */
1.1 noro 3131: cont = ndc_div(0,hc,HCU(nf));
1.6 noro 3132: if ( nd_gentrace ) finalize_tracelist(i,cont);
3133: nfv = ndtondv(0,nf);
3134: nd_free(nf);
3135: nd_bound[i] = ndv_compute_bound(nfv);
3136: register_hcf(nfv);
3137: if ( nd_demand ) {
3138: ndv_save(nfv,i);
3139: ndv_free(nfv);
3140: } else
3141: nd_ps_trace[i] = nfv;
3142: }
3143: return 1;
1.1 noro 3144: }
3145:
3146: static struct oEGT eg_invdalg;
3147: struct oEGT eg_le;
3148:
3149: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
3150: {
3151: NODE tn;
3152: P p1;
3153:
3154: for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
3155: substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
3156: }
3157: *r = p;
3158: }
3159:
3160: NODE nd_gb_trace(int m,int ishomo,int **indp)
3161: {
1.6 noro 3162: int i,nh,sugar,stat;
3163: NODE r,g,t;
3164: ND_pairs d;
3165: ND_pairs l;
3166: ND h,nf,nfq,s,head;
3167: NDV nfv,nfqv;
3168: Z q,den,num;
3169: P hc;
3170: union oNDC dn,hnfq;
3171: struct oEGT eg_monic,egm0,egm1;
3172: int diag_count = 0;
3173: P cont;
3174: LIST list;
3175:
3176: init_eg(&eg_monic);
3177: init_eg(&eg_invdalg);
3178: init_eg(&eg_le);
3179: g = 0; d = 0;
3180: for ( i = 0; i < nd_psn; i++ ) {
3181: d = update_pairs(d,g,i,0);
3182: g = update_base(g,i);
3183: }
3184: sugar = 0;
3185: while ( d ) {
1.1 noro 3186: again:
1.6 noro 3187: l = nd_minp(d,&d);
3188: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
3189: if ( SG(l) != sugar ) {
1.1 noro 3190: #if 1
1.6 noro 3191: if ( ishomo ) {
3192: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3193: stat = do_diagonalize_trace(sugar,m);
3194: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3195: diag_count = 0;
1.1 noro 3196: if ( !stat ) {
1.6 noro 3197: NEXT(l) = d; d = l;
3198: d = nd_reconstruct(1,d);
3199: goto again;
1.1 noro 3200: }
1.6 noro 3201: }
3202: #endif
3203: sugar = SG(l);
3204: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
3205: }
3206: stat = nd_sp(m,0,l,&h);
3207: if ( !stat ) {
3208: NEXT(l) = d; d = l;
3209: d = nd_reconstruct(1,d);
3210: goto again;
3211: }
1.1 noro 3212: #if USE_GEOBUCKET
1.39 noro 3213: stat = nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3214: #else
1.39 noro 3215: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3216: #endif
1.6 noro 3217: if ( !stat ) {
3218: NEXT(l) = d; d = l;
3219: d = nd_reconstruct(1,d);
3220: goto again;
3221: } else if ( nf ) {
3222: if ( nd_demand ) {
3223: nfqv = ndv_load(nd_psn);
3224: nfq = ndvtond(0,nfqv);
3225: } else
3226: nfq = 0;
3227: if ( !nfq ) {
1.39 noro 3228: if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!nd_top&&!Top,&nfq) ) {
1.6 noro 3229: NEXT(l) = d; d = l;
3230: d = nd_reconstruct(1,d);
3231: goto again;
3232: }
3233: }
3234: if ( nfq ) {
3235: /* m|HC(nfq) => failure */
3236: if ( nd_vc ) {
3237: nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Z)hc;
3238: } else
3239: q = HCZ(nfq);
3240: if ( !remqi((Q)q,m) ) return 0;
3241:
3242: if ( DP_Print ) { printf("+"); fflush(stdout); }
3243: hnfq = HCU(nfq);
3244: if ( nd_nalg ) {
3245: /* m|DN(HC(nf)^(-1)) => failure */
3246: get_eg(&egm0);
3247: if ( !nd_monic(m,&nfq) ) return 0;
3248: get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
3249: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3250: nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
3251: } else {
3252: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3253: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
3254: }
3255: if ( nd_gentrace ) {
3256: /* exact division */
3257: cont = ndc_div(0,hnfq,HCU(nfqv));
3258: if ( !UNIQ(cont) ) {
3259: t = mknode(4,NULLP,NULLP,NULLP,cont);
3260: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
3261: nd_tracelist = t;
3262: }
3263: }
1.24 noro 3264: nh = ndv_newps(0,nfv,nfqv);
1.6 noro 3265: if ( ishomo && ++diag_count == diag_period ) {
3266: diag_count = 0;
3267: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3268: stat = do_diagonalize_trace(sugar,m);
3269: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3270: if ( !stat ) {
1.1 noro 3271: NEXT(l) = d; d = l;
3272: d = nd_reconstruct(1,d);
3273: goto again;
1.6 noro 3274: }
1.1 noro 3275: }
1.6 noro 3276: d = update_pairs(d,g,nh,0);
3277: g = update_base(g,nh);
3278: } else {
3279: if ( DP_Print ) { printf("*"); fflush(stdout); }
3280: }
3281: } else {
3282: if ( DP_Print ) { printf("."); fflush(stdout); }
1.1 noro 3283: }
1.6 noro 3284: FREENDP(l);
3285: }
3286: if ( nd_nalg ) {
3287: if ( DP_Print ) {
3288: print_eg("monic",&eg_monic);
3289: print_eg("invdalg",&eg_invdalg);
3290: print_eg("le",&eg_le);
1.1 noro 3291: }
1.6 noro 3292: }
1.1 noro 3293: conv_ilist(nd_demand,1,g,indp);
1.41 noro 3294: if ( DP_Print ) { printf("\nnd_gb_trace done.\n"); fflush(stdout); }
1.6 noro 3295: return g;
1.1 noro 3296: }
3297:
3298: int ndv_compare(NDV *p1,NDV *p2)
3299: {
3300: return DL_COMPARE(HDL(*p1),HDL(*p2));
3301: }
3302:
3303: int ndv_compare_rev(NDV *p1,NDV *p2)
3304: {
3305: return -DL_COMPARE(HDL(*p1),HDL(*p2));
3306: }
3307:
3308: int ndvi_compare(NDVI p1,NDVI p2)
3309: {
3310: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
3311: }
3312:
3313: int ndvi_compare_rev(NDVI p1,NDVI p2)
3314: {
3315: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3316: }
3317:
3318: NODE ndv_reduceall(int m,NODE f)
3319: {
3320: int i,j,n,stat;
3321: ND nf,g,head;
3322: NODE t,a0,a;
3323: union oNDC dn;
3324: Q q,num,den;
3325: NODE node;
3326: LIST l;
3327: Z iq,jq;
3328: int *perm;
3329: union oNDC hc;
3330: P cont,cont1;
3331:
3332: if ( nd_nora ) return f;
3333: n = length(f);
1.24 noro 3334: ndv_setup(m,0,f,0,1,0);
1.1 noro 3335: perm = (int *)MALLOC(n*sizeof(int));
3336: if ( nd_gentrace ) {
3337: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3338: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3339: }
3340: for ( i = 0; i < n; ) {
3341: if ( nd_gentrace ) {
3342: /* Trace = [1,index,1,1] */
1.6 noro 3343: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3344: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3345: }
3346: g = ndvtond(m,nd_ps[i]);
3347: g = nd_separate_head(g,&head);
1.6 noro 3348: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3349: if ( !stat )
3350: nd_reconstruct(0,0);
3351: else {
3352: if ( DP_Print ) { printf("."); fflush(stdout); }
3353: ndv_free(nd_ps[i]);
3354: hc = HCU(nf); nd_removecont(m,nf);
3355: if ( nd_gentrace ) {
3356: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3357: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3358: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3359: }
1.6 noro 3360: /* exact division */
1.1 noro 3361: cont = ndc_div(m,hc,HCU(nf));
3362: finalize_tracelist(perm[i],cont);
3363: }
3364: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3365: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3366: i++;
3367: }
3368: }
3369: if ( DP_Print ) { printf("\n"); }
3370: for ( a0 = 0, i = 0; i < n; i++ ) {
3371: NEXTNODE(a0,a);
3372: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3373: else {
3374: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3375: BDY(a) = (pointer)nd_ps[j];
3376: }
3377: }
3378: NEXT(a) = 0;
3379: return a0;
3380: }
3381:
1.41 noro 3382: int ndplength(ND_pairs d)
3383: {
3384: int i;
3385: for ( i = 0; d; i++ ) d = NEXT(d);
3386: return i;
3387: }
3388:
1.1 noro 3389: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3390: {
3391: ND_pairs d1,nd,cur,head,prev,remove;
1.41 noro 3392: int len0;
1.1 noro 3393:
3394: if ( !g ) return d;
3395: /* for testing */
3396: if ( gensyz && nd_gensyz == 2 ) {
3397: d1 = nd_newpairs(g,t);
3398: if ( !d )
3399: return d1;
3400: else {
3401: nd = d;
3402: while ( NEXT(nd) ) nd = NEXT(nd);
3403: NEXT(nd) = d1;
3404: return d;
3405: }
3406: }
3407: d = crit_B(d,t);
3408: d1 = nd_newpairs(g,t);
1.41 noro 3409: len0 = ndplength(d1);
1.1 noro 3410: d1 = crit_M(d1);
3411: d1 = crit_F(d1);
1.41 noro 3412: NcriMF += len0-ndplength(d1);
1.1 noro 3413: if ( gensyz || do_weyl )
3414: head = d1;
3415: else {
3416: prev = 0; cur = head = d1;
3417: while ( cur ) {
3418: if ( crit_2( cur->i1,cur->i2 ) ) {
3419: remove = cur;
3420: if ( !prev ) head = cur = NEXT(cur);
3421: else cur = NEXT(prev) = NEXT(cur);
1.41 noro 3422: FREENDP(remove); Ncri2++;
1.1 noro 3423: } else {
3424: prev = cur; cur = NEXT(cur);
3425: }
3426: }
3427: }
3428: if ( !d )
3429: return head;
3430: else {
3431: nd = d;
3432: while ( NEXT(nd) ) nd = NEXT(nd);
3433: NEXT(nd) = head;
3434: return d;
3435: }
3436: }
3437:
1.24 noro 3438: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3439:
1.30 noro 3440: ND_pairs update_pairs_s( ND_pairs d, int t,NODE *syz)
1.24 noro 3441: {
3442: ND_pairs d1;
1.26 noro 3443: struct oEGT eg1,eg2,eg3;
1.24 noro 3444:
1.30 noro 3445: if ( !t ) return d;
1.26 noro 3446: get_eg(&eg1);
1.30 noro 3447: d1 = nd_newpairs_s(t,syz);
1.26 noro 3448: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3449: d = merge_pairs_s(d,d1);
1.26 noro 3450: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3451: return d;
3452: }
1.1 noro 3453:
1.47 ! noro 3454: int update_pairs_array_s( ND_pairs *d, int t,NODE *syz)
! 3455: {
! 3456: ND_pairs *d1;
! 3457: struct oEGT eg1,eg2,eg3;
! 3458: int i;
! 3459:
! 3460: if ( !t ) return 0;
! 3461: get_eg(&eg1);
! 3462: Nnewpair = 0;
! 3463: d1 = nd_newpairs_array_s(t,syz);
! 3464: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
! 3465: for ( i = 0; i < nd_nbase; i++ )
! 3466: d[i] = merge_pairs_s(d[i],d1[i]);
! 3467: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
! 3468: return Nnewpair;
! 3469: }
! 3470:
1.1 noro 3471: ND_pairs nd_newpairs( NODE g, int t )
3472: {
3473: NODE h;
3474: UINT *dl;
3475: int ts,s,i,t0,min,max;
3476: ND_pairs r,r0;
3477:
3478: dl = DL(nd_psh[t]);
3479: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3480: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3481: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3482: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3483: continue;
3484: if ( nd_gbblock ) {
3485: t0 = (long)BDY(h);
3486: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3487: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3488: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3489: break;
3490: }
3491: if ( nd_gbblock[i] >= 0 )
3492: continue;
3493: }
1.41 noro 3494: NEXTND_pairs(r0,r); Npairs++;
1.1 noro 3495: r->i1 = (long)BDY(h);
3496: r->i2 = t;
3497: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3498: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3499: SG(r) = MAX(s,ts) + TD(LCM(r));
3500: /* experimental */
3501: if ( nd_sugarweight )
3502: r->sugar2 = ndl_weight2(r->lcm);
3503: }
3504: if ( r0 ) NEXT(r) = 0;
3505: return r0;
3506: }
3507:
1.46 noro 3508: int sig_cmpdl_op(int n,DL d1,DL d2)
3509: {
3510: int e1,e2,i,j,l;
3511: int *t1,*t2;
3512: int len,head;
3513: struct order_pair *pair;
3514:
3515: len = nd_sba_modord->block_length;
3516: pair = nd_sba_modord->order_pair;
3517:
3518: head = 0;
3519: for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {
3520: l = pair[i].length;
3521: switch ( pair[i].order ) {
3522: case 0:
3523: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3524: e1 += t1[j];
3525: e2 += t2[j];
3526: }
3527: if ( e1 > e2 )
3528: return 1;
3529: else if ( e1 < e2 )
3530: return -1;
3531: else {
3532: for ( j = l - 1; j >= 0 && t1[j] == t2[j]; j-- );
3533: if ( j >= 0 )
3534: return t1[j] < t2[j] ? 1 : -1;
3535: }
3536: break;
3537: case 1:
3538: for ( j = 0, e1 = e2 = 0; j < l; j++ ) {
3539: e1 += t1[j];
3540: e2 += t2[j];
3541: }
3542: if ( e1 > e2 )
3543: return 1;
3544: else if ( e1 < e2 )
3545: return -1;
3546: else {
3547: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3548: if ( j < l )
3549: return t1[j] > t2[j] ? 1 : -1;
3550: }
3551: break;
3552: case 2:
3553: for ( j = 0; j < l && t1[j] == t2[j]; j++ );
3554: if ( j < l )
3555: return t1[j] > t2[j] ? 1 : -1;
3556: break;
3557: default:
3558: error("sig_cmpdl_op : invalid order"); break;
3559: }
3560: t1 += l; t2 += l; head += l;
3561: }
3562: return 0;
3563: }
3564:
3565: int sig_cmpdl_mat(int n,DL d1,DL d2)
3566: {
3567: int *v,*t1,*t2;
3568: int s,i,j,len;
3569: int **matrix;
3570: static int *w;
3571: static int nvar = 0;
3572:
3573: if ( nvar != n ) {
3574: nvar = n; w = (int *)MALLOC(n*sizeof(int));
3575: }
3576: for ( i = 0, t1 = d1->d, t2 = d2->d; i < n; i++ )
3577: w[i] = t1[i]-t2[i];
3578: len = nd_sba_modord->row;
3579: matrix = nd_sba_modord->matrix;
3580: for ( j = 0; j < len; j++ ) {
3581: v = matrix[j];
3582: for ( i = 0, s = 0; i < n; i++ )
3583: s += v[i]*w[i];
3584: if ( s > 0 )
3585: return 1;
3586: else if ( s < 0 )
3587: return -1;
3588: }
3589: return 0;
3590: }
3591:
3592: struct comp_sig_spec *create_comp_sig_spec(VL current_vl,VL old_vl,Obj ord,Obj weight)
3593: {
3594: struct comp_sig_spec *spec;
3595: VL ovl,vl;
3596: V ov;
3597: int i,j,n,nvar,s;
3598: NODE node,t,tn;
3599: struct order_pair *l;
3600: MAT m;
3601: Obj **b;
3602: int **w;
3603: int *a;
3604:
3605: spec = (struct comp_sig_spec *)MALLOC(sizeof(struct comp_sig_spec));
3606: for ( i = 0, vl = current_vl; vl; vl = NEXT(vl), i++ );
3607: spec->n = nvar = i;
3608: if ( old_vl != 0 ) {
3609: spec->oldv = (int *)MALLOC(nvar*sizeof(int));
3610: for ( i = 0, ovl = old_vl; i < nvar; ovl = NEXT(ovl), i++ ) {
3611: ov = ovl->v;
3612: for ( j = 0, vl = current_vl; vl; vl = NEXT(vl), j++ )
3613: if ( ov == vl->v ) break;
3614: spec->oldv[i] = j;
3615: }
3616: } else
3617: spec->oldv = 0;
3618: if ( !ord || NUM(ord) ) {
3619: switch ( ZTOS((Z)ord) ) {
3620: case 0:
3621: spec->cmpdl = cmpdl_revgradlex; break;
3622: case 1:
3623: spec->cmpdl = cmpdl_gradlex; break;
3624: case 2:
3625: spec->cmpdl = cmpdl_lex; break;
3626: default:
3627: error("create_comp_sig_spec : invalid spec"); break;
3628: }
3629: } else if ( OID(ord) == O_LIST ) {
3630: node = BDY((LIST)ord);
3631: for ( n = 0, t = node; t; t = NEXT(t), n++ );
3632: l = (struct order_pair *)MALLOC_ATOMIC(n*sizeof(struct order_pair));
3633: for ( i = 0, t = node, s = 0; i < n; t = NEXT(t), i++ ) {
3634: tn = BDY((LIST)BDY(t)); l[i].order = ZTOS((Q)BDY(tn));
3635: tn = NEXT(tn); l[i].length = ZTOS((Q)BDY(tn));
3636: s += l[i].length;
3637: }
3638: if ( s != nvar )
3639: error("create_comp_sig_spec : invalid spec");
3640: spec->order_pair = l;
3641: spec->block_length = n;
3642: spec->cmpdl = sig_cmpdl_op;
3643: } else if ( OID(ord) == O_MAT ) {
3644: m = (MAT)ord; b = (Obj **)BDY(m);
3645: if ( m->col != nvar )
3646: error("create_comp_sig_spec : invalid spec");
3647: w = almat(m->row,m->col);
3648: for ( i = 0; i < m->row; i++ )
3649: for ( j = 0; j < m->col; j++ )
3650: w[i][j] = ZTOS((Q)b[i][j]);
3651: spec->row = m->row;
3652: spec->matrix = w;
3653: spec->cmpdl = sig_cmpdl_mat;
3654: } else
3655: error("create_comp_sig_spec : invalid spec");
3656: if ( weight != 0 ) {
3657: node = BDY((LIST)weight);
3658: a = (int *)MALLOC(nvar*sizeof(int));
3659: for ( i = 0; i < nvar; i++, node = NEXT(node) )
3660: a[i] = ZTOS((Z)BDY(node));
3661: spec->weight = a;
3662: }
3663: return spec;
3664: }
3665:
3666: #define SIG_MUL_WEIGHT(a,i) (weight?(a)*weight[i]:(a))
3667:
3668: int comp_sig_monomial(int n,DL d1,DL d2)
3669: {
3670: static DL m1,m2;
3671: static int nvar = 0;
3672: int *oldv,*weight;
3673: int i,w1,w2;
3674:
3675: if ( nvar != n ) {
3676: nvar = n; NEWDL(m1,nvar); NEWDL(m2,nvar);
3677: }
3678: if ( !nd_sba_modord )
3679: return (*cmpdl)(n,d1,d2);
3680: else {
3681: weight = nd_sba_modord->weight;
3682: oldv = nd_sba_modord->oldv;
3683: if ( oldv ) {
3684: for ( i = 0; i < n; i++ ) {
3685: m1->d[i] = d1->d[oldv[i]]; m2->d[i] = d2->d[oldv[i]];
3686: }
3687: } else {
3688: for ( i = 0; i < n; i++ ) {
3689: m1->d[i] = d1->d[i]; m2->d[i] = d2->d[i];
3690: }
3691: }
3692: for ( i = 0, w1 = w2 = 0; i < n; i++ ) {
3693: w1 += SIG_MUL_WEIGHT(m1->d[i],i);
3694: w2 += SIG_MUL_WEIGHT(m2->d[i],i);
3695: }
3696: m1->td = w1; m2->td = w2;
3697: return (*nd_sba_modord->cmpdl)(n,m1,m2);
3698: }
3699: }
3700:
1.24 noro 3701: int comp_sig(SIG s1,SIG s2)
3702: {
1.38 noro 3703: if ( nd_sba_pot ) {
3704: if ( s1->pos > s2->pos ) return 1;
3705: else if ( s1->pos < s2->pos ) return -1;
1.46 noro 3706: else return comp_sig_monomial(nd_nvar,s1->dl,s2->dl);
1.38 noro 3707: } else {
3708: static DL m1,m2;
1.44 noro 3709: static int nvar = 0;
1.38 noro 3710: int ret;
3711:
3712: if ( nvar != nd_nvar ) {
3713: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
3714: }
3715: _adddl(nd_nvar,s1->dl,nd_sba_hm[s1->pos],m1);
3716: _adddl(nd_nvar,s2->dl,nd_sba_hm[s2->pos],m2);
1.47 ! noro 3717: if ( !nd_sba_modord )
! 3718: ret = (*cmpdl)(nd_nvar,m1,m2);
! 3719: else
! 3720: ret = comp_sig_monomial(nd_nvar,m1,m2);
1.38 noro 3721: if ( ret != 0 ) return ret;
3722: else if ( s1->pos > s2->pos ) return 1;
3723: else if ( s1->pos < s2->pos ) return -1;
3724: else return 0;
1.24 noro 3725: }
3726: }
3727:
3728: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3729: {
3730: int ret,s1,s2;
3731: RHist p1,p2;
3732: static int wpd;
3733: static UINT *lcm;
3734:
3735: sp->i1 = i1;
3736: sp->i2 = i2;
3737: p1 = nd_psh[i1];
3738: p2 = nd_psh[i2];
3739: ndl_lcm(DL(p1),DL(p2),sp->lcm);
3740: s1 = SG(p1)-TD(DL(p1));
3741: s2 = SG(p2)-TD(DL(p2));
3742: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
3743:
1.26 noro 3744: if ( wpd != nd_wpd ) {
1.24 noro 3745: wpd = nd_wpd;
3746: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
3747: }
3748: // DL(sig1) <- sp->lcm
3749: // DL(sig1) -= DL(p1)
3750: // DL(sig1) += DL(p1->sig)
1.27 noro 3751: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 3752: _ndltodl(lcm,DL(sig1));
3753: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
3754: sig1->pos = p1->sig->pos;
3755:
3756: // DL(sig2) <- sp->lcm
3757: // DL(sig2) -= DL(p2)
3758: // DL(sig2) += DL(p2->sig)
1.27 noro 3759: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 3760: _ndltodl(lcm,DL(sig2));
3761: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
3762: sig2->pos = p2->sig->pos;
3763:
3764: ret = comp_sig(sig1,sig2);
3765: if ( ret == 0 ) return 0;
3766: else if ( ret > 0 ) sp->sig = sig1;
3767: else sp->sig = sig2;
3768: return 1;
3769: }
3770:
3771: SIG dup_sig(SIG sig)
3772: {
3773: SIG r;
3774:
3775: if ( !sig ) return 0;
3776: else {
3777: NEWSIG(r);
3778: _copydl(nd_nvar,DL(sig),DL(r));
3779: r->pos = sig->pos;
3780: return r;
3781: }
3782: }
3783:
3784: void dup_ND_pairs(ND_pairs to,ND_pairs from)
3785: {
3786: to->i1 = from->i1;
3787: to->i2 = from->i2;
3788: to->sugar = from->sugar;
3789: to->sugar2 = from->sugar2;
3790: ndl_copy(from->lcm,to->lcm);
3791: to->sig = dup_sig(from->sig);
3792: }
3793:
3794: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
3795: {
3796: struct oND_pairs root;
3797: ND_pairs q1,q2,r0,r;
3798: int ret;
3799:
3800: r = &root;
3801: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
3802: ret = comp_sig(q1->sig,q2->sig);
3803: if ( ret < 0 ) {
3804: r->next = q1; r = q1; q1 = q1->next;
3805: } else if ( ret > 0 ) {
3806: r->next = q2; r = q2; q2 = q2->next;
3807: } else {
1.47 ! noro 3808: Nnewpair--;
1.24 noro 3809: ret = DL_COMPARE(q1->lcm,q2->lcm);
1.35 noro 3810: Nsamesig++;
1.24 noro 3811: if ( ret < 0 ) {
3812: r->next = q1; r = q1; q1 = q1->next;
3813: q2 = q2->next;
3814: } else {
3815: r->next = q2; r = q2; q2 = q2->next;
3816: q1 = q1->next;
3817: }
3818: }
3819: }
3820: if ( q1 ) {
3821: r->next = q1;
3822: } else {
3823: r->next = q2;
3824: }
3825: return root.next;
3826: }
3827:
3828: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
3829: {
3830: ND_pairs p,prev;
1.47 ! noro 3831: int ret=1;
1.24 noro 3832:
3833: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
3834: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
3835: break;
3836: }
3837: if ( ret == 0 ) {
3838: ret = DL_COMPARE(s->lcm,p->lcm);
3839: if ( ret < 0 ) {
3840: // replace p with s
3841: s->next = p->next;
3842: if ( prev == 0 ) {
3843: return s;
3844: } else {
3845: prev->next = s;
3846: return l;
3847: }
3848: } else
3849: return l;
3850: } else {
3851: // insert s between prev and p
1.47 ! noro 3852: Nnewpair++;
1.24 noro 3853: s->next = p;
3854: if ( prev == 0 ) {
3855: return s;
3856: } else {
3857: prev->next = s;
3858: return l;
3859: }
3860: }
3861: }
3862:
1.29 noro 3863: INLINE int __dl_redble(DL d1,DL d2,int nvar)
3864: {
3865: int i;
3866:
3867: if ( d1->td > d2->td )
3868: return 0;
3869: for ( i = nvar-1; i >= 0; i-- )
3870: if ( d1->d[i] > d2->d[i] )
3871: break;
3872: if ( i >= 0 )
3873: return 0;
3874: else
3875: return 1;
3876: }
3877:
1.30 noro 3878: ND_pairs nd_newpairs_s(int t, NODE *syz)
1.24 noro 3879: {
3880: NODE h,s;
3881: UINT *dl;
1.27 noro 3882: int ts,ret,i;
1.24 noro 3883: ND_pairs r,r0,_sp,sp;
1.29 noro 3884: SIG spsig,tsig;
1.44 noro 3885: static int nvar = 0;
1.29 noro 3886: static SIG _sig1,_sig2;
1.26 noro 3887: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 3888:
3889: NEWND_pairs(_sp);
1.29 noro 3890: if ( !_sig1 || nvar != nd_nvar ) {
3891: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
3892: }
1.24 noro 3893: r0 = 0;
1.27 noro 3894: for ( i = 0; i < t; i++ ) {
3895: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
1.24 noro 3896: if ( ret ) {
3897: spsig = _sp->sig;
1.29 noro 3898: for ( s = syz[spsig->pos]; s; s = s->next ) {
1.24 noro 3899: tsig = (SIG)s->body;
1.29 noro 3900: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
1.24 noro 3901: break;
3902: }
3903: if ( s == 0 ) {
3904: NEWND_pairs(sp);
3905: dup_ND_pairs(sp,_sp);
3906: r0 = insert_pair_s(r0,sp);
1.26 noro 3907: } else
3908: Nsyz++;
1.24 noro 3909: }
3910: }
3911: return r0;
3912: }
3913:
1.47 ! noro 3914: ND_pairs *nd_newpairs_array_s(int t, NODE *syz)
! 3915: {
! 3916: NODE h,s;
! 3917: UINT *dl;
! 3918: int ts,ret,i;
! 3919: ND_pairs r,r0,_sp,sp;
! 3920: ND_pairs *d;
! 3921: SIG spsig,tsig;
! 3922: static int nvar = 0;
! 3923: static SIG _sig1,_sig2;
! 3924: struct oEGT eg1,eg2,eg3,eg4;
! 3925:
! 3926: NEWND_pairs(_sp);
! 3927: if ( !_sig1 || nvar != nd_nvar ) {
! 3928: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
! 3929: }
! 3930: d = (ND_pairs *)MALLOC(nd_nbase*sizeof(ND_pairs));
! 3931: Nnewpair = 0;
! 3932: for ( i = 0; i < t; i++ ) {
! 3933: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
! 3934: if ( ret ) {
! 3935: spsig = _sp->sig;
! 3936: for ( s = syz[spsig->pos]; s; s = s->next ) {
! 3937: tsig = (SIG)s->body;
! 3938: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
! 3939: break;
! 3940: }
! 3941: if ( s == 0 ) {
! 3942: NEWND_pairs(sp);
! 3943: dup_ND_pairs(sp,_sp);
! 3944: d[spsig->pos] = insert_pair_s(d[spsig->pos],sp);
! 3945: } else
! 3946: Nsyz++;
! 3947: }
! 3948: }
! 3949: return d;
! 3950: }
! 3951:
1.1 noro 3952: /* ipair = [i1,i2],[i1,i2],... */
3953: ND_pairs nd_ipairtospair(NODE ipair)
3954: {
3955: int s1,s2;
3956: NODE tn,t;
3957: ND_pairs r,r0;
3958:
3959: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
3960: NEXTND_pairs(r0,r);
3961: tn = BDY((LIST)BDY(t));
1.6 noro 3962: r->i1 = ZTOS((Q)ARG0(tn));
3963: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 3964: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
3965: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3966: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
3967: SG(r) = MAX(s1,s2) + TD(LCM(r));
3968: /* experimental */
3969: if ( nd_sugarweight )
3970: r->sugar2 = ndl_weight2(r->lcm);
3971: }
3972: if ( r0 ) NEXT(r) = 0;
3973: return r0;
3974: }
3975:
3976: /* kokokara */
3977:
3978: ND_pairs crit_B( ND_pairs d, int s )
3979: {
3980: ND_pairs cur,head,prev,remove;
3981: UINT *t,*tl,*lcm;
3982: int td,tdl;
3983:
3984: if ( !d ) return 0;
3985: t = DL(nd_psh[s]);
3986: prev = 0;
3987: head = cur = d;
3988: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
3989: while ( cur ) {
3990: tl = cur->lcm;
3991: if ( ndl_reducible(tl,t) ) {
3992: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
3993: if ( !ndl_equal(lcm,tl) ) {
3994: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
3995: if (!ndl_equal(lcm,tl)) {
3996: remove = cur;
3997: if ( !prev ) {
3998: head = cur = NEXT(cur);
3999: } else {
4000: cur = NEXT(prev) = NEXT(cur);
4001: }
1.41 noro 4002: FREENDP(remove); NcriB++;
1.1 noro 4003: } else {
4004: prev = cur; cur = NEXT(cur);
4005: }
4006: } else {
4007: prev = cur; cur = NEXT(cur);
4008: }
4009: } else {
4010: prev = cur; cur = NEXT(cur);
4011: }
4012: }
4013: return head;
4014: }
4015:
4016: ND_pairs crit_M( ND_pairs d1 )
4017: {
4018: ND_pairs e,d2,d3,dd,p;
4019: UINT *id,*jd;
4020:
4021: if ( !d1 ) return d1;
4022: for ( dd = 0, e = d1; e; e = d3 ) {
4023: if ( !(d2 = NEXT(e)) ) {
4024: NEXT(e) = dd;
4025: return e;
4026: }
4027: id = LCM(e);
4028: for ( d3 = 0; d2; d2 = p ) {
4029: p = NEXT(d2);
4030: jd = LCM(d2);
4031: if ( ndl_equal(jd,id) )
4032: ;
4033: else if ( TD(jd) > TD(id) )
4034: if ( ndl_reducible(jd,id) ) continue;
4035: else ;
4036: else if ( ndl_reducible(id,jd) ) goto delit;
4037: NEXT(d2) = d3;
4038: d3 = d2;
4039: }
4040: NEXT(e) = dd;
4041: dd = e;
4042: continue;
4043: /**/
4044: delit: NEXT(d2) = d3;
4045: d3 = d2;
4046: for ( ; p; p = d2 ) {
4047: d2 = NEXT(p);
4048: NEXT(p) = d3;
4049: d3 = p;
4050: }
4051: FREENDP(e);
4052: }
4053: return dd;
4054: }
4055:
4056: ND_pairs crit_F( ND_pairs d1 )
4057: {
4058: ND_pairs rest, head,remove;
4059: ND_pairs last, p, r, w;
4060: int s;
4061:
4062: if ( !d1 ) return d1;
4063: for ( head = last = 0, p = d1; NEXT(p); ) {
4064: r = w = equivalent_pairs(p,&rest);
4065: s = SG(r);
4066: w = NEXT(w);
4067: while ( w ) {
4068: if ( crit_2(w->i1,w->i2) ) {
4069: r = w;
4070: w = NEXT(w);
4071: while ( w ) {
4072: remove = w;
4073: w = NEXT(w);
4074: FREENDP(remove);
4075: }
4076: break;
4077: } else if ( SG(w) < s ) {
4078: FREENDP(r);
4079: r = w;
4080: s = SG(r);
4081: w = NEXT(w);
4082: } else {
4083: remove = w;
4084: w = NEXT(w);
4085: FREENDP(remove);
4086: }
4087: }
4088: if ( last ) NEXT(last) = r;
4089: else head = r;
4090: NEXT(last = r) = 0;
4091: p = rest;
4092: if ( !p ) return head;
4093: }
4094: if ( !last ) return p;
4095: NEXT(last) = p;
4096: return head;
4097: }
4098:
4099: int crit_2( int dp1, int dp2 )
4100: {
4101: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
4102: }
4103:
4104: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
4105: {
4106: ND_pairs w,p,r,s;
4107: UINT *d;
4108:
4109: w = d1;
4110: d = LCM(w);
4111: s = NEXT(w);
4112: NEXT(w) = 0;
4113: for ( r = 0; s; s = p ) {
4114: p = NEXT(s);
4115: if ( ndl_equal(d,LCM(s)) ) {
4116: NEXT(s) = w; w = s;
4117: } else {
4118: NEXT(s) = r; r = s;
4119: }
4120: }
4121: *prest = r;
4122: return w;
4123: }
4124:
4125: NODE update_base(NODE nd,int ndp)
4126: {
4127: UINT *dl, *dln;
4128: NODE last, p, head;
4129:
4130: dl = DL(nd_psh[ndp]);
4131: for ( head = last = 0, p = nd; p; ) {
4132: dln = DL(nd_psh[(long)BDY(p)]);
4133: if ( ndl_reducible( dln, dl ) ) {
4134: p = NEXT(p);
4135: if ( last ) NEXT(last) = p;
4136: } else {
4137: if ( !last ) head = p;
4138: p = NEXT(last = p);
4139: }
4140: }
4141: head = append_one(head,ndp);
4142: return head;
4143: }
4144:
4145: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
4146: {
4147: ND_pairs m,ml,p,l;
4148: UINT *lcm;
4149: int s,td,len,tlen,c,c1;
4150:
4151: if ( !(p = NEXT(m = d)) ) {
4152: *prest = p;
4153: NEXT(m) = 0;
4154: return m;
4155: }
4156: if ( !NoSugar ) {
4157: if ( nd_sugarweight ) {
4158: s = m->sugar2;
4159: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4160: if ( (p->sugar2 < s)
4161: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4162: ml = l; m = p; s = m->sugar2;
4163: }
4164: } else {
4165: s = SG(m);
4166: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4167: if ( (SG(p) < s)
4168: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
4169: ml = l; m = p; s = SG(m);
4170: }
4171: }
4172: } else {
4173: for ( ml = 0, l = m; p; p = NEXT(l = p) )
4174: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
4175: ml = l; m = p; s = SG(m);
4176: }
4177: }
4178: if ( !ml ) *prest = NEXT(m);
4179: else {
4180: NEXT(ml) = NEXT(m);
4181: *prest = d;
4182: }
4183: NEXT(m) = 0;
4184: return m;
4185: }
4186:
4187: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
4188: {
4189: int msugar,i;
4190: ND_pairs t,dm0,dm,dr0,dr;
4191:
4192: if ( nd_sugarweight ) {
4193: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
4194: if ( t->sugar2 < msugar ) msugar = t->sugar2;
4195: dm0 = 0; dr0 = 0;
4196: for ( i = 0, t = d; t; t = NEXT(t) )
4197: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
4198: if ( dm0 ) NEXT(dm) = t;
4199: else dm0 = t;
4200: dm = t;
4201: i++;
4202: } else {
4203: if ( dr0 ) NEXT(dr) = t;
4204: else dr0 = t;
4205: dr = t;
4206: }
4207: } else {
4208: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
4209: if ( SG(t) < msugar ) msugar = SG(t);
4210: dm0 = 0; dr0 = 0;
4211: for ( i = 0, t = d; t; t = NEXT(t) )
4212: if ( i < nd_f4_nsp && SG(t) == msugar ) {
4213: if ( dm0 ) NEXT(dm) = t;
4214: else dm0 = t;
4215: dm = t;
4216: i++;
4217: } else {
4218: if ( dr0 ) NEXT(dr) = t;
4219: else dr0 = t;
4220: dr = t;
4221: }
4222: }
4223: NEXT(dm) = 0;
4224: if ( dr0 ) NEXT(dr) = 0;
4225: *prest = dr0;
4226: return dm0;
4227: }
4228:
1.28 noro 4229: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
4230: {
4231: int msugar;
4232: ND_pairs t,last;
4233:
4234: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
4235: if ( SG(t) == msugar ) last = t;
4236: *prest = last->next;
4237: last->next = 0;
4238: return d;
4239: }
4240:
1.1 noro 4241: int nd_tdeg(NDV c)
4242: {
4243: int wmax = 0;
4244: int i,len;
4245: NMV a;
4246:
4247: len = LEN(c);
4248: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4249: wmax = MAX(TD(DL(a)),wmax);
4250: return wmax;
4251: }
4252:
1.24 noro 4253: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 4254: {
4255: int len;
4256: RHist r;
4257: NDV b;
4258: NODE tn;
4259: LIST l;
4260: Z iq;
4261:
4262: if ( nd_psn == nd_pslen ) {
4263: nd_pslen *= 2;
4264: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
4265: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
4266: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
4267: nd_bound = (UINT **)
4268: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
4269: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
4270: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
4271: }
4272: NEWRHist(r); nd_psh[nd_psn] = r;
4273: nd_ps[nd_psn] = a;
4274: if ( aq ) {
4275: nd_ps_trace[nd_psn] = aq;
4276: if ( !m ) {
4277: register_hcf(aq);
4278: } else if ( m == -2 ) {
4279: /* do nothing */
4280: } else
4281: error("ndv_newps : invalud modulus");
4282: nd_bound[nd_psn] = ndv_compute_bound(aq);
4283: #if 1
4284: SG(r) = SG(aq);
4285: #else
4286: SG(r) = nd_tdeg(aq);
4287: #endif
4288: ndl_copy(HDL(aq),DL(r));
1.24 noro 4289: r->sig = dup_sig(aq->sig);
1.1 noro 4290: } else {
4291: if ( !m ) register_hcf(a);
4292: nd_bound[nd_psn] = ndv_compute_bound(a);
4293: #if 1
4294: SG(r) = SG(a);
4295: #else
4296: SG(r) = nd_tdeg(a);
4297: #endif
4298: ndl_copy(HDL(a),DL(r));
1.24 noro 4299: r->sig = dup_sig(a->sig);
1.1 noro 4300: }
4301: if ( nd_demand ) {
4302: if ( aq ) {
4303: ndv_save(nd_ps_trace[nd_psn],nd_psn);
4304: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4305: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
4306: nd_ps_trace[nd_psn] = 0;
4307: } else {
4308: ndv_save(nd_ps[nd_psn],nd_psn);
4309: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
4310: nd_ps[nd_psn] = 0;
4311: }
4312: }
4313: if ( nd_gentrace ) {
4314: /* reverse the tracelist and append it to alltracelist */
4315: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 4316: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 4317: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
4318: }
4319: return nd_psn++;
4320: }
4321:
1.46 noro 4322: // find LM wrt the specified modord
4323: void ndv_lm_modord(NDV p,DL d)
1.45 noro 4324: {
4325: NMV m;
4326: DL tmp;
4327: int len,i,ret;
4328:
4329: NEWDL(tmp,nd_nvar);
4330: m = BDY(p); len = LEN(p);
1.46 noro 4331: _ndltodl(DL(m),d); // printdl(d); printf("->");
1.45 noro 4332: for ( i = 1, NMV_ADV(m); i < len; i++, NMV_ADV(m) ) {
4333: _ndltodl(DL(m),tmp);
1.46 noro 4334: ret = comp_sig_monomial(nd_nvar,tmp,d);
1.45 noro 4335: if ( ret > 0 ) _copydl(nd_nvar,tmp,d);
4336: }
1.46 noro 4337: // printdl(d); printf("\n");
1.45 noro 4338: }
4339:
1.1 noro 4340: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
4341: /* return 1 if success, 0 if failure (HC(a mod p)) */
4342:
1.24 noro 4343: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 4344: {
1.6 noro 4345: int i,j,td,len,max;
4346: NODE s,s0,f0,tn;
4347: UINT *d;
4348: RHist r;
4349: NDVI w;
4350: NDV a,am;
4351: union oNDC hc;
4352: NODE node;
4353: P hcp;
4354: Z iq,jq;
4355: LIST l;
4356:
4357: nd_found = 0; nd_notfirst = 0; nd_create = 0;
4358: /* initialize the tracelist */
4359: nd_tracelist = 0;
4360:
4361: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
4362: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
4363: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
4364: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
4365: if ( !dont_sort ) {
4366: /* XXX heuristic */
1.26 noro 4367: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 4368: qsort(w,nd_psn,sizeof(struct oNDVI),
4369: (int (*)(const void *,const void *))ndvi_compare_rev);
4370: else
4371: qsort(w,nd_psn,sizeof(struct oNDVI),
4372: (int (*)(const void *,const void *))ndvi_compare);
4373: }
4374: nd_pslen = 2*nd_psn;
4375: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4376: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4377: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4378: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4379: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
4380: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
4381: nd_hcf = 0;
1.1 noro 4382:
1.6 noro 4383: if ( trace && nd_vc )
4384: makesubst(nd_vc,&nd_subst);
4385: else
4386: nd_subst = 0;
1.1 noro 4387:
1.6 noro 4388: if ( !nd_red )
4389: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
4390: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
4391: for ( i = 0; i < nd_psn; i++ ) {
4392: hc = HCU(w[i].p);
4393: if ( trace ) {
4394: if ( mod == -2 ) {
4395: /* over a large finite field */
4396: /* trace = small modulus */
4397: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
4398: ndv_mod(-2,a);
4399: if ( !dont_removecont) ndv_removecont(-2,a);
4400: am = nd_ps[i] = ndv_dup(trace,w[i].p);
4401: ndv_mod(trace,am);
4402: if ( DL_COMPARE(HDL(am),HDL(a)) )
4403: return 0;
4404: ndv_removecont(trace,am);
4405: } else {
4406: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
4407: if ( !dont_removecont) ndv_removecont(0,a);
4408: register_hcf(a);
4409: am = nd_ps[i] = ndv_dup(mod,a);
4410: ndv_mod(mod,am);
4411: if ( DL_COMPARE(HDL(am),HDL(a)) )
4412: return 0;
4413: ndv_removecont(mod,am);
4414: }
4415: } else {
4416: a = nd_ps[i] = ndv_dup(mod,w[i].p);
4417: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
4418: if ( !mod ) register_hcf(a);
1.1 noro 4419: }
1.6 noro 4420: if ( nd_gentrace ) {
4421: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
4422: /* exact division */
1.1 noro 4423: if ( !dont_removecont )
1.6 noro 4424: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
4425: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
4426: }
4427: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
4428: nd_bound[i] = ndv_compute_bound(a);
4429: nd_psh[i] = r;
4430: if ( nd_demand ) {
4431: if ( trace ) {
4432: ndv_save(nd_ps_trace[i],i);
4433: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4434: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4435: nd_ps_trace[i] = 0;
4436: } else {
4437: ndv_save(nd_ps[i],i);
4438: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
4439: nd_ps[i] = 0;
4440: }
1.1 noro 4441: }
1.6 noro 4442: }
1.24 noro 4443: if ( sba ) {
1.27 noro 4444: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 4445: // setup signatures
1.27 noro 4446: for ( i = 0; i < nd_psn; i++ ) {
4447: SIG sig;
1.24 noro 4448:
1.27 noro 4449: NEWSIG(sig); sig->pos = i;
4450: nd_ps[i]->sig = sig;
4451: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
4452: nd_psh[i]->sig = sig;
4453: if ( trace ) {
4454: nd_ps_trace[i]->sig = sig;
4455: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
4456: }
4457: NEWDL(nd_sba_hm[i],nd_nvar);
1.46 noro 4458: if ( nd_sba_modord )
4459: ndv_lm_modord(nd_ps[i],nd_sba_hm[i]);
1.45 noro 4460: else
4461: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
1.27 noro 4462: }
1.29 noro 4463: nd_sba_pos = (NODE *)MALLOC(nd_psn*sizeof(NODE));
4464: for ( i = 0; i < nd_psn; i++ ) {
4465: j = nd_psh[i]->sig->pos;
4466: nd_sba_pos[j] = append_one(nd_sba_pos[j],i);
4467: }
1.24 noro 4468: }
1.6 noro 4469: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
4470: return 1;
1.1 noro 4471: }
4472:
4473: struct order_spec *append_block(struct order_spec *spec,
4474: int nv,int nalg,int ord);
4475:
4476: extern VECT current_dl_weight_vector_obj;
4477: static VECT prev_weight_vector_obj;
4478:
4479: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
4480: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
4481: {
4482: NODE alist,t,s,r0,r,arg;
4483: VL tv;
4484: P poly;
4485: DP d;
4486: Alg alpha,dp;
4487: DAlg inv,da,hc;
4488: MP m;
4489: int i,nvar,nalg,n;
4490: NumberField nf;
4491: LIST f1,f2;
4492: struct order_spec *current_spec;
4493: VECT obj,obj0;
4494: VECT tmp;
4495:
4496: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
4497: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
4498:
4499: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
4500: NEXTNODE(alist,t); MKV(tv->v,poly);
4501: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
4502: tv->v = tv->v->priv;
4503: }
4504: NEXT(t) = 0;
4505:
4506: /* simplification, making polynomials monic */
4507: setfield_dalg(alist);
4508: obj_algtodalg((Obj)f,(Obj *)&f1);
4509: for ( t = BDY(f); t; t = NEXT(t) ) {
4510: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
4511: hc = (DAlg)BDY(d)->c;
4512: if ( NID(hc) == N_DA ) {
4513: invdalg(hc,&inv);
4514: for ( m = BDY(d); m; m = NEXT(m) ) {
4515: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
4516: }
4517: }
4518: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
4519: }
4520: obj_dalgtoalg((Obj)f1,(Obj *)&f);
4521:
4522: /* append alg vars to the var list */
4523: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
4524: NEXT(tv) = av;
4525:
4526: /* append a block to ord */
4527: *ord1p = append_block(ord,nvar,nalg,2);
4528:
4529: /* create generator list */
4530: nf = get_numberfield();
4531: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
4532: MKAlg(nf->defpoly[i],dp);
4533: MKNODE(s,dp,t); t = s;
4534: }
4535: MKLIST(f1,t);
4536: *alistp = alist;
4537: algobjtorat((Obj)f1,(Obj *)f1p);
4538:
4539: /* creating a new weight vector */
4540: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
4541: n = nvar+nalg+1;
4542: MKVECT(obj,n);
4543: if ( obj0 && obj0->len == nvar )
4544: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
4545: else
4546: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
4547: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
4548: BDY(obj)[n-1] = (pointer)ONE;
4549: arg = mknode(1,obj);
4550: Pdp_set_weight(arg,&tmp);
4551: }
4552:
4553: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
4554: {
4555: NODE s,t,u0,u;
4556: P p;
4557: VL tv;
4558: Obj obj;
4559: VECT tmp;
4560: NODE arg;
4561:
4562: u0 = 0;
4563: for ( t = r; t; t = NEXT(t) ) {
4564: p = (P)BDY(t);
4565: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
4566: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
4567: }
4568: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
4569: NEXTNODE(u0,u);
4570: BDY(u) = (pointer)p;
4571: }
4572: }
4573: arg = mknode(1,prev_weight_vector_obj);
4574: Pdp_set_weight(arg,&tmp);
4575:
4576: return u0;
4577: }
4578:
4579: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
4580: {
4581: VL tv,fv,vv,vc,av;
4582: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4583: int e,max,nvar,i;
4584: NDV b;
4585: int ishomo,nalg,mrank,trank,wmax,len;
4586: NMV a;
4587: Alg alpha,dp;
4588: P p,zp;
4589: Q dmy;
4590: LIST f1,f2,zpl;
4591: Obj obj;
4592: NumberField nf;
4593: struct order_spec *ord1;
4594: NODE tr,tl1,tl2,tl3,tl4,nzlist;
4595: LIST l1,l2,l3,l4,l5;
4596: int j;
4597: Z jq,bpe,last_nonzero;
4598: int *perm;
4599: EPOS oepos;
4600: int obpe,oadv,ompos,cbpe;
1.15 noro 4601: VECT hvect;
1.1 noro 4602:
1.41 noro 4603: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 4604: nd_module = 0;
4605: if ( !m && Demand ) nd_demand = 1;
4606: else nd_demand = 0;
4607:
4608: if ( DP_Multiple )
4609: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4610: #if 0
4611: ndv_alloc = 0;
4612: #endif
4613: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 4614: parse_nd_option(vv,current_option);
1.1 noro 4615: if ( m && nd_vc )
4616: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4617: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4618: switch ( ord->id ) {
4619: case 1:
4620: if ( ord->nv != nvar )
4621: error("nd_{gr,f4} : invalid order specification");
4622: break;
4623: default:
4624: break;
4625: }
4626: nd_nalg = 0;
4627: av = 0;
4628: if ( !m ) {
4629: get_algtree((Obj)f,&av);
4630: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4631: nd_ntrans = nvar;
4632: nd_nalg = nalg;
4633: /* #i -> t#i */
4634: if ( nalg ) {
4635: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4636: ord = ord1;
4637: f = f1;
4638: }
4639: nvar += nalg;
4640: }
4641: nd_init_ord(ord);
4642: mrank = 0;
4643: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4644: for ( tv = vv; tv; tv = NEXT(tv) ) {
4645: if ( nd_module ) {
1.16 noro 4646: if ( OID(BDY(t)) == O_DPM ) {
4647: e = dpm_getdeg((DPM)BDY(t),&trank);
4648: max = MAX(e,max);
4649: mrank = MAX(mrank,trank);
4650: } else {
4651: s = BDY((LIST)BDY(t));
4652: trank = length(s);
4653: mrank = MAX(mrank,trank);
4654: for ( ; s; s = NEXT(s) ) {
4655: e = getdeg(tv->v,(P)BDY(s));
4656: max = MAX(e,max);
4657: }
1.1 noro 4658: }
4659: } else {
1.43 noro 4660: if ( OID(BDY(t)) == O_DP ) {
4661: e = dp_getdeg((DP)BDY(t));
4662: max = MAX(e,max);
4663: } else {
4664: e = getdeg(tv->v,(P)BDY(t));
4665: max = MAX(e,max);
4666: }
1.1 noro 4667: }
4668: }
4669: nd_setup_parameters(nvar,nd_nzlist?0:max);
4670: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4671: ishomo = 1;
4672: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4673: if ( nd_module ) {
1.16 noro 4674: if ( OID(BDY(t)) == O_DPM ) {
4675: Z cont;
4676: DPM zdpm;
4677:
4678: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4679: else zdpm = (DPM)BDY(t);
4680: b = (pointer)dpmtondv(m,zdpm);
4681: } else {
4682: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4683: else zpl = (LIST)BDY(t);
1.1 noro 4684: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4685: }
1.1 noro 4686: } else {
1.43 noro 4687: if ( OID(BDY(t)) == O_DP ) {
4688: DP zdp;
4689:
4690: if ( !m && !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
4691: else zdp = (DP)BDY(t);
4692: b = (pointer)dptondv(m,zdp);
4693: } else {
4694: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4695: else zp = (P)BDY(t);
4696: b = (pointer)ptondv(CO,vv,zp);
4697: }
1.1 noro 4698: }
4699: if ( ishomo )
4700: ishomo = ishomo && ndv_ishomo(b);
4701: if ( m ) ndv_mod(m,b);
4702: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4703: }
4704: if ( fd0 ) NEXT(fd) = 0;
4705:
4706: if ( !ishomo && homo ) {
4707: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4708: b = (NDV)BDY(t); len = LEN(b);
4709: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4710: wmax = MAX(TD(DL(a)),wmax);
4711: }
4712: homogenize_order(ord,nvar,&ord1);
4713: nd_init_ord(ord1);
4714: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4715: for ( t = fd0; t; t = NEXT(t) )
4716: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4717: }
4718:
1.24 noro 4719: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4720: if ( nd_gentrace ) {
4721: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4722: }
4723: if ( nd_splist ) {
4724: *rp = compute_splist();
4725: return;
4726: }
4727: if ( nd_check_splist ) {
4728: if ( f4 ) {
4729: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4730: else *rp = 0;
4731: } else {
4732: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4733: else *rp = 0;
4734: }
4735: return;
4736: }
4737: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
4738: if ( !x ) {
4739: *rp = 0; return;
4740: }
1.15 noro 4741: if ( nd_gentrace ) {
4742: MKVECT(hvect,nd_psn);
4743: for ( i = 0; i < nd_psn; i++ )
4744: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4745: }
1.1 noro 4746: if ( !ishomo && homo ) {
4747: /* dehomogenization */
4748: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4749: nd_init_ord(ord);
4750: nd_setup_parameters(nvar,0);
4751: }
4752: nd_demand = 0;
4753: if ( nd_module && nd_intersect ) {
4754: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 4755: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 4756: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
4757: }
4758: conv_ilist(nd_demand,0,x,0);
4759: goto FINAL;
4760: }
4761: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
4762: x = ndv_reducebase(x,perm);
4763: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4764: x = ndv_reduceall(m,x);
4765: cbpe = nd_bpe;
4766: if ( nd_gentrace && !f4 ) {
4767: tl2 = nd_alltracelist; nd_alltracelist = 0;
4768: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
4769: tl3 = nd_alltracelist; nd_alltracelist = 0;
4770: if ( nd_gensyz ) {
4771: nd_gb(m,0,1,1,0);
4772: tl4 = nd_alltracelist; nd_alltracelist = 0;
4773: } else tl4 = 0;
4774: }
4775: nd_bpe = cbpe;
4776: nd_setup_parameters(nd_nvar,0);
4777: FINAL:
4778: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 4779: NEXTNODE(r0,r);
4780: if ( nd_module ) {
4781: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
4782: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
4783: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
4784: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 4785: }
4786: if ( r0 ) NEXT(r) = 0;
4787: if ( !m && nd_nalg )
4788: r0 = postprocess_algcoef(av,alist,r0);
4789: MKLIST(*rp,r0);
4790: if ( nd_gentrace ) {
4791: if ( f4 ) {
1.6 noro 4792: STOZ(16,bpe);
4793: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 4794: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 4795: } else {
4796: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4797: tl3 = reverse_node(tl3);
4798: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4799: for ( t = tl2; t; t = NEXT(t) ) {
4800: /* s = [i,[*,j,*,*],...] */
4801: s = BDY((LIST)BDY(t));
1.6 noro 4802: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4803: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4804: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4805: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4806: }
4807: }
4808: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4809: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4810: }
4811: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4812: MKLIST(l5,tl4);
1.6 noro 4813: STOZ(nd_bpe,bpe);
1.15 noro 4814: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4815: }
4816: }
4817: #if 0
4818: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
4819: #endif
4820: }
4821:
1.28 noro 4822: NODE nd_sba_f4(int m,int **indp);
4823:
4824: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 4825: {
4826: VL tv,fv,vv,vc,av;
1.44 noro 4827: NODE fd,fd0,r,r0,t,x,s,xx,nd,syz;
1.24 noro 4828: int e,max,nvar,i;
4829: NDV b;
4830: int ishomo,nalg,wmax,len;
4831: NMV a;
4832: P p,zp;
4833: Q dmy;
4834: struct order_spec *ord1;
4835: int j;
4836: int *perm;
4837: EPOS oepos;
4838: int obpe,oadv,ompos,cbpe;
1.29 noro 4839: struct oEGT eg0,eg1,egconv;
1.24 noro 4840:
4841: nd_module = 0;
4842: nd_demand = 0;
1.35 noro 4843: Nsamesig = 0;
1.24 noro 4844: if ( DP_Multiple )
4845: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4846: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 4847: parse_nd_option(vv,current_option);
1.24 noro 4848: if ( m && nd_vc )
4849: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4850: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4851: switch ( ord->id ) {
4852: case 1:
4853: if ( ord->nv != nvar )
4854: error("nd_sba : invalid order specification");
4855: break;
4856: default:
4857: break;
4858: }
4859: nd_nalg = 0;
4860: nd_init_ord(ord);
4861: // for SIG comparison
4862: initd(ord);
4863: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
4864: for ( tv = vv; tv; tv = NEXT(tv) ) {
1.43 noro 4865: if ( OID(BDY(t)) == O_DP ) {
4866: e = dp_getdeg((DP)BDY(t));
4867: max = MAX(e,max);
4868: } else {
4869: e = getdeg(tv->v,(P)BDY(t));
4870: max = MAX(e,max);
4871: }
1.24 noro 4872: }
4873: }
1.25 noro 4874: nd_setup_parameters(nvar,max);
1.24 noro 4875: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4876: ishomo = 1;
4877: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
1.43 noro 4878: if ( OID(BDY(t)) == O_DP ) {
4879: DP zdp;
4880:
4881: if ( !m ) dp_ptozp((DP)BDY(t),&zdp);
4882: else zdp = (DP)BDY(t);
4883: b = (pointer)dptondv(m,zdp);
4884: } else {
4885: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
4886: else zp = (P)BDY(t);
4887: b = (pointer)ptondv(CO,vv,zp);
4888: }
1.24 noro 4889: if ( ishomo )
4890: ishomo = ishomo && ndv_ishomo(b);
4891: if ( m ) ndv_mod(m,b);
4892: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4893: }
4894: if ( fd0 ) NEXT(fd) = 0;
4895:
4896: if ( !ishomo && homo ) {
4897: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4898: b = (NDV)BDY(t); len = LEN(b);
4899: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4900: wmax = MAX(TD(DL(a)),wmax);
4901: }
4902: homogenize_order(ord,nvar,&ord1);
4903: nd_init_ord(ord1);
1.42 noro 4904: // for SIG comparison
4905: initd(ord1);
1.24 noro 4906: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4907: for ( t = fd0; t; t = NEXT(t) )
4908: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4909: }
4910:
1.39 noro 4911: ndv_setup(m,0,fd0,nd_sba_dontsort,0,1);
1.44 noro 4912: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm,&syz);
1.24 noro 4913: if ( !x ) {
4914: *rp = 0; return;
4915: }
4916: if ( !ishomo && homo ) {
4917: /* dehomogenization */
4918: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4919: nd_init_ord(ord);
1.42 noro 4920: // for SIG comparison
4921: initd(ord);
1.24 noro 4922: nd_setup_parameters(nvar,0);
4923: }
4924: nd_demand = 0;
4925: x = ndv_reducebase(x,perm);
4926: x = ndv_reduceall(m,x);
4927: nd_setup_parameters(nd_nvar,0);
1.29 noro 4928: get_eg(&eg0);
1.24 noro 4929: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4930: NEXTNODE(r0,r);
4931: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
1.34 noro 4932: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.24 noro 4933: }
4934: if ( r0 ) NEXT(r) = 0;
1.44 noro 4935: if ( nd_sba_syz ) {
4936: LIST gb,hsyz;
4937: NODE nd;
4938:
4939: MKLIST(gb,r0);
4940: MKLIST(hsyz,syz);
4941: nd = mknode(2,gb,hsyz);
4942: MKLIST(*rp,nd);
4943: } else
4944: MKLIST(*rp,r0);
1.29 noro 4945: get_eg(&eg1); init_eg(&egconv); add_eg(&egconv,&eg0,&eg1);
4946: print_eg("conv",&egconv); fprintf(asir_out,"\n");
1.24 noro 4947: }
4948:
1.1 noro 4949: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
4950: {
4951: VL tv,fv,vv,vc,av;
4952: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4953: int e,max,nvar,i;
4954: NDV b;
4955: int ishomo,nalg;
4956: Alg alpha,dp;
4957: P p,zp;
4958: Q dmy;
4959: LIST f1,f2;
4960: Obj obj;
4961: NumberField nf;
4962: struct order_spec *ord1;
4963: int *perm;
4964:
4965: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 4966: parse_nd_option(vv,current_option);
1.1 noro 4967: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4968: switch ( ord->id ) {
4969: case 1:
4970: if ( ord->nv != nvar )
4971: error("nd_check : invalid order specification");
4972: break;
4973: default:
4974: break;
4975: }
4976: nd_nalg = 0;
4977: av = 0;
4978: if ( !m ) {
4979: get_algtree((Obj)f,&av);
4980: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4981: nd_ntrans = nvar;
4982: nd_nalg = nalg;
4983: /* #i -> t#i */
4984: if ( nalg ) {
4985: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4986: ord = ord1;
4987: f = f1;
4988: }
4989: nvar += nalg;
4990: }
4991: nd_init_ord(ord);
4992: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4993: for ( tv = vv; tv; tv = NEXT(tv) ) {
4994: e = getdeg(tv->v,(P)BDY(t));
4995: max = MAX(e,max);
4996: }
4997: nd_setup_parameters(nvar,max);
4998: ishomo = 1;
4999: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5000: ptozp((P)BDY(t),1,&dmy,&zp);
5001: b = (pointer)ptondv(CO,vv,zp);
5002: if ( ishomo )
5003: ishomo = ishomo && ndv_ishomo(b);
5004: if ( m ) ndv_mod(m,b);
5005: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
5006: }
5007: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 5008: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 5009: for ( x = 0, i = 0; i < nd_psn; i++ )
5010: x = update_base(x,i);
5011: if ( do_check ) {
5012: x = nd_gb(m,ishomo,1,0,&perm);
5013: if ( !x ) {
5014: *rp = 0;
5015: return;
5016: }
5017: } else {
5018: #if 0
5019: /* bug ? */
5020: for ( t = x; t; t = NEXT(t) )
5021: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
5022: #else
5023: conv_ilist(0,0,x,&perm);
5024: #endif
5025: }
5026: x = ndv_reducebase(x,perm);
5027: x = ndv_reduceall(m,x);
5028: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
5029: NEXTNODE(r0,r);
5030: BDY(r) = ndvtop(m,CO,vv,BDY(t));
5031: }
5032: if ( r0 ) NEXT(r) = 0;
5033: if ( !m && nd_nalg )
5034: r0 = postprocess_algcoef(av,alist,r0);
5035: MKLIST(*rp,r0);
5036: }
5037:
5038: NDV recompute_trace(NODE trace,NDV *p,int m);
5039: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
5040:
5041: NDV recompute_trace(NODE ti,NDV *p,int mod)
5042: {
5043: int c,c1,c2,i;
5044: NM mul,m,tail;
5045: ND d,r,rm;
5046: NODE sj;
5047: NDV red;
5048: Obj mj;
5049:
5050: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
5051: CM(mul) = 1;
5052: tail = 0;
5053: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
5054: sj = BDY((LIST)BDY(ti));
5055: if ( ARG0(sj) ) {
1.6 noro 5056: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 5057: mj = (Obj)ARG2(sj);
5058: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
5059: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
5060: rm = ndv_mul_nm(mod,mul,red);
5061: if ( !r ) r = rm;
5062: else {
5063: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
5064: if ( d ) {
5065: NEXT(tail) = m; tail = m; LEN(d)++;
5066: } else {
5067: MKND(nd_nvar,m,1,d); tail = BDY(d);
5068: }
5069: }
5070: if ( !m ) return 0; /* failure */
5071: else {
5072: BDY(r) = m;
5073: if ( mod > 0 || mod == -1 ) {
5074: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
5075: DMAR(c1,c2,0,mod,c);
5076: nd_mul_c(mod,rm,c);
5077: } else {
5078: Z t,u;
5079:
5080: chsgnlf(HCZ(r),&t);
5081: divlf(t,HCZ(rm),&u);
5082: nd_mul_c_lf(rm,u);
5083: }
5084: r = nd_add(mod,r,rm);
5085: }
5086: }
5087: }
5088: }
5089: if ( tail ) NEXT(tail) = 0;
5090: d = nd_add(mod,d,r);
5091: nd_mul_c(mod,d,invm(HCM(d),mod));
5092: return ndtondv(mod,d);
5093: }
5094:
5095: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
5096: {
5097: VL tv,fv,vv,vc,av;
5098: NODE fd,fd0,r,r0,t,x,s,xx,alist;
5099: int e,max,nvar,i;
5100: NDV b;
5101: int ishomo,nalg;
5102: Alg alpha,dp;
5103: P p,zp;
5104: Q dmy;
5105: LIST f1,f2;
5106: Obj obj;
5107: NumberField nf;
5108: struct order_spec *ord1;
5109: NODE permtrace,intred,ind,perm,trace,ti;
5110: int len,n,j;
5111: NDV *db,*pb;
5112:
5113: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 5114: parse_nd_option(vv,current_option);
1.1 noro 5115: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5116: switch ( ord->id ) {
5117: case 1:
5118: if ( ord->nv != nvar )
5119: error("nd_check : invalid order specification");
5120: break;
5121: default:
5122: break;
5123: }
5124: nd_init_ord(ord);
1.6 noro 5125: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 5126: nd_setup_parameters(nvar,0);
5127:
5128: len = length(BDY(f));
5129: db = (NDV *)MALLOC(len*sizeof(NDV *));
5130: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
5131: ptozp((P)BDY(t),1,&dmy,&zp);
5132: b = ptondv(CO,vv,zp);
5133: ndv_mod(m,b);
5134: ndv_mul_c(m,b,invm(HCM(b),m));
5135: db[i] = b;
5136: }
5137:
5138: permtrace = BDY((LIST)ARG2(BDY(tlist)));
5139: intred = BDY((LIST)ARG3(BDY(tlist)));
5140: ind = BDY((LIST)ARG4(BDY(tlist)));
5141: perm = BDY((LIST)ARG0(permtrace));
5142: trace = NEXT(permtrace);
5143:
5144: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 5145: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 5146: if ( j > i ) i = j;
5147: }
5148: n = i+1;
5149: pb = (NDV *)MALLOC(n*sizeof(NDV *));
5150: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
5151: ti = BDY((LIST)BDY(t));
1.6 noro 5152: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 5153: }
5154: for ( t = trace; t; t = NEXT(t) ) {
5155: ti = BDY((LIST)BDY(t));
1.6 noro 5156: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5157: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5158: if ( DP_Print ) {
5159: fprintf(asir_out,"."); fflush(asir_out);
5160: }
5161: }
5162: for ( t = intred; t; t = NEXT(t) ) {
5163: ti = BDY((LIST)BDY(t));
1.6 noro 5164: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
5165: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 5166: if ( DP_Print ) {
5167: fprintf(asir_out,"*"); fflush(asir_out);
5168: }
5169: }
5170: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
5171: NEXTNODE(r0,r);
1.6 noro 5172: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 5173: ndv_mul_c(m,b,invm(HCM(b),m));
5174: #if 0
1.6 noro 5175: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5176: #else
1.6 noro 5177: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 5178: #endif
5179: }
5180: if ( r0 ) NEXT(r) = 0;
5181: MKLIST(*rp,r0);
5182: if ( DP_Print ) fprintf(asir_out,"\n");
5183: }
5184:
1.16 noro 5185: 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 5186: {
5187: VL tv,fv,vv,vc,av;
5188: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
5189: int m,nocheck,nvar,mindex,e,max;
5190: NDV c;
5191: NMV a;
5192: P p,zp;
5193: Q dmy;
5194: EPOS oepos;
5195: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
5196: Alg alpha,dp;
5197: P poly;
5198: LIST f1,f2,zpl;
5199: Obj obj;
5200: NumberField nf;
5201: struct order_spec *ord1;
5202: struct oEGT eg_check,eg0,eg1;
5203: NODE tr,tl1,tl2,tl3,tl4;
5204: LIST l1,l2,l3,l4,l5;
5205: int *perm;
5206: int j,ret;
5207: Z jq,bpe;
1.15 noro 5208: VECT hvect;
1.1 noro 5209:
1.41 noro 5210: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 5211: nd_module = 0;
5212: nd_lf = 0;
1.46 noro 5213: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
5214: parse_nd_option(vv,current_option);
1.1 noro 5215: if ( nd_lf ) {
5216: if ( f4 )
5217: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
5218: else
5219: error("nd_gr_trace is not implemented yet over a large finite field");
5220: return;
5221: }
5222: if ( DP_Multiple )
5223: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
5224:
5225: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
5226: switch ( ord->id ) {
5227: case 1:
5228: if ( ord->nv != nvar )
5229: error("nd_gr_trace : invalid order specification");
5230: break;
5231: default:
5232: break;
5233: }
5234:
5235: get_algtree((Obj)f,&av);
5236: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
5237: nd_ntrans = nvar;
5238: nd_nalg = nalg;
5239: /* #i -> t#i */
5240: if ( nalg ) {
5241: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
5242: ord = ord1;
5243: f = f1;
5244: }
5245: nvar += nalg;
5246:
5247: nocheck = 0;
5248: mindex = 0;
5249:
5250: if ( Demand ) nd_demand = 1;
5251: else nd_demand = 0;
5252:
5253: /* setup modulus */
5254: if ( trace < 0 ) {
5255: trace = -trace;
5256: nocheck = 1;
5257: }
5258: m = trace > 1 ? trace : get_lprime(mindex);
5259: nd_init_ord(ord);
5260: mrank = 0;
5261: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
5262: for ( tv = vv; tv; tv = NEXT(tv) ) {
5263: if ( nd_module ) {
1.16 noro 5264: if ( OID(BDY(t)) == O_DPM ) {
5265: e = dpm_getdeg((DPM)BDY(t),&trank);
5266: max = MAX(e,max);
5267: mrank = MAX(mrank,trank);
5268: } else {
1.1 noro 5269: s = BDY((LIST)BDY(t));
5270: trank = length(s);
5271: mrank = MAX(mrank,trank);
5272: for ( ; s; s = NEXT(s) ) {
5273: e = getdeg(tv->v,(P)BDY(s));
5274: max = MAX(e,max);
5275: }
1.16 noro 5276: }
1.1 noro 5277: } else {
1.43 noro 5278: if ( OID(BDY(t)) == O_DP ) {
5279: e = dp_getdeg((DP)BDY(t));
5280: max = MAX(e,max);
5281: } else {
1.1 noro 5282: e = getdeg(tv->v,(P)BDY(t));
5283: max = MAX(e,max);
1.43 noro 5284: }
1.1 noro 5285: }
5286: }
5287: nd_setup_parameters(nvar,max);
5288: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
5289: ishomo = 1;
5290: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
5291: if ( nd_module ) {
1.16 noro 5292: if ( OID(BDY(t)) == O_DPM ) {
5293: Z cont;
5294: DPM zdpm;
5295:
1.17 noro 5296: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 5297: else zdpm = (DPM)BDY(t);
5298: c = (pointer)dpmtondv(m,zdpm);
5299: } else {
5300: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
5301: else zpl = (LIST)BDY(t);
1.1 noro 5302: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 5303: }
1.1 noro 5304: } else {
1.43 noro 5305: if ( OID(BDY(t)) == O_DP ) {
5306: DP zdp;
5307:
5308: if ( !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
5309: else zdp = (DP)BDY(t);
5310: c = (pointer)dptondv(m,zdp);
5311: } else {
5312: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
5313: else zp = (P)BDY(t);
5314: c = (pointer)ptondv(CO,vv,zp);
5315: }
1.1 noro 5316: }
5317: if ( ishomo )
5318: ishomo = ishomo && ndv_ishomo(c);
5319: if ( c ) {
5320: NEXTNODE(in0,in); BDY(in) = (pointer)c;
5321: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
5322: }
5323: }
5324: if ( in0 ) NEXT(in) = 0;
5325: if ( fd0 ) NEXT(fd) = 0;
5326: if ( !ishomo && homo ) {
5327: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
5328: c = (NDV)BDY(t); len = LEN(c);
5329: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
5330: wmax = MAX(TD(DL(a)),wmax);
5331: }
5332: homogenize_order(ord,nvar,&ord1);
5333: nd_init_ord(ord1);
5334: nd_setup_parameters(nvar+1,wmax);
5335: for ( t = fd0; t; t = NEXT(t) )
5336: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5337: }
5338: if ( MaxDeg > 0 ) nocheck = 1;
5339: while ( 1 ) {
5340: tl1 = tl2 = tl3 = tl4 = 0;
5341: if ( Demand )
5342: nd_demand = 1;
1.24 noro 5343: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 5344: if ( nd_gentrace ) {
5345: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5346: }
5347: if ( ret )
5348: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
5349: if ( !ret || !cand ) {
5350: /* failure */
5351: if ( trace > 1 ) { *rp = 0; return; }
5352: else m = get_lprime(++mindex);
5353: continue;
5354: }
1.15 noro 5355: if ( nd_gentrace ) {
5356: MKVECT(hvect,nd_psn);
5357: for ( i = 0; i < nd_psn; i++ )
5358: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5359: }
1.1 noro 5360: if ( !ishomo && homo ) {
5361: /* dehomogenization */
5362: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5363: nd_init_ord(ord);
5364: nd_setup_parameters(nvar,0);
5365: }
5366: nd_demand = 0;
5367: cand = ndv_reducebase(cand,perm);
5368: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5369: cand = ndv_reduceall(0,cand);
5370: cbpe = nd_bpe;
5371: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
5372: get_eg(&eg0);
5373: if ( nocheck )
5374: break;
5375: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
5376: if ( nd_gentrace ) {
5377: tl3 = nd_alltracelist; nd_alltracelist = 0;
5378: } else tl3 = 0;
5379: /* gbcheck : cand is a GB of Id(cand) ? */
5380: if ( nd_vc || nd_gentrace || nd_gensyz )
5381: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
5382: else
5383: ret = nd_f4(0,1,0)!=0;
5384: if ( nd_gentrace && nd_gensyz ) {
5385: tl4 = nd_alltracelist; nd_alltracelist = 0;
5386: } else tl4 = 0;
5387: }
5388: if ( ret ) break;
5389: else if ( trace > 1 ) {
5390: /* failure */
5391: *rp = 0; return;
5392: } else {
5393: /* try the next modulus */
5394: m = get_lprime(++mindex);
5395: /* reset the parameters */
5396: if ( !ishomo && homo ) {
5397: nd_init_ord(ord1);
5398: nd_setup_parameters(nvar+1,wmax);
5399: } else {
5400: nd_init_ord(ord);
5401: nd_setup_parameters(nvar,max);
5402: }
5403: }
5404: }
5405: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
5406: if ( DP_Print )
1.6 noro 5407: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 5408: /* dp->p */
5409: nd_bpe = cbpe;
5410: nd_setup_parameters(nd_nvar,0);
5411: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 5412: if ( nd_module ) {
1.17 noro 5413: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 5414: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 5415: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
5416: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 5417: }
5418: if ( nd_nalg )
5419: cand = postprocess_algcoef(av,alist,cand);
5420: MKLIST(*rp,cand);
5421: if ( nd_gentrace ) {
5422: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5423: tl3 = reverse_node(tl3);
5424: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5425: for ( t = tl2; t; t = NEXT(t) ) {
5426: /* s = [i,[*,j,*,*],...] */
5427: s = BDY((LIST)BDY(t));
1.6 noro 5428: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5429: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5430: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5431: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5432: }
5433: }
5434: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5435: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5436: }
5437: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5438: MKLIST(l5,tl4);
1.6 noro 5439: STOZ(nd_bpe,bpe);
1.15 noro 5440: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5441: }
5442: }
5443:
5444: /* XXX : module element is not considered */
5445:
5446: void dltondl(int n,DL dl,UINT *r)
5447: {
5448: UINT *d;
5449: int i,j,l,s,ord_l;
5450: struct order_pair *op;
5451:
5452: d = (unsigned int *)dl->d;
5453: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
5454: if ( nd_blockmask ) {
5455: l = nd_blockmask->n;
5456: op = nd_blockmask->order_pair;
5457: for ( j = 0, s = 0; j < l; j++ ) {
5458: ord_l = op[j].length;
5459: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
5460: }
5461: TD(r) = ndl_weight(r);
5462: ndl_weight_mask(r);
5463: } else {
5464: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
5465: TD(r) = ndl_weight(r);
5466: }
5467: }
5468:
5469: DL ndltodl(int n,UINT *ndl)
5470: {
5471: DL dl;
5472: int *d;
5473: int i,j,l,s,ord_l;
5474: struct order_pair *op;
5475:
1.33 noro 5476: NEWDL_NOINIT(dl,n);
1.1 noro 5477: dl->td = TD(ndl);
5478: d = dl->d;
5479: if ( nd_blockmask ) {
5480: l = nd_blockmask->n;
5481: op = nd_blockmask->order_pair;
5482: for ( j = 0, s = 0; j < l; j++ ) {
5483: ord_l = op[j].length;
5484: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5485: }
5486: } else {
5487: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5488: }
5489: return dl;
5490: }
5491:
1.24 noro 5492: void _ndltodl(UINT *ndl,DL dl)
5493: {
5494: int *d;
5495: int i,j,l,s,ord_l,n;
5496: struct order_pair *op;
5497:
5498: n = nd_nvar;
5499: dl->td = TD(ndl);
5500: d = dl->d;
5501: if ( nd_blockmask ) {
5502: l = nd_blockmask->n;
5503: op = nd_blockmask->order_pair;
5504: for ( j = 0, s = 0; j < l; j++ ) {
5505: ord_l = op[j].length;
5506: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5507: }
5508: } else {
5509: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5510: }
5511: }
5512:
1.1 noro 5513: void nmtodp(int mod,NM m,DP *r)
5514: {
5515: DP dp;
5516: MP mr;
5517:
5518: NEWMP(mr);
5519: mr->dl = ndltodl(nd_nvar,DL(m));
5520: mr->c = (Obj)ndctop(mod,m->c);
5521: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5522: *r = dp;
5523: }
5524:
1.15 noro 5525: void ndltodp(UINT *d,DP *r)
5526: {
5527: DP dp;
5528: MP mr;
5529:
5530: NEWMP(mr);
5531: mr->dl = ndltodl(nd_nvar,d);
5532: mr->c = (Obj)ONE;
5533: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5534: *r = dp;
5535: }
5536:
1.1 noro 5537: void ndl_print(UINT *dl)
5538: {
5539: int n;
5540: int i,j,l,ord_l,s,s0;
5541: struct order_pair *op;
5542:
5543: n = nd_nvar;
5544: printf("<<");
5545: if ( nd_blockmask ) {
5546: l = nd_blockmask->n;
5547: op = nd_blockmask->order_pair;
5548: for ( j = 0, s = s0 = 0; j < l; j++ ) {
5549: ord_l = op[j].length;
5550: for ( i = 0; i < ord_l; i++, s++ )
5551: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
5552: }
5553: } else {
5554: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
5555: }
5556: printf(">>");
5557: if ( nd_module && MPOS(dl) )
5558: printf("*e%d",MPOS(dl));
5559: }
5560:
5561: void nd_print(ND p)
5562: {
5563: NM m;
5564:
5565: if ( !p )
5566: printf("0\n");
5567: else {
5568: for ( m = BDY(p); m; m = NEXT(m) ) {
5569: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 5570: else printf("+%ld*",CM(m));
1.1 noro 5571: ndl_print(DL(m));
5572: }
5573: printf("\n");
5574: }
5575: }
5576:
5577: void nd_print_q(ND p)
5578: {
5579: NM m;
5580:
5581: if ( !p )
5582: printf("0\n");
5583: else {
5584: for ( m = BDY(p); m; m = NEXT(m) ) {
5585: printf("+");
1.6 noro 5586: printexpr(CO,(Obj)CZ(m));
1.1 noro 5587: printf("*");
5588: ndl_print(DL(m));
5589: }
5590: printf("\n");
5591: }
5592: }
5593:
5594: void ndp_print(ND_pairs d)
5595: {
5596: ND_pairs t;
5597:
5598: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
5599: printf("\n");
5600: }
5601:
5602: void nd_removecont(int mod,ND p)
5603: {
5604: int i,n;
5605: Z *w;
5606: NM m;
5607: struct oVECT v;
5608:
5609: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
5610: else if ( mod == -2 ) {
5611: Z inv;
5612: divlf(ONE,HCZ(p),&inv);
5613: nd_mul_c_lf(p,inv);
5614: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
5615: else {
5616: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
5617: w = (Z *)MALLOC(n*sizeof(Q));
5618: v.len = n;
5619: v.body = (pointer *)w;
1.6 noro 5620: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5621: removecont_array((P *)w,n,1);
1.6 noro 5622: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5623: }
5624: }
5625:
5626: void nd_removecont2(ND p1,ND p2)
5627: {
5628: int i,n1,n2,n;
5629: Z *w;
5630: NM m;
5631: struct oVECT v;
5632:
5633: n1 = nd_length(p1);
5634: n2 = nd_length(p2);
5635: n = n1+n2;
5636: w = (Z *)MALLOC(n*sizeof(Q));
5637: v.len = n;
5638: v.body = (pointer *)w;
5639: i = 0;
5640: if ( p1 )
1.6 noro 5641: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5642: if ( p2 )
1.6 noro 5643: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5644: removecont_array((P *)w,n,1);
5645: i = 0;
5646: if ( p1 )
1.6 noro 5647: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5648: if ( p2 )
1.6 noro 5649: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5650: }
5651:
5652: void ndv_removecont(int mod,NDV p)
5653: {
5654: int i,len,all_p;
5655: Z *c;
5656: P *w;
5657: Z dvr,t;
5658: P g,cont,tp;
5659: NMV m;
5660:
5661: if ( mod == -1 )
5662: ndv_mul_c(mod,p,_invsf(HCM(p)));
5663: else if ( mod == -2 ) {
5664: Z inv;
5665: divlf(ONE,HCZ(p),&inv);
5666: ndv_mul_c_lf(p,inv);
5667: } else if ( mod )
5668: ndv_mul_c(mod,p,invm(HCM(p),mod));
5669: else {
5670: len = p->len;
5671: w = (P *)MALLOC(len*sizeof(P));
5672: c = (Z *)MALLOC(len*sizeof(Q));
5673: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5674: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5675: all_p = all_p && !NUM(w[i]);
5676: }
5677: if ( all_p ) {
5678: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5679: mulp(nd_vc,(P)dvr,g,&cont);
5680: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5681: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5682: }
5683: } else {
5684: sortbynm((Q *)c,len);
5685: qltozl((Q *)c,len,&dvr);
5686: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5687: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5688: }
5689: }
5690: }
5691: }
5692:
5693: /* koko */
5694:
5695: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5696: {
5697: int len,i,max;
5698: NMV m,mr0,mr,t;
5699:
5700: len = p->len;
1.14 noro 5701: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5702: max = MAX(max,TD(DL(m)));
5703: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5704: m = (NMV)((char *)mr0+(len-1)*oadv);
5705: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5706: t = (NMV)MALLOC(nmv_adv);
5707: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5708: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5709: CZ(mr) = CZ(m);
1.1 noro 5710: ndl_copy(DL(t),DL(mr));
5711: }
5712: NV(p)++;
5713: BDY(p) = mr0;
5714: }
5715:
5716: void ndv_dehomogenize(NDV p,struct order_spec *ord)
5717: {
5718: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
5719: int pos;
5720: Q *w;
5721: Q dvr,t;
5722: NMV m,r;
5723:
5724: len = p->len;
5725: newnvar = nd_nvar-1;
5726: newexporigin = nd_get_exporigin(ord);
5727: if ( nd_module ) newmpos = newexporigin-1;
5728: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
5729: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
5730: ndl_dehomogenize(DL(m));
5731: if ( newwpd != nd_wpd ) {
5732: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
5733: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 5734: CZ(r) = CZ(m);
1.1 noro 5735: if ( nd_module ) pos = MPOS(DL(m));
5736: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
5737: adj = nd_exporigin-newexporigin;
5738: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
5739: if ( nd_module ) {
5740: DL(r)[newmpos] = pos;
5741: }
5742: }
5743: }
5744: NV(p)--;
5745: }
5746:
5747: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
5748: {
5749: int i;
5750: P *tpl,*tpl1;
5751: NODE l;
5752: P h,gcd,t;
5753:
5754: tpl = (P *)MALLOC(m*sizeof(P));
5755: tpl1 = (P *)MALLOC(m*sizeof(P));
5756: bcopy(pl,tpl,m*sizeof(P));
5757: gcd = (P)ONE;
5758: for ( l = nd_hcf; l; l = NEXT(l) ) {
5759: h = (P)BDY(l);
5760: while ( 1 ) {
5761: for ( i = 0; i < m; i++ )
5762: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
5763: break;
5764: if ( i == m ) {
5765: bcopy(tpl1,tpl,m*sizeof(P));
5766: mulp(vl,gcd,h,&t); gcd = t;
5767: } else
5768: break;
5769: }
5770: }
5771: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
5772: if ( full ) {
5773: heu_nezgcdnpz(vl,tpl,m,&t);
5774: mulp(vl,gcd,t,pr);
5775: } else
5776: *pr = gcd;
5777: }
5778:
5779: void removecont_array(P *p,int n,int full)
5780: {
5781: int all_p,all_q,i;
5782: Z *c;
5783: P *w;
5784: P t,s;
5785:
5786: for ( all_q = 1, i = 0; i < n; i++ )
5787: all_q = all_q && NUM(p[i]);
5788: if ( all_q ) {
5789: removecont_array_q((Z *)p,n);
5790: } else {
5791: c = (Z *)MALLOC(n*sizeof(Z));
5792: w = (P *)MALLOC(n*sizeof(P));
5793: for ( i = 0; i < n; i++ ) {
5794: ptozp(p[i],1,(Q *)&c[i],&w[i]);
5795: }
5796: removecont_array_q(c,n);
5797: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
5798: for ( i = 0; i < n; i++ ) {
5799: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
5800: }
5801: }
5802: }
5803:
5804: /* c is an int array */
5805:
5806: void removecont_array_q(Z *c,int n)
5807: {
5808: struct oVECT v;
5809: Z d0,d1,a,u,u1,gcd;
5810: int i,j;
5811: Z *q,*r;
5812:
5813: q = (Z *)MALLOC(n*sizeof(Z));
5814: r = (Z *)MALLOC(n*sizeof(Z));
5815: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
5816: gcdvz_estimate(&v,&d0);
5817: for ( i = 0; i < n; i++ ) {
5818: divqrz(c[i],d0,&q[i],&r[i]);
5819: }
5820: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
5821: if ( i < n ) {
5822: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
5823: gcdvz(&v,&d1);
5824: gcdz(d0,d1,&gcd);
1.6 noro 5825: /* exact division */
5826: divsz(d0,gcd,&a);
1.1 noro 5827: for ( i = 0; i < n; i++ ) {
5828: mulz(a,q[i],&u);
5829: if ( r[i] ) {
1.6 noro 5830: /* exact division */
5831: divsz(r[i],gcd,&u1);
1.1 noro 5832: addz(u,u1,&q[i]);
5833: } else
5834: q[i] = u;
5835: }
5836: }
5837: for ( i = 0; i < n; i++ ) c[i] = q[i];
5838: }
5839:
1.4 noro 5840: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
5841:
5842: void mpz_removecont_array(mpz_t *c,int n)
5843: {
5844: mpz_t d0,a,u,u1,gcd;
5845: int i,j;
1.13 noro 5846: static mpz_t *q,*r;
5847: static int c_len = 0;
1.4 noro 5848:
5849: for ( i = 0; i < n; i++ )
5850: if ( mpz_sgn(c[i]) ) break;
5851: if ( i == n ) return;
5852: gcdv_mpz_estimate(d0,c,n);
1.13 noro 5853: if ( n > c_len ) {
5854: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5855: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5856: c_len = n;
5857: }
1.4 noro 5858: for ( i = 0; i < n; i++ ) {
5859: mpz_init(q[i]); mpz_init(r[i]);
5860: mpz_fdiv_qr(q[i],r[i],c[i],d0);
5861: }
5862: for ( i = 0; i < n; i++ )
5863: if ( mpz_sgn(r[i]) ) break;
5864: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
5865: if ( i < n ) {
5866: mpz_gcd(gcd,d0,r[i]);
5867: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
5868: mpz_div(a,d0,gcd);
5869: for ( i = 0; i < n; i++ ) {
5870: mpz_mul(u,a,q[i]);
5871: if ( mpz_sgn(r[i]) ) {
5872: mpz_div(u1,r[i],gcd);
5873: mpz_add(q[i],u,u1);
5874: } else
5875: mpz_set(q[i],u);
5876: }
5877: }
5878: for ( i = 0; i < n; i++ )
5879: mpz_set(c[i],q[i]);
5880: }
5881:
1.1 noro 5882: void nd_mul_c(int mod,ND p,int mul)
5883: {
5884: NM m;
5885: int c,c1;
5886:
5887: if ( !p ) return;
5888: if ( mul == 1 ) return;
5889: if ( mod == -1 )
5890: for ( m = BDY(p); m; m = NEXT(m) )
5891: CM(m) = _mulsf(CM(m),mul);
5892: else
5893: for ( m = BDY(p); m; m = NEXT(m) ) {
5894: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5895: }
5896: }
5897:
5898: void nd_mul_c_lf(ND p,Z mul)
5899: {
5900: NM m;
5901: Z c;
5902:
5903: if ( !p ) return;
5904: if ( UNIZ(mul) ) return;
5905: for ( m = BDY(p); m; m = NEXT(m) ) {
5906: mullf(CZ(m),mul,&c); CZ(m) = c;
5907: }
5908: }
5909:
5910: void nd_mul_c_q(ND p,P mul)
5911: {
5912: NM m;
5913: P c;
5914:
5915: if ( !p ) return;
5916: if ( UNIQ(mul) ) return;
5917: for ( m = BDY(p); m; m = NEXT(m) ) {
5918: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
5919: }
5920: }
5921:
5922: void nd_mul_c_p(VL vl,ND p,P mul)
5923: {
5924: NM m;
5925: P c;
5926:
5927: if ( !p ) return;
5928: for ( m = BDY(p); m; m = NEXT(m) ) {
5929: mulp(vl,CP(m),mul,&c); CP(m) = c;
5930: }
5931: }
5932:
5933: void nd_free(ND p)
5934: {
5935: NM t,s;
5936:
5937: if ( !p ) return;
5938: t = BDY(p);
5939: while ( t ) {
5940: s = NEXT(t);
5941: FREENM(t);
5942: t = s;
5943: }
5944: FREEND(p);
5945: }
5946:
5947: void ndv_free(NDV p)
5948: {
5949: GCFREE(BDY(p));
5950: }
5951:
5952: void nd_append_red(UINT *d,int i)
5953: {
5954: RHist m,m0;
5955: int h;
5956:
5957: NEWRHist(m);
5958: h = ndl_hash_value(d);
5959: m->index = i;
5960: ndl_copy(d,DL(m));
5961: NEXT(m) = nd_red[h];
5962: nd_red[h] = m;
5963: }
5964:
5965: UINT *ndv_compute_bound(NDV p)
5966: {
5967: UINT *d1,*d2,*t;
5968: UINT u;
5969: int i,j,k,l,len,ind;
5970: NMV m;
5971:
5972: if ( !p )
5973: return 0;
5974: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5975: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5976: len = LEN(p);
5977: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
5978: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
5979: ndl_max(DL(m),d1,d2);
5980: t = d1; d1 = d2; d2 = t;
5981: }
5982: l = nd_nvar+31;
5983: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5984: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5985: u = d1[i];
5986: k = (nd_epw-1)*nd_bpe;
5987: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5988: t[ind] = (u>>k)&nd_mask0;
5989: }
5990: for ( ; ind < l; ind++ ) t[ind] = 0;
5991: return t;
5992: }
5993:
5994: UINT *nd_compute_bound(ND p)
5995: {
5996: UINT *d1,*d2,*t;
5997: UINT u;
5998: int i,j,k,l,len,ind;
5999: NM m;
6000:
6001: if ( !p )
6002: return 0;
6003: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6004: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6005: len = LEN(p);
6006: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
6007: for ( m = NEXT(m); m; m = NEXT(m) ) {
6008: ndl_lcm(DL(m),d1,d2);
6009: t = d1; d1 = d2; d2 = t;
6010: }
6011: l = nd_nvar+31;
6012: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
6013: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
6014: u = d1[i];
6015: k = (nd_epw-1)*nd_bpe;
6016: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
6017: t[ind] = (u>>k)&nd_mask0;
6018: }
6019: for ( ; ind < l; ind++ ) t[ind] = 0;
6020: return t;
6021: }
6022:
6023: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
6024: /* of a term. In this case we need additional 1 word. */
6025:
6026: int nd_get_exporigin(struct order_spec *ord)
6027: {
6028: switch ( ord->id ) {
1.21 noro 6029: case 0: case 2: case 256: case 258: case 300:
1.1 noro 6030: return 1+nd_module;
6031: case 1: case 257:
6032: /* block order */
6033: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
6034: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
6035: return ord->ord.block.length+1+nd_module;
6036: case 3: case 259:
6037: #if 0
6038: error("nd_get_exporigin : composite order is not supported yet.");
6039: #else
6040: return 1+nd_module;
6041: #endif
6042: default:
6043: error("nd_get_exporigin : ivalid argument.");
6044: return 0;
6045: }
6046: }
6047:
6048: void nd_setup_parameters(int nvar,int max) {
6049: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
6050: struct order_pair *op;
1.45 noro 6051: extern int CNVars;
1.1 noro 6052:
6053: nd_nvar = nvar;
1.45 noro 6054: CNVars = nvar;
1.1 noro 6055: if ( max ) {
6056: /* XXX */
6057: if ( do_weyl ) nd_bpe = 32;
6058: else if ( max < 2 ) nd_bpe = 1;
6059: else if ( max < 4 ) nd_bpe = 2;
6060: else if ( max < 8 ) nd_bpe = 3;
6061: else if ( max < 16 ) nd_bpe = 4;
6062: else if ( max < 32 ) nd_bpe = 5;
6063: else if ( max < 64 ) nd_bpe = 6;
6064: else if ( max < 256 ) nd_bpe = 8;
6065: else if ( max < 1024 ) nd_bpe = 10;
6066: else if ( max < 65536 ) nd_bpe = 16;
6067: else nd_bpe = 32;
6068: }
6069: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
6070: UINT t;
6071: int st;
6072: int *v;
6073: /* t = max(weights) */
6074: t = 0;
6075: if ( current_dl_weight_vector )
6076: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
6077: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
6078: if ( t < st ) t = st;
6079: }
6080: if ( nd_matrix )
6081: for ( i = 0; i < nd_matrix_len; i++ )
6082: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
6083: if ( (st=v[j]) < 0 ) st = -st;
6084: if ( t < st ) t = st;
6085: }
6086: /* i = bitsize of t */
6087: for ( i = 0; t; t >>=1, i++ );
6088: /* i += bitsize of nd_nvar */
6089: for ( t = nd_nvar; t; t >>=1, i++);
6090: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
6091: if ( (nd_bpe+i) >= 31 )
6092: error("nd_setup_parameters : too large weight");
6093: }
6094: nd_epw = (sizeof(UINT)*8)/nd_bpe;
6095: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
6096: nd_exporigin = nd_get_exporigin(nd_ord);
6097: wpd = nd_exporigin+elen;
6098: if ( nd_module )
6099: nd_mpos = nd_exporigin-1;
6100: else
6101: nd_mpos = -1;
6102: if ( wpd != nd_wpd ) {
6103: nd_free_private_storage();
6104: nd_wpd = wpd;
6105: }
6106: if ( nd_bpe < 32 ) {
6107: nd_mask0 = (1<<nd_bpe)-1;
6108: } else {
6109: nd_mask0 = 0xffffffff;
6110: }
6111: bzero(nd_mask,sizeof(nd_mask));
6112: nd_mask1 = 0;
6113: for ( i = 0; i < nd_epw; i++ ) {
6114: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
6115: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
6116: }
6117: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
6118: nd_epos = nd_create_epos(nd_ord);
6119: nd_blockmask = nd_create_blockmask(nd_ord);
6120: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
6121: }
6122:
6123: ND_pairs nd_reconstruct(int trace,ND_pairs d)
6124: {
6125: int i,obpe,oadv,h;
6126: static NM prev_nm_free_list;
6127: static ND_pairs prev_ndp_free_list;
6128: RHist mr0,mr;
6129: RHist r;
6130: RHist *old_red;
6131: ND_pairs s0,s,t;
6132: EPOS oepos;
6133:
6134: obpe = nd_bpe;
6135: oadv = nmv_adv;
6136: oepos = nd_epos;
6137: if ( obpe < 2 ) nd_bpe = 2;
6138: else if ( obpe < 3 ) nd_bpe = 3;
6139: else if ( obpe < 4 ) nd_bpe = 4;
6140: else if ( obpe < 5 ) nd_bpe = 5;
6141: else if ( obpe < 6 ) nd_bpe = 6;
6142: else if ( obpe < 8 ) nd_bpe = 8;
6143: else if ( obpe < 10 ) nd_bpe = 10;
6144: else if ( obpe < 16 ) nd_bpe = 16;
6145: else if ( obpe < 32 ) nd_bpe = 32;
6146: else error("nd_reconstruct : exponent too large");
6147:
6148: nd_setup_parameters(nd_nvar,0);
6149: prev_nm_free_list = _nm_free_list;
6150: prev_ndp_free_list = _ndp_free_list;
6151: _nm_free_list = 0;
6152: _ndp_free_list = 0;
6153: for ( i = nd_psn-1; i >= 0; i-- ) {
6154: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6155: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6156: }
6157: if ( trace )
6158: for ( i = nd_psn-1; i >= 0; i-- ) {
6159: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6160: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6161: }
6162: s0 = 0;
6163: for ( t = d; t; t = NEXT(t) ) {
6164: NEXTND_pairs(s0,s);
6165: s->i1 = t->i1;
6166: s->i2 = t->i2;
1.24 noro 6167: s->sig = t->sig;
1.1 noro 6168: SG(s) = SG(t);
6169: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6170: }
6171:
6172: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6173: for ( i = 0; i < REDTAB_LEN; i++ ) {
6174: old_red[i] = nd_red[i];
6175: nd_red[i] = 0;
6176: }
6177: for ( i = 0; i < REDTAB_LEN; i++ )
6178: for ( r = old_red[i]; r; r = NEXT(r) ) {
6179: NEWRHist(mr);
6180: mr->index = r->index;
6181: SG(mr) = SG(r);
6182: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6183: h = ndl_hash_value(DL(mr));
6184: NEXT(mr) = nd_red[h];
6185: nd_red[h] = mr;
1.24 noro 6186: mr->sig = r->sig;
1.1 noro 6187: }
6188: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6189: old_red = 0;
6190: for ( i = 0; i < nd_psn; i++ ) {
6191: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6192: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 6193: r->sig = nd_psh[i]->sig;
1.1 noro 6194: nd_psh[i] = r;
6195: }
6196: if ( s0 ) NEXT(s) = 0;
6197: prev_nm_free_list = 0;
6198: prev_ndp_free_list = 0;
6199: #if 0
6200: GC_gcollect();
6201: #endif
6202: return s0;
6203: }
6204:
1.30 noro 6205: void nd_reconstruct_s(int trace,ND_pairs *d)
6206: {
6207: int i,obpe,oadv,h;
6208: static NM prev_nm_free_list;
6209: static ND_pairs prev_ndp_free_list;
6210: RHist mr0,mr;
6211: RHist r;
6212: RHist *old_red;
6213: ND_pairs s0,s,t;
6214: EPOS oepos;
6215:
6216: obpe = nd_bpe;
6217: oadv = nmv_adv;
6218: oepos = nd_epos;
6219: if ( obpe < 2 ) nd_bpe = 2;
6220: else if ( obpe < 3 ) nd_bpe = 3;
6221: else if ( obpe < 4 ) nd_bpe = 4;
6222: else if ( obpe < 5 ) nd_bpe = 5;
6223: else if ( obpe < 6 ) nd_bpe = 6;
6224: else if ( obpe < 8 ) nd_bpe = 8;
6225: else if ( obpe < 10 ) nd_bpe = 10;
6226: else if ( obpe < 16 ) nd_bpe = 16;
6227: else if ( obpe < 32 ) nd_bpe = 32;
6228: else error("nd_reconstruct_s : exponent too large");
6229:
6230: nd_setup_parameters(nd_nvar,0);
6231: prev_nm_free_list = _nm_free_list;
6232: prev_ndp_free_list = _ndp_free_list;
6233: _nm_free_list = 0;
6234: _ndp_free_list = 0;
6235: for ( i = nd_psn-1; i >= 0; i-- ) {
6236: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
6237: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
6238: }
6239: if ( trace )
6240: for ( i = nd_psn-1; i >= 0; i-- ) {
6241: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
6242: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
6243: }
6244:
6245: for ( i = 0; i < nd_nbase; i++ ) {
6246: s0 = 0;
6247: for ( t = d[i]; t; t = NEXT(t) ) {
6248: NEXTND_pairs(s0,s);
6249: s->i1 = t->i1;
6250: s->i2 = t->i2;
6251: s->sig = t->sig;
6252: SG(s) = SG(t);
6253: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
6254: }
1.47 ! noro 6255: if ( s0 ) NEXT(s) = 0;
1.30 noro 6256: d[i] = s0;
6257: }
6258:
6259: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
6260: for ( i = 0; i < REDTAB_LEN; i++ ) {
6261: old_red[i] = nd_red[i];
6262: nd_red[i] = 0;
6263: }
6264: for ( i = 0; i < REDTAB_LEN; i++ )
6265: for ( r = old_red[i]; r; r = NEXT(r) ) {
6266: NEWRHist(mr);
6267: mr->index = r->index;
6268: SG(mr) = SG(r);
6269: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
6270: h = ndl_hash_value(DL(mr));
6271: NEXT(mr) = nd_red[h];
6272: nd_red[h] = mr;
6273: mr->sig = r->sig;
6274: }
6275: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
6276: old_red = 0;
6277: for ( i = 0; i < nd_psn; i++ ) {
6278: NEWRHist(r); SG(r) = SG(nd_psh[i]);
6279: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
6280: r->sig = nd_psh[i]->sig;
6281: nd_psh[i] = r;
6282: }
6283: if ( s0 ) NEXT(s) = 0;
6284: prev_nm_free_list = 0;
6285: prev_ndp_free_list = 0;
6286: #if 0
6287: GC_gcollect();
6288: #endif
6289: }
6290:
1.1 noro 6291: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
6292: {
6293: int n,i,ei,oepw,omask0,j,s,ord_l,l;
6294: struct order_pair *op;
6295:
6296: n = nd_nvar;
6297: oepw = (sizeof(UINT)*8)/obpe;
6298: omask0 = (1<<obpe)-1;
6299: TD(r) = TD(d);
6300: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
6301: if ( nd_blockmask ) {
6302: l = nd_blockmask->n;
6303: op = nd_blockmask->order_pair;
6304: for ( i = 1; i < nd_exporigin; i++ )
6305: r[i] = d[i];
6306: for ( j = 0, s = 0; j < l; j++ ) {
6307: ord_l = op[j].length;
6308: for ( i = 0; i < ord_l; i++, s++ ) {
6309: ei = GET_EXP_OLD(d,s);
6310: PUT_EXP(r,s,ei);
6311: }
6312: }
6313: } else {
6314: for ( i = 0; i < n; i++ ) {
6315: ei = GET_EXP_OLD(d,i);
6316: PUT_EXP(r,i,ei);
6317: }
6318: }
6319: if ( nd_module ) MPOS(r) = MPOS(d);
6320: }
6321:
6322: ND nd_copy(ND p)
6323: {
6324: NM m,mr,mr0;
6325: int c,n;
6326: ND r;
6327:
6328: if ( !p )
6329: return 0;
6330: else {
6331: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
6332: NEXTNM(mr0,mr);
6333: CM(mr) = CM(m);
6334: ndl_copy(DL(m),DL(mr));
6335: }
6336: NEXT(mr) = 0;
6337: MKND(NV(p),mr0,LEN(p),r);
6338: SG(r) = SG(p);
6339: return r;
6340: }
6341: }
6342:
6343: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
6344: {
6345: NM m1,m2;
6346: NDV p1,p2;
6347: ND t1,t2;
6348: UINT *lcm;
6349: P gp,tp;
6350: Z g,t;
6351: Z iq;
6352: int td;
6353: LIST hist;
6354: NODE node;
6355: DP d;
6356:
6357: if ( !mod && nd_demand ) {
6358: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
6359: } else {
6360: if ( trace ) {
6361: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
6362: } else {
6363: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
6364: }
6365: }
6366: lcm = LCM(p);
6367: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
6368: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
6369: FREENM(m1); return 0;
6370: }
6371: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
6372: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
6373: FREENM(m1); FREENM(m2); return 0;
6374: }
6375:
6376: if ( mod == -1 ) {
6377: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
6378: } else if ( mod > 0 ) {
6379: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
6380: } else if ( mod == -2 ) {
6381: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
6382: } else if ( nd_vc ) {
6383: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
6384: divsp(nd_vc,HCP(p2),gp,&CP(m1));
6385: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
6386: } else {
1.6 noro 6387: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 6388: }
6389: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
6390: *rp = nd_add(mod,t1,t2);
6391: if ( nd_gentrace ) {
6392: /* nd_tracelist is initialized */
1.6 noro 6393: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6394: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 6395: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6396: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
6397: nd_tracelist = node;
6398: }
1.24 noro 6399: if ( *rp )
6400: (*rp)->sig = p->sig;
1.1 noro 6401: FREENM(m1); FREENM(m2);
6402: return 1;
6403: }
6404:
6405: void ndv_mul_c(int mod,NDV p,int mul)
6406: {
6407: NMV m;
6408: int c,c1,len,i;
6409:
6410: if ( !p ) return;
6411: len = LEN(p);
6412: if ( mod == -1 )
6413: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
6414: CM(m) = _mulsf(CM(m),mul);
6415: else
6416: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6417: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6418: }
6419: }
6420:
6421: void ndv_mul_c_lf(NDV p,Z mul)
6422: {
6423: NMV m;
6424: Z c;
6425: int len,i;
6426:
6427: if ( !p ) return;
6428: len = LEN(p);
6429: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6430: mullf(CZ(m),mul,&c); CZ(m) = c;
6431: }
6432: }
6433:
6434: /* for nd_det */
6435: void ndv_mul_c_q(NDV p,Z mul)
6436: {
6437: NMV m;
6438: Z c;
6439: int len,i;
6440:
6441: if ( !p ) return;
6442: len = LEN(p);
6443: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 6444: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 6445: }
6446: }
6447:
6448: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
6449: int n2,i,j,l,n,tlen;
6450: UINT *d0;
6451: NM *tab,*psum;
6452: ND s,r;
6453: NM t;
6454: NMV m1;
6455:
6456: if ( !p ) return 0;
6457: n = NV(p); n2 = n>>1;
6458: d0 = DL(m0);
6459: l = LEN(p);
6460: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
6461: tab = (NM *)MALLOC(tlen*sizeof(NM));
6462: psum = (NM *)MALLOC(tlen*sizeof(NM));
6463: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
6464: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
6465: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
6466: /* m0(NM) * m1(NMV) => tab(NM) */
6467: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
6468: for ( j = 0; j < tlen; j++ ) {
6469: if ( tab[j] ) {
6470: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
6471: }
6472: }
6473: }
6474: for ( i = tlen-1, r = 0; i >= 0; i-- )
6475: if ( psum[i] ) {
6476: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
6477: MKND(n,psum[i],j,s);
6478: r = nd_add(mod,r,s);
6479: }
6480: if ( r ) SG(r) = SG(p)+TD(d0);
6481: return r;
6482: }
6483:
6484: /* product of monomials */
6485: /* XXX block order is not handled correctly */
6486:
6487: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
6488: {
6489: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
6490: UINT *d0,*d1,*d,*dt,*ctab;
6491: Z *ctab_q;
6492: Z q,q1;
6493: UINT c0,c1,c;
6494: NM *p;
6495: NM m,t;
6496: int mpos;
6497:
6498: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
6499: if ( !m0 || !m1 ) return;
6500: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
6501: if ( nd_module )
6502: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
6503:
6504: NEWNM(m); d = DL(m);
6505: if ( mod ) {
6506: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
6507: } else if ( nd_vc )
6508: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
6509: else
1.6 noro 6510: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 6511: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
6512: homo = n&1 ? 1 : 0;
6513: if ( homo ) {
6514: /* offset of h-degree */
6515: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
6516: PUT_EXP(DL(m),n-1,h);
6517: TD(DL(m)) = h;
6518: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6519: }
6520: tab[0] = m;
6521: NEWNM(m); d = DL(m);
6522: for ( i = 0, curlen = 1; i < n2; i++ ) {
6523: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
6524: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
6525: /* xi^a*(Di^k*xi^l)*Di^b */
6526: a += l; b += k;
6527: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
6528: if ( !k || !l ) {
6529: for ( j = 0; j < curlen; j++ )
6530: if ( (t = tab[j]) != 0 ) {
6531: dt = DL(t);
6532: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
6533: if ( nd_blockmask ) ndl_weight_mask(dt);
6534: }
6535: curlen *= k+1;
6536: continue;
6537: }
6538: min = MIN(k,l);
6539: if ( mod ) {
6540: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
6541: mkwcm(k,l,mod,(int *)ctab);
6542: } else {
6543: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
6544: mkwc(k,l,ctab_q);
6545: }
6546: for ( j = min; j >= 0; j-- ) {
6547: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
6548: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
6549: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
6550: if ( homo ) {
6551: TD(d) = s;
6552: PUT_EXP(d,n-1,s-h);
6553: } else TD(d) = h;
6554: if ( nd_blockmask ) ndl_weight_mask(d);
6555: if ( mod ) c = ctab[j];
6556: else q = ctab_q[j];
6557: p = tab+curlen*j;
6558: if ( j == 0 ) {
6559: for ( u = 0; u < curlen; u++, p++ ) {
6560: if ( tab[u] ) {
6561: ndl_addto(DL(tab[u]),d);
6562: if ( mod ) {
6563: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
6564: } else if ( nd_vc )
6565: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
6566: else {
1.6 noro 6567: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 6568: }
6569: }
6570: }
6571: } else {
6572: for ( u = 0; u < curlen; u++, p++ ) {
6573: if ( tab[u] ) {
6574: NEWNM(t);
6575: ndl_add(DL(tab[u]),d,DL(t));
6576: if ( mod ) {
6577: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
6578: } else if ( nd_vc )
6579: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
6580: else
1.6 noro 6581: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 6582: *p = t;
6583: }
6584: }
6585: }
6586: }
6587: curlen *= k+1;
6588: }
6589: FREENM(m);
6590: if ( nd_module ) {
6591: mpos = MPOS(d1);
6592: for ( i = 0; i < tlen; i++ )
6593: if ( tab[i] ) {
6594: d = DL(tab[i]);
6595: MPOS(d) = mpos;
6596: TD(d) = ndl_weight(d);
6597: }
6598: }
6599: }
6600:
6601: ND ndv_mul_nm_symbolic(NM m0,NDV p)
6602: {
6603: NM mr,mr0;
6604: NMV m;
6605: UINT *d,*dt,*dm;
6606: int c,n,td,i,c1,c2,len;
6607: Q q;
6608: ND r;
6609:
6610: if ( !p ) return 0;
6611: else {
6612: n = NV(p); m = BDY(p);
6613: d = DL(m0);
6614: len = LEN(p);
6615: mr0 = 0;
6616: td = TD(d);
6617: c = CM(m0);
6618: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6619: NEXTNM(mr0,mr);
6620: CM(mr) = 1;
6621: ndl_add(DL(m),d,DL(mr));
6622: }
6623: NEXT(mr) = 0;
6624: MKND(NV(p),mr0,len,r);
6625: SG(r) = SG(p) + TD(d);
6626: return r;
6627: }
6628: }
6629:
6630: ND ndv_mul_nm(int mod,NM m0,NDV p)
6631: {
6632: NM mr,mr0;
6633: NMV m;
6634: UINT *d,*dt,*dm;
6635: int c,n,td,i,c1,c2,len;
6636: P q;
6637: ND r;
6638:
6639: if ( !p ) return 0;
6640: else if ( do_weyl ) {
6641: if ( mod < 0 ) {
6642: error("ndv_mul_nm : not implemented (weyl)");
6643: return 0;
6644: } else
6645: return weyl_ndv_mul_nm(mod,m0,p);
6646: } else {
6647: n = NV(p); m = BDY(p);
6648: d = DL(m0);
6649: len = LEN(p);
6650: mr0 = 0;
6651: td = TD(d);
6652: if ( mod == -1 ) {
6653: c = CM(m0);
6654: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6655: NEXTNM(mr0,mr);
6656: CM(mr) = _mulsf(CM(m),c);
6657: ndl_add(DL(m),d,DL(mr));
6658: }
6659: } else if ( mod == -2 ) {
6660: Z cl;
6661: cl = CZ(m0);
6662: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6663: NEXTNM(mr0,mr);
6664: mullf(CZ(m),cl,&CZ(mr));
6665: ndl_add(DL(m),d,DL(mr));
6666: }
6667: } else if ( mod ) {
6668: c = CM(m0);
6669: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6670: NEXTNM(mr0,mr);
6671: c1 = CM(m);
6672: DMAR(c1,c,0,mod,c2);
6673: CM(mr) = c2;
6674: ndl_add(DL(m),d,DL(mr));
6675: }
6676: } else {
6677: q = CP(m0);
6678: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6679: NEXTNM(mr0,mr);
6680: mulp(nd_vc,CP(m),q,&CP(mr));
6681: ndl_add(DL(m),d,DL(mr));
6682: }
6683: }
6684: NEXT(mr) = 0;
6685: MKND(NV(p),mr0,len,r);
6686: SG(r) = SG(p) + TD(d);
6687: return r;
6688: }
6689: }
6690:
6691: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
6692: {
6693: NM mq0,mq;
6694: NMV tm;
6695: Q q;
6696: int i,nv,sg,c,c1,c2,hindex;
6697: ND p,t,r;
6698:
6699: if ( bucket->m < 0 ) return 0;
6700: else {
6701: nv = NV(d);
6702: mq0 = 0;
6703: tm = (NMV)MALLOC(nmv_adv);
6704: while ( 1 ) {
6705: if ( mod > 0 || mod == -1 )
6706: hindex = head_pbucket(mod,bucket);
6707: else if ( mod == -2 )
6708: hindex = head_pbucket_lf(bucket);
6709: else
6710: hindex = head_pbucket_q(bucket);
6711: if ( hindex < 0 ) break;
6712: p = bucket->body[hindex];
6713: NEXTNM(mq0,mq);
6714: ndl_sub(HDL(p),HDL(d),DL(mq));
6715: ndl_copy(DL(mq),DL(tm));
6716: if ( mod ) {
6717: c1 = invm(HCM(d),mod); c2 = HCM(p);
6718: DMAR(c1,c2,0,mod,c); CM(mq) = c;
6719: CM(tm) = mod-c;
6720: } else {
1.6 noro 6721: divsz(HCZ(p),HCZ(d),&CZ(mq));
6722: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 6723: }
6724: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
6725: bucket->body[hindex] = nd_remove_head(p);
6726: t = nd_remove_head(t);
6727: add_pbucket(mod,bucket,t);
6728: }
6729: if ( !mq0 )
6730: r = 0;
6731: else {
6732: NEXT(mq) = 0;
6733: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
6734: MKND(nv,mq0,i,r);
6735: /* XXX */
6736: SG(r) = HTD(r);
6737: }
6738: return r;
6739: }
6740: }
6741:
6742: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6743: {
6744: NMV m,mr,mr0,t;
6745: int len,i,k;
6746:
6747: if ( !p ) return;
6748: m = BDY(p); len = LEN(p);
6749: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
6750: m = (NMV)((char *)mr0+(len-1)*oadv);
6751: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
6752: t = (NMV)MALLOC(nmv_adv);
6753: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 6754: CZ(t) = CZ(m);
1.1 noro 6755: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
6756: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 6757: CZ(mr) = CZ(t);
1.1 noro 6758: ndl_copy(DL(t),DL(mr));
6759: }
6760: BDY(p) = mr0;
6761: }
6762:
6763: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6764: {
6765: NMV m,mr,mr0;
6766: int len,i;
6767: NDV r;
6768:
6769: if ( !p ) return 0;
6770: m = BDY(p); len = LEN(p);
6771: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
6772: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
6773: ndl_zero(DL(mr));
6774: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 6775: CZ(mr) = CZ(m);
1.1 noro 6776: }
6777: MKNDV(NV(p),mr0,len,r);
6778: SG(r) = SG(p);
1.24 noro 6779: r->sig = p->sig;
1.1 noro 6780: return r;
6781: }
6782:
6783: /* duplicate p */
6784:
6785: NDV ndv_dup(int mod,NDV p)
6786: {
6787: NDV d;
6788: NMV t,m,m0;
6789: int i,len;
6790:
6791: if ( !p ) return 0;
6792: len = LEN(p);
6793: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6794: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6795: ndl_copy(DL(t),DL(m));
1.6 noro 6796: CZ(m) = CZ(t);
1.1 noro 6797: }
6798: MKNDV(NV(p),m0,len,d);
6799: SG(d) = SG(p);
6800: return d;
6801: }
6802:
6803: NDV ndv_symbolic(int mod,NDV p)
6804: {
6805: NDV d;
6806: NMV t,m,m0;
6807: int i,len;
6808:
6809: if ( !p ) return 0;
6810: len = LEN(p);
6811: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6812: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6813: ndl_copy(DL(t),DL(m));
1.6 noro 6814: CZ(m) = ONE;
1.1 noro 6815: }
6816: MKNDV(NV(p),m0,len,d);
6817: SG(d) = SG(p);
6818: return d;
6819: }
6820:
6821: ND nd_dup(ND p)
6822: {
6823: ND d;
6824: NM t,m,m0;
6825:
6826: if ( !p ) return 0;
6827: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
6828: NEXTNM(m0,m);
6829: ndl_copy(DL(t),DL(m));
1.6 noro 6830: CZ(m) = CZ(t);
1.1 noro 6831: }
6832: if ( m0 ) NEXT(m) = 0;
6833: MKND(NV(p),m0,LEN(p),d);
6834: SG(d) = SG(p);
6835: return d;
6836: }
6837:
6838: /* XXX if p->len == 0 then it represents 0 */
6839:
6840: void ndv_mod(int mod,NDV p)
6841: {
6842: NMV t,d;
6843: int r,s,u;
6844: int i,len,dlen;
6845: P cp;
6846: Z c;
6847: Obj gfs;
6848:
6849: if ( !p ) return;
6850: len = LEN(p);
6851: dlen = 0;
6852: if ( mod == -1 )
6853: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6854: simp_ff((Obj)CP(t),&gfs);
6855: if ( gfs ) {
6856: r = FTOIF(CONT((GFS)gfs));
6857: CM(d) = r;
6858: ndl_copy(DL(t),DL(d));
6859: NMV_ADV(d);
6860: dlen++;
6861: }
6862: }
6863: else if ( mod == -2 )
6864: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6865: simp_ff((Obj)CP(t),&gfs);
6866: if ( gfs ) {
6867: lmtolf((LM)gfs,&CZ(d));
6868: ndl_copy(DL(t),DL(d));
6869: NMV_ADV(d);
6870: dlen++;
6871: }
6872: }
6873: else
6874: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6875: if ( nd_vc ) {
6876: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
6877: c = (Z)cp;
6878: } else
1.6 noro 6879: c = CZ(t);
1.1 noro 6880: r = remqi((Q)c,mod);
6881: if ( r ) {
6882: CM(d) = r;
6883: ndl_copy(DL(t),DL(d));
6884: NMV_ADV(d);
6885: dlen++;
6886: }
6887: }
6888: LEN(p) = dlen;
6889: }
6890:
6891: NDV ptondv(VL vl,VL dvl,P p)
6892: {
6893: ND nd;
6894:
6895: nd = ptond(vl,dvl,p);
6896: return ndtondv(0,nd);
6897: }
6898:
6899: void pltozpl(LIST l,Q *cont,LIST *pp)
6900: {
1.16 noro 6901: NODE nd,nd1;
6902: int n;
6903: P *pl;
6904: Q *cl;
6905: int i;
6906: P dmy;
6907: Z dvr,inv;
6908: LIST r;
6909:
6910: nd = BDY(l); n = length(nd);
6911: pl = (P *)MALLOC(n*sizeof(P));
6912: cl = (Q *)MALLOC(n*sizeof(Q));
6913: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
6914: ptozp((P)BDY(nd),1,&cl[i],&dmy);
6915: }
6916: qltozl(cl,n,&dvr);
6917: divz(ONE,dvr,&inv);
6918: nd = BDY(l);
6919: for ( i = 0; i < n; i++, nd = NEXT(nd) )
6920: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
6921: nd = 0;
6922: for ( i = n-1; i >= 0; i-- ) {
6923: MKNODE(nd1,pl[i],nd); nd = nd1;
6924: }
6925: MKLIST(r,nd);
6926: *pp = r;
1.1 noro 6927: }
6928:
6929: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
6930:
6931: NDV pltondv(VL vl,VL dvl,LIST p)
6932: {
6933: int i;
6934: NODE t;
6935: ND r,ri;
6936: NM m;
6937:
6938: if ( !nd_module ) error("pltond : module order must be set");
6939: r = 0;
6940: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
6941: ri = ptond(vl,dvl,(P)BDY(t));
6942: if ( ri )
6943: for ( m = BDY(ri); m; m = NEXT(m) ) {
6944: MPOS(DL(m)) = i;
6945: TD(DL(m)) = ndl_weight(DL(m));
6946: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6947: }
6948: r = nd_add(0,r,ri);
6949: }
6950: return ndtondv(0,r);
6951: }
6952:
6953: ND ptond(VL vl,VL dvl,P p)
6954: {
6955: int n,i,j,k,e;
6956: VL tvl;
6957: V v;
6958: DCP dc;
6959: DCP *w;
6960: ND r,s,t,u;
6961: P x;
6962: int c;
6963: UINT *d;
6964: NM m,m0;
6965:
6966: if ( !p )
6967: return 0;
6968: else if ( NUM(p) ) {
6969: NEWNM(m);
6970: ndl_zero(DL(m));
6971: if ( !INT((Q)p) )
6972: error("ptond : input must be integer-coefficient");
1.6 noro 6973: CZ(m) = (Z)p;
1.1 noro 6974: NEXT(m) = 0;
6975: MKND(nd_nvar,m,1,r);
6976: SG(r) = 0;
6977: return r;
6978: } else {
6979: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
6980: w = (DCP *)MALLOC(k*sizeof(DCP));
6981: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
6982: for ( i = 0, tvl = dvl, v = VR(p);
6983: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
6984: if ( !tvl ) {
6985: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
6986: t = ptond(vl,dvl,COEF(w[j]));
6987: pwrp(vl,x,DEG(w[j]),&p);
6988: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
6989: }
6990: return s;
6991: } else {
6992: NEWNM(m0); d = DL(m0);
6993: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 6994: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 6995: TD(d) = MUL_WEIGHT(e,i);
6996: if ( nd_blockmask) ndl_weight_mask(d);
6997: if ( nd_module ) MPOS(d) = 0;
6998: t = ptond(vl,dvl,COEF(w[j]));
6999: for ( m = BDY(t); m; m = NEXT(m) )
7000: ndl_addto(DL(m),d);
7001: SG(t) += TD(d);
7002: s = nd_add(0,s,t);
7003: }
7004: FREENM(m0);
7005: return s;
7006: }
7007: }
7008: }
7009:
7010: P ndvtop(int mod,VL vl,VL dvl,NDV p)
7011: {
7012: VL tvl;
7013: int len,n,j,i,e;
7014: NMV m;
7015: Z q;
7016: P c;
7017: UINT *d;
7018: P s,r,u,t,w;
7019: GFS gfs;
7020:
7021: if ( !p ) return 0;
7022: else {
7023: len = LEN(p);
7024: n = NV(p);
7025: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7026: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
7027: if ( mod == -1 ) {
7028: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7029: } else if ( mod == -2 ) {
7030: c = (P)CZ(m);
7031: } else if ( mod > 0 ) {
1.6 noro 7032: STOZ(CM(m),q); c = (P)q;
1.1 noro 7033: } else
7034: c = CP(m);
7035: d = DL(m);
7036: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7037: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7038: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7039: }
7040: addp(vl,s,t,&u); s = u;
7041: }
7042: return s;
7043: }
7044: }
7045:
7046: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
7047: {
7048: VL tvl;
7049: int len,n,j,i,e;
7050: NMV m;
7051: Z q;
7052: P c;
7053: UINT *d;
7054: P s,r,u,t,w;
7055: GFS gfs;
7056: P *a;
7057: LIST l;
7058: NODE nd,nd1;
7059:
7060: if ( !p ) return 0;
7061: else {
7062: a = (P *)MALLOC((rank+1)*sizeof(P));
7063: for ( i = 0; i <= rank; i++ ) a[i] = 0;
7064: len = LEN(p);
7065: n = NV(p);
7066: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
7067: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
7068: if ( mod == -1 ) {
7069: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
7070: } else if ( mod ) {
1.6 noro 7071: STOZ(CM(m),q); c = (P)q;
1.1 noro 7072: } else
7073: c = CP(m);
7074: d = DL(m);
7075: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 7076: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 7077: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
7078: }
7079: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
7080: }
7081: nd = 0;
7082: for ( i = rank; i > 0; i-- ) {
7083: MKNODE(nd1,a[i],nd); nd = nd1;
7084: }
7085: MKLIST(l,nd);
7086: return l;
7087: }
7088: }
7089:
7090: NDV ndtondv(int mod,ND p)
7091: {
7092: NDV d;
7093: NMV m,m0;
7094: NM t;
7095: int i,len;
7096:
7097: if ( !p ) return 0;
7098: len = LEN(p);
7099: if ( mod > 0 || mod == -1 )
7100: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7101: else
7102: m0 = m = MALLOC(len*nmv_adv);
7103: #if 0
7104: ndv_alloc += nmv_adv*len;
7105: #endif
7106: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
7107: ndl_copy(DL(t),DL(m));
1.6 noro 7108: CZ(m) = CZ(t);
1.1 noro 7109: }
7110: MKNDV(NV(p),m0,len,d);
7111: SG(d) = SG(p);
1.24 noro 7112: d->sig = p->sig;
1.1 noro 7113: return d;
7114: }
7115:
1.16 noro 7116: static int dmm_comp_nv;
7117:
7118: int dmm_comp(DMM *a,DMM *b)
7119: {
7120: return -compdmm(dmm_comp_nv,*a,*b);
7121: }
7122:
7123: void dmm_sort_by_ord(DMM *a,int len,int nv)
7124: {
7125: dmm_comp_nv = nv;
7126: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
7127: }
7128:
7129: void dpm_sort(DPM p,DPM *rp)
7130: {
7131: DMM t,t1;
7132: int len,i,n;
7133: DMM *a;
7134: DPM d;
7135:
7136: if ( !p ) *rp = 0;
7137: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7138: a = (DMM *)MALLOC(len*sizeof(DMM));
7139: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7140: n = p->nv;
7141: dmm_sort_by_ord(a,len,n);
7142: t = 0;
7143: for ( i = len-1; i >= 0; i-- ) {
7144: NEWDMM(t1);
7145: t1->c = a[i]->c;
7146: t1->dl = a[i]->dl;
7147: t1->pos = a[i]->pos;
7148: t1->next = t;
7149: t = t1;
7150: }
7151: MKDPM(n,t,d);
7152: SG(d) = SG(p);
7153: *rp = d;
7154: }
7155:
1.18 noro 7156: int dpm_comp(DPM *a,DPM *b)
7157: {
1.22 noro 7158: return -compdpm(CO,*a,*b);
1.18 noro 7159: }
7160:
7161: NODE dpm_sort_list(NODE l)
7162: {
7163: int i,len;
7164: NODE t,t1;
7165: DPM *a;
7166:
7167: len = length(l);
7168: a = (DPM *)MALLOC(len*sizeof(DPM));
7169: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
7170: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
7171: t = 0;
7172: for ( i = len-1; i >= 0; i-- ) {
7173: MKNODE(t1,(pointer)a[i],t); t = t1;
7174: }
7175: return t;
7176: }
7177:
1.20 noro 7178: int nmv_comp(NMV a,NMV b)
7179: {
1.21 noro 7180: int t;
7181: t = DL_COMPARE(a->dl,b->dl);
7182: return -t;
1.20 noro 7183: }
7184:
1.43 noro 7185: NDV dptondv(int mod,DP p)
7186: {
7187: NDV d;
7188: NMV m,m0;
7189: MP t;
7190: MP *a;
7191: int i,len,n;
7192:
7193: if ( !p ) return 0;
7194: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7195: n = p->nv;
7196: if ( mod > 0 || mod == -1 )
7197: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7198: else
7199: m0 = m = MALLOC(len*nmv_adv);
7200: for ( i = 0, t = BDY(p); i < len; i++, NMV_ADV(m), t = NEXT(t) ) {
7201: dltondl(n,t->dl,DL(m));
7202: TD(DL(m)) = ndl_weight(DL(m));
7203: CZ(m) = (Z)t->c;
7204: }
7205: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
7206: MKNDV(NV(p),m0,len,d);
7207: SG(d) = SG(p);
7208: return d;
7209: }
7210:
1.16 noro 7211: NDV dpmtondv(int mod,DPM p)
7212: {
7213: NDV d;
7214: NMV m,m0;
7215: DMM t;
7216: DMM *a;
7217: int i,len,n;
7218:
7219: if ( !p ) return 0;
7220: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
7221: a = (DMM *)MALLOC(len*sizeof(DMM));
7222: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
7223: n = p->nv;
7224: dmm_sort_by_ord(a,len,n);
7225: if ( mod > 0 || mod == -1 )
7226: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
7227: else
7228: m0 = m = MALLOC(len*nmv_adv);
7229: #if 0
7230: ndv_alloc += nmv_adv*len;
7231: #endif
7232: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
7233: dltondl(n,a[i]->dl,DL(m));
7234: MPOS(DL(m)) = a[i]->pos;
1.20 noro 7235: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 7236: CZ(m) = (Z)a[i]->c;
7237: }
1.20 noro 7238: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 7239: MKNDV(NV(p),m0,len,d);
7240: SG(d) = SG(p);
7241: return d;
7242: }
7243:
1.1 noro 7244: ND ndvtond(int mod,NDV p)
7245: {
7246: ND d;
7247: NM m,m0;
7248: NMV t;
7249: int i,len;
7250:
7251: if ( !p ) return 0;
7252: m0 = 0;
7253: len = p->len;
7254: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7255: NEXTNM(m0,m);
7256: ndl_copy(DL(t),DL(m));
1.6 noro 7257: CZ(m) = CZ(t);
1.1 noro 7258: }
7259: NEXT(m) = 0;
7260: MKND(NV(p),m0,len,d);
7261: SG(d) = SG(p);
1.28 noro 7262: d->sig = p->sig;
1.1 noro 7263: return d;
7264: }
7265:
7266: DP ndvtodp(int mod,NDV p)
7267: {
7268: MP m,m0;
7269: DP d;
7270: NMV t;
7271: int i,len;
7272:
7273: if ( !p ) return 0;
7274: m0 = 0;
7275: len = p->len;
7276: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7277: NEXTMP(m0,m);
7278: m->dl = ndltodl(nd_nvar,DL(t));
7279: m->c = (Obj)ndctop(mod,t->c);
7280: }
7281: NEXT(m) = 0;
7282: MKDP(nd_nvar,m0,d);
7283: SG(d) = SG(p);
7284: return d;
7285: }
7286:
1.44 noro 7287: DPM sigtodpm(SIG s)
7288: {
7289: DMM m;
7290: DPM d;
7291:
7292: NEWDMM(m);
7293: m->c = (Obj)ONE;
7294: m->dl = s->dl;
7295: m->pos = s->pos+1;
7296: m->next = 0;
7297: MKDPM(nd_nvar,m,d);
7298: SG(d) = s->dl->td;
7299: return d;
7300: }
7301:
1.16 noro 7302: DPM ndvtodpm(int mod,NDV p)
7303: {
7304: DMM m,m0;
7305: DPM d;
7306: NMV t;
7307: int i,len;
7308:
7309: if ( !p ) return 0;
7310: m0 = 0;
7311: len = p->len;
7312: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
7313: NEXTDMM(m0,m);
7314: m->dl = ndltodl(nd_nvar,DL(t));
7315: m->c = (Obj)ndctop(mod,t->c);
7316: m->pos = MPOS(DL(t));
7317: }
7318: NEXT(m) = 0;
7319: MKDPM(nd_nvar,m0,d);
7320: SG(d) = SG(p);
7321: return d;
7322: }
7323:
7324:
1.1 noro 7325: DP ndtodp(int mod,ND p)
7326: {
7327: MP m,m0;
7328: DP d;
7329: NM t;
7330: int i,len;
7331:
7332: if ( !p ) return 0;
7333: m0 = 0;
7334: len = p->len;
7335: for ( t = BDY(p); t; t = NEXT(t) ) {
7336: NEXTMP(m0,m);
7337: m->dl = ndltodl(nd_nvar,DL(t));
7338: m->c = (Obj)ndctop(mod,t->c);
7339: }
7340: NEXT(m) = 0;
7341: MKDP(nd_nvar,m0,d);
7342: SG(d) = SG(p);
7343: return d;
7344: }
7345:
7346: void ndv_print(NDV p)
7347: {
7348: NMV m;
7349: int i,len;
7350:
7351: if ( !p ) printf("0\n");
7352: else {
7353: len = LEN(p);
7354: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7355: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 7356: else printf("+%ld*",CM(m));
1.1 noro 7357: ndl_print(DL(m));
7358: }
7359: printf("\n");
7360: }
7361: }
7362:
7363: void ndv_print_q(NDV p)
7364: {
7365: NMV m;
7366: int i,len;
7367:
7368: if ( !p ) printf("0\n");
7369: else {
7370: len = LEN(p);
7371: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7372: printf("+");
1.6 noro 7373: printexpr(CO,(Obj)CZ(m));
1.1 noro 7374: printf("*");
7375: ndl_print(DL(m));
7376: }
7377: printf("\n");
7378: }
7379: }
7380:
7381: NODE ndv_reducebase(NODE x,int *perm)
7382: {
7383: int len,i,j;
7384: NDVI w;
7385: NODE t,t0;
7386:
1.41 noro 7387: if ( nd_norb ) return x;
1.1 noro 7388: len = length(x);
7389: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
7390: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
7391: w[i].p = BDY(t); w[i].i = perm[i];
7392: }
7393: for ( i = 0; i < len; i++ ) {
7394: for ( j = 0; j < i; j++ ) {
7395: if ( w[i].p && w[j].p ) {
7396: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
7397: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
7398: }
7399: }
7400: }
7401: for ( i = j = 0, t0 = 0; i < len; i++ ) {
7402: if ( w[i].p ) {
7403: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
7404: perm[j++] = w[i].i;
7405: }
7406: }
7407: NEXT(t) = 0; x = t0;
7408: return x;
7409: }
7410:
7411: /* XXX incomplete */
7412:
1.21 noro 7413: extern DMMstack dmm_stack;
7414: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 7415:
1.1 noro 7416: void nd_init_ord(struct order_spec *ord)
7417: {
7418: nd_module = (ord->id >= 256);
7419: if ( nd_module ) {
7420: nd_dcomp = -1;
1.21 noro 7421: nd_module_ordtype = ord->module_ordtype;
1.1 noro 7422: nd_pot_nelim = ord->pot_nelim;
7423: nd_poly_weight_len = ord->nv;
7424: nd_poly_weight = ord->top_weight;
7425: nd_module_rank = ord->module_rank;
7426: nd_module_weight = ord->module_top_weight;
7427: }
7428: nd_matrix = 0;
7429: nd_matrix_len = 0;
7430: switch ( ord->id ) {
7431: case 0:
7432: switch ( ord->ord.simple ) {
7433: case 0:
7434: nd_dcomp = 1;
7435: nd_isrlex = 1;
7436: break;
7437: case 1:
7438: nd_dcomp = 1;
7439: nd_isrlex = 0;
7440: break;
7441: case 2:
7442: nd_dcomp = 0;
7443: nd_isrlex = 0;
7444: ndl_compare_function = ndl_lex_compare;
7445: break;
7446: case 11:
7447: /* XXX */
7448: nd_dcomp = 0;
7449: nd_isrlex = 1;
7450: ndl_compare_function = ndl_ww_lex_compare;
7451: break;
7452: default:
7453: error("nd_gr : unsupported order");
7454: }
7455: break;
7456: case 1:
7457: /* block order */
7458: /* XXX */
7459: nd_dcomp = -1;
7460: nd_isrlex = 0;
7461: ndl_compare_function = ndl_block_compare;
7462: break;
7463: case 2:
7464: /* matrix order */
7465: /* XXX */
7466: nd_dcomp = -1;
7467: nd_isrlex = 0;
7468: nd_matrix_len = ord->ord.matrix.row;
7469: nd_matrix = ord->ord.matrix.matrix;
7470: ndl_compare_function = ndl_matrix_compare;
7471: break;
7472: case 3:
7473: /* composite order */
7474: nd_dcomp = -1;
7475: nd_isrlex = 0;
7476: nd_worb_len = ord->ord.composite.length;
7477: nd_worb = ord->ord.composite.w_or_b;
7478: ndl_compare_function = ndl_composite_compare;
7479: break;
7480:
7481: /* module order */
7482: case 256:
7483: switch ( ord->ord.simple ) {
7484: case 0:
1.21 noro 7485: nd_dcomp = 0;
1.1 noro 7486: nd_isrlex = 1;
1.21 noro 7487: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 7488: break;
7489: case 1:
1.21 noro 7490: nd_dcomp = 0;
1.1 noro 7491: nd_isrlex = 0;
7492: ndl_compare_function = ndl_module_glex_compare;
7493: break;
7494: case 2:
1.21 noro 7495: nd_dcomp = 0;
1.1 noro 7496: nd_isrlex = 0;
1.21 noro 7497: ndl_compare_function = ndl_module_compare;
7498: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 7499: break;
7500: default:
1.21 noro 7501: error("nd_init_ord : unsupported order");
1.1 noro 7502: }
7503: break;
7504: case 257:
7505: /* block order */
7506: nd_isrlex = 0;
1.21 noro 7507: ndl_compare_function = ndl_module_compare;
7508: ndl_base_compare_function = ndl_block_compare;
1.1 noro 7509: break;
7510: case 258:
7511: /* matrix order */
7512: nd_isrlex = 0;
7513: nd_matrix_len = ord->ord.matrix.row;
7514: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 7515: ndl_compare_function = ndl_module_compare;
7516: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 7517: break;
7518: case 259:
7519: /* composite order */
7520: nd_isrlex = 0;
7521: nd_worb_len = ord->ord.composite.length;
7522: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 7523: ndl_compare_function = ndl_module_compare;
7524: ndl_base_compare_function = ndl_composite_compare;
7525: break;
7526: case 300:
7527: /* schreyer order */
7528: if ( ord->base->id != 256 )
7529: error("nd_init_ord : unsupported base order");
7530: ndl_compare_function = ndl_module_schreyer_compare;
7531: dmm_stack = ord->dmmstack;
7532: switch ( ord->base->ord.simple ) {
7533: case 0:
7534: nd_isrlex = 1;
7535: ndl_base_compare_function = ndl_glex_compare;
7536: dl_base_compare_function = cmpdl_revgradlex;
7537: break;
7538: case 1:
7539: nd_isrlex = 0;
7540: ndl_base_compare_function = ndl_glex_compare;
7541: dl_base_compare_function = cmpdl_gradlex;
7542: break;
7543: case 2:
7544: nd_isrlex = 0;
7545: ndl_base_compare_function = ndl_lex_compare;
7546: dl_base_compare_function = cmpdl_lex;
7547: break;
7548: default:
7549: error("nd_init_ord : unsupported order");
7550: }
1.1 noro 7551: break;
7552: }
7553: nd_ord = ord;
7554: }
7555:
7556: BlockMask nd_create_blockmask(struct order_spec *ord)
7557: {
7558: int n,i,j,s,l;
7559: UINT *t;
7560: BlockMask bm;
7561:
7562: /* we only create mask table for block order */
7563: if ( ord->id != 1 && ord->id != 257 )
7564: return 0;
7565: n = ord->ord.block.length;
7566: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
7567: bm->n = n;
7568: bm->order_pair = ord->ord.block.order_pair;
7569: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
7570: for ( i = 0, s = 0; i < n; i++ ) {
7571: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
7572: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
7573: l = bm->order_pair[i].length;
7574: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
7575: }
7576: return bm;
7577: }
7578:
7579: EPOS nd_create_epos(struct order_spec *ord)
7580: {
7581: int i,j,l,s,ord_l,ord_o;
7582: EPOS epos;
7583: struct order_pair *op;
7584:
7585: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
7586: switch ( ord->id ) {
1.21 noro 7587: case 0: case 256: case 300:
1.1 noro 7588: if ( nd_isrlex ) {
7589: for ( i = 0; i < nd_nvar; i++ ) {
7590: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
7591: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
7592: }
7593: } else {
7594: for ( i = 0; i < nd_nvar; i++ ) {
7595: epos[i].i = nd_exporigin + i/nd_epw;
7596: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7597: }
7598: }
7599: break;
7600: case 1: case 257:
7601: /* block order */
7602: l = ord->ord.block.length;
7603: op = ord->ord.block.order_pair;
7604: for ( j = 0, s = 0; j < l; j++ ) {
7605: ord_o = op[j].order;
7606: ord_l = op[j].length;
7607: if ( !ord_o )
7608: for ( i = 0; i < ord_l; i++ ) {
7609: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
7610: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
7611: }
7612: else
7613: for ( i = 0; i < ord_l; i++ ) {
7614: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
7615: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
7616: }
7617: s += ord_l;
7618: }
7619: break;
7620: case 2:
7621: /* matrix order */
7622: case 3:
7623: /* composite order */
7624: default:
7625: for ( i = 0; i < nd_nvar; i++ ) {
7626: epos[i].i = nd_exporigin + i/nd_epw;
7627: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7628: }
7629: break;
7630: }
7631: return epos;
7632: }
7633:
7634: /* external interface */
7635:
7636: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
7637: {
7638: NODE t,in0,in;
7639: ND ndf,nf;
7640: NDV ndvf;
7641: VL vv,tv;
7642: int stat,nvar,max,mrank;
7643: union oNDC dn;
7644: Q cont;
7645: P pp;
7646: LIST ppl;
7647:
7648: if ( !f ) {
7649: *rp = 0;
7650: return;
7651: }
7652: pltovl(v,&vv);
7653: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
7654:
7655: /* max=65536 implies nd_bpe=32 */
7656: max = 65536;
7657:
7658: nd_module = 0;
7659: /* nd_module will be set if ord is a module ordering */
7660: nd_init_ord(ord);
7661: nd_setup_parameters(nvar,max);
7662: if ( nd_module && OID(f) != O_LIST )
7663: error("nd_nf_p : the first argument must be a list");
7664: if ( nd_module ) mrank = length(BDY((LIST)f));
7665: /* conversion to ndv */
7666: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
7667: NEXTNODE(in0,in);
7668: if ( nd_module ) {
7669: if ( !BDY(t) || OID(BDY(t)) != O_LIST
7670: || length(BDY((LIST)BDY(t))) != mrank )
7671: error("nd_nf_p : inconsistent basis element");
7672: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
7673: else ppl = (LIST)BDY(t);
7674: BDY(in) = (pointer)pltondv(CO,vv,ppl);
7675: } else {
7676: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
7677: else pp = (P)BDY(t);
7678: BDY(in) = (pointer)ptondv(CO,vv,pp);
7679: }
7680: if ( m ) ndv_mod(m,(NDV)BDY(in));
7681: }
7682: if ( in0 ) NEXT(in) = 0;
7683:
7684: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
7685: else ndvf = ptondv(CO,vv,(P)f);
7686: if ( m ) ndv_mod(m,ndvf);
7687: ndf = (pointer)ndvtond(m,ndvf);
7688:
7689: /* dont sort, dont removecont */
1.24 noro 7690: ndv_setup(m,0,in0,1,1,0);
1.1 noro 7691: nd_scale=2;
1.6 noro 7692: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 7693: if ( !stat )
7694: error("nd_nf_p : exponent too large");
7695: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
7696: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
7697: }
7698:
7699: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
7700: {
7701: NM m;
7702: UINT *t,*s;
7703: int i;
7704:
7705: for ( i = 0; i < n; i++ ) r[i] = 0;
7706: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7707: t = DL(m);
7708: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7709: r[i] = CM(m);
7710: }
7711: for ( i = 0; !r[i]; i++ );
7712: return i;
7713: }
7714:
7715: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
7716: {
7717: NM m;
7718: UINT *t,*s;
7719: int i;
7720:
7721: for ( i = 0; i < n; i++ ) r[i] = 0;
7722: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7723: t = DL(m);
7724: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7725: r[i] = CZ(m);
1.1 noro 7726: }
7727: for ( i = 0; !r[i]; i++ );
7728: return i;
7729: }
7730:
7731: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
7732: {
7733: NM m;
7734: UINT *t,*s;
7735: int i;
7736:
7737: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
7738: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7739: t = DL(m);
7740: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7741: mpz_set(r[i],BDY(CZ(m)));
7742: }
7743: for ( i = 0; !mpz_sgn(r[i]); i++ );
7744: return i;
7745: }
7746:
7747: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
7748: {
7749: NM m;
7750: unsigned long *v;
7751: int i,j,h,size;
7752: UINT *s,*t;
7753:
7754: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
7755: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
7756: bzero(v,size);
7757: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
7758: t = DL(m);
7759: h = ndl_hash_value(t);
7760: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7761: v[i/BLEN] |= 1L <<(i%BLEN);
7762: }
7763: return v;
7764: }
7765:
7766: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
7767: {
7768: NMV mr;
7769: UINT *d,*t,*s;
7770: int i,j,len,h,head;
7771:
7772: d = DL(m);
7773: len = LEN(p);
7774: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7775: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7776: ndl_add(d,DL(mr),t);
7777: h = ndl_hash_value(t);
7778: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7779: if ( j == 0 ) head = i;
7780: v[i/BLEN] |= 1L <<(i%BLEN);
7781: }
7782: return head;
7783: }
7784:
7785: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
7786: {
7787: NM m;
7788: NMV mr;
7789: UINT *d,*t,*s;
7790: NDV p;
7791: int i,j,len;
7792: Z *r;
7793:
7794: m = pair->mul;
7795: d = DL(m);
7796: p = nd_ps[pair->index];
7797: len = LEN(p);
7798: r = (Z *)CALLOC(n,sizeof(Q));
7799: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7800: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7801: ndl_add(d,DL(mr),t);
7802: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7803: r[i] = CZ(mr);
1.1 noro 7804: }
7805: return r;
7806: }
7807:
1.11 noro 7808: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 7809: {
7810: NM m;
7811: NMV mr;
1.11 noro 7812: UINT *d,*t,*s,*u;
1.1 noro 7813: NDV p;
7814: unsigned char *ivc;
7815: unsigned short *ivs;
7816: UINT *v,*ivi,*s0v;
1.11 noro 7817: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 7818: IndArray r;
7819:
7820: m = pair->mul;
7821: d = DL(m);
7822: if ( trace )
7823: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
7824: else
7825: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
7826:
7827: len = LEN(p);
7828: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7829: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 7830: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
7831: ndl_add(d,DL(mr),t);
7832: st = prev;
7833: ed = n;
7834: while ( ed > st ) {
7835: md = (st+ed)/2;
7836: u = s0+md*nd_wpd;
7837: c = DL_COMPARE(u,t);
7838: if ( c == 0 ) break;
7839: else if ( c > 0 ) st = md;
7840: else ed = md;
7841: }
7842: prev = v[j] = md;
1.1 noro 7843: }
7844: r = (IndArray)MALLOC(sizeof(struct oIndArray));
7845: r->head = v[0];
7846: diff = 0;
7847: for ( i = 1; i < len; i++ ) {
7848: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
7849: }
7850: if ( diff < 256 ) {
7851: r->width = 1;
7852: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
7853: r->index.c = ivc;
7854: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
7855: } else if ( diff < 65536 ) {
7856: r->width = 2;
7857: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
7858: r->index.s = ivs;
7859: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
7860: } else {
7861: r->width = 4;
7862: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
7863: r->index.i = ivi;
7864: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
7865: }
7866: return r;
7867: }
7868:
7869: int compress_array(Z *svect,Z *cvect,int n)
7870: {
7871: int i,j;
7872:
7873: for ( i = j = 0; i < n; i++ )
7874: if ( svect[i] ) cvect[j++] = svect[i];
7875: return j;
7876: }
7877:
7878: void expand_array(Z *svect,Z *cvect,int n)
7879: {
7880: int i,j;
7881:
7882: for ( i = j = 0; j < n; i++ )
7883: if ( svect[i] ) svect[i] = cvect[j++];
7884: }
7885:
1.8 noro 7886: #if 0
1.1 noro 7887: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7888: {
7889: int i,j,k,len,pos,prev,nz;
7890: Z cs,mcs,c1,c2,cr,gcd,t;
7891: IndArray ivect;
7892: unsigned char *ivc;
7893: unsigned short *ivs;
7894: unsigned int *ivi;
7895: NDV redv;
7896: NMV mr;
7897: NODE rp;
7898: int maxrs;
7899: double hmag;
7900: Z *cvect;
1.3 noro 7901: int l;
1.1 noro 7902:
7903: maxrs = 0;
7904: for ( i = 0; i < col && !svect[i]; i++ );
7905: if ( i == col ) return maxrs;
7906: hmag = p_mag((P)svect[i])*nd_scale;
7907: cvect = (Z *)MALLOC(col*sizeof(Q));
7908: for ( i = 0; i < nred; i++ ) {
7909: ivect = imat[i];
7910: k = ivect->head;
7911: if ( svect[k] ) {
7912: maxrs = MAX(maxrs,rp0[i]->sugar);
7913: redv = nd_demand?ndv_load(rp0[i]->index)
7914: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7915: len = LEN(redv); mr = BDY(redv);
1.6 noro 7916: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 7917: chsgnz(cs,&mcs);
7918: if ( !UNIQ(cr) ) {
7919: for ( j = 0; j < col; j++ ) {
7920: mulz(svect[j],cr,&c1); svect[j] = c1;
7921: }
7922: }
7923: svect[k] = 0; prev = k;
7924: switch ( ivect->width ) {
7925: case 1:
7926: ivc = ivect->index.c;
7927: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7928: pos = prev+ivc[j]; prev = pos;
1.6 noro 7929: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7930: }
7931: break;
7932: case 2:
7933: ivs = ivect->index.s;
7934: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7935: pos = prev+ivs[j]; prev = pos;
1.6 noro 7936: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7937: }
7938: break;
7939: case 4:
7940: ivi = ivect->index.i;
7941: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7942: pos = prev+ivi[j]; prev = pos;
1.6 noro 7943: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7944: }
7945: break;
7946: }
7947: for ( j = k+1; j < col && !svect[j]; j++ );
7948: if ( j == col ) break;
7949: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
7950: nz = compress_array(svect,cvect,col);
7951: removecont_array((P *)cvect,nz,1);
7952: expand_array(svect,cvect,nz);
7953: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
7954: }
7955: }
7956: }
7957: nz = compress_array(svect,cvect,col);
7958: removecont_array((P *)cvect,nz,1);
7959: expand_array(svect,cvect,nz);
7960: if ( DP_Print ) {
7961: fprintf(asir_out,"-"); fflush(asir_out);
7962: }
7963: return maxrs;
7964: }
1.4 noro 7965: #else
1.9 noro 7966:
1.4 noro 7967: /* direct mpz version */
7968: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7969: {
7970: int i,j,k,len,pos,prev;
7971: mpz_t cs,cr,gcd;
7972: IndArray ivect;
7973: unsigned char *ivc;
7974: unsigned short *ivs;
7975: unsigned int *ivi;
7976: NDV redv;
7977: NMV mr;
7978: NODE rp;
7979: int maxrs;
7980: double hmag;
7981: int l;
1.13 noro 7982: static mpz_t *svect;
7983: static int svect_len=0;
1.4 noro 7984:
7985: maxrs = 0;
7986: for ( i = 0; i < col && !svect0[i]; i++ );
7987: if ( i == col ) return maxrs;
7988: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 7989: if ( col > svect_len ) {
7990: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
7991: svect_len = col;
7992: }
1.4 noro 7993: for ( i = 0; i < col; i++ ) {
7994: mpz_init(svect[i]);
7995: if ( svect0[i] )
7996: mpz_set(svect[i],BDY(svect0[i]));
7997: else
7998: mpz_set_ui(svect[i],0);
7999: }
8000: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
8001: for ( i = 0; i < nred; i++ ) {
8002: ivect = imat[i];
8003: k = ivect->head;
8004: if ( mpz_sgn(svect[k]) ) {
8005: maxrs = MAX(maxrs,rp0[i]->sugar);
8006: redv = nd_demand?ndv_load(rp0[i]->index)
8007: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
8008: len = LEN(redv); mr = BDY(redv);
1.6 noro 8009: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 8010: mpz_div(cs,svect[k],gcd);
1.6 noro 8011: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 8012: mpz_neg(cs,cs);
1.9 noro 8013: if ( MUNIMPZ(cr) )
8014: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
8015: else if ( !UNIMPZ(cr) )
8016: for ( j = 0; j < col; j++ ) {
8017: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
8018: }
1.4 noro 8019: mpz_set_ui(svect[k],0);
8020: prev = k;
8021: switch ( ivect->width ) {
8022: case 1:
8023: ivc = ivect->index.c;
8024: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8025: pos = prev+ivc[j]; prev = pos;
1.6 noro 8026: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8027: }
8028: break;
8029: case 2:
8030: ivs = ivect->index.s;
8031: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8032: pos = prev+ivs[j]; prev = pos;
1.6 noro 8033: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8034: }
8035: break;
8036: case 4:
8037: ivi = ivect->index.i;
8038: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8039: pos = prev+ivi[j]; prev = pos;
1.6 noro 8040: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 8041: }
8042: break;
8043: }
8044: for ( j = k+1; j < col && !svect[j]; j++ );
8045: if ( j == col ) break;
8046: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
8047: mpz_removecont_array(svect,col);
8048: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
8049: }
8050: }
8051: }
8052: mpz_removecont_array(svect,col);
8053: if ( DP_Print ) {
8054: fprintf(asir_out,"-"); fflush(asir_out);
8055: }
8056: for ( i = 0; i < col; i++ )
8057: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
8058: else svect0[i] = 0;
8059: return maxrs;
8060: }
8061: #endif
1.1 noro 8062:
1.40 noro 8063: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.1 noro 8064: {
8065: int i,j,k,len,pos,prev;
8066: UINT c,c1,c2,c3,up,lo,dmy;
8067: IndArray ivect;
8068: unsigned char *ivc;
8069: unsigned short *ivs;
8070: unsigned int *ivi;
8071: NDV redv;
8072: NMV mr;
8073: NODE rp;
8074: int maxrs;
8075:
8076: maxrs = 0;
8077: for ( i = 0; i < nred; i++ ) {
8078: ivect = imat[i];
8079: k = ivect->head; svect[k] %= m;
1.40 noro 8080: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.1 noro 8081: maxrs = MAX(maxrs,rp0[i]->sugar);
8082: c = m-c; redv = nd_ps[rp0[i]->index];
8083: len = LEN(redv); mr = BDY(redv);
8084: svect[k] = 0; prev = k;
8085: switch ( ivect->width ) {
8086: case 1:
8087: ivc = ivect->index.c;
8088: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8089: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.40 noro 8090: if ( c1 ) {
8091: c2 = svect[pos];
1.1 noro 8092: DMA(c1,c,c2,up,lo);
8093: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8094: } else svect[pos] = lo;
1.40 noro 8095: }
1.1 noro 8096: }
8097: break;
8098: case 2:
8099: ivs = ivect->index.s;
8100: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8101: pos = prev+ivs[j]; c1 = CM(mr);
8102: prev = pos;
1.40 noro 8103: if ( c1 ) {
8104: c2 = svect[pos];
1.1 noro 8105: DMA(c1,c,c2,up,lo);
8106: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8107: } else svect[pos] = lo;
1.40 noro 8108: }
1.1 noro 8109: }
8110: break;
8111: case 4:
8112: ivi = ivect->index.i;
8113: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8114: pos = prev+ivi[j]; c1 = CM(mr);
8115: prev = pos;
1.40 noro 8116: if ( c1 ) {
8117: c2 = svect[pos];
1.1 noro 8118: DMA(c1,c,c2,up,lo);
8119: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
8120: } else svect[pos] = lo;
1.40 noro 8121: }
1.1 noro 8122: }
8123: break;
8124: }
8125: }
8126: }
8127: for ( i = 0; i < col; i++ )
8128: if ( svect[i] >= (UINT)m ) svect[i] %= m;
8129: return maxrs;
8130: }
8131:
8132: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8133: {
8134: int i,j,k,len,pos,prev;
8135: UINT c,c1,c2,c3,up,lo,dmy;
8136: IndArray ivect;
8137: unsigned char *ivc;
8138: unsigned short *ivs;
8139: unsigned int *ivi;
8140: NDV redv;
8141: NMV mr;
8142: NODE rp;
8143: int maxrs;
8144:
8145: maxrs = 0;
8146: for ( i = 0; i < nred; i++ ) {
8147: ivect = imat[i];
8148: k = ivect->head;
8149: if ( (c = svect[k]) != 0 ) {
8150: maxrs = MAX(maxrs,rp0[i]->sugar);
8151: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
8152: len = LEN(redv); mr = BDY(redv);
8153: svect[k] = 0; prev = k;
8154: switch ( ivect->width ) {
8155: case 1:
8156: ivc = ivect->index.c;
8157: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8158: pos = prev+ivc[j]; prev = pos;
8159: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8160: }
8161: break;
8162: case 2:
8163: ivs = ivect->index.s;
8164: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8165: pos = prev+ivs[j]; prev = pos;
8166: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8167: }
8168: break;
8169: case 4:
8170: ivi = ivect->index.i;
8171: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8172: pos = prev+ivi[j]; prev = pos;
8173: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
8174: }
8175: break;
8176: }
8177: }
8178: }
8179: return maxrs;
8180: }
8181:
8182: ND nd_add_lf(ND p1,ND p2)
8183: {
8184: int n,c,can;
8185: ND r;
8186: NM m1,m2,mr0,mr,s;
8187: Z t;
8188:
8189: if ( !p1 ) return p2;
8190: else if ( !p2 ) return p1;
8191: else {
8192: can = 0;
8193: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
8194: c = DL_COMPARE(DL(m1),DL(m2));
8195: switch ( c ) {
8196: case 0:
8197: addlf(CZ(m1),CZ(m2),&t);
8198: s = m1; m1 = NEXT(m1);
8199: if ( t ) {
8200: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
8201: } else {
8202: can += 2; FREENM(s);
8203: }
8204: s = m2; m2 = NEXT(m2); FREENM(s);
8205: break;
8206: case 1:
8207: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
8208: break;
8209: case -1:
8210: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
8211: break;
8212: }
8213: }
8214: if ( !mr0 )
8215: if ( m1 ) mr0 = m1;
8216: else if ( m2 ) mr0 = m2;
8217: else return 0;
8218: else if ( m1 ) NEXT(mr) = m1;
8219: else if ( m2 ) NEXT(mr) = m2;
8220: else NEXT(mr) = 0;
8221: BDY(p1) = mr0;
8222: SG(p1) = MAX(SG(p1),SG(p2));
8223: LEN(p1) = LEN(p1)+LEN(p2)-can;
8224: FREEND(p2);
8225: return p1;
8226: }
8227: }
8228:
8229: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
8230: {
8231: int i,j,k,len,pos,prev;
8232: mpz_t c,mc,c1;
8233: IndArray ivect;
8234: unsigned char *ivc;
8235: unsigned short *ivs;
8236: unsigned int *ivi;
8237: NDV redv;
8238: NMV mr;
8239: NODE rp;
8240: int maxrs;
8241:
8242: maxrs = 0;
8243: lf_lazy = 1;
8244: for ( i = 0; i < nred; i++ ) {
8245: ivect = imat[i];
8246: k = ivect->head;
8247: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
8248: if ( mpz_sgn(svect[k]) ) {
8249: maxrs = MAX(maxrs,rp0[i]->sugar);
8250: mpz_neg(svect[k],svect[k]);
8251: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
8252: len = LEN(redv); mr = BDY(redv);
8253: prev = k;
8254: switch ( ivect->width ) {
8255: case 1:
8256: ivc = ivect->index.c;
8257: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8258: pos = prev+ivc[j]; prev = pos;
8259: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8260: }
8261: break;
8262: case 2:
8263: ivs = ivect->index.s;
8264: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8265: pos = prev+ivs[j]; prev = pos;
8266: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8267: }
8268: break;
8269: case 4:
8270: ivi = ivect->index.i;
8271: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
8272: pos = prev+ivi[j]; prev = pos;
8273: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
8274: }
8275: break;
8276: }
8277: mpz_set_ui(svect[k],0);
8278: }
8279: }
8280: lf_lazy=0;
8281: for ( i = 0; i < col; i++ ) {
8282: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
8283: }
8284: return maxrs;
8285: }
8286:
8287: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
8288: {
8289: int i,j,k,l,rank,s;
8290: mpz_t a,a1,inv;
8291: mpz_t *t,*pivot,*pk;
8292: mpz_t **mat;
8293: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
8294: int size,size1;
8295:
8296: mpz_init(inv);
8297: mpz_init(a);
8298: mat = (mpz_t **)mat0;
8299: size = 0;
8300: for ( rank = 0, j = 0; j < col; j++ ) {
8301: for ( i = rank; i < row; i++ ) {
8302: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
8303: }
8304: for ( i = rank; i < row; i++ )
8305: if ( mpz_sgn(mat[i][j]) )
8306: break;
8307: if ( i == row ) {
8308: colstat[j] = 0;
8309: continue;
8310: } else
8311: colstat[j] = 1;
8312: if ( i != rank ) {
8313: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8314: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8315: }
8316: pivot = mat[rank];
8317: s = sugar[rank];
8318: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
8319: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8320: if ( mpz_sgn(*pk) ) {
8321: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
8322: }
8323: for ( i = rank+1; i < row; i++ ) {
8324: t = mat[i];
8325: if ( mpz_sgn(t[j]) ) {
8326: sugar[i] = MAX(sugar[i],s);
8327: mpz_neg(a,t[j]);
8328: red_by_vect_lf(t+j,pivot+j,a,col-j);
8329: }
8330: }
8331: rank++;
8332: }
8333: for ( j = col-1, l = rank-1; j >= 0; j-- )
8334: if ( colstat[j] ) {
8335: pivot = mat[l];
8336: s = sugar[l];
8337: for ( k = j; k < col; k++ )
8338: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
8339: for ( i = 0; i < l; i++ ) {
8340: t = mat[i];
8341: if ( mpz_sgn(t[j]) ) {
8342: sugar[i] = MAX(sugar[i],s);
8343: mpz_neg(a,t[j]);
8344: red_by_vect_lf(t+j,pivot+j,a,col-j);
8345: }
8346: }
8347: l--;
8348: }
8349: for ( j = 0, l = 0; l < rank; j++ )
8350: if ( colstat[j] ) {
8351: t = mat[l];
8352: for ( k = j; k < col; k++ ) {
8353: mpz_mod(t[k],t[k],BDY(current_mod_lf));
8354: }
8355: l++;
8356: }
8357: return rank;
8358: }
8359:
8360:
8361: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
8362: {
8363: int j,k,len;
8364: UINT *p;
8365: UINT c;
8366: NDV r;
8367: NMV mr0,mr;
8368:
8369: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8370: if ( !len ) return 0;
8371: else {
8372: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8373: #if 0
8374: ndv_alloc += nmv_adv*len;
8375: #endif
8376: mr = mr0;
8377: p = s0vect;
8378: for ( j = k = 0; j < col; j++, p += nd_wpd )
8379: if ( !rhead[j] ) {
8380: if ( (c = vect[k++]) != 0 ) {
8381: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8382: }
8383: }
8384: MKNDV(nd_nvar,mr0,len,r);
8385: return r;
8386: }
8387: }
8388:
1.40 noro 8389: NDV vect_to_ndv_s(UINT *vect,int col,UINT *s0vect)
8390: {
8391: int j,k,len;
8392: UINT *p;
8393: UINT c;
8394: NDV r;
8395: NMV mr0,mr;
8396:
8397: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8398: if ( !len ) return 0;
8399: else {
8400: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8401: mr = mr0;
8402: p = s0vect;
8403: for ( j = k = 0; j < col; j++, p += nd_wpd )
8404: if ( (c = vect[k++]) != 0 ) {
8405: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8406: }
8407: MKNDV(nd_nvar,mr0,len,r);
8408: return r;
8409: }
8410: }
8411:
1.1 noro 8412: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
8413: {
8414: int j,k,len;
8415: UINT *p;
8416: NDV r;
8417: NMV mr0,mr;
8418:
8419: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
8420: if ( !len ) return 0;
8421: else {
8422: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8423: mr = mr0;
8424: p = s0vect;
8425: for ( j = 0; j < col; j++, p += nd_wpd )
8426: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
8427: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
8428: }
8429: MKNDV(nd_nvar,mr0,len,r);
8430: return r;
8431: }
8432: }
8433:
8434: /* for preprocessed vector */
8435:
8436: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
8437: {
1.6 noro 8438: int j,k,len;
8439: UINT *p;
8440: Z c;
8441: NDV r;
8442: NMV mr0,mr;
1.1 noro 8443:
1.6 noro 8444: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8445: if ( !len ) return 0;
8446: else {
8447: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 8448: #if 0
1.6 noro 8449: ndv_alloc += nmv_adv*len;
1.1 noro 8450: #endif
1.6 noro 8451: mr = mr0;
8452: p = s0vect;
8453: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
8454: if ( !rhead[j] ) {
8455: if ( (c = vect[k++]) != 0 ) {
8456: if ( !INT(c) )
8457: error("vect_to_ndv_q : components must be integers");
8458: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
8459: }
8460: }
1.1 noro 8461: }
1.6 noro 8462: MKNDV(nd_nvar,mr0,len,r);
8463: return r;
8464: }
1.1 noro 8465: }
8466:
8467: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
8468: {
8469: int j,k,len;
8470: UINT *p;
8471: mpz_t c;
8472: NDV r;
8473: NMV mr0,mr;
8474:
8475: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
8476: if ( !len ) return 0;
8477: else {
8478: mr0 = (NMV)MALLOC(nmv_adv*len);
8479: #if 0
8480: ndv_alloc += nmv_adv*len;
8481: #endif
8482: mr = mr0;
8483: p = s0vect;
8484: for ( j = k = 0; j < col; j++, p += nd_wpd )
8485: if ( !rhead[j] ) {
8486: c[0] = vect[k++][0];
8487: if ( mpz_sgn(c) ) {
8488: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
8489: }
8490: }
8491: MKNDV(nd_nvar,mr0,len,r);
8492: return r;
8493: }
8494: }
8495:
8496: /* for plain vector */
8497:
8498: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
8499: {
8500: int j,k,len;
8501: UINT *p;
8502: Z c;
8503: NDV r;
8504: NMV mr0,mr;
8505:
8506: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8507: if ( !len ) return 0;
8508: else {
8509: mr0 = (NMV)MALLOC(nmv_adv*len);
8510: #if 0
8511: ndv_alloc += nmv_adv*len;
8512: #endif
8513: mr = mr0;
8514: p = s0vect;
8515: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
8516: if ( (c = vect[k]) != 0 ) {
8517: if ( !INT(c) )
1.6 noro 8518: error("plain_vect_to_ndv_q : components must be integers");
8519: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 8520: }
8521: MKNDV(nd_nvar,mr0,len,r);
8522: return r;
8523: }
8524: }
8525:
8526: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
8527: {
8528: ND_pairs t;
8529: NODE sp0,sp;
8530: int stat;
8531: ND spol;
8532:
8533: for ( t = l; t; t = NEXT(t) ) {
8534: stat = nd_sp(m,trace,t,&spol);
8535: if ( !stat ) return 0;
8536: if ( spol ) {
8537: add_pbucket_symbolic(bucket,spol);
8538: }
8539: }
8540: return 1;
8541: }
8542:
8543: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
8544: {
8545: NODE rp0,rp;
8546: NM mul,head,s0,s;
8547: int index,col,i,sugar;
8548: RHist h;
8549: UINT *s0v,*p;
8550: NM_ind_pair pair;
8551: ND red;
8552: NDV *ps;
8553:
8554: s0 = 0; rp0 = 0; col = 0;
8555: if ( nd_demand )
8556: ps = trace?nd_ps_trace_sym:nd_ps_sym;
8557: else
8558: ps = trace?nd_ps_trace:nd_ps;
8559: while ( 1 ) {
8560: head = remove_head_pbucket_symbolic(bucket);
8561: if ( !head ) break;
8562: if ( !s0 ) s0 = head;
8563: else NEXT(s) = head;
8564: s = head;
8565: index = ndl_find_reducer(DL(head));
8566: if ( index >= 0 ) {
8567: h = nd_psh[index];
8568: NEWNM(mul);
8569: ndl_sub(DL(head),DL(h),DL(mul));
8570: if ( ndl_check_bound2(index,DL(mul)) )
8571: return 0;
8572: sugar = TD(DL(mul))+SG(ps[index]);
1.28 noro 8573: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 8574: red = ndv_mul_nm_symbolic(mul,ps[index]);
8575: add_pbucket_symbolic(bucket,nd_remove_head(red));
8576: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
8577: }
8578: col++;
8579: }
8580: if ( rp0 ) NEXT(rp) = 0;
8581: NEXT(s) = 0;
8582: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
8583: for ( i = 0, p = s0v, s = s0; i < col;
8584: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
8585: *s0vect = s0v;
8586: *r = rp0;
8587: return col;
8588: }
8589:
8590: void print_ndp(ND_pairs l)
8591: {
8592: ND_pairs t;
8593:
8594: for ( t = l; t; t = NEXT(t) )
8595: printf("[%d,%d] ",t->i1,t->i2);
8596: printf("\n");
8597: }
8598:
8599: NODE nd_f4(int m,int checkonly,int **indp)
8600: {
8601: int i,nh,stat,index,f4red;
8602: NODE r,g,tn0,tn,node;
8603: ND_pairs d,l,t,ll0,ll,lh;
8604: LIST l0,l1;
8605: ND spol,red;
8606: NDV nf,redv;
8607: NM s0,s;
8608: NODE rp0,srp0,nflist,nzlist,nzlist_t;
8609: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
8610: UINT c;
8611: UINT **spmat;
8612: UINT *s0vect,*svect,*p,*v;
8613: int *colstat;
8614: IndArray *imat;
8615: int *rhead;
8616: int spcol,sprow;
8617: int sugar,sugarh;
8618: PGeoBucket bucket;
8619: struct oEGT eg0,eg1,eg_f4;
8620: Z i1,i2,sugarq;
1.12 noro 8621:
8622: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 8623: #if 0
8624: ndv_alloc = 0;
8625: #endif
1.11 noro 8626: Nf4_red=0;
1.1 noro 8627: g = 0; d = 0;
8628: for ( i = 0; i < nd_psn; i++ ) {
8629: d = update_pairs(d,g,i,0);
8630: g = update_base(g,i);
8631: }
8632: nzlist = 0;
8633: nzlist_t = nd_nzlist;
8634: f4red = 1;
8635: nd_last_nonzero = 0;
8636: while ( d ) {
8637: get_eg(&eg0);
8638: l = nd_minsugarp(d,&d);
8639: sugar = nd_sugarweight?l->sugar2:SG(l);
8640: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8641: if ( nzlist_t ) {
8642: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 8643: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 8644: tn = BDY((LIST)ARG1(node));
8645: if ( !tn ) {
8646: nzlist_t = NEXT(nzlist_t);
8647: continue;
8648: }
8649: /* tn = [[i1,i2],...] */
8650: lh = nd_ipairtospair(tn);
8651: }
8652: bucket = create_pbucket();
8653: stat = nd_sp_f4(m,0,l,bucket);
8654: if ( !stat ) {
8655: for ( t = l; NEXT(t); t = NEXT(t) );
8656: NEXT(t) = d; d = l;
8657: d = nd_reconstruct(0,d);
8658: continue;
8659: }
8660: if ( bucket->m < 0 ) continue;
8661: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8662: if ( !col ) {
8663: for ( t = l; NEXT(t); t = NEXT(t) );
8664: NEXT(t) = d; d = l;
8665: d = nd_reconstruct(0,d);
8666: continue;
8667: }
1.12 noro 8668: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 8669: if ( DP_Print )
1.6 noro 8670: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 8671: sugar,eg_f4.exectime);
1.1 noro 8672: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
8673: if ( checkonly && nflist ) return 0;
8674: /* adding new bases */
8675: if ( nflist ) nd_last_nonzero = f4red;
8676: for ( r = nflist; r; r = NEXT(r) ) {
8677: nf = (NDV)BDY(r);
1.38 noro 8678: if ( nd_f4_td ) SG(nf) = nd_tdeg(nf);
1.1 noro 8679: ndv_removecont(m,nf);
8680: if ( !m && nd_nalg ) {
8681: ND nf1;
8682:
8683: nf1 = ndvtond(m,nf);
8684: nd_monic(0,&nf1);
8685: nd_removecont(m,nf1);
8686: nf = ndtondv(m,nf1);
8687: }
1.24 noro 8688: nh = ndv_newps(m,nf,0);
1.1 noro 8689: d = update_pairs(d,g,nh,0);
8690: g = update_base(g,nh);
8691: }
8692: if ( DP_Print ) {
8693: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
8694: }
8695: if ( nd_gentrace ) {
8696: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
8697: NEXTNODE(tn0,tn);
1.6 noro 8698: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 8699: node = mknode(2,i1,i2); MKLIST(l0,node);
8700: BDY(tn) = l0;
8701: }
8702: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 8703: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 8704: MKNODE(node,l1,nzlist); nzlist = node;
8705: }
8706: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
8707: f4red++;
8708: if ( nd_f4red && f4red > nd_f4red ) break;
8709: if ( nd_rank0 && !nflist ) break;
8710: }
8711: if ( nd_gentrace ) {
8712: MKLIST(l0,reverse_node(nzlist));
8713: MKNODE(nd_alltracelist,l0,0);
8714: }
8715: #if 0
8716: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8717: #endif
1.12 noro 8718: if ( DP_Print ) {
8719: fprintf(asir_out,"number of red=%d,",Nf4_red);
8720: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
8721: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
1.41 noro 8722: fprintf(asir_out,"number of removed pairs=%d\n,",NcriB+NcriMF+Ncri2);
1.12 noro 8723: }
1.1 noro 8724: conv_ilist(nd_demand,0,g,indp);
8725: return g;
8726: }
8727:
8728: NODE nd_f4_trace(int m,int **indp)
8729: {
8730: int i,nh,stat,index;
8731: NODE r,g;
8732: ND_pairs d,l,l0,t;
8733: ND spol,red;
8734: NDV nf,redv,nfqv,nfv;
8735: NM s0,s;
8736: NODE rp0,srp0,nflist;
8737: int nsp,nred,col,rank,len,k,j,a;
8738: UINT c;
8739: UINT **spmat;
8740: UINT *s0vect,*svect,*p,*v;
8741: int *colstat;
8742: IndArray *imat;
8743: int *rhead;
8744: int spcol,sprow;
8745: int sugar;
8746: PGeoBucket bucket;
8747: struct oEGT eg0,eg1,eg_f4;
8748:
8749: g = 0; d = 0;
8750: for ( i = 0; i < nd_psn; i++ ) {
8751: d = update_pairs(d,g,i,0);
8752: g = update_base(g,i);
8753: }
8754: while ( d ) {
8755: get_eg(&eg0);
8756: l = nd_minsugarp(d,&d);
8757: sugar = SG(l);
8758: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8759: bucket = create_pbucket();
8760: stat = nd_sp_f4(m,0,l,bucket);
8761: if ( !stat ) {
8762: for ( t = l; NEXT(t); t = NEXT(t) );
8763: NEXT(t) = d; d = l;
8764: d = nd_reconstruct(1,d);
8765: continue;
8766: }
8767: if ( bucket->m < 0 ) continue;
8768: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8769: if ( !col ) {
8770: for ( t = l; NEXT(t); t = NEXT(t) );
8771: NEXT(t) = d; d = l;
8772: d = nd_reconstruct(1,d);
8773: continue;
8774: }
8775: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
8776: if ( DP_Print )
1.3 noro 8777: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 8778: sugar,eg_f4.exectime);
1.1 noro 8779: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
8780: if ( !l0 ) continue;
8781: l = l0;
8782:
8783: /* over Q */
8784: bucket = create_pbucket();
8785: stat = nd_sp_f4(0,1,l,bucket);
8786: if ( !stat ) {
8787: for ( t = l; NEXT(t); t = NEXT(t) );
8788: NEXT(t) = d; d = l;
8789: d = nd_reconstruct(1,d);
8790: continue;
8791: }
8792: if ( bucket->m < 0 ) continue;
8793: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
8794: if ( !col ) {
8795: for ( t = l; NEXT(t); t = NEXT(t) );
8796: NEXT(t) = d; d = l;
8797: d = nd_reconstruct(1,d);
8798: continue;
8799: }
8800: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
8801: /* adding new bases */
8802: for ( r = nflist; r; r = NEXT(r) ) {
8803: nfqv = (NDV)BDY(r);
8804: ndv_removecont(0,nfqv);
1.6 noro 8805: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 8806: if ( nd_nalg ) {
8807: ND nf1;
8808:
8809: nf1 = ndvtond(m,nfqv);
8810: nd_monic(0,&nf1);
8811: nd_removecont(0,nf1);
8812: nfqv = ndtondv(0,nf1); nd_free(nf1);
8813: }
8814: nfv = ndv_dup(0,nfqv);
8815: ndv_mod(m,nfv);
8816: ndv_removecont(m,nfv);
1.24 noro 8817: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 8818: d = update_pairs(d,g,nh,0);
8819: g = update_base(g,nh);
8820: }
8821: }
8822: #if 0
8823: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8824: #endif
8825: conv_ilist(nd_demand,1,g,indp);
8826: return g;
8827: }
8828:
8829: int rref(matrix mat,int *sugar)
8830: {
8831: int row,col,i,j,k,l,s,wcol,wj;
8832: unsigned long bj;
8833: unsigned long **a;
8834: unsigned long *ai,*ak,*as,*t;
8835: int *pivot;
8836:
8837: row = mat->row;
8838: col = mat->col;
8839: a = mat->a;
8840: wcol = (col+BLEN-1)/BLEN;
8841: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
8842: i = 0;
8843: for ( j = 0; j < col; j++ ) {
8844: wj = j/BLEN; bj = 1L<<(j%BLEN);
8845: for ( k = i; k < row; k++ )
8846: if ( a[k][wj] & bj ) break;
8847: if ( k == row ) continue;
8848: pivot[i] = j;
8849: if ( k != i ) {
8850: t = a[i]; a[i] = a[k]; a[k] = t;
8851: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
8852: }
8853: ai = a[i];
8854: for ( k = i+1; k < row; k++ ) {
8855: ak = a[k];
8856: if ( ak[wj] & bj ) {
8857: for ( l = wj; l < wcol; l++ )
8858: ak[l] ^= ai[l];
8859: sugar[k] = MAX(sugar[k],sugar[i]);
8860: }
8861: }
8862: i++;
8863: }
8864: for ( k = i-1; k >= 0; k-- ) {
8865: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
8866: ak = a[k];
8867: for ( s = 0; s < k; s++ ) {
8868: as = a[s];
8869: if ( as[wj] & bj ) {
8870: for ( l = wj; l < wcol; l++ )
8871: as[l] ^= ak[l];
8872: sugar[s] = MAX(sugar[s],sugar[k]);
8873: }
8874: }
8875: }
8876: return i;
8877: }
8878:
8879: void print_matrix(matrix mat)
8880: {
8881: int row,col,i,j;
8882: unsigned long *ai;
8883:
8884: row = mat->row;
8885: col = mat->col;
8886: printf("%d x %d\n",row,col);
8887: for ( i = 0; i < row; i++ ) {
8888: ai = mat->a[i];
8889: for ( j = 0; j < col; j++ ) {
8890: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
8891: else putchar('0');
8892: }
8893: putchar('\n');
8894: }
8895: }
8896:
8897: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
8898:
8899: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
8900: {
8901: int row,col,wcol,wj,i,j;
8902: unsigned long bj;
8903: unsigned long *ai;
8904: unsigned long **a;
8905: int len;
8906: int *pos;
8907:
8908: row = mat->row;
8909: col = mat->col;
8910: wcol = (col+BLEN-1)/BLEN;
8911: pos = (int *)MALLOC(wcol*sizeof(int));
8912: bzero(pos,wcol*sizeof(int));
8913: for ( i = j = 0; i < wcol; i++ )
8914: if ( v[i] ) pos[j++] = i;;
8915: len = j;
8916: wj = rhead/BLEN;
8917: bj = 1L<<rhead%BLEN;
8918: a = mat->a;
8919: for ( i = 0; i < row; i++ ) {
8920: ai = a[i];
8921: if ( ai[wj]&bj ) {
8922: for ( j = 0; j < len; j++ )
8923: ai[pos[j]] ^= v[pos[j]];
8924: sugar[i] = MAX(sugar[i],rsugar);
8925: }
8926: }
8927: }
8928:
8929: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8930: {
8931: int nsp,nred,i,i0,k,rank,row;
8932: NODE r0,rp;
8933: ND_pairs sp;
8934: ND spol;
8935: NM_ind_pair rt;
8936: int *s0hash;
8937: UINT *s;
8938: int *pivot,*sugar,*head;
8939: matrix mat;
8940: NM m;
8941: NODE r;
8942: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
8943: int rhead,rsugar,size;
8944: unsigned long *v;
8945:
8946: get_eg(&eg0);
8947: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8948: nred = length(rp0);
8949: mat = alloc_matrix(nsp,col);
8950: s0hash = (int *)MALLOC(col*sizeof(int));
8951: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
8952: s0hash[i] = ndl_hash_value(s);
8953:
8954: sugar = (int *)MALLOC(nsp*sizeof(int));
8955: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
8956: nd_sp(2,0,sp,&spol);
8957: if ( spol ) {
8958: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
8959: sugar[i] = SG(spol);
8960: i++;
8961: }
8962: }
8963: mat->row = i;
8964: if ( DP_Print ) {
8965: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
8966: }
8967: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
8968: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
8969: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
8970: rt = (NM_ind_pair)BDY(rp);
8971: bzero(v,size);
8972: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
8973: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
8974: red_by_vect_2(mat,sugar,v,rhead,rsugar);
8975: }
8976:
8977: get_eg(&eg1);
8978: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
8979: rank = rref(mat,sugar);
8980:
8981: for ( i = 0, r0 = 0; i < rank; i++ ) {
8982: NEXTNODE(r0,r);
8983: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
8984: SG((NDV)BDY(r)) = sugar[i];
8985: }
8986: if ( r0 ) NEXT(r) = 0;
8987: get_eg(&eg2);
8988: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
8989: if ( DP_Print ) {
8990: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 8991: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 8992: fflush(asir_out);
8993: }
8994: return r0;
8995: }
8996:
8997:
8998: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8999: {
9000: IndArray *imat;
1.11 noro 9001: int nsp,nred,i,start;
1.1 noro 9002: int *rhead;
9003: NODE r0,rp;
9004: ND_pairs sp;
9005: NM_ind_pair *rvect;
9006: UINT *s;
9007: int *s0hash;
1.11 noro 9008: struct oEGT eg0,eg1,eg_conv;
1.1 noro 9009:
9010: if ( m == 2 && nd_rref2 )
9011: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
9012:
9013: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
9014: nred = length(rp0);
9015: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
9016: rhead = (int *)MALLOC(col*sizeof(int));
9017: for ( i = 0; i < col; i++ ) rhead[i] = 0;
9018:
9019: /* construction of index arrays */
1.11 noro 9020: get_eg(&eg0);
1.1 noro 9021: if ( DP_Print ) {
1.11 noro 9022: fprintf(asir_out,"%dx%d,",nsp+nred,col);
9023: fflush(asir_out);
1.1 noro 9024: }
9025: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 9026: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 9027: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 9028: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 9029: rhead[imat[i]->head] = 1;
1.11 noro 9030: start = imat[i]->head;
9031: }
1.12 noro 9032: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 9033: if ( DP_Print ) {
9034: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
9035: fflush(asir_out);
1.1 noro 9036: }
9037: if ( m > 0 )
1.7 noro 9038: #if SIZEOF_LONG==8
1.1 noro 9039: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9040: #else
9041: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9042: #endif
9043: else if ( m == -1 )
9044: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
9045: else if ( m == -2 )
9046: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9047: else
9048: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
9049: return r0;
9050: }
9051:
9052: /* for Fp, 2<=p<2^16 */
9053:
9054: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9055: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9056: {
9057: int spcol,sprow,a;
9058: int i,j,k,l,rank;
9059: NODE r0,r;
9060: ND_pairs sp;
9061: ND spol;
9062: UINT **spmat;
9063: UINT *svect,*v;
9064: int *colstat;
9065: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9066: int maxrs;
9067: int *spsugar;
9068: ND_pairs *spactive;
9069:
9070: spcol = col-nred;
9071: get_eg(&eg0);
9072: /* elimination (1st step) */
9073: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9074: svect = (UINT *)MALLOC(col*sizeof(UINT));
9075: spsugar = (int *)MALLOC(nsp*sizeof(int));
9076: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9077: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9078: nd_sp(m,0,sp,&spol);
9079: if ( !spol ) continue;
9080: nd_to_vect(m,s0vect,col,spol,svect);
9081: if ( m == -1 )
9082: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9083: else
1.40 noro 9084: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,0);
1.1 noro 9085: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9086: if ( i < col ) {
9087: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9088: for ( j = k = 0; j < col; j++ )
9089: if ( !rhead[j] ) v[k++] = svect[j];
9090: spsugar[sprow] = MAX(maxrs,SG(spol));
9091: if ( nz )
9092: spactive[sprow] = sp;
9093: sprow++;
9094: }
9095: nd_free(spol);
9096: }
9097: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9098: if ( DP_Print ) {
1.5 noro 9099: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9100: fflush(asir_out);
9101: }
9102: /* free index arrays */
9103: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9104:
9105: /* elimination (2nd step) */
9106: colstat = (int *)MALLOC(spcol*sizeof(int));
9107: if ( m == -1 )
9108: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9109: else
9110: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
9111: r0 = 0;
9112: for ( i = 0; i < rank; i++ ) {
9113: NEXTNODE(r0,r); BDY(r) =
9114: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9115: SG((NDV)BDY(r)) = spsugar[i];
9116: GCFREE(spmat[i]);
9117: }
9118: if ( r0 ) NEXT(r) = 0;
9119:
9120: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9121: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9122: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9123: if ( DP_Print ) {
1.5 noro 9124: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9125: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9126: nsp,nred,sprow,spcol,rank);
1.5 noro 9127: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9128: }
9129: if ( nz ) {
9130: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9131: if ( rank > 0 ) {
9132: NEXT(spactive[rank-1]) = 0;
9133: *nz = spactive[0];
9134: } else
9135: *nz = 0;
9136: }
9137: return r0;
9138: }
9139:
1.40 noro 9140: NODE nd_f4_red_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9141: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
9142: {
9143: int spcol,sprow,a;
9144: int i,j,k,l,rank;
9145: NODE r0,r;
9146: ND_pairs sp;
9147: ND spol;
9148: UINT **spmat;
9149: UINT *svect,*cvect;
9150: UINT *v;
9151: int *colstat;
9152: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9153: int maxrs;
9154: int *spsugar;
9155: ND_pairs *spactive;
9156: SIG *spsig;
9157:
9158: get_eg(&eg0);
9159: /* elimination (1st step) */
9160: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9161: spsugar = (int *)MALLOC(nsp*sizeof(int));
9162: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
9163: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9164: nd_sp(m,0,sp,&spol);
9165: if ( !spol ) {
9166: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9167: continue;
9168: }
9169: svect = (UINT *)MALLOC(col*sizeof(UINT));
9170: nd_to_vect(m,s0vect,col,spol,svect);
9171: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,spol->sig);
9172: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9173: if ( i < col ) {
9174: spmat[sprow] = svect;
9175: spsugar[sprow] = MAX(maxrs,SG(spol));
9176: spsig[sprow] = sp->sig;
9177: sprow++;
9178: } else {
9179: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
9180: }
9181: nd_free(spol);
9182: }
9183: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
9184: if ( DP_Print ) {
9185: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
9186: fflush(asir_out);
9187: }
9188: /* free index arrays */
9189: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9190:
9191: /* elimination (2nd step) */
9192: colstat = (int *)MALLOC(col*sizeof(int));
9193: rank = nd_gauss_elim_mod_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
9194: r0 = 0;
9195: for ( i = 0; i < sprow; i++ ) {
9196: if ( spsugar[i] >= 0 ) {
9197: NEXTNODE(r0,r);
9198: BDY(r) = vect_to_ndv_s(spmat[i],col,s0vect);
9199: SG((NDV)BDY(r)) = spsugar[i];
9200: ((NDV)BDY(r))->sig = spsig[i];
9201: } else
9202: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
9203: GCFREE(spmat[i]);
9204: }
9205: if ( r0 ) NEXT(r) = 0;
9206: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
9207: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9208: if ( DP_Print ) {
9209: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
9210: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9211: nsp,nred,sprow,col,rank);
9212: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
9213: }
9214: return r0;
9215: }
9216:
1.1 noro 9217:
9218: /* for small finite fields */
9219:
9220: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
9221: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
9222: {
9223: int spcol,sprow,a;
9224: int i,j,k,l,rank;
9225: NODE r0,r;
9226: ND_pairs sp;
9227: ND spol;
9228: UINT **spmat;
9229: UINT *svect,*v;
9230: int *colstat;
9231: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9232: int maxrs;
9233: int *spsugar;
9234: ND_pairs *spactive;
9235:
9236: spcol = col-nred;
9237: get_eg(&eg0);
9238: /* elimination (1st step) */
9239: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
9240: svect = (UINT *)MALLOC(col*sizeof(UINT));
9241: spsugar = (int *)MALLOC(nsp*sizeof(int));
9242: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
9243: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9244: nd_sp(m,0,sp,&spol);
9245: if ( !spol ) continue;
9246: nd_to_vect(m,s0vect,col,spol,svect);
9247: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
9248: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9249: if ( i < col ) {
9250: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
9251: for ( j = k = 0; j < col; j++ )
9252: if ( !rhead[j] ) v[k++] = svect[j];
9253: spsugar[sprow] = MAX(maxrs,SG(spol));
9254: if ( nz )
9255: spactive[sprow] = sp;
9256: sprow++;
9257: }
9258: nd_free(spol);
9259: }
9260: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9261: if ( DP_Print ) {
1.5 noro 9262: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9263: fflush(asir_out);
9264: }
9265: /* free index arrays */
9266: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
9267:
9268: /* elimination (2nd step) */
9269: colstat = (int *)MALLOC(spcol*sizeof(int));
9270: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
9271: r0 = 0;
9272: for ( i = 0; i < rank; i++ ) {
9273: NEXTNODE(r0,r); BDY(r) =
9274: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
9275: SG((NDV)BDY(r)) = spsugar[i];
9276: GCFREE(spmat[i]);
9277: }
9278: if ( r0 ) NEXT(r) = 0;
9279:
9280: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
9281: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9282: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9283: if ( DP_Print ) {
1.5 noro 9284: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9285: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9286: nsp,nred,sprow,spcol,rank);
1.5 noro 9287: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9288: }
9289: if ( nz ) {
9290: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
9291: if ( rank > 0 ) {
9292: NEXT(spactive[rank-1]) = 0;
9293: *nz = spactive[0];
9294: } else
9295: *nz = 0;
9296: }
9297: return r0;
9298: }
9299:
9300: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9301: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9302: {
9303: int spcol,sprow,a;
9304: int i,j,k,l,rank;
9305: NODE r0,r;
9306: ND_pairs sp;
9307: ND spol;
9308: mpz_t **spmat;
9309: mpz_t *svect,*v;
9310: int *colstat;
9311: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9312: int maxrs;
9313: int *spsugar;
9314: pointer *w;
9315:
9316: spcol = col-nred;
9317: get_eg(&eg0);
9318: /* elimination (1st step) */
9319: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
9320: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
9321: spsugar = (int *)MALLOC(nsp*sizeof(int));
9322: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9323: nd_sp(m,trace,sp,&spol);
9324: if ( !spol ) continue;
9325: nd_to_vect_lf(s0vect,col,spol,svect);
9326: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
9327: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
9328: if ( i < col ) {
9329: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
9330: for ( j = k = 0; j < col; j++ )
9331: if ( !rhead[j] ) v[k++][0] = svect[j][0];
9332: spsugar[sprow] = MAX(maxrs,SG(spol));
9333: sprow++;
9334: }
9335: /* nd_free(spol); */
9336: }
9337: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9338: if ( DP_Print ) {
1.5 noro 9339: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9340: fflush(asir_out);
9341: }
9342: /* free index arrays */
9343: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9344:
9345: /* elimination (2nd step) */
9346: colstat = (int *)MALLOC(spcol*sizeof(int));
9347: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
9348: w = (pointer *)MALLOC(rank*sizeof(pointer));
9349: for ( i = 0; i < rank; i++ ) {
9350: #if 0
9351: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9352: SG((NDV)w[rank-i-1]) = spsugar[i];
9353: #else
9354: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9355: SG((NDV)w[i]) = spsugar[i];
9356: #endif
9357: /* GCFREE(spmat[i]); */
9358:
9359: }
9360: #if 0
9361: qsort(w,rank,sizeof(NDV),
9362: (int (*)(const void *,const void *))ndv_compare);
9363: #endif
9364: r0 = 0;
9365: for ( i = 0; i < rank; i++ ) {
9366: NEXTNODE(r0,r); BDY(r) = w[i];
9367: }
9368: if ( r0 ) NEXT(r) = 0;
9369:
9370: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9371: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9372: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9373: if ( DP_Print ) {
1.5 noro 9374: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9375: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9376: nsp,nred,sprow,spcol,rank);
1.5 noro 9377: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9378: }
9379: return r0;
9380: }
9381:
9382: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9383: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9384: {
9385: int spcol,sprow,a;
9386: int i,j,k,l,rank;
9387: NODE r0,r;
9388: ND_pairs sp;
9389: ND spol;
9390: Z **spmat;
9391: Z *svect,*v;
9392: int *colstat;
9393: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9394: int maxrs;
9395: int *spsugar;
9396: pointer *w;
9397:
9398: spcol = col-nred;
9399: get_eg(&eg0);
9400: /* elimination (1st step) */
9401: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
9402: svect = (Z *)MALLOC(col*sizeof(Q));
9403: spsugar = (int *)MALLOC(nsp*sizeof(int));
9404: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9405: nd_sp(0,trace,sp,&spol);
9406: if ( !spol ) continue;
9407: nd_to_vect_q(s0vect,col,spol,svect);
9408: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
9409: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9410: if ( i < col ) {
9411: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
9412: for ( j = k = 0; j < col; j++ )
9413: if ( !rhead[j] ) v[k++] = svect[j];
9414: spsugar[sprow] = MAX(maxrs,SG(spol));
9415: sprow++;
9416: }
9417: /* nd_free(spol); */
9418: }
9419: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9420: if ( DP_Print ) {
1.5 noro 9421: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9422: fflush(asir_out);
9423: }
9424: /* free index arrays */
9425: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9426:
9427: /* elimination (2nd step) */
9428: colstat = (int *)MALLOC(spcol*sizeof(int));
9429: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
9430: w = (pointer *)MALLOC(rank*sizeof(pointer));
9431: for ( i = 0; i < rank; i++ ) {
9432: #if 0
9433: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9434: SG((NDV)w[rank-i-1]) = spsugar[i];
9435: #else
9436: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9437: SG((NDV)w[i]) = spsugar[i];
9438: #endif
9439: /* GCFREE(spmat[i]); */
9440: }
9441: #if 0
9442: qsort(w,rank,sizeof(NDV),
9443: (int (*)(const void *,const void *))ndv_compare);
9444: #endif
9445: r0 = 0;
9446: for ( i = 0; i < rank; i++ ) {
9447: NEXTNODE(r0,r); BDY(r) = w[i];
9448: }
9449: if ( r0 ) NEXT(r) = 0;
9450:
9451: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9452: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9453: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9454: if ( DP_Print ) {
1.5 noro 9455: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9456: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9457: nsp,nred,sprow,spcol,rank);
1.5 noro 9458: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9459: }
9460: return r0;
9461: }
9462:
9463: FILE *nd_write,*nd_read;
9464:
9465: void nd_send_int(int a) {
9466: write_int(nd_write,(unsigned int *)&a);
9467: }
9468:
9469: void nd_send_intarray(int *p,int len) {
9470: write_intarray(nd_write,(unsigned int *)p,len);
9471: }
9472:
9473: int nd_recv_int() {
9474: int a;
9475:
9476: read_int(nd_read,(unsigned int *)&a);
9477: return a;
9478: }
9479:
9480: void nd_recv_intarray(int *p,int len) {
9481: read_intarray(nd_read,(unsigned int *)p,len);
9482: }
9483:
9484: void nd_send_ndv(NDV p) {
9485: int len,i;
9486: NMV m;
9487:
9488: if ( !p ) nd_send_int(0);
9489: else {
9490: len = LEN(p);
9491: nd_send_int(len);
9492: m = BDY(p);
9493: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9494: nd_send_int(CM(m));
9495: nd_send_intarray((int *)DL(m),nd_wpd);
9496: }
9497: }
9498: }
9499:
9500: void nd_send_nd(ND p) {
9501: int len,i;
9502: NM m;
9503:
9504: if ( !p ) nd_send_int(0);
9505: else {
9506: len = LEN(p);
9507: nd_send_int(len);
9508: m = BDY(p);
9509: for ( i = 0; i < len; i++, m = NEXT(m) ) {
9510: nd_send_int(CM(m));
9511: nd_send_intarray((int *)DL(m),nd_wpd);
9512: }
9513: }
9514: }
9515:
9516: NDV nd_recv_ndv()
9517: {
9518: int len,i;
9519: NMV m,m0;
9520: NDV r;
9521:
9522: len = nd_recv_int();
9523: if ( !len ) return 0;
9524: else {
9525: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
9526: #if 0
9527: ndv_alloc += len*nmv_adv;
9528: #endif
9529: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9530: CM(m) = nd_recv_int();
9531: nd_recv_intarray((int *)DL(m),nd_wpd);
9532: }
9533: MKNDV(nd_nvar,m0,len,r);
9534: return r;
9535: }
9536: }
9537:
9538: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
9539: {
9540: int i,j,t,c,rank,inv;
9541: int *ci,*ri;
9542: Z dn;
9543: MAT m,nm;
9544:
9545: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
9546: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
9547: for ( i = 0; i < row; i++ )
9548: for ( j = 0; j < col; j++ )
9549: mat0[i][j] = 0;
9550: c = col-rank;
9551: for ( i = 0; i < rank; i++ ) {
9552: mat0[i][ri[i]] = dn;
9553: for ( j = 0; j < c; j++ )
9554: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
9555: }
9556: return rank;
9557: }
9558:
9559: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
9560: {
9561: int i,j,k,l,inv,a,rank,s;
9562: unsigned int *t,*pivot,*pk;
9563: unsigned int **mat;
9564: ND_pairs pair;
9565:
9566: mat = (unsigned int **)mat0;
9567: for ( rank = 0, j = 0; j < col; j++ ) {
9568: for ( i = rank; i < row; i++ )
9569: mat[i][j] %= md;
9570: for ( i = rank; i < row; i++ )
9571: if ( mat[i][j] )
9572: break;
9573: if ( i == row ) {
9574: colstat[j] = 0;
9575: continue;
9576: } else
9577: colstat[j] = 1;
9578: if ( i != rank ) {
9579: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9580: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9581: if ( spactive ) {
9582: pair = spactive[i]; spactive[i] = spactive[rank];
9583: spactive[rank] = pair;
9584: }
9585: }
9586: pivot = mat[rank];
9587: s = sugar[rank];
9588: inv = invm(pivot[j],md);
9589: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9590: if ( *pk ) {
9591: if ( *pk >= (unsigned int)md )
9592: *pk %= md;
9593: DMAR(*pk,inv,0,md,*pk)
9594: }
9595: for ( i = rank+1; i < row; i++ ) {
9596: t = mat[i];
9597: if ( (a = t[j]) != 0 ) {
9598: sugar[i] = MAX(sugar[i],s);
9599: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9600: }
9601: }
9602: rank++;
9603: }
9604: for ( j = col-1, l = rank-1; j >= 0; j-- )
9605: if ( colstat[j] ) {
9606: pivot = mat[l];
9607: s = sugar[l];
9608: for ( i = 0; i < l; i++ ) {
9609: t = mat[i];
9610: t[j] %= md;
9611: if ( (a = t[j]) != 0 ) {
9612: sugar[i] = MAX(sugar[i],s);
9613: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9614: }
9615: }
9616: l--;
9617: }
9618: for ( j = 0, l = 0; l < rank; j++ )
9619: if ( colstat[j] ) {
9620: t = mat[l];
9621: for ( k = j; k < col; k++ )
9622: if ( t[k] >= (unsigned int)md )
9623: t[k] %= md;
9624: l++;
9625: }
9626: return rank;
9627: }
9628:
1.40 noro 9629: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
9630: {
9631: int i,j,k,l,rank,s,imin;
9632: UINT inv;
9633: UINT a;
9634: UINT *t,*pivot,*pk;
9635: UINT *ck;
9636: UINT *ct;
9637: ND_pairs pair;
9638: SIG sg;
9639: int *used;
9640:
9641: used = (int *)MALLOC(row*sizeof(int));
9642: for ( j = 0; j < col; j++ ) {
9643: for ( i = 0; i < row; i++ )
9644: a = mat[i][j] %= md;
9645: for ( i = 0; i < row; i++ )
9646: if ( !used[i] && mat[i][j] ) break;
9647: if ( i == row ) {
9648: colstat[j] = 0;
9649: continue;
9650: } else {
9651: colstat[j] = 1;
9652: used[i] = 1;
9653: }
9654: /* column j is normalized */
9655: s = sugar[i];
9656: inv = invm(mat[i][j],md);
9657: /* normalize pivot row */
9658: for ( k = j, pk = mat[i]+j; k < col; k++, pk++, ck++ ) {
9659: DMAR(*pk,inv,0,md,*pk);
9660: }
9661: for ( k = i+1; k < row; k++ ) {
9662: if ( (a = mat[k][j]) != 0 ) {
9663: sugar[k] = MAX(sugar[k],s);
9664: red_by_vect(md,mat[k]+j,mat[i]+j,(int)(md-a),col-j);
9665: Nf4_red++;
9666: }
9667: }
9668: }
9669: rank = 0;
9670: for ( i = 0; i < row; i++ ) {
9671: for ( j = 0; j < col; j++ )
9672: if ( mat[i][j] ) break;
9673: if ( j == col ) sugar[i] = -1;
9674: else rank++;
9675: }
9676: return rank;
9677: }
9678:
1.1 noro 9679:
1.7 noro 9680: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 9681: {
1.7 noro 9682: int i,j,k,l,inv,a,rank,s;
9683: unsigned int *t,*pivot,*pk;
9684: unsigned int **mat;
9685:
9686: mat = (unsigned int **)mat0;
9687: for ( rank = 0, j = 0; j < col; j++ ) {
9688: for ( i = rank; i < row; i++ )
9689: if ( mat[i][j] )
9690: break;
9691: if ( i == row ) {
9692: colstat[j] = 0;
9693: continue;
9694: } else
9695: colstat[j] = 1;
9696: if ( i != rank ) {
9697: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9698: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9699: }
9700: pivot = mat[rank];
9701: s = sugar[rank];
9702: inv = _invsf(pivot[j]);
9703: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9704: if ( *pk )
9705: *pk = _mulsf(*pk,inv);
9706: for ( i = rank+1; i < row; i++ ) {
9707: t = mat[i];
9708: if ( (a = t[j]) != 0 ) {
9709: sugar[i] = MAX(sugar[i],s);
9710: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9711: }
9712: }
9713: rank++;
9714: }
9715: for ( j = col-1, l = rank-1; j >= 0; j-- )
9716: if ( colstat[j] ) {
9717: pivot = mat[l];
9718: s = sugar[l];
9719: for ( i = 0; i < l; i++ ) {
9720: t = mat[i];
9721: if ( (a = t[j]) != 0 ) {
9722: sugar[i] = MAX(sugar[i],s);
9723: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9724: }
9725: }
9726: l--;
9727: }
9728: return rank;
9729: }
1.1 noro 9730:
1.7 noro 9731: int ndv_ishomo(NDV p)
9732: {
9733: NMV m;
9734: int len,h;
1.1 noro 9735:
9736: if ( !p ) return 1;
9737: len = LEN(p);
9738: m = BDY(p);
9739: h = TD(DL(m));
9740: NMV_ADV(m);
9741: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 9742: if ( TD(DL(m)) != h ) {
9743: return 0;
9744: }
1.1 noro 9745: return 1;
9746: }
9747:
9748: void ndv_save(NDV p,int index)
9749: {
9750: FILE *s;
9751: char name[BUFSIZ];
9752: short id;
9753: int nv,sugar,len,n,i,td,e,j;
9754: NMV m;
9755: unsigned int *dl;
9756: int mpos;
9757:
9758: sprintf(name,"%s/%d",Demand,index);
9759: s = fopen(name,"w");
9760: savevl(s,0);
9761: if ( !p ) {
9762: saveobj(s,0);
9763: return;
9764: }
9765: id = O_DP;
9766: nv = NV(p);
9767: sugar = SG(p);
9768: len = LEN(p);
9769: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
9770: write_int(s,(unsigned int *)&len);
9771:
9772: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9773: saveobj(s,(Obj)CZ(m));
1.1 noro 9774: dl = DL(m);
9775: td = TD(dl);
9776: write_int(s,(unsigned int *)&td);
9777: for ( j = 0; j < nv; j++ ) {
9778: e = GET_EXP(dl,j);
9779: write_int(s,(unsigned int *)&e);
9780: }
9781: if ( nd_module ) {
9782: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
9783: }
9784: }
9785: fclose(s);
9786: }
9787:
9788: void nd_save_mod(ND p,int index)
9789: {
9790: FILE *s;
9791: char name[BUFSIZ];
9792: int nv,sugar,len,c;
9793: NM m;
9794:
9795: sprintf(name,"%s/%d",Demand,index);
9796: s = fopen(name,"w");
9797: if ( !p ) {
9798: len = 0;
9799: write_int(s,(unsigned int *)&len);
9800: fclose(s);
9801: return;
9802: }
9803: nv = NV(p);
9804: sugar = SG(p);
9805: len = LEN(p);
9806: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
9807: for ( m = BDY(p); m; m = NEXT(m) ) {
9808: c = CM(m); write_int(s,(unsigned int *)&c);
9809: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
9810: }
9811: fclose(s);
9812: }
9813:
9814: NDV ndv_load(int index)
9815: {
9816: FILE *s;
9817: char name[BUFSIZ];
9818: short id;
9819: int nv,sugar,len,n,i,td,e,j;
9820: NDV d;
9821: NMV m0,m;
9822: unsigned int *dl;
9823: Obj obj;
9824: int mpos;
9825:
9826: sprintf(name,"%s/%d",Demand,index);
9827: s = fopen(name,"r");
9828: if ( !s ) return 0;
9829:
9830: skipvl(s);
9831: read_short(s,(unsigned short *)&id);
9832: if ( !id ) return 0;
9833: read_int(s,(unsigned int *)&nv);
9834: read_int(s,(unsigned int *)&sugar);
9835: read_int(s,(unsigned int *)&len);
9836:
9837: m0 = m = MALLOC(len*nmv_adv);
9838: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9839: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 9840: dl = DL(m);
9841: ndl_zero(dl);
9842: read_int(s,(unsigned int *)&td); TD(dl) = td;
9843: for ( j = 0; j < nv; j++ ) {
9844: read_int(s,(unsigned int *)&e);
9845: PUT_EXP(dl,j,e);
9846: }
9847: if ( nd_module ) {
9848: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
9849: }
9850: if ( nd_blockmask ) ndl_weight_mask(dl);
9851: }
9852: fclose(s);
9853: MKNDV(nv,m0,len,d);
9854: SG(d) = sugar;
9855: return d;
9856: }
9857:
9858: ND nd_load_mod(int index)
9859: {
9860: FILE *s;
9861: char name[BUFSIZ];
9862: int nv,sugar,len,i,c;
9863: ND d;
9864: NM m0,m;
9865:
9866: sprintf(name,"%s/%d",Demand,index);
9867: s = fopen(name,"r");
9868: /* if the file does not exist, it means p[index]=0 */
9869: if ( !s ) return 0;
9870:
9871: read_int(s,(unsigned int *)&nv);
9872: if ( !nv ) { fclose(s); return 0; }
9873:
9874: read_int(s,(unsigned int *)&sugar);
9875: read_int(s,(unsigned int *)&len);
9876: for ( m0 = 0, i = 0; i < len; i++ ) {
9877: NEXTNM(m0,m);
9878: read_int(s,(unsigned int *)&c); CM(m) = c;
9879: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
9880: }
9881: NEXT(m) = 0;
9882: MKND(nv,m0,len,d);
9883: SG(d) = sugar;
9884: fclose(s);
9885: return d;
9886: }
9887:
9888: void nd_det(int mod,MAT f,P *rp)
9889: {
9890: VL fv,tv;
9891: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
9892: pointer **m;
9893: P **w;
9894: P mp,r;
9895: NDV **dm;
9896: NDV *t,*mi,*mj;
9897: NDV d,s,mij,mjj;
9898: ND u;
9899: NMV nmv;
9900: UINT *bound;
9901: PGeoBucket bucket;
9902: struct order_spec *ord;
9903: Z dq,dt,ds;
9904: Z mone;
9905: Z gn,qn,dn0,nm,dn;
9906:
9907: create_order_spec(0,0,&ord);
9908: nd_init_ord(ord);
9909: get_vars((Obj)f,&fv);
9910: if ( f->row != f->col )
9911: error("nd_det : non-square matrix");
9912: n = f->row;
9913: m = f->body;
9914: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
9915:
9916: if ( !nvar ) {
9917: if ( !mod )
9918: detp(CO,(P **)m,n,rp);
9919: else {
9920: w = (P **)almat_pointer(n,n);
9921: for ( i = 0; i < n; i++ )
9922: for ( j = 0; j < n; j++ )
9923: ptomp(mod,(P)m[i][j],&w[i][j]);
9924: detmp(CO,mod,w,n,&mp);
9925: mptop(mp,rp);
9926: }
9927: return;
9928: }
9929:
9930: if ( !mod ) {
9931: w = (P **)almat_pointer(n,n);
9932: dq = ONE;
9933: for ( i = 0; i < n; i++ ) {
9934: dn0 = ONE;
9935: for ( j = 0; j < n; j++ ) {
9936: if ( !m[i][j] ) continue;
9937: lgp(m[i][j],&nm,&dn);
1.6 noro 9938: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 9939: }
9940: if ( !UNIZ(dn0) ) {
9941: ds = dn0;
9942: for ( j = 0; j < n; j++ )
9943: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
9944: mulz(dq,ds,&dt); dq = dt;
9945: } else
9946: for ( j = 0; j < n; j++ )
9947: w[i][j] = (P)m[i][j];
9948: }
9949: m = (pointer **)w;
9950: }
9951:
9952: for ( i = 0, max = 1; i < n; i++ )
9953: for ( j = 0; j < n; j++ )
9954: for ( tv = fv; tv; tv = NEXT(tv) ) {
9955: e = getdeg(tv->v,(P)m[i][j]);
9956: max = MAX(e,max);
9957: }
9958: nd_setup_parameters(nvar,max);
9959: dm = (NDV **)almat_pointer(n,n);
9960: for ( i = 0, max = 1; i < n; i++ )
9961: for ( j = 0; j < n; j++ ) {
9962: dm[i][j] = ptondv(CO,fv,m[i][j]);
9963: if ( mod ) ndv_mod(mod,dm[i][j]);
9964: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
9965: }
9966: d = ptondv(CO,fv,(P)ONE);
9967: if ( mod ) ndv_mod(mod,d);
9968: chsgnz(ONE,&mone);
9969: for ( j = 0, sgn = 1; j < n; j++ ) {
9970: if ( DP_Print ) {
9971: fprintf(asir_out,".");
9972: }
9973: for ( i = j; i < n && !dm[i][j]; i++ );
9974: if ( i == n ) {
9975: *rp = 0;
9976: return;
9977: }
9978: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
9979: for ( k = j; k < n; k++ )
9980: for ( l = j; l < n; l++ )
9981: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
9982: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
9983: }
9984: if ( k0 != j ) {
9985: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
9986: sgn = -sgn;
9987: }
9988: if ( l0 != j ) {
9989: for ( k = j; k < n; k++ ) {
9990: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
9991: }
9992: sgn = -sgn;
9993: }
9994: bound = nd_det_compute_bound(dm,n,j);
9995: for ( k = 0; k < nd_nvar; k++ )
9996: if ( bound[k]*2 > nd_mask0 ) break;
9997: if ( k < nd_nvar )
9998: nd_det_reconstruct(dm,n,j,d);
9999:
10000: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
10001: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
10002: mi = dm[i]; mij = mi[j];
10003: if ( mod )
10004: ndv_mul_c(mod,mij,mod-1);
10005: else
10006: ndv_mul_c_q(mij,mone);
10007: for ( k = j+1; k < n; k++ ) {
10008: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
10009: bucket = create_pbucket();
10010: if ( mi[k] ) {
10011: nmv = BDY(mjj); len = LEN(mjj);
10012: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10013: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
10014: add_pbucket(mod,bucket,u);
10015: }
10016: }
10017: if ( mj[k] && mij ) {
10018: nmv = BDY(mij); len = LEN(mij);
10019: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
10020: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
10021: add_pbucket(mod,bucket,u);
10022: }
10023: }
10024: u = nd_quo(mod,bucket,d);
10025: mi[k] = ndtondv(mod,u);
10026: }
10027: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
10028: }
10029: d = mjj;
10030: }
10031: if ( DP_Print ) {
10032: fprintf(asir_out,"\n");
10033: }
10034: if ( sgn < 0 ) {
10035: if ( mod )
10036: ndv_mul_c(mod,d,mod-1);
10037: else
10038: ndv_mul_c_q(d,mone);
10039: }
10040: r = ndvtop(mod,CO,fv,d);
10041: if ( !mod && !UNIQ(dq) )
10042: divsp(CO,r,(P)dq,rp);
10043: else
10044: *rp = r;
10045: }
10046:
10047: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
10048: {
10049: NM mr,mr0;
10050: NM tnm;
10051: NMV m;
10052: UINT *d0,*dt,*dm;
10053: int c,n,td,i,c1,c2,len;
10054: Z q;
10055: ND r;
10056:
10057: if ( !p ) return 0;
10058: else {
10059: n = NV(p); m = BDY(p); len = LEN(p);
10060: d0 = DL(m0);
10061: td = TD(d);
10062: mr0 = 0;
10063: NEWNM(tnm);
10064: if ( mod ) {
10065: c = CM(m0);
10066: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10067: ndl_add(DL(m),d0,DL(tnm));
10068: if ( ndl_reducible(DL(tnm),d) ) {
10069: NEXTNM(mr0,mr);
10070: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
10071: ndl_copy(DL(tnm),DL(mr));
10072: }
10073: }
10074: } else {
1.6 noro 10075: q = CZ(m0);
1.1 noro 10076: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
10077: ndl_add(DL(m),d0,DL(tnm));
10078: if ( ndl_reducible(DL(tnm),d) ) {
10079: NEXTNM(mr0,mr);
1.6 noro 10080: mulz(CZ(m),q,&CZ(mr));
1.1 noro 10081: ndl_copy(DL(tnm),DL(mr));
10082: }
10083: }
10084: }
10085: if ( !mr0 )
10086: return 0;
10087: else {
10088: NEXT(mr) = 0;
10089: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10090: MKND(NV(p),mr0,len,r);
10091: SG(r) = SG(p) + TD(d0);
10092: return r;
10093: }
10094: }
10095: }
10096:
10097: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
10098: {
10099: int i,obpe,oadv,h,k,l;
10100: static NM prev_nm_free_list;
10101: EPOS oepos;
10102:
10103: obpe = nd_bpe;
10104: oadv = nmv_adv;
10105: oepos = nd_epos;
10106: if ( obpe < 2 ) nd_bpe = 2;
10107: else if ( obpe < 3 ) nd_bpe = 3;
10108: else if ( obpe < 4 ) nd_bpe = 4;
10109: else if ( obpe < 5 ) nd_bpe = 5;
10110: else if ( obpe < 6 ) nd_bpe = 6;
10111: else if ( obpe < 8 ) nd_bpe = 8;
10112: else if ( obpe < 10 ) nd_bpe = 10;
10113: else if ( obpe < 16 ) nd_bpe = 16;
10114: else if ( obpe < 32 ) nd_bpe = 32;
10115: else error("nd_det_reconstruct : exponent too large");
10116:
10117: nd_setup_parameters(nd_nvar,0);
10118: prev_nm_free_list = _nm_free_list;
10119: _nm_free_list = 0;
10120: for ( k = j; k < n; k++ )
10121: for (l = j; l < n; l++ )
10122: ndv_realloc(dm[k][l],obpe,oadv,oepos);
10123: ndv_realloc(d,obpe,oadv,oepos);
10124: prev_nm_free_list = 0;
10125: #if 0
10126: GC_gcollect();
10127: #endif
10128: }
10129:
10130: /* returns a UINT array containing degree bounds */
10131:
10132: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
10133: {
10134: UINT *d0,*d1,*d,*t,*r;
10135: int k,l,i;
10136:
10137: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
10138: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
10139: for ( k = j; k < n; k++ )
10140: for ( l = j; l < n; l++ )
10141: if ( dm[k][l] ) {
10142: d = ndv_compute_bound(dm[k][l]);
10143: for ( i = 0; i < nd_nvar; i++ )
10144: d0[i] = MAX(d0[i],d[i]);
10145: }
10146: return d0;
10147: }
10148:
10149: DL nd_separate_d(UINT *d,UINT *trans)
10150: {
10151: int n,td,i,e,j;
10152: DL a;
10153:
10154: ndl_zero(trans);
10155: td = 0;
10156: for ( i = 0; i < nd_ntrans; i++ ) {
10157: e = GET_EXP(d,i);
10158: PUT_EXP(trans,i,e);
10159: td += MUL_WEIGHT(e,i);
10160: }
10161: if ( nd_ntrans+nd_nalg < nd_nvar ) {
10162: /* homogenized */
10163: i = nd_nvar-1;
10164: e = GET_EXP(d,i);
10165: PUT_EXP(trans,i,e);
10166: td += MUL_WEIGHT(e,i);
10167: }
10168: TD(trans) = td;
10169: if ( nd_blockmask) ndl_weight_mask(trans);
10170: NEWDL(a,nd_nalg);
10171: td = 0;
10172: for ( i = 0; i < nd_nalg; i++ ) {
10173: j = nd_ntrans+i;
10174: e = GET_EXP(d,j);
10175: a->d[i] = e;
10176: td += e;
10177: }
10178: a->td = td;
10179: return a;
10180: }
10181:
10182: int nd_monic(int mod,ND *p)
10183: {
10184: UINT *trans,*t;
10185: DL alg;
10186: MP mp0,mp;
10187: NM m,m0,m1,ma0,ma,mb,mr0,mr;
10188: ND r;
10189: DL dl;
10190: DP nm;
10191: NDV ndv;
10192: DAlg inv,cd;
10193: ND s,c;
10194: Z l,mul;
10195: Z ln;
10196: int n,ntrans,i,e,td,is_lc,len;
10197: NumberField nf;
10198: struct oEGT eg0,eg1;
10199:
10200: if ( !(nf = get_numberfield()) )
10201: error("nd_monic : current_numberfield is not set");
10202:
10203: /* Q coef -> DAlg coef */
10204: NEWNM(ma0); ma = ma0;
10205: m = BDY(*p);
10206: is_lc = 1;
10207: while ( 1 ) {
10208: NEWMP(mp0); mp = mp0;
1.6 noro 10209: mp->c = (Obj)CZ(m);
1.1 noro 10210: mp->dl = nd_separate_d(DL(m),DL(ma));
10211: NEWNM(mb);
10212: for ( m = NEXT(m); m; m = NEXT(m) ) {
10213: alg = nd_separate_d(DL(m),DL(mb));
10214: if ( !ndl_equal(DL(ma),DL(mb)) )
10215: break;
1.6 noro 10216: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 10217: }
10218: NEXT(mp) = 0;
10219: MKDP(nd_nalg,mp0,nm);
10220: MKDAlg(nm,ONE,cd);
10221: if ( is_lc == 1 ) {
10222: /* if the lc is a rational number, we have nothing to do */
10223: if ( !mp0->dl->td )
10224: return 1;
10225:
10226: get_eg(&eg0);
10227: invdalg(cd,&inv);
10228: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
10229: /* check the validity of inv */
10230: if ( mod && !remqi((Q)inv->dn,mod) )
10231: return 0;
10232: CA(ma) = nf->one;
10233: is_lc = 0;
10234: ln = ONE;
10235: } else {
10236: muldalg(cd,inv,&CA(ma));
10237: lcmz(ln,CA(ma)->dn,&ln);
10238: }
10239: if ( m ) {
10240: NEXT(ma) = mb; ma = mb;
10241: } else {
10242: NEXT(ma) = 0;
10243: break;
10244: }
10245: }
10246: /* l = lcm(denoms) */
10247: l = ln;
10248: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 10249: divsz(l,CA(m)->dn,&mul);
1.1 noro 10250: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
10251: NEXTNM(mr0,mr);
1.6 noro 10252: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 10253: dl = mp->dl;
10254: td = TD(DL(m));
10255: ndl_copy(DL(m),DL(mr));
10256: for ( i = 0; i < nd_nalg; i++ ) {
10257: e = dl->d[i];
10258: PUT_EXP(DL(mr),i+nd_ntrans,e);
10259: td += MUL_WEIGHT(e,i+nd_ntrans);
10260: }
10261: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
10262: TD(DL(mr)) = td;
10263: if ( nd_blockmask) ndl_weight_mask(DL(mr));
10264: }
10265: }
10266: NEXT(mr) = 0;
10267: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
10268: MKND(NV(*p),mr0,len,r);
10269: /* XXX */
10270: SG(r) = SG(*p);
10271: nd_free(*p);
10272: *p = r;
10273: return 1;
10274: }
10275:
10276: NODE reverse_node(NODE n)
10277: {
10278: NODE t,t1;
10279:
10280: for ( t = 0; n; n = NEXT(n) ) {
10281: MKNODE(t1,BDY(n),t); t = t1;
10282: }
10283: return t;
10284: }
10285:
10286: P ndc_div(int mod,union oNDC a,union oNDC b)
10287: {
10288: union oNDC c;
10289: int inv,t;
10290:
10291: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 10292: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 10293: else if ( mod ) {
10294: inv = invm(b.m,mod);
10295: DMAR(a.m,inv,0,mod,t); c.m = t;
10296: } else if ( nd_vc )
10297: divsp(nd_vc,a.p,b.p,&c.p);
10298: else
10299: divsz(a.z,b.z,&c.z);
10300: return ndctop(mod,c);
10301: }
10302:
10303: P ndctop(int mod,union oNDC c)
10304: {
10305: Z q;
10306: int e;
10307: GFS gfs;
10308:
10309: if ( mod == -1 ) {
10310: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
10311: } else if ( mod == -2 ) {
1.10 noro 10312: q = c.z; return (P)q;
1.1 noro 10313: } else if ( mod > 0 ) {
1.6 noro 10314: STOZ(c.m,q); return (P)q;
1.1 noro 10315: } else
10316: return (P)c.p;
10317: }
10318:
10319: /* [0,0,0,cont] = p -> p/cont */
10320:
10321: void finalize_tracelist(int i,P cont)
10322: {
10323: LIST l;
10324: NODE node;
10325: Z iq;
10326:
10327: if ( !UNIQ(cont) ) {
10328: node = mknode(4,NULLP,NULLP,NULLP,cont);
10329: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
10330: nd_tracelist = node;
10331: }
1.6 noro 10332: STOZ(i,iq);
1.1 noro 10333: nd_tracelist = reverse_node(nd_tracelist);
10334: MKLIST(l,nd_tracelist);
10335: node = mknode(2,iq,l); MKLIST(l,node);
10336: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
10337: nd_alltracelist = node; nd_tracelist = 0;
10338: }
10339:
10340: void conv_ilist(int demand,int trace,NODE g,int **indp)
10341: {
10342: int n,i,j;
10343: int *ind;
10344: NODE t;
10345:
10346: n = length(g);
10347: ind = (int *)MALLOC(n*sizeof(int));
10348: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
10349: j = (long)BDY(t); ind[i] = j;
10350: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
10351: }
10352: if ( indp ) *indp = ind;
10353: }
10354:
1.30 noro 10355: NODE conv_ilist_s(int demand,int trace,int **indp)
10356: {
10357: int n,i,j;
10358: int *ind;
10359: NODE g0,g;
10360:
10361: n = nd_psn;
10362: ind = (int *)MALLOC(n*sizeof(int));
10363: g0 = 0;
10364: for ( i = 0; i < n; i++ ) {
10365: ind[i] = i;
10366: NEXTNODE(g0,g);
10367: BDY(g) = (pointer)(demand?ndv_load(i):(trace?nd_ps_trace[i]:nd_ps[i]));
10368: }
10369: if ( g0 ) NEXT(g) = 0;
10370: if ( indp ) *indp = ind;
10371: return g0;
10372: }
10373:
1.46 noro 10374: void parse_nd_option(VL vl,NODE opt)
1.1 noro 10375: {
1.38 noro 10376: NODE t,p,u;
1.1 noro 10377: int i,s,n;
1.38 noro 10378: char *key;
10379: Obj value;
1.46 noro 10380: VL oldvl;
1.1 noro 10381:
1.41 noro 10382: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_norb = 0; nd_gbblock = 0;
1.1 noro 10383: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
10384: nd_splist = 0; nd_check_splist = 0;
1.38 noro 10385: nd_sugarweight = 0; nd_f4red =0; nd_rank0 = 0;
10386: nd_f4_td = 0; nd_sba_f4step = 2; nd_sba_pot = 0; nd_sba_largelcm = 0;
1.41 noro 10387: nd_sba_dontsort = 0; nd_top = 0; nd_sba_redundant_check = 0;
1.46 noro 10388: nd_sba_syz = 0; nd_sba_modord = 0; nd_sba_inputisgb = 0;
1.39 noro 10389:
1.38 noro 10390: for ( t = opt; t; t = NEXT(t) ) {
10391: p = BDY((LIST)BDY(t));
10392: key = BDY((STRING)BDY(p));
10393: value = (Obj)BDY(NEXT(p));
10394: if ( !strcmp(key,"gentrace") )
10395: nd_gentrace = value?1:0;
10396: else if ( !strcmp(key,"gensyz") )
10397: nd_gensyz = value?1:0;
10398: else if ( !strcmp(key,"nora") )
10399: nd_nora = value?1:0;
1.41 noro 10400: else if ( !strcmp(key,"norb") )
10401: nd_norb = value?1:0;
1.38 noro 10402: else if ( !strcmp(key,"gbblock") ) {
10403: if ( value && OID(value) == O_LIST ) {
1.1 noro 10404: u = BDY((LIST)value);
1.38 noro 10405: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
1.1 noro 10406: for ( i = 0; u; u = NEXT(u) ) {
10407: p = BDY((LIST)BDY(u));
1.6 noro 10408: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
10409: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 10410: }
10411: nd_gbblock[i] = -1;
1.38 noro 10412: } else
10413: nd_gbblock = 0;
1.1 noro 10414: } else if ( !strcmp(key,"newelim") )
10415: nd_newelim = value?1:0;
10416: else if ( !strcmp(key,"intersect") )
10417: nd_intersect = value?1:0;
1.17 noro 10418: else if ( !strcmp(key,"syzgen") )
10419: nd_intersect = ZTOS((Q)value);
1.1 noro 10420: else if ( !strcmp(key,"lf") )
10421: nd_lf = value?1:0;
10422: else if ( !strcmp(key,"trace") ) {
1.38 noro 10423: if ( value ) {
10424: u = BDY((LIST)value);
10425: nd_nzlist = BDY((LIST)ARG2(u));
10426: nd_bpe = ZTOS((Q)ARG3(u));
10427: }
1.1 noro 10428: } else if ( !strcmp(key,"f4red") ) {
1.38 noro 10429: nd_f4red = ZTOS((Q)value);
1.1 noro 10430: } else if ( !strcmp(key,"rank0") ) {
1.38 noro 10431: nd_rank0 = value?1:0;
1.1 noro 10432: } else if ( !strcmp(key,"splist") ) {
1.38 noro 10433: nd_splist = value?1:0;
1.1 noro 10434: } else if ( !strcmp(key,"check_splist") ) {
10435: nd_check_splist = BDY((LIST)value);
10436: } else if ( !strcmp(key,"sugarweight") ) {
10437: u = BDY((LIST)value);
1.38 noro 10438: n = length(u);
10439: nd_sugarweight = MALLOC(n*sizeof(int));
1.1 noro 10440: for ( i = 0; i < n; i++, u = NEXT(u) )
1.38 noro 10441: nd_sugarweight[i] = ZTOS((Q)BDY(u));
10442: } else if ( !strcmp(key,"f4_td") ) {
10443: nd_f4_td = value?1:0;
10444: } else if ( !strcmp(key,"sba_f4step") ) {
10445: nd_sba_f4step = value?ZTOS((Q)value):0;
10446: } else if ( !strcmp(key,"sba_pot") ) {
1.44 noro 10447: nd_sba_pot = ZTOS((Q)value);
1.38 noro 10448: } else if ( !strcmp(key,"sba_largelcm") ) {
10449: nd_sba_largelcm = value?1:0;
1.39 noro 10450: } else if ( !strcmp(key,"sba_dontsort") ) {
10451: nd_sba_dontsort = value?1:0;
1.44 noro 10452: } else if ( !strcmp(key,"sba_syz") ) {
10453: nd_sba_syz = value?1:0;
1.46 noro 10454: } else if ( !strcmp(key,"sba_modord") ) {
10455: // value=[vlist,ordspec,weight]
10456: u = BDY((LIST)value);
10457: pltovl((LIST)ARG0(u),&oldvl);
10458: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10459: } else if ( !strcmp(key,"sba_gbinput") ) {
10460: nd_sba_inputisgb = value?1:0;
10461: if ( nd_sba_inputisgb != 0 ) {
10462: // value=[vlist,ordspec,weight]
10463: u = BDY((LIST)value);
10464: pltovl((LIST)ARG0(u),&oldvl);
10465: nd_sba_modord = create_comp_sig_spec(vl,oldvl,(Obj)ARG1(u),argc(u)==3?ARG2(u):0);
10466: }
1.41 noro 10467: } else if ( !strcmp(key,"sba_redundant_check") ) {
10468: nd_sba_redundant_check = value?1:0;
1.39 noro 10469: } else if ( !strcmp(key,"top") ) {
10470: nd_top = value?1:0;
1.1 noro 10471: }
1.38 noro 10472: }
1.44 noro 10473: if ( nd_sba_syz ) nd_sba_dontsort = 1;
1.1 noro 10474: }
10475:
10476: ND mdptond(DP d);
10477: ND nd_mul_nm(int mod,NM m0,ND p);
10478: ND nd_mul_nm_lf(NM m0,ND p);
10479: ND *btog(NODE ti,ND **p,int nb,int mod);
10480: ND btog_one(NODE ti,ND *p,int nb,int mod);
10481: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
10482: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
10483:
10484: /* d:monomial */
10485: ND mdptond(DP d)
10486: {
10487: NM m;
10488: ND r;
10489:
10490: if ( OID(d) == 1 )
10491: r = ptond(CO,CO,(P)d);
10492: else {
10493: NEWNM(m);
10494: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 10495: CZ(m) = (Z)BDY(d)->c;
1.1 noro 10496: NEXT(m) = 0;
10497: MKND(NV(d),m,1,r);
10498: }
10499: return r;
10500: }
10501:
10502: ND nd_mul_nm(int mod,NM m0,ND p)
10503: {
10504: UINT *d0;
10505: int c0,c1,c;
10506: NM tm,mr,mr0;
10507: ND r;
10508:
10509: if ( !p ) return 0;
10510: d0 = DL(m0);
10511: c0 = CM(m0);
10512: mr0 = 0;
10513: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10514: NEXTNM(mr0,mr);
10515: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
10516: ndl_add(d0,DL(tm),DL(mr));
10517: }
10518: NEXT(mr) = 0;
10519: MKND(NV(p),mr0,LEN(p),r);
10520: return r;
10521: }
10522:
10523: ND nd_mul_nm_lf(NM m0,ND p)
10524: {
10525: UINT *d0;
10526: Z c0,c1,c;
10527: NM tm,mr,mr0;
10528: ND r;
10529:
10530: if ( !p ) return 0;
10531: d0 = DL(m0);
10532: c0 = CZ(m0);
10533: mr0 = 0;
10534: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10535: NEXTNM(mr0,mr);
10536: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
10537: ndl_add(d0,DL(tm),DL(mr));
10538: }
10539: NEXT(mr) = 0;
10540: MKND(NV(p),mr0,LEN(p),r);
10541: return r;
10542: }
10543:
10544: ND *btog(NODE ti,ND **p,int nb,int mod)
10545: {
10546: PGeoBucket *r;
10547: int i,ci;
10548: NODE t,s;
10549: ND m,tp;
10550: ND *pi,*rd;
10551: P c;
10552:
10553: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10554: for ( i = 0; i < nb; i++ )
10555: r[i] = create_pbucket();
10556: for ( t = ti; t; t = NEXT(t) ) {
10557: s = BDY((LIST)BDY(t));
10558: if ( ARG0(s) ) {
10559: m = mdptond((DP)ARG2(s));
1.6 noro 10560: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10561: if ( (ci = ((MQ)c)->cont) != 0 ) {
10562: HCM(m) = ci;
1.6 noro 10563: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10564: for ( i = 0; i < nb; i++ ) {
10565: tp = nd_mul_nm(mod,BDY(m),pi[i]);
10566: add_pbucket(mod,r[i],tp);
10567: }
10568: }
10569: ci = 1;
10570: } else {
10571: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10572: ci = invm(ci,mod);
10573: }
10574: }
10575: rd = (ND *)MALLOC(nb*sizeof(ND));
10576: for ( i = 0; i < nb; i++ )
10577: rd[i] = normalize_pbucket(mod,r[i]);
10578: if ( ci != 1 )
10579: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
10580: return rd;
10581: }
10582:
10583: /* YYY */
10584: ND *btog_lf(NODE ti,ND **p,int nb)
10585: {
10586: PGeoBucket *r;
10587: int i;
10588: NODE t,s;
10589: ND m,tp;
10590: ND *pi,*rd;
10591: LM lm;
10592: Z lf,c;
10593:
10594: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10595: for ( i = 0; i < nb; i++ )
10596: r[i] = create_pbucket();
10597: for ( t = ti; t; t = NEXT(t) ) {
10598: s = BDY((LIST)BDY(t));
10599: if ( ARG0(s) ) {
10600: m = mdptond((DP)ARG2(s));
1.6 noro 10601: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 10602: if ( lm ) {
10603: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 10604: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10605: for ( i = 0; i < nb; i++ ) {
10606: tp = nd_mul_nm_lf(BDY(m),pi[i]);
10607: add_pbucket(-2,r[i],tp);
10608: }
10609: }
10610: c = ONE;
10611: } else {
10612: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
10613: }
10614: }
10615: rd = (ND *)MALLOC(nb*sizeof(ND));
10616: for ( i = 0; i < nb; i++ )
10617: rd[i] = normalize_pbucket(-2,r[i]);
10618: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
10619: return rd;
10620: }
10621:
10622: ND btog_one(NODE ti,ND *p,int nb,int mod)
10623: {
10624: PGeoBucket r;
10625: int i,ci,j;
10626: NODE t,s;
10627: ND m,tp;
10628: ND pi,rd;
10629: P c;
10630:
10631: r = create_pbucket();
10632: for ( t = ti; t; t = NEXT(t) ) {
10633: s = BDY((LIST)BDY(t));
10634: if ( ARG0(s) ) {
10635: m = mdptond((DP)ARG2(s));
1.6 noro 10636: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10637: if ( (ci = ((MQ)c)->cont) != 0 ) {
10638: HCM(m) = ci;
1.6 noro 10639: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 10640: if ( !pi ) {
10641: pi = nd_load_mod(j);
10642: tp = nd_mul_nm(mod,BDY(m),pi);
10643: nd_free(pi);
10644: add_pbucket(mod,r,tp);
10645: } else {
10646: tp = nd_mul_nm(mod,BDY(m),pi);
10647: add_pbucket(mod,r,tp);
10648: }
10649: }
10650: ci = 1;
10651: } else {
10652: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10653: ci = invm(ci,mod);
10654: }
10655: }
10656: rd = normalize_pbucket(mod,r);
10657: free_pbucket(r);
10658: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
10659: return rd;
10660: }
10661:
10662: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
10663:
10664: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
10665: {
10666: int i,j,n,m,nb,pi0,pi1,nvar;
10667: VL fv,tv,vv;
10668: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10669: ND **p;
10670: ND *c;
10671: ND u;
10672: P inv;
10673: MAT mat;
10674:
10675: if ( mod == -2 )
10676: return nd_btog_lf(f,v,ord,tlist,rp);
10677:
10678: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10679: parse_nd_option(vv,current_option);
1.1 noro 10680: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10681: switch ( ord->id ) {
10682: case 1:
10683: if ( ord->nv != nvar )
10684: error("nd_check : invalid order specification");
10685: break;
10686: default:
10687: break;
10688: }
10689: nd_init_ord(ord);
10690: #if 0
1.6 noro 10691: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10692: #else
10693: nd_bpe = 32;
10694: #endif
10695: nd_setup_parameters(nvar,0);
10696: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10697: intred = BDY((LIST)ARG3(BDY(tlist)));
10698: ind = BDY((LIST)ARG4(BDY(tlist)));
10699: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10700: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10701: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10702: if ( j > i ) i = j;
10703: }
10704: n = i+1;
10705: nb = length(BDY(f));
10706: p = (ND **)MALLOC(n*sizeof(ND *));
10707: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10708: pi = BDY((LIST)BDY(t));
1.6 noro 10709: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10710: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10711: ptomp(mod,(P)ARG2(pi),&inv);
10712: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10713: u = ptond(CO,vv,(P)ONE);
10714: HCM(u) = ((MQ)inv)->cont;
10715: c[pi1] = u;
10716: }
10717: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10718: printf("%d ",i); fflush(stdout);
10719: ti = BDY((LIST)BDY(t));
1.6 noro 10720: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10721: }
10722: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10723: printf("%d ",i); fflush(stdout);
10724: ti = BDY((LIST)BDY(t));
1.6 noro 10725: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10726: }
10727: m = length(ind);
10728: MKMAT(mat,nb,m);
10729: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10730: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10731: BDY(mat)[i][j] = ndtodp(mod,c[i]);
10732: return mat;
10733: }
10734:
10735: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
10736: {
10737: int i,j,n,m,nb,pi0,pi1,nvar;
10738: VL fv,tv,vv;
10739: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10740: ND **p;
10741: ND *c;
10742: ND u;
10743: MAT mat;
10744: LM lm;
10745: Z lf,inv;
10746:
10747: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10748: parse_nd_option(vv,current_option);
1.1 noro 10749: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10750: switch ( ord->id ) {
10751: case 1:
10752: if ( ord->nv != nvar )
10753: error("nd_check : invalid order specification");
10754: break;
10755: default:
10756: break;
10757: }
10758: nd_init_ord(ord);
10759: #if 0
1.6 noro 10760: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10761: #else
10762: nd_bpe = 32;
10763: #endif
10764: nd_setup_parameters(nvar,0);
10765: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10766: intred = BDY((LIST)ARG3(BDY(tlist)));
10767: ind = BDY((LIST)ARG4(BDY(tlist)));
10768: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10769: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10770: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10771: if ( j > i ) i = j;
10772: }
10773: n = i+1;
10774: nb = length(BDY(f));
10775: p = (ND **)MALLOC(n*sizeof(ND *));
10776: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10777: pi = BDY((LIST)BDY(t));
1.6 noro 10778: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10779: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10780: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
10781: u = ptond(CO,vv,(P)ONE);
10782: HCZ(u) = inv;
10783: c[pi1] = u;
10784: }
10785: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10786: printf("%d ",i); fflush(stdout);
10787: ti = BDY((LIST)BDY(t));
1.6 noro 10788: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10789: }
10790: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10791: printf("%d ",i); fflush(stdout);
10792: ti = BDY((LIST)BDY(t));
1.6 noro 10793: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10794: }
10795: m = length(ind);
10796: MKMAT(mat,nb,m);
10797: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10798: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10799: BDY(mat)[i][j] = ndtodp(-2,c[i]);
10800: return mat;
10801: }
10802:
10803: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
10804: LIST tlist,int pos,MAT *rp)
10805: {
10806: int i,j,n,m,nb,pi0,pi1,nvar;
10807: VL fv,tv,vv;
10808: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10809: ND *p;
10810: ND *c;
10811: ND u;
10812: P inv;
10813: VECT vect;
10814:
10815: if ( mod == -2 )
10816: error("nd_btog_one : not implemented yet for a large finite field");
10817:
10818: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10819: parse_nd_option(vv,current_option);
1.1 noro 10820: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10821: switch ( ord->id ) {
10822: case 1:
10823: if ( ord->nv != nvar )
10824: error("nd_check : invalid order specification");
10825: break;
10826: default:
10827: break;
10828: }
10829: nd_init_ord(ord);
10830: #if 0
1.6 noro 10831: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10832: #else
10833: nd_bpe = 32;
10834: #endif
10835: nd_setup_parameters(nvar,0);
10836: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10837: intred = BDY((LIST)ARG3(BDY(tlist)));
10838: ind = BDY((LIST)ARG4(BDY(tlist)));
10839: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10840: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10841: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10842: if ( j > i ) i = j;
10843: }
10844: n = i+1;
10845: nb = length(BDY(f));
10846: p = (ND *)MALLOC(n*sizeof(ND *));
10847: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10848: pi = BDY((LIST)BDY(t));
1.6 noro 10849: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10850: if ( pi1 == pos ) {
10851: ptomp(mod,(P)ARG2(pi),&inv);
10852: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10853: u = ptond(CO,vv,(P)ONE);
10854: HCM(u) = ((MQ)inv)->cont;
10855: p[pi0] = u;
10856: }
10857: }
10858: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10859: printf("%d ",i); fflush(stdout);
10860: ti = BDY((LIST)BDY(t));
1.6 noro 10861: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10862: if ( Demand ) {
10863: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10864: }
10865: }
10866: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10867: printf("%d ",i); fflush(stdout);
10868: ti = BDY((LIST)BDY(t));
1.6 noro 10869: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10870: if ( Demand ) {
10871: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10872: }
10873: }
10874: m = length(ind);
10875: MKVECT(vect,m);
10876: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 10877: u = p[ZTOS((Q)BDY(t))];
1.1 noro 10878: if ( !u ) {
1.6 noro 10879: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 10880: BDY(vect)[j] = ndtodp(mod,u);
10881: nd_free(u);
10882: } else
10883: BDY(vect)[j] = ndtodp(mod,u);
10884: }
10885: return vect;
10886: }
10887:
10888: void ndv_print_lf(NDV p)
10889: {
10890: NMV m;
10891: int i,len;
10892:
10893: if ( !p ) printf("0\n");
10894: else {
10895: len = LEN(p);
10896: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
10897: printf("+");
10898: mpz_out_str(asir_out,10,BDY(CZ(m)));
10899: printf("*");
10900: ndl_print(DL(m));
10901: }
10902: printf("\n");
10903: }
10904: }
10905:
10906: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
10907: {
10908: VL tv,fv,vv,vc,av;
10909: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
10910: int m,nocheck,nvar,mindex,e,max;
10911: NDV c;
10912: NMV a;
10913: P p,zp;
10914: Q dmy;
10915: EPOS oepos;
10916: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
10917: Alg alpha,dp;
10918: P poly;
10919: LIST f1,f2,zpl;
10920: Obj obj;
10921: NumberField nf;
10922: struct order_spec *ord1;
10923: struct oEGT eg_check,eg0,eg1;
10924: NODE tr,tl1,tl2,tl3,tl4;
10925: LIST l1,l2,l3,l4,l5;
10926: int *perm;
10927: int j,ret;
10928: NODE retn;
10929: Q jq,bpe;
10930:
10931: nd_module = 0;
10932: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
1.46 noro 10933: parse_nd_option(vv,current_option);
1.1 noro 10934: if ( nd_vc )
10935: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
10936: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10937: switch ( ord->id ) {
10938: case 1:
10939: if ( ord->nv != nvar )
10940: error("nd_f4_lf_trace : invalid order specification");
10941: break;
10942: default:
10943: break;
10944: }
10945:
10946: nd_ntrans = nvar;
10947: nd_nalg = 0;
10948:
10949: nocheck = 0;
10950: mindex = 0;
10951:
10952: /* do not use on-demand load/save */
10953: nd_demand = 0;
10954: m = trace > 1 ? trace : get_lprime(mindex);
10955: nd_init_ord(ord);
10956: mrank = 0;
10957: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
10958: for ( tv = vv; tv; tv = NEXT(tv) ) {
10959: if ( nd_module ) {
10960: s = BDY((LIST)BDY(t));
10961: trank = length(s);
10962: mrank = MAX(mrank,trank);
10963: for ( ; s; s = NEXT(s) ) {
10964: e = getdeg(tv->v,(P)BDY(s));
10965: max = MAX(e,max);
10966: }
10967: } else {
10968: e = getdeg(tv->v,(P)BDY(t));
10969: max = MAX(e,max);
10970: }
10971: }
10972: nd_setup_parameters(nvar,max);
10973: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
10974: ishomo = 1;
10975: /* XXX */
10976: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
10977: if ( nd_module ) {
10978: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
10979: } else {
10980: c = (pointer)ptondv(CO,vv,(P)BDY(t));
10981: }
10982: if ( ishomo )
10983: ishomo = ishomo && ndv_ishomo(c);
10984: if ( c ) {
10985: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
10986: ndv_mod(-2,c);
10987: NEXTNODE(in0,in); BDY(in) = (pointer)c;
10988: }
10989: }
10990: if ( in0 ) NEXT(in) = 0;
10991: if ( fd0 ) NEXT(fd) = 0;
10992: if ( !ishomo && homo ) {
10993: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
10994: c = (NDV)BDY(t); len = LEN(c);
10995: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
10996: wmax = MAX(TD(DL(a)),wmax);
10997: }
10998: homogenize_order(ord,nvar,&ord1);
10999: nd_init_ord(ord1);
11000: nd_setup_parameters(nvar+1,wmax);
11001: for ( t = fd0; t; t = NEXT(t) )
11002: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
11003: }
11004: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 11005: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 11006: if ( ret )
11007: cand = nd_f4_lf_trace_main(m,&perm);
11008: if ( !ret || !cand ) {
11009: *rp = 0; return;
11010: }
11011: if ( !ishomo && homo ) {
11012: /* dehomogenization */
11013: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
11014: nd_init_ord(ord);
11015: nd_setup_parameters(nvar,0);
11016: }
11017: cand = ndv_reducebase(cand,perm);
11018: cand = ndv_reduceall(-2,cand);
11019: cbpe = nd_bpe;
11020: get_eg(&eg0);
11021: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
11022: /* gbcheck : cand is a GB of Id(cand) ? */
11023: retn = nd_f4(-2,0,0);
11024: }
11025: if ( !retn ) {
11026: /* failure */
11027: *rp = 0; return;
11028: }
11029: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
11030: if ( DP_Print )
1.5 noro 11031: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 11032: /* dp->p */
11033: nd_bpe = cbpe;
11034: nd_setup_parameters(nd_nvar,0);
11035: for ( r = cand; r; r = NEXT(r) ) {
11036: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
11037: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
11038: }
11039: MKLIST(*rp,cand);
11040: }
11041:
11042: NODE nd_f4_lf_trace_main(int m,int **indp)
11043: {
11044: int i,nh,stat,index;
11045: NODE r,rm,g;
11046: ND_pairs d,l,l0,t;
11047: ND spol,red;
11048: NDV nf,redv,nfqv,nfv;
11049: NM s0,s;
11050: NODE rp0,srp0,nflist,nflist_lf;
11051: int nsp,nred,col,rank,len,k,j,a;
11052: UINT c;
11053: UINT **spmat;
11054: UINT *s0vect,*svect,*p,*v;
11055: int *colstat;
11056: IndArray *imat;
11057: int *rhead;
11058: int spcol,sprow;
11059: int sugar;
11060: PGeoBucket bucket;
11061: struct oEGT eg0,eg1,eg_f4;
11062:
11063: g = 0; d = 0;
11064: for ( i = 0; i < nd_psn; i++ ) {
11065: d = update_pairs(d,g,i,0);
11066: g = update_base(g,i);
11067: }
11068: while ( d ) {
11069: get_eg(&eg0);
11070: l = nd_minsugarp(d,&d);
11071: sugar = SG(l);
11072: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
11073: bucket = create_pbucket();
11074: stat = nd_sp_f4(m,0,l,bucket);
11075: if ( !stat ) {
11076: for ( t = l; NEXT(t); t = NEXT(t) );
11077: NEXT(t) = d; d = l;
11078: d = nd_reconstruct(1,d);
11079: continue;
11080: }
11081: if ( bucket->m < 0 ) continue;
11082: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
11083: if ( !col ) {
11084: for ( t = l; NEXT(t); t = NEXT(t) );
11085: NEXT(t) = d; d = l;
11086: d = nd_reconstruct(1,d);
11087: continue;
11088: }
11089: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
11090: if ( DP_Print )
1.5 noro 11091: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 11092: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
11093: if ( !l0 ) continue;
11094: l = l0;
11095:
11096: /* over LF */
11097: bucket = create_pbucket();
11098: stat = nd_sp_f4(-2,1,l,bucket);
11099: if ( !stat ) {
11100: for ( t = l; NEXT(t); t = NEXT(t) );
11101: NEXT(t) = d; d = l;
11102: d = nd_reconstruct(1,d);
11103: continue;
11104: }
11105: if ( bucket->m < 0 ) continue;
11106: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
11107: if ( !col ) {
11108: for ( t = l; NEXT(t); t = NEXT(t) );
11109: NEXT(t) = d; d = l;
11110: d = nd_reconstruct(1,d);
11111: continue;
11112: }
11113: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
11114: /* adding new bases */
11115: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
11116: nfv = (NDV)BDY(rm);
11117: nfqv = (NDV)BDY(r);
11118: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
11119: ndv_removecont(m,nfv);
11120: ndv_removecont(-2,nfqv);
1.24 noro 11121: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 11122: d = update_pairs(d,g,nh,0);
11123: g = update_base(g,nh);
11124: }
11125: if ( r || rm ) return 0;
11126: }
11127: conv_ilist(nd_demand,1,g,indp);
11128: return g;
11129: }
11130:
1.7 noro 11131: #if SIZEOF_LONG==8
11132:
11133: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
11134: {
11135: int j,k,len;
11136: UINT *p;
11137: UINT c;
11138: NDV r;
11139: NMV mr0,mr;
11140:
11141: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
11142: if ( !len ) return 0;
11143: else {
11144: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11145: #if 0
11146: ndv_alloc += nmv_adv*len;
11147: #endif
11148: mr = mr0;
11149: p = s0vect;
11150: for ( j = k = 0; j < col; j++, p += nd_wpd )
11151: if ( !rhead[j] ) {
11152: if ( (c = (UINT)vect[k++]) != 0 ) {
11153: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11154: }
11155: }
11156: MKNDV(nd_nvar,mr0,len,r);
11157: return r;
11158: }
11159: }
11160:
1.28 noro 11161: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
11162: {
11163: int j,k,len;
11164: UINT *p;
11165: UINT c;
11166: NDV r;
11167: NMV mr0,mr;
11168:
11169: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
11170: if ( !len ) return 0;
11171: else {
11172: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
11173: mr = mr0;
11174: p = s0vect;
11175: for ( j = k = 0; j < col; j++, p += nd_wpd )
11176: if ( (c = (UINT)vect[k++]) != 0 ) {
11177: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
11178: }
11179: MKNDV(nd_nvar,mr0,len,r);
11180: return r;
11181: }
11182: }
11183:
1.7 noro 11184: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
11185: {
11186: NM m;
1.11 noro 11187: UINT *t,*s,*u;
11188: int i,st,ed,md,prev,c;
1.7 noro 11189:
11190: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 11191: prev = 0;
11192: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
11193: t = DL(m);
11194: st = prev;
11195: ed = n;
11196: while ( ed > st ) {
11197: md = (st+ed)/2;
11198: u = s0+md*nd_wpd;
11199: c = DL_COMPARE(u,t);
11200: if ( c == 0 ) break;
11201: else if ( c > 0 ) st = md;
11202: else ed = md;
11203: }
11204: r[md] = (mp_limb_t)CM(m);
11205: prev = md;
1.7 noro 11206: }
11207: for ( i = 0; !r[i]; i++ );
11208: return i;
11209: }
11210:
11211: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
11212:
1.28 noro 11213: 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 11214: {
11215: int i,j,k,len,pos,prev;
11216: mp_limb_t a,c,c1,c2;
11217: IndArray ivect;
11218: unsigned char *ivc;
11219: unsigned short *ivs;
11220: unsigned int *ivi;
11221: NDV redv;
11222: NMV mr;
11223: NODE rp;
11224: int maxrs;
11225:
11226: for ( i = 0; i < col; i++ ) cvect[i] = 0;
11227: maxrs = 0;
11228: for ( i = 0; i < nred; i++ ) {
11229: ivect = imat[i];
11230: k = ivect->head;
11231: a = svect[k]; c = cvect[k];
11232: MOD128(a,c,m);
11233: svect[k] = a; cvect[k] = 0;
1.28 noro 11234: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 11235: Nf4_red++;
1.7 noro 11236: maxrs = MAX(maxrs,rp0[i]->sugar);
11237: c = m-c; redv = nd_ps[rp0[i]->index];
11238: len = LEN(redv); mr = BDY(redv);
11239: svect[k] = 0; prev = k;
11240: switch ( ivect->width ) {
11241: case 1:
11242: ivc = ivect->index.c;
11243: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11244: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 11245: c2 = svect[pos]+c1*c;
11246: if ( c2 < svect[pos] ) cvect[pos]++;
11247: svect[pos] = c2;
1.7 noro 11248: }
11249: break;
11250: case 2:
11251: ivs = ivect->index.s;
11252: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11253: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 11254: c2 = svect[pos]+c1*c;
11255: if ( c2 < svect[pos] ) cvect[pos]++;
11256: svect[pos] = c2;
1.7 noro 11257: }
11258: break;
11259: case 4:
11260: ivi = ivect->index.i;
11261: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
11262: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 11263: c2 = svect[pos]+c1*c;
11264: if ( c2 < svect[pos] ) cvect[pos]++;
11265: svect[pos] = c2;
1.7 noro 11266: }
11267: break;
11268: }
11269: }
11270: }
11271: for ( i = 0; i < col; i++ ) {
11272: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
11273: }
11274: return maxrs;
11275: }
11276:
11277: /* for Fp, 2^15=<p<2^29 */
11278:
11279: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11280: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
11281: {
11282: int spcol,sprow,a;
11283: int i,j,k,l,rank;
11284: NODE r0,r;
11285: ND_pairs sp;
11286: ND spol;
11287: mp_limb_t **spmat;
11288: mp_limb_t *svect,*cvect;
11289: mp_limb_t *v;
11290: int *colstat;
11291: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11292: int maxrs;
11293: int *spsugar;
11294: ND_pairs *spactive;
11295:
11296: spcol = col-nred;
11297: get_eg(&eg0);
11298: /* elimination (1st step) */
11299: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11300: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11301: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11302: spsugar = (int *)MALLOC(nsp*sizeof(int));
11303: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
11304: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11305: nd_sp(m,0,sp,&spol);
11306: if ( !spol ) continue;
11307: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 noro 11308: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 11309: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11310: if ( i < col ) {
11311: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
11312: for ( j = k = 0; j < col; j++ )
11313: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
11314: spsugar[sprow] = MAX(maxrs,SG(spol));
11315: if ( nz )
11316: spactive[sprow] = sp;
11317: sprow++;
11318: }
11319: nd_free(spol);
11320: }
1.12 noro 11321: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 11322: if ( DP_Print ) {
11323: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11324: fflush(asir_out);
11325: }
11326: /* free index arrays */
11327: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11328:
11329: /* elimination (2nd step) */
11330: colstat = (int *)MALLOC(spcol*sizeof(int));
11331: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
11332: r0 = 0;
11333: for ( i = 0; i < rank; i++ ) {
11334: NEXTNODE(r0,r); BDY(r) =
11335: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
11336: SG((NDV)BDY(r)) = spsugar[i];
11337: GCFREE(spmat[i]);
11338: }
11339: if ( r0 ) NEXT(r) = 0;
11340:
11341: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 11342: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 11343: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11344: if ( DP_Print ) {
11345: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11346: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11347: nsp,nred,sprow,spcol,rank);
11348: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11349: }
11350: if ( nz ) {
11351: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
11352: if ( rank > 0 ) {
11353: NEXT(spactive[rank-1]) = 0;
11354: *nz = spactive[0];
11355: } else
11356: *nz = 0;
11357: }
11358: return r0;
11359: }
11360:
11361: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
11362: {
11363: int i,j,k,l,rank,s;
11364: mp_limb_t inv;
11365: mp_limb_t a;
11366: UINT c;
11367: mp_limb_t *t,*pivot,*pk;
11368: UINT *ck;
11369: UINT **cmat;
11370: UINT *ct;
11371: ND_pairs pair;
11372:
11373: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11374: for ( i = 0; i < row; i++ ) {
11375: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11376: bzero(cmat[i],col*sizeof(UINT));
11377: }
11378:
11379: for ( rank = 0, j = 0; j < col; j++ ) {
11380: for ( i = rank; i < row; i++ ) {
11381: a = mat[i][j]; c = cmat[i][j];
11382: MOD128(a,c,md);
11383: mat[i][j] = a; cmat[i][j] = 0;
11384: }
11385: for ( i = rank; i < row; i++ )
11386: if ( mat[i][j] )
11387: break;
11388: if ( i == row ) {
11389: colstat[j] = 0;
11390: continue;
11391: } else
11392: colstat[j] = 1;
11393: if ( i != rank ) {
11394: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
11395: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
11396: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
11397: if ( spactive ) {
11398: pair = spactive[i]; spactive[i] = spactive[rank];
11399: spactive[rank] = pair;
11400: }
11401: }
11402: /* column j is normalized */
11403: s = sugar[rank];
11404: inv = invm((UINT)mat[rank][j],md);
11405: /* normalize pivot row */
11406: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
11407: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11408: }
11409: for ( i = rank+1; i < row; i++ ) {
11410: if ( (a = mat[i][j]) != 0 ) {
11411: sugar[i] = MAX(sugar[i],s);
11412: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 11413: Nf4_red++;
1.7 noro 11414: }
11415: }
11416: rank++;
11417: }
11418: for ( j = col-1, l = rank-1; j >= 0; j-- )
11419: if ( colstat[j] ) {
11420: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
11421: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
11422: }
11423: s = sugar[l];
11424: for ( i = 0; i < l; i++ ) {
11425: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
11426: if ( a ) {
11427: sugar[i] = MAX(sugar[i],s);
11428: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 11429: Nf4_red++;
1.7 noro 11430: }
11431: }
11432: l--;
11433: }
11434: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11435: GCFREE(cmat);
11436: return rank;
11437: }
11438:
1.28 noro 11439: 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)
11440: {
11441: int i,j,k,l,rank,s,imin;
11442: mp_limb_t inv;
11443: mp_limb_t a;
11444: UINT c;
11445: mp_limb_t *t,*pivot,*pk;
11446: UINT *ck;
11447: UINT **cmat;
11448: UINT *ct;
11449: ND_pairs pair;
11450: SIG sg;
1.31 noro 11451: int *used;
1.28 noro 11452:
1.31 noro 11453: used = (int *)MALLOC(row*sizeof(int));
1.28 noro 11454: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11455: for ( i = 0; i < row; i++ ) {
11456: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11457: bzero(cmat[i],col*sizeof(UINT));
11458: }
11459:
1.31 noro 11460: for ( j = 0; j < col; j++ ) {
11461: for ( i = 0; i < row; i++ ) {
1.28 noro 11462: a = mat[i][j]; c = cmat[i][j];
11463: MOD128(a,c,md);
11464: mat[i][j] = a; cmat[i][j] = 0;
11465: }
1.31 noro 11466: for ( i = 0; i < row; i++ )
11467: if ( !used[i] && mat[i][j] ) break;
11468: if ( i == row ) {
1.28 noro 11469: colstat[j] = 0;
11470: continue;
1.31 noro 11471: } else {
1.28 noro 11472: colstat[j] = 1;
1.31 noro 11473: used[i] = 1;
1.28 noro 11474: }
11475: /* column j is normalized */
1.31 noro 11476: s = sugar[i];
11477: inv = invm((UINT)mat[i][j],md);
1.28 noro 11478: /* normalize pivot row */
1.31 noro 11479: for ( k = j, pk = mat[i]+j, ck = cmat[i]+j; k < col; k++, pk++, ck++ ) {
1.28 noro 11480: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11481: }
1.31 noro 11482: for ( k = i+1; k < row; k++ ) {
11483: if ( (a = mat[k][j]) != 0 ) {
11484: sugar[k] = MAX(sugar[k],s);
11485: red_by_vect64(md,mat[k]+j,cmat[k]+j,mat[i]+j,(int)(md-a),col-j);
1.28 noro 11486: Nf4_red++;
11487: }
11488: }
11489: }
1.31 noro 11490: rank = 0;
11491: for ( i = 0; i < row; i++ ) {
11492: for ( j = 0; j < col; j++ )
11493: if ( mat[i][j] ) break;
11494: if ( j == col ) sugar[i] = -1;
11495: else rank++;
11496: }
1.28 noro 11497: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11498: GCFREE(cmat);
11499: return rank;
11500: }
11501:
11502: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11503: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
11504: {
11505: int spcol,sprow,a;
11506: int i,j,k,l,rank;
11507: NODE r0,r;
11508: ND_pairs sp;
11509: ND spol;
11510: mp_limb_t **spmat;
11511: mp_limb_t *svect,*cvect;
11512: mp_limb_t *v;
11513: int *colstat;
11514: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11515: int maxrs;
11516: int *spsugar;
11517: ND_pairs *spactive;
11518: SIG *spsig;
11519:
11520: get_eg(&eg0);
11521: /* elimination (1st step) */
11522: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11523: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11524: spsugar = (int *)MALLOC(nsp*sizeof(int));
11525: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
11526: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11527: nd_sp(m,0,sp,&spol);
11528: if ( !spol ) {
1.29 noro 11529: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11530: continue;
11531: }
11532: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11533: nd_to_vect64(m,s0vect,col,spol,svect);
11534: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
11535: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11536: if ( i < col ) {
11537: spmat[sprow] = svect;
11538: spsugar[sprow] = MAX(maxrs,SG(spol));
11539: spsig[sprow] = sp->sig;
11540: sprow++;
11541: } else {
1.29 noro 11542: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11543: }
11544: nd_free(spol);
11545: }
11546: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
11547: if ( DP_Print ) {
11548: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11549: fflush(asir_out);
11550: }
11551: /* free index arrays */
11552: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11553:
11554: /* elimination (2nd step) */
11555: colstat = (int *)MALLOC(col*sizeof(int));
11556: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
11557: r0 = 0;
1.31 noro 11558: for ( i = 0; i < sprow; i++ ) {
11559: if ( spsugar[i] >= 0 ) {
11560: NEXTNODE(r0,r);
11561: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
11562: SG((NDV)BDY(r)) = spsugar[i];
11563: ((NDV)BDY(r))->sig = spsig[i];
11564: } else
11565: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
1.28 noro 11566: GCFREE(spmat[i]);
11567: }
11568: if ( r0 ) NEXT(r) = 0;
11569: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
11570: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11571: if ( DP_Print ) {
11572: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11573: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11574: nsp,nred,sprow,col,rank);
11575: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11576: }
11577: return r0;
11578: }
1.40 noro 11579: #endif
1.28 noro 11580:
11581: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
11582: {
11583: IndArray *imat;
11584: int nsp,nred,i,start;
11585: int *rhead;
11586: NODE r0,rp;
11587: ND_pairs sp;
11588: NM_ind_pair *rvect;
11589: UINT *s;
11590: int *s0hash;
11591: struct oEGT eg0,eg1,eg_conv;
11592:
11593: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
11594: nred = length(rp0);
11595: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
11596: rhead = (int *)MALLOC(col*sizeof(int));
11597: for ( i = 0; i < col; i++ ) rhead[i] = 0;
11598:
11599: /* construction of index arrays */
11600: get_eg(&eg0);
11601: if ( DP_Print ) {
11602: fprintf(asir_out,"%dx%d,",nsp+nred,col);
11603: fflush(asir_out);
11604: }
11605: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
11606: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
11607: rvect[i] = (NM_ind_pair)BDY(rp);
11608: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
11609: rhead[imat[i]->head] = 1;
11610: start = imat[i]->head;
11611: }
11612: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
11613: if ( DP_Print ) {
11614: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
11615: fflush(asir_out);
11616: }
11617: if ( m > 0 )
1.40 noro 11618: #if SIZEOF_LONG==8
1.28 noro 11619: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
1.40 noro 11620: #else
11621: r0 = nd_f4_red_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
11622: #endif
1.28 noro 11623: else
11624: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
11625: error("nd_f4_red_q_main_s : not implemented yet");
11626: return r0;
11627: }
11628:
11629: INLINE int ndl_find_reducer_minsig(UINT *dg)
11630: {
11631: RHist r;
11632: int i,singular,ret,d,k,imin;
11633: SIG t;
11634: static int wpd,nvar;
11635: static SIG quo,quomin;
11636: static UINT *tmp;
11637:
11638: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
11639: if ( wpd != nd_wpd ) {
11640: wpd = nd_wpd;
11641: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
11642: }
11643: #if 0
11644: d = ndl_hash_value(dg);
11645: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
11646: if ( ndl_equal(dg,DL(r)) ) {
11647: return r->index;
11648: }
11649: }
11650: #endif
11651: imin = -1;
11652: for ( i = 0; i < nd_psn; i++ ) {
11653: r = nd_psh[i];
11654: if ( ndl_reducible(dg,DL(r)) ) {
11655: ndl_sub(dg,DL(r),tmp);
11656: _ndltodl(tmp,DL(quo));
11657: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
11658: quo->pos = nd_psh[i]->sig->pos;
11659: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
11660: t = quo; quo = quomin; quomin = t;
11661: imin = i;
11662: }
11663: }
11664: }
11665: if ( imin == -1 ) return nd_psn;
11666: else {
11667: #if 0
11668: nd_append_red(dg,i);
11669: #endif
11670: return imin;
11671: }
11672: }
11673:
11674: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
11675: {
11676: NODE rp0,rp;
11677: NM mul,head,s0,s;
11678: int index,col,i,sugar;
11679: RHist h;
11680: UINT *s0v,*p;
11681: NM_ind_pair pair;
11682: ND red;
11683: NDV *ps;
11684: SIG sig;
11685:
11686: s0 = 0; rp0 = 0; col = 0;
11687: if ( nd_demand )
11688: ps = trace?nd_ps_trace_sym:nd_ps_sym;
11689: else
11690: ps = trace?nd_ps_trace:nd_ps;
11691: while ( 1 ) {
11692: head = remove_head_pbucket_symbolic(bucket);
11693: if ( !head ) break;
11694: if ( !s0 ) s0 = head;
11695: else NEXT(s) = head;
11696: s = head;
11697: index = ndl_find_reducer_minsig(DL(head));
11698: if ( index >= 0 && index < nd_psn ) {
11699: h = nd_psh[index];
11700: NEWNM(mul);
11701: ndl_sub(DL(head),DL(h),DL(mul));
11702: if ( ndl_check_bound2(index,DL(mul)) )
11703: return 0;
11704: sugar = TD(DL(mul))+SG(ps[index]);
11705: NEWSIG(sig);
11706: _ndltodl(DL(mul),DL(sig));
11707: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
11708: sig->pos = nd_psh[index]->sig->pos;
11709: MKNM_ind_pair(pair,mul,index,sugar,sig);
11710: red = ndv_mul_nm_symbolic(mul,ps[index]);
11711: add_pbucket_symbolic(bucket,nd_remove_head(red));
11712: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
11713: }
11714: col++;
11715: }
11716: if ( rp0 ) NEXT(rp) = 0;
11717: NEXT(s) = 0;
11718: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
11719: for ( i = 0, p = s0v, s = s0; i < col;
11720: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
11721: *s0vect = s0v;
11722: *r = rp0;
11723:
11724: return col;
11725: }
11726:
11727: NODE nd_sba_f4(int m,int **indp)
11728: {
1.34 noro 11729: int i,nh,stat,index,f4red,f4step;
1.33 noro 11730: int col,rank,len,k,j,a,sugar,nbase,psugar,ms;
11731: NODE r,g,rp0,nflist;
1.41 noro 11732: ND_pairs d,l,t,l1;
1.33 noro 11733: ND h,nf;
11734: NDV nfv;
11735: union oNDC hc;
11736: UINT *s0vect;
1.28 noro 11737: UINT c;
11738: PGeoBucket bucket;
1.33 noro 11739: NODE *syzlist;
11740: SIG sig;
1.28 noro 11741: struct oEGT eg0,eg1,eg_f4;
1.33 noro 11742: struct oEGT eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.28 noro 11743:
11744: Nf4_red=0;
1.30 noro 11745: d = 0;
1.29 noro 11746: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.28 noro 11747: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 11748: d = update_pairs_s(d,i,syzlist);
1.28 noro 11749: }
1.30 noro 11750: nd_nbase = nd_psn;
1.28 noro 11751: f4red = 1;
1.33 noro 11752: psugar = 0;
1.34 noro 11753: f4step = 0;
1.28 noro 11754: while ( d ) {
1.33 noro 11755: for ( t = d, ms = SG(d); t; t = NEXT(t) )
11756: if ( SG(t) < ms ) ms = SG(t);
1.38 noro 11757: if ( ms == psugar && f4step >= nd_sba_f4step ) {
1.33 noro 11758: again:
11759: l = d; d = d->next;
1.41 noro 11760: #if 0
1.33 noro 11761: if ( small_lcm(l) ) {
11762: if ( DP_Print ) fprintf(asir_out,"M");
11763: continue;
11764: }
11765: sig = l->sig;
11766: stat = nd_sp(m,0,l,&h);
1.41 noro 11767: #else
11768: l1 = find_smallest_lcm(l);
11769: if ( l1 == 0 ) {
11770: if ( DP_Print ) fprintf(asir_out,"M");
11771: continue;
11772: }
11773: sig = l1->sig;
11774: stat = nd_sp(m,0,l1,&h);
11775: #endif
1.33 noro 11776: if ( !stat ) {
11777: NEXT(l) = d; d = l;
11778: d = nd_reconstruct(0,d);
11779: goto again;
11780: }
11781: get_eg(&eg1);
11782: #if USE_GEOBUCKET
1.39 noro 11783: 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 11784: #else
1.39 noro 11785: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 11786: #endif
11787: get_eg(&eg2);
11788: if ( !stat ) {
11789: NEXT(l) = d; d = l;
11790: d = nd_reconstruct(0,d);
11791: goto again;
11792: } else if ( stat == -1 ) {
11793: if ( DP_Print ) { printf("S"); fflush(stdout); }
11794: FREENDP(l);
11795: } else if ( nf ) {
11796: if ( DP_Print ) { printf("+"); fflush(stdout); }
11797: add_eg(&eg_nf,&eg1,&eg2);
11798: hc = HCU(nf);
11799: nd_removecont(m,nf);
11800: nfv = ndtondv(m,nf); nd_free(nf);
11801: nh = ndv_newps(m,nfv,0);
11802:
1.30 noro 11803: d = update_pairs_s(d,nh,syzlist);
11804: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.33 noro 11805: FREENDP(l);
1.28 noro 11806: } else {
1.33 noro 11807: add_eg(&eg_nfzero,&eg1,&eg2);
11808: // syzygy
11809: get_eg(&eg1);
11810: d = remove_spair_s(d,sig);
11811: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 11812: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.33 noro 11813: if ( DP_Print ) { printf("."); fflush(stdout); }
11814: FREENDP(l);
11815: }
11816: } else {
1.34 noro 11817: if ( ms != psugar ) f4step = 1;
11818: else f4step++;
1.33 noro 11819: again2:
11820: psugar = ms;
11821: l = nd_minsugarp_s(d,&d);
11822: sugar = nd_sugarweight?d->sugar2:SG(d);
11823: bucket = create_pbucket();
11824: stat = nd_sp_f4(m,0,l,bucket);
11825: if ( !stat ) {
11826: for ( t = l; NEXT(t); t = NEXT(t) );
11827: NEXT(t) = d; d = l;
11828: d = nd_reconstruct(0,d);
11829: goto again2;
11830: }
11831: if ( bucket->m < 0 ) continue;
11832: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
11833: if ( !col ) {
1.37 noro 11834: for ( t = l; NEXT(t); t = NEXT(t) )
11835: ;
11836: NEXT(t) = d; d = l;
1.33 noro 11837: d = nd_reconstruct(0,d);
11838: goto again2;
11839: }
1.34 noro 11840: if ( DP_Print ) fprintf(asir_out,"\nsugar=%d,",psugar);
1.33 noro 11841: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,syzlist);
11842: /* adding new bases */
11843: for ( r = nflist; r; r = NEXT(r) ) {
11844: nfv = (NDV)BDY(r);
1.38 noro 11845: if ( nd_f4_td ) SG(nfv) = nd_tdeg(nfv);
1.33 noro 11846: ndv_removecont(m,nfv);
11847: nh = ndv_newps(m,nfv,0);
11848: d = update_pairs_s(d,nh,syzlist);
11849: nd_sba_pos[nfv->sig->pos] = append_one(nd_sba_pos[nfv->sig->pos],nh);
11850: }
11851: for ( i = 0; i < nd_nbase; i++ )
11852: for ( r = syzlist[i]; r; r = NEXT(r) )
11853: d = remove_spair_s(d,(SIG)BDY(r));
11854: d = remove_large_lcm(d);
11855: if ( DP_Print ) {
1.34 noro 11856: fprintf(asir_out,"f4red=%d,gblen=%d",f4red,nd_psn); fflush(asir_out);
1.33 noro 11857: }
11858: f4red++;
1.28 noro 11859: }
11860: }
11861: if ( DP_Print ) {
1.34 noro 11862: fprintf(asir_out,"\nnumber of red=%d,",Nf4_red);
1.28 noro 11863: }
1.30 noro 11864: g = conv_ilist_s(nd_demand,0,indp);
1.28 noro 11865: return g;
11866: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>