Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.40
1.40 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.39 2020/10/29 01:50:35 noro Exp $ */
1.1 noro 2:
3: #include "nd.h"
4:
1.11 noro 5: int Nnd_add,Nf4_red;
1.12 noro 6: struct oEGT eg_search,f4_symb,f4_conv,f4_elim1,f4_elim2;
1.1 noro 7:
8: int diag_period = 6;
9: int weight_check = 1;
10: int (*ndl_compare_function)(UINT *a1,UINT *a2);
1.21 noro 11: /* for general module order */
1.19 noro 12: int (*ndl_base_compare_function)(UINT *a1,UINT *a2);
1.21 noro 13: int (*dl_base_compare_function)(int nv,DL a,DL b);
14: int nd_base_ordtype;
1.1 noro 15: int nd_dcomp;
16: int nd_rref2;
17: NM _nm_free_list;
18: ND _nd_free_list;
19: ND_pairs _ndp_free_list;
20: NODE nd_hcf;
1.35 noro 21: int Nsyz,Nsamesig;
1.1 noro 22:
23: Obj nd_top_weight;
24:
25: static NODE nd_subst;
26: static VL nd_vc;
27: static int nd_ntrans;
28: static int nd_nalg;
29: #if 0
30: static int ndv_alloc;
31: #endif
32: #if 1
33: static int nd_f4_nsp=0x7fffffff;
34: #else
35: static int nd_f4_nsp=50;
36: #endif
37: static double nd_scale=2;
38: static UINT **nd_bound;
39: static struct order_spec *nd_ord;
40: static EPOS nd_epos;
41: static BlockMask nd_blockmask;
42: static int nd_nvar;
43: static int nd_isrlex;
44: static int nd_epw,nd_bpe,nd_wpd,nd_exporigin;
45: static UINT nd_mask[32];
46: static UINT nd_mask0,nd_mask1;
47:
48: static NDV *nd_ps;
49: static NDV *nd_ps_trace;
50: static NDV *nd_ps_sym;
51: static NDV *nd_ps_trace_sym;
52: static RHist *nd_psh;
1.30 noro 53: static int nd_psn,nd_pslen,nd_nbase;
1.1 noro 54: static RHist *nd_red;
55: static int *nd_work_vector;
56: static int **nd_matrix;
57: static int nd_matrix_len;
58: static struct weight_or_block *nd_worb;
59: static int nd_worb_len;
60: static int nd_found,nd_create,nd_notfirst;
61: static int nmv_adv;
62: static int nd_demand;
1.21 noro 63: static int nd_module,nd_module_ordtype,nd_mpos,nd_pot_nelim;
1.1 noro 64: static int nd_module_rank,nd_poly_weight_len;
65: static int *nd_poly_weight,*nd_module_weight;
66: static NODE nd_tracelist;
67: static NODE nd_alltracelist;
68: static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect,nd_lf;
1.39 noro 69: static int nd_f4_td,nd_sba_f4step,nd_sba_pot,nd_sba_largelcm,nd_sba_dontsort;
70: static int nd_top;
1.1 noro 71: static int *nd_gbblock;
72: static NODE nd_nzlist,nd_check_splist;
73: static int nd_splist;
74: static int *nd_sugarweight;
75: static int nd_f4red,nd_rank0,nd_last_nonzero;
1.27 noro 76: static DL *nd_sba_hm;
1.29 noro 77: static NODE *nd_sba_pos;
1.1 noro 78:
79: NumberField get_numberfield();
80: UINT *nd_det_compute_bound(NDV **dm,int n,int j);
81: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d);
82: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr);
83: int nd_monic(int m,ND *p);
84: NDV plain_vect_to_ndv_q(Z *mat,int col,UINT *s0vect);
85: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank);
86: NDV pltondv(VL vl,VL dvl,LIST p);
87: void pltozpl(LIST l,Q *cont,LIST *pp);
88: void ndl_max(UINT *d1,unsigned *d2,UINT *d);
89: void nmtodp(int mod,NM m,DP *r);
1.15 noro 90: void ndltodp(UINT *d,DP *r);
1.1 noro 91: NODE reverse_node(NODE n);
92: P ndc_div(int mod,union oNDC a,union oNDC b);
93: P ndctop(int mod,union oNDC c);
94: void finalize_tracelist(int i,P cont);
95: void conv_ilist(int demand,int trace,NODE g,int **indp);
96: void parse_nd_option(NODE opt);
97: void dltondl(int n,DL dl,UINT *r);
98: DP ndvtodp(int mod,NDV p);
99: DP ndtodp(int mod,ND p);
1.16 noro 100: DPM ndvtodpm(int mod,NDV p);
101: NDV dpmtondv(int mod,DPM p);
102: int dpm_getdeg(DPM p,int *rank);
103: void dpm_ptozp(DPM p,Z *cont,DPM *r);
104: int compdmm(int nv,DMM a,DMM b);
1.1 noro 105:
106: void Pdp_set_weight(NODE,VECT *);
107: void Pox_cmo_rpc(NODE,Obj *);
108:
109: ND nd_add_lf(ND p1,ND p2);
110: void nd_mul_c_lf(ND p,Z mul);
111: void ndv_mul_c_lf(NDV p,Z mul);
112: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
113: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
114: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
115: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
116: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
117: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred);
118: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat);
1.40 ! noro 119: 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 120: NODE nd_f4_lf_trace_main(int m,int **indp);
121: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp);
122:
123: extern int lf_lazy;
124: extern Z current_mod_lf;
125:
126: extern int Denominator,DP_Multiple,MaxDeg;
127:
128: #define BLEN (8*sizeof(unsigned long))
129:
130: typedef struct matrix {
131: int row,col;
132: unsigned long **a;
133: } *matrix;
134:
135:
136: void nd_free_private_storage()
137: {
138: _nm_free_list = 0;
139: _ndp_free_list = 0;
140: #if 0
141: GC_gcollect();
142: #endif
143: }
144:
145: void _NM_alloc()
146: {
147: NM p;
148: int i;
149:
150: for ( i = 0; i < 1024; i++ ) {
151: p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
152: p->next = _nm_free_list; _nm_free_list = p;
153: }
154: }
155:
156: matrix alloc_matrix(int row,int col)
157: {
158: unsigned long **a;
159: int i,len,blen;
160: matrix mat;
161:
162: mat = (matrix)MALLOC(sizeof(struct matrix));
163: mat->row = row;
164: mat->col = col;
165: mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *));
166: return mat;
167: }
168:
169:
170: void _ND_alloc()
171: {
172: ND p;
173: int i;
174:
175: for ( i = 0; i < 1024; i++ ) {
176: p = (ND)MALLOC(sizeof(struct oND));
177: p->body = (NM)_nd_free_list; _nd_free_list = p;
178: }
179: }
180:
181: void _NDP_alloc()
182: {
183: ND_pairs p;
184: int i;
185:
186: for ( i = 0; i < 1024; i++ ) {
187: p = (ND_pairs)MALLOC(sizeof(struct oND_pairs)
188: +(nd_wpd-1)*sizeof(UINT));
189: p->next = _ndp_free_list; _ndp_free_list = p;
190: }
191: }
192:
193: INLINE int nd_length(ND p)
194: {
195: NM m;
196: int i;
197:
198: if ( !p )
199: return 0;
200: else {
201: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
202: return i;
203: }
204: }
205:
206: extern int dp_negative_weight;
207:
208: INLINE int ndl_reducible(UINT *d1,UINT *d2)
209: {
210: UINT u1,u2;
211: int i,j;
212:
213: if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
214:
215: if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0;
216: #if USE_UNROLL
217: switch ( nd_bpe ) {
218: case 3:
219: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
220: u1 = d1[i]; u2 = d2[i];
221: if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
222: if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
223: if ( (u1& 0xe00000) < (u2& 0xe00000) ) return 0;
224: if ( (u1& 0x1c0000) < (u2& 0x1c0000) ) return 0;
225: if ( (u1& 0x38000) < (u2& 0x38000) ) return 0;
226: if ( (u1& 0x7000) < (u2& 0x7000) ) return 0;
227: if ( (u1& 0xe00) < (u2& 0xe00) ) return 0;
228: if ( (u1& 0x1c0) < (u2& 0x1c0) ) return 0;
229: if ( (u1& 0x38) < (u2& 0x38) ) return 0;
230: if ( (u1& 0x7) < (u2& 0x7) ) return 0;
231: }
232: return 1;
233: break;
234: case 4:
235: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
236: u1 = d1[i]; u2 = d2[i];
237: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
238: if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
239: if ( (u1& 0xf00000) < (u2& 0xf00000) ) return 0;
240: if ( (u1& 0xf0000) < (u2& 0xf0000) ) return 0;
241: if ( (u1& 0xf000) < (u2& 0xf000) ) return 0;
242: if ( (u1& 0xf00) < (u2& 0xf00) ) return 0;
243: if ( (u1& 0xf0) < (u2& 0xf0) ) return 0;
244: if ( (u1& 0xf) < (u2& 0xf) ) return 0;
245: }
246: return 1;
247: break;
248: case 6:
249: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
250: u1 = d1[i]; u2 = d2[i];
251: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
252: if ( (u1& 0xfc0000) < (u2& 0xfc0000) ) return 0;
253: if ( (u1& 0x3f000) < (u2& 0x3f000) ) return 0;
254: if ( (u1& 0xfc0) < (u2& 0xfc0) ) return 0;
255: if ( (u1& 0x3f) < (u2& 0x3f) ) return 0;
256: }
257: return 1;
258: break;
259: case 8:
260: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
261: u1 = d1[i]; u2 = d2[i];
262: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
263: if ( (u1& 0xff0000) < (u2& 0xff0000) ) return 0;
264: if ( (u1& 0xff00) < (u2& 0xff00) ) return 0;
265: if ( (u1& 0xff) < (u2& 0xff) ) return 0;
266: }
267: return 1;
268: break;
269: case 16:
270: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
271: u1 = d1[i]; u2 = d2[i];
272: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
273: if ( (u1& 0xffff) < (u2& 0xffff) ) return 0;
274: }
275: return 1;
276: break;
277: case 32:
278: for ( i = nd_exporigin; i < nd_wpd; i++ )
279: if ( d1[i] < d2[i] ) return 0;
280: return 1;
281: break;
282: default:
283: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
284: u1 = d1[i]; u2 = d2[i];
285: for ( j = 0; j < nd_epw; j++ )
286: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
287: }
288: return 1;
289: }
290: #else
291: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
292: u1 = d1[i]; u2 = d2[i];
293: for ( j = 0; j < nd_epw; j++ )
294: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
295: }
296: return 1;
297: #endif
298: }
299:
300: /*
301: * If the current order is a block order,
302: * then the last block is length 1 and contains
303: * the homo variable. Otherwise, the original
304: * order is either 0 or 2.
305: */
306:
307: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int ompos,int weight)
308: {
309: int w,i,e,n,omask0;
310:
311: omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
312: n = nd_nvar-1;
313: ndl_zero(r);
314: for ( i = 0; i < n; i++ ) {
315: e = GET_EXP_OLD(d,i);
316: PUT_EXP(r,i,e);
317: }
318: w = TD(d);
319: PUT_EXP(r,nd_nvar-1,weight-w);
320: if ( nd_module ) MPOS(r) = d[ompos];
321: TD(r) = weight;
322: if ( nd_blockmask ) ndl_weight_mask(r);
323: }
324:
325: void ndl_dehomogenize(UINT *d)
326: {
327: UINT mask;
328: UINT h;
329: int i,bits;
330:
331: if ( nd_blockmask ) {
332: h = GET_EXP(d,nd_nvar-1);
333: XOR_EXP(d,nd_nvar-1,h);
334: TD(d) -= h;
335: ndl_weight_mask(d);
336: } else {
337: if ( nd_isrlex ) {
338: if ( nd_bpe == 32 ) {
339: h = d[nd_exporigin];
340: for ( i = nd_exporigin+1; i < nd_wpd; i++ )
341: d[i-1] = d[i];
342: d[i-1] = 0;
343: TD(d) -= h;
344: } else {
345: bits = nd_epw*nd_bpe;
346: mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
347: h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
348: for ( i = nd_exporigin; i < nd_wpd; i++ )
349: d[i] = ((d[i]<<nd_bpe)&mask)
350: |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
351: TD(d) -= h;
352: }
353: } else {
354: h = GET_EXP(d,nd_nvar-1);
355: XOR_EXP(d,nd_nvar-1,h);
356: TD(d) -= h;
357: }
358: }
359: }
360:
361: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
362: {
363: UINT t1,t2,u,u1,u2;
364: int i,j,l;
365:
366: if ( nd_module && (MPOS(d1) != MPOS(d2)) )
367: error("ndl_lcm : inconsistent monomials");
368: #if USE_UNROLL
369: switch ( nd_bpe ) {
370: case 3:
371: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
372: u1 = d1[i]; u2 = d2[i];
373: t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
374: t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
375: t1 = (u1& 0xe00000); t2 = (u2& 0xe00000); u |= t1>t2?t1:t2;
376: t1 = (u1& 0x1c0000); t2 = (u2& 0x1c0000); u |= t1>t2?t1:t2;
377: t1 = (u1& 0x38000); t2 = (u2& 0x38000); u |= t1>t2?t1:t2;
378: t1 = (u1& 0x7000); t2 = (u2& 0x7000); u |= t1>t2?t1:t2;
379: t1 = (u1& 0xe00); t2 = (u2& 0xe00); u |= t1>t2?t1:t2;
380: t1 = (u1& 0x1c0); t2 = (u2& 0x1c0); u |= t1>t2?t1:t2;
381: t1 = (u1& 0x38); t2 = (u2& 0x38); u |= t1>t2?t1:t2;
382: t1 = (u1& 0x7); t2 = (u2& 0x7); u |= t1>t2?t1:t2;
383: d[i] = u;
384: }
385: break;
386: case 4:
387: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
388: u1 = d1[i]; u2 = d2[i];
389: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
390: t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
391: t1 = (u1& 0xf00000); t2 = (u2& 0xf00000); u |= t1>t2?t1:t2;
392: t1 = (u1& 0xf0000); t2 = (u2& 0xf0000); u |= t1>t2?t1:t2;
393: t1 = (u1& 0xf000); t2 = (u2& 0xf000); u |= t1>t2?t1:t2;
394: t1 = (u1& 0xf00); t2 = (u2& 0xf00); u |= t1>t2?t1:t2;
395: t1 = (u1& 0xf0); t2 = (u2& 0xf0); u |= t1>t2?t1:t2;
396: t1 = (u1& 0xf); t2 = (u2& 0xf); u |= t1>t2?t1:t2;
397: d[i] = u;
398: }
399: break;
400: case 6:
401: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
402: u1 = d1[i]; u2 = d2[i];
403: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
404: t1 = (u1& 0xfc0000); t2 = (u2& 0xfc0000); u |= t1>t2?t1:t2;
405: t1 = (u1& 0x3f000); t2 = (u2& 0x3f000); u |= t1>t2?t1:t2;
406: t1 = (u1& 0xfc0); t2 = (u2& 0xfc0); u |= t1>t2?t1:t2;
407: t1 = (u1& 0x3f); t2 = (u2& 0x3f); u |= t1>t2?t1:t2;
408: d[i] = u;
409: }
410: break;
411: case 8:
412: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
413: u1 = d1[i]; u2 = d2[i];
414: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
415: t1 = (u1& 0xff0000); t2 = (u2& 0xff0000); u |= t1>t2?t1:t2;
416: t1 = (u1& 0xff00); t2 = (u2& 0xff00); u |= t1>t2?t1:t2;
417: t1 = (u1& 0xff); t2 = (u2& 0xff); u |= t1>t2?t1:t2;
418: d[i] = u;
419: }
420: break;
421: case 16:
422: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
423: u1 = d1[i]; u2 = d2[i];
424: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
425: t1 = (u1& 0xffff); t2 = (u2& 0xffff); u |= t1>t2?t1:t2;
426: d[i] = u;
427: }
428: break;
429: case 32:
430: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
431: u1 = d1[i]; u2 = d2[i];
432: d[i] = u1>u2?u1:u2;
433: }
434: break;
435: default:
436: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
437: u1 = d1[i]; u2 = d2[i];
438: for ( j = 0, u = 0; j < nd_epw; j++ ) {
439: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
440: }
441: d[i] = u;
442: }
443: break;
444: }
445: #else
446: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
447: u1 = d1[i]; u2 = d2[i];
448: for ( j = 0, u = 0; j < nd_epw; j++ ) {
449: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
450: }
451: d[i] = u;
452: }
453: #endif
454: if ( nd_module ) MPOS(d) = MPOS(d1);
455: TD(d) = ndl_weight(d);
456: if ( nd_blockmask ) ndl_weight_mask(d);
457: }
458:
459: void ndl_max(UINT *d1,unsigned *d2,UINT *d)
460: {
461: UINT t1,t2,u,u1,u2;
462: int i,j,l;
463:
464: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
465: u1 = d1[i]; u2 = d2[i];
466: for ( j = 0, u = 0; j < nd_epw; j++ ) {
467: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
468: }
469: d[i] = u;
470: }
471: }
472:
473: int ndl_weight(UINT *d)
474: {
475: UINT t,u;
476: int i,j;
477:
478: if ( current_dl_weight_vector )
479: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
480: u = GET_EXP(d,i);
481: t += MUL_WEIGHT(u,i);
482: }
483: else
484: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
485: u = d[i];
486: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
487: t += (u&nd_mask0);
488: }
1.20 noro 489: if ( nd_module && nd_module_rank && MPOS(d) )
490: t += nd_module_weight[MPOS(d)-1];
491: for ( i = nd_exporigin; i < nd_wpd; i++ )
492: if ( d[i] && !t )
493: printf("afo\n");
1.1 noro 494: return t;
495: }
496:
497: /* for sugarweight */
498:
499: int ndl_weight2(UINT *d)
500: {
501: int t,u;
502: int i,j;
503:
504: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
505: u = GET_EXP(d,i);
506: t += nd_sugarweight[i]*u;
507: }
1.20 noro 508: if ( nd_module && nd_module_rank && MPOS(d) )
509: t += nd_module_weight[MPOS(d)-1];
1.1 noro 510: return t;
511: }
512:
513: void ndl_weight_mask(UINT *d)
514: {
515: UINT t,u;
516: UINT *mask;
517: int i,j,k,l;
518:
519: l = nd_blockmask->n;
520: for ( k = 0; k < l; k++ ) {
521: mask = nd_blockmask->mask[k];
522: if ( current_dl_weight_vector )
523: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
524: u = GET_EXP_MASK(d,i,mask);
525: t += MUL_WEIGHT(u,i);
526: }
527: else
528: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
529: u = d[i]&mask[i];
530: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
531: t += (u&nd_mask0);
532: }
533: d[k+1] = t;
534: }
535: }
536:
1.21 noro 537: int ndl_glex_compare(UINT *d1,UINT *d2)
538: {
539: if ( TD(d1) > TD(d2) ) return 1;
540: else if ( TD(d1) < TD(d2) ) return -1;
541: else return ndl_lex_compare(d1,d2);
542: }
543:
1.1 noro 544: int ndl_lex_compare(UINT *d1,UINT *d2)
545: {
546: int i;
547:
548: d1 += nd_exporigin;
549: d2 += nd_exporigin;
550: for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
551: if ( *d1 > *d2 )
552: return nd_isrlex ? -1 : 1;
553: else if ( *d1 < *d2 )
554: return nd_isrlex ? 1 : -1;
555: return 0;
556: }
557:
558: int ndl_block_compare(UINT *d1,UINT *d2)
559: {
560: int i,l,j,ord_o,ord_l;
561: struct order_pair *op;
562: UINT t1,t2,m;
563: UINT *mask;
564:
565: l = nd_blockmask->n;
566: op = nd_blockmask->order_pair;
567: for ( j = 0; j < l; j++ ) {
568: mask = nd_blockmask->mask[j];
569: ord_o = op[j].order;
570: if ( ord_o < 2 ) {
571: if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
572: else if ( t1 < t2 ) return -1;
573: }
574: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
575: m = mask[i];
576: t1 = d1[i]&m;
577: t2 = d2[i]&m;
578: if ( t1 > t2 )
579: return !ord_o ? -1 : 1;
580: else if ( t1 < t2 )
581: return !ord_o ? 1 : -1;
582: }
583: }
584: return 0;
585: }
586:
587: int ndl_matrix_compare(UINT *d1,UINT *d2)
588: {
589: int i,j,s,row;
590: int *v;
591: Z **mat;
592: Z *w;
593: Z t1;
594: Z t,t2;
595:
1.6 noro 596: for ( j = 0; j < nd_nvar; j++ )
597: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
1.1 noro 598: if ( nd_top_weight ) {
599: if ( OID(nd_top_weight) == O_VECT ) {
1.6 noro 600: mat = (Z **)&BDY((VECT)nd_top_weight);
601: row = 1;
1.1 noro 602: } else {
603: mat = (Z **)BDY((MAT)nd_top_weight);
1.6 noro 604: row = ((MAT)nd_top_weight)->row;
1.1 noro 605: }
606: for ( i = 0; i < row; i++ ) {
1.6 noro 607: w = mat[i];
1.1 noro 608: for ( j = 0, t = 0; j < nd_nvar; j++ ) {
1.6 noro 609: STOZ(nd_work_vector[j],t1);
1.1 noro 610: mulz(w[j],t1,&t2);
611: addz(t,t2,&t1);
612: t = t1;
613: }
1.6 noro 614: if ( t ) {
615: s = sgnz(t);
1.1 noro 616: if ( s > 0 ) return 1;
617: else if ( s < 0 ) return -1;
1.6 noro 618: }
1.1 noro 619: }
1.6 noro 620: }
621: for ( i = 0; i < nd_matrix_len; i++ ) {
622: v = nd_matrix[i];
623: for ( j = 0, s = 0; j < nd_nvar; j++ )
624: s += v[j]*nd_work_vector[j];
625: if ( s > 0 ) return 1;
626: else if ( s < 0 ) return -1;
627: }
1.1 noro 628: if ( !ndl_equal(d1,d2) )
1.6 noro 629: error("ndl_matrix_compare : invalid matrix");
630: return 0;
1.1 noro 631: }
632:
633: int ndl_composite_compare(UINT *d1,UINT *d2)
634: {
635: int i,j,s,start,end,len,o;
636: int *v;
637: struct sparse_weight *sw;
638:
639: for ( j = 0; j < nd_nvar; j++ )
640: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
641: for ( i = 0; i < nd_worb_len; i++ ) {
642: len = nd_worb[i].length;
643: switch ( nd_worb[i].type ) {
644: case IS_DENSE_WEIGHT:
645: v = nd_worb[i].body.dense_weight;
646: for ( j = 0, s = 0; j < len; j++ )
647: s += v[j]*nd_work_vector[j];
648: if ( s > 0 ) return 1;
649: else if ( s < 0 ) return -1;
650: break;
651: case IS_SPARSE_WEIGHT:
652: sw = nd_worb[i].body.sparse_weight;
653: for ( j = 0, s = 0; j < len; j++ )
654: s += sw[j].value*nd_work_vector[sw[j].pos];
655: if ( s > 0 ) return 1;
656: else if ( s < 0 ) return -1;
657: break;
658: case IS_BLOCK:
659: o = nd_worb[i].body.block.order;
660: start = nd_worb[i].body.block.start;
661: switch ( o ) {
662: case 0:
663: end = start+len;
664: for ( j = start, s = 0; j < end; j++ )
665: s += MUL_WEIGHT(nd_work_vector[j],j);
666: if ( s > 0 ) return 1;
667: else if ( s < 0 ) return -1;
668: for ( j = end-1; j >= start; j-- )
669: if ( nd_work_vector[j] < 0 ) return 1;
670: else if ( nd_work_vector[j] > 0 ) return -1;
671: break;
672: case 1:
673: end = start+len;
674: for ( j = start, s = 0; j < end; j++ )
675: s += MUL_WEIGHT(nd_work_vector[j],j);
676: if ( s > 0 ) return 1;
677: else if ( s < 0 ) return -1;
678: for ( j = start; j < end; j++ )
679: if ( nd_work_vector[j] > 0 ) return 1;
680: else if ( nd_work_vector[j] < 0 ) return -1;
681: break;
682: case 2:
683: end = start+len;
684: for ( j = start; j < end; j++ )
685: if ( nd_work_vector[j] > 0 ) return 1;
686: else if ( nd_work_vector[j] < 0 ) return -1;
687: break;
688: }
689: break;
690: }
691: }
692: return 0;
693: }
694:
695: /* TDH -> WW -> TD-> RL */
696:
697: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
698: {
699: int i,m,e1,e2;
700:
701: if ( TD(d1) > TD(d2) ) return 1;
702: else if ( TD(d1) < TD(d2) ) return -1;
703: m = nd_nvar>>1;
704: for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
705: e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
706: e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
707: }
708: if ( e1 > e2 ) return 1;
709: else if ( e1 < e2 ) return -1;
710: return ndl_lex_compare(d1,d2);
711: }
712:
1.21 noro 713: // common function for module glex and grlex comparison
714: int ndl_module_glex_compare(UINT *d1,UINT *d2)
1.1 noro 715: {
1.21 noro 716: int c;
1.1 noro 717:
1.21 noro 718: switch ( nd_module_ordtype ) {
719: case 0:
720: if ( TD(d1) > TD(d2) ) return 1;
721: else if ( TD(d1) < TD(d2) ) return -1;
722: else if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
723: else if ( MPOS(d1) < MPOS(d2) ) return 1;
724: else if ( MPOS(d1) > MPOS(d2) ) return -1;
725: else return 0;
726: break;
1.1 noro 727:
1.21 noro 728: case 1:
1.19 noro 729: if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) {
730: if ( TD(d1) > TD(d2) ) return 1;
731: else if ( TD(d1) < TD(d2) ) return -1;
732: if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
733: if ( MPOS(d1) < MPOS(d2) ) return 1;
734: else if ( MPOS(d1) > MPOS(d2) ) return -1;
735: }
736: if ( MPOS(d1) < MPOS(d2) ) return 1;
737: else if ( MPOS(d1) > MPOS(d2) ) return -1;
1.21 noro 738: else if ( TD(d1) > TD(d2) ) return 1;
739: else if ( TD(d1) < TD(d2) ) return -1;
740: else return ndl_lex_compare(d1,d2);
741: break;
1.1 noro 742:
1.21 noro 743: case 2: // weight -> POT
744: if ( TD(d1) > TD(d2) ) return 1;
745: else if ( TD(d1) < TD(d2) ) return -1;
746: else if ( MPOS(d1) < MPOS(d2) ) return 1;
747: else if ( MPOS(d1) > MPOS(d2) ) return -1;
748: else return ndl_lex_compare(d1,d2);
749: break;
1.1 noro 750:
1.21 noro 751: default:
752: error("ndl_module_glex_compare : invalid module_ordtype");
1.28 noro 753: return 0;
1.21 noro 754: }
1.1 noro 755: }
756:
1.21 noro 757: // common for module comparison
758: int ndl_module_compare(UINT *d1,UINT *d2)
1.1 noro 759: {
1.21 noro 760: int c;
1.1 noro 761:
1.21 noro 762: switch ( nd_module_ordtype ) {
763: case 0:
1.23 noro 764: if ( (c = (*ndl_base_compare_function)(d1,d2)) != 0 ) return c;
1.21 noro 765: else if ( MPOS(d1) > MPOS(d2) ) return -1;
766: else if ( MPOS(d1) < MPOS(d2) ) return 1;
767: else return 0;
768: break;
1.1 noro 769:
1.21 noro 770: case 1:
771: if ( MPOS(d1) < MPOS(d2) ) return 1;
772: else if ( MPOS(d1) > MPOS(d2) ) return -1;
773: else return (*ndl_base_compare_function)(d1,d2);
774: break;
1.1 noro 775:
1.21 noro 776: case 2: // weight -> POT
777: if ( TD(d1) > TD(d2) ) return 1;
778: else if ( TD(d1) < TD(d2) ) return -1;
779: else if ( MPOS(d1) < MPOS(d2) ) return 1;
780: else if ( MPOS(d1) > MPOS(d2) ) return -1;
781: else return (*ndl_base_compare_function)(d1,d2);
782: break;
1.1 noro 783:
1.21 noro 784: default:
785: error("ndl_module_compare : invalid module_ordtype");
1.28 noro 786: return 0;
1.21 noro 787: }
1.1 noro 788: }
789:
1.21 noro 790: extern DMMstack dmm_stack;
791: void _addtodl(int n,DL d1,DL d2);
1.31 noro 792: void _adddl(int n,DL d1,DL d2,DL d3);
1.21 noro 793: int _eqdl(int n,DL d1,DL d2);
794:
795: int ndl_module_schreyer_compare(UINT *m1,UINT *m2)
796: {
797: int pos1,pos2,t,j;
798: DMM *in;
799: DMMstack s;
800: static DL d1=0;
801: static DL d2=0;
802: static int dlen=0;
803:
804: pos1 = MPOS(m1); pos2 = MPOS(m2);
805: if ( pos1 == pos2 ) return (*ndl_base_compare_function)(m1,m2);
806: if ( nd_nvar > dlen ) {
807: NEWDL(d1,nd_nvar);
808: NEWDL(d2,nd_nvar);
809: dlen = nd_nvar;
810: }
811: d1->td = TD(m1);
812: for ( j = 0; j < nd_nvar; j++ ) d1->d[j] = GET_EXP(m1,j);
813: d2->td = TD(m2);
814: for ( j = 0; j < nd_nvar; j++ ) d2->d[j] = GET_EXP(m2,j);
815: for ( s = dmm_stack; s; s = NEXT(s) ) {
816: in = s->in;
817: _addtodl(nd_nvar,in[pos1]->dl,d1);
818: _addtodl(nd_nvar,in[pos2]->dl,d2);
819: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(nd_nvar,d1,d2)) {
820: if ( pos1 < pos2 ) return 1;
821: else if ( pos1 > pos2 ) return -1;
822: else return 0;
823: }
824: pos1 = in[pos1]->pos;
825: pos2 = in[pos2]->pos;
826: if ( pos1 == pos2 ) return (*dl_base_compare_function)(nd_nvar,d1,d2);
827: }
828: // comparison by the bottom order
829: LAST:
830: switch ( nd_base_ordtype ) {
831: case 0:
832: t = (*dl_base_compare_function)(nd_nvar,d1,d2);
833: if ( t ) return t;
834: else if ( pos1 < pos2 ) return 1;
835: else if ( pos1 > pos2 ) return -1;
836: else return 0;
837: break;
838: case 1:
839: if ( pos1 < pos2 ) return 1;
840: else if ( pos1 > pos2 ) return -1;
841: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
842: break;
843: case 2:
844: if ( d1->td > d2->td ) return 1;
845: else if ( d1->td < d2->td ) return -1;
846: else if ( pos1 < pos2 ) return 1;
847: else if ( pos1 > pos2 ) return -1;
848: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
849: break;
850: default:
851: error("ndl_schreyer_compare : invalid base ordtype");
1.28 noro 852: return 0;
1.21 noro 853: }
1.1 noro 854: }
855:
856: INLINE int ndl_equal(UINT *d1,UINT *d2)
857: {
858: int i;
859:
860: switch ( nd_wpd ) {
861: case 2:
862: if ( TD(d2) != TD(d1) ) return 0;
863: if ( d2[1] != d1[1] ) return 0;
864: return 1;
865: break;
866: case 3:
867: if ( TD(d2) != TD(d1) ) return 0;
868: if ( d2[1] != d1[1] ) return 0;
869: if ( d2[2] != d1[2] ) return 0;
870: return 1;
871: break;
872: default:
873: for ( i = 0; i < nd_wpd; i++ )
874: if ( *d1++ != *d2++ ) return 0;
875: return 1;
876: break;
877: }
878: }
879:
880: INLINE void ndl_copy(UINT *d1,UINT *d2)
881: {
882: int i;
883:
884: switch ( nd_wpd ) {
885: case 2:
886: TD(d2) = TD(d1);
887: d2[1] = d1[1];
888: break;
889: case 3:
890: TD(d2) = TD(d1);
891: d2[1] = d1[1];
892: d2[2] = d1[2];
893: break;
894: default:
895: for ( i = 0; i < nd_wpd; i++ )
896: d2[i] = d1[i];
897: break;
898: }
899: }
900:
901: INLINE void ndl_zero(UINT *d)
902: {
903: int i;
904: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
905: }
906:
907: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
908: {
909: int i;
910:
911: if ( nd_module ) {
912: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
913: error("ndl_add : invalid operation");
914: }
915: #if 1
916: switch ( nd_wpd ) {
917: case 2:
918: TD(d) = TD(d1)+TD(d2);
919: d[1] = d1[1]+d2[1];
920: break;
921: case 3:
922: TD(d) = TD(d1)+TD(d2);
923: d[1] = d1[1]+d2[1];
924: d[2] = d1[2]+d2[2];
925: break;
926: default:
927: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
928: break;
929: }
930: #else
931: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
932: #endif
933: }
934:
935: /* d1 += d2 */
936: INLINE void ndl_addto(UINT *d1,UINT *d2)
937: {
938: int i;
939:
940: if ( nd_module ) {
941: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
942: error("ndl_addto : invalid operation");
943: }
944: #if 1
945: switch ( nd_wpd ) {
946: case 2:
947: TD(d1) += TD(d2);
948: d1[1] += d2[1];
949: break;
950: case 3:
951: TD(d1) += TD(d2);
952: d1[1] += d2[1];
953: d1[2] += d2[2];
954: break;
955: default:
956: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
957: break;
958: }
959: #else
960: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
961: #endif
962: }
963:
964: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
965: {
966: int i;
967:
968: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
969: }
970:
971: int ndl_disjoint(UINT *d1,UINT *d2)
972: {
973: UINT t1,t2,u,u1,u2;
974: int i,j;
975:
976: if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
977: #if USE_UNROLL
978: switch ( nd_bpe ) {
979: case 3:
980: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
981: u1 = d1[i]; u2 = d2[i];
982: t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
983: t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
984: t1 = u1& 0xe00000; t2 = u2& 0xe00000; if ( t1&&t2 ) return 0;
985: t1 = u1& 0x1c0000; t2 = u2& 0x1c0000; if ( t1&&t2 ) return 0;
986: t1 = u1& 0x38000; t2 = u2& 0x38000; if ( t1&&t2 ) return 0;
987: t1 = u1& 0x7000; t2 = u2& 0x7000; if ( t1&&t2 ) return 0;
988: t1 = u1& 0xe00; t2 = u2& 0xe00; if ( t1&&t2 ) return 0;
989: t1 = u1& 0x1c0; t2 = u2& 0x1c0; if ( t1&&t2 ) return 0;
990: t1 = u1& 0x38; t2 = u2& 0x38; if ( t1&&t2 ) return 0;
991: t1 = u1& 0x7; t2 = u2& 0x7; if ( t1&&t2 ) return 0;
992: }
993: return 1;
994: break;
995: case 4:
996: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
997: u1 = d1[i]; u2 = d2[i];
998: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
999: t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
1000: t1 = u1& 0xf00000; t2 = u2& 0xf00000; if ( t1&&t2 ) return 0;
1001: t1 = u1& 0xf0000; t2 = u2& 0xf0000; if ( t1&&t2 ) return 0;
1002: t1 = u1& 0xf000; t2 = u2& 0xf000; if ( t1&&t2 ) return 0;
1003: t1 = u1& 0xf00; t2 = u2& 0xf00; if ( t1&&t2 ) return 0;
1004: t1 = u1& 0xf0; t2 = u2& 0xf0; if ( t1&&t2 ) return 0;
1005: t1 = u1& 0xf; t2 = u2& 0xf; if ( t1&&t2 ) return 0;
1006: }
1007: return 1;
1008: break;
1009: case 6:
1010: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1011: u1 = d1[i]; u2 = d2[i];
1012: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1013: t1 = u1& 0xfc0000; t2 = u2& 0xfc0000; if ( t1&&t2 ) return 0;
1014: t1 = u1& 0x3f000; t2 = u2& 0x3f000; if ( t1&&t2 ) return 0;
1015: t1 = u1& 0xfc0; t2 = u2& 0xfc0; if ( t1&&t2 ) return 0;
1016: t1 = u1& 0x3f; t2 = u2& 0x3f; if ( t1&&t2 ) return 0;
1017: }
1018: return 1;
1019: break;
1020: case 8:
1021: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1022: u1 = d1[i]; u2 = d2[i];
1023: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1024: t1 = u1& 0xff0000; t2 = u2& 0xff0000; if ( t1&&t2 ) return 0;
1025: t1 = u1& 0xff00; t2 = u2& 0xff00; if ( t1&&t2 ) return 0;
1026: t1 = u1& 0xff; t2 = u2& 0xff; if ( t1&&t2 ) return 0;
1027: }
1028: return 1;
1029: break;
1030: case 16:
1031: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1032: u1 = d1[i]; u2 = d2[i];
1033: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1034: t1 = u1& 0xffff; t2 = u2& 0xffff; if ( t1&&t2 ) return 0;
1035: }
1036: return 1;
1037: break;
1038: case 32:
1039: for ( i = nd_exporigin; i < nd_wpd; i++ )
1040: if ( d1[i] && d2[i] ) return 0;
1041: return 1;
1042: break;
1043: default:
1044: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1045: u1 = d1[i]; u2 = d2[i];
1046: for ( j = 0; j < nd_epw; j++ ) {
1047: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1048: u1 >>= nd_bpe; u2 >>= nd_bpe;
1049: }
1050: }
1051: return 1;
1052: break;
1053: }
1054: #else
1055: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1056: u1 = d1[i]; u2 = d2[i];
1057: for ( j = 0; j < nd_epw; j++ ) {
1058: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1059: u1 >>= nd_bpe; u2 >>= nd_bpe;
1060: }
1061: }
1062: return 1;
1063: #endif
1064: }
1065:
1066: int ndl_check_bound(UINT *d1,UINT *d2)
1067: {
1068: UINT u2;
1069: int i,j,ind,k;
1070:
1071: ind = 0;
1072: #if USE_UNROLL
1073: switch ( nd_bpe ) {
1074: case 3:
1075: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1076: u2 = d2[i];
1077: if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
1078: if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
1079: if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
1080: if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
1081: if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
1082: if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
1083: if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
1084: if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
1085: if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
1086: if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
1087: }
1088: return 0;
1089: break;
1090: case 4:
1091: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1092: u2 = d2[i];
1093: if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
1094: if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
1095: if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
1096: if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
1097: if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
1098: if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
1099: if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
1100: if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
1101: }
1102: return 0;
1103: break;
1104: case 6:
1105: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1106: u2 = d2[i];
1107: if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
1108: if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
1109: if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
1110: if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
1111: if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
1112: }
1113: return 0;
1114: break;
1115: case 8:
1116: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1117: u2 = d2[i];
1118: if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
1119: if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
1120: if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
1121: if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
1122: }
1123: return 0;
1124: break;
1125: case 16:
1126: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1127: u2 = d2[i];
1128: if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
1129: if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
1130: }
1131: return 0;
1132: break;
1133: case 32:
1134: for ( i = nd_exporigin; i < nd_wpd; i++ )
1135: if ( d1[i]+d2[i]<d1[i] ) return 1;
1136: return 0;
1137: break;
1138: default:
1139: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1140: u2 = d2[i];
1141: k = (nd_epw-1)*nd_bpe;
1142: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1143: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1144: }
1145: return 0;
1146: break;
1147: }
1148: #else
1149: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1150: u2 = d2[i];
1151: k = (nd_epw-1)*nd_bpe;
1152: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1153: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1154: }
1155: return 0;
1156: #endif
1157: }
1158:
1159: int ndl_check_bound2(int index,UINT *d2)
1160: {
1161: return ndl_check_bound(nd_bound[index],d2);
1162: }
1163:
1164: INLINE int ndl_hash_value(UINT *d)
1165: {
1166: int i;
1.11 noro 1167: UINT r;
1.1 noro 1168:
1169: r = 0;
1170: for ( i = 0; i < nd_wpd; i++ )
1.12 noro 1171: r = (r*1511+d[i]);
1.11 noro 1172: r %= REDTAB_LEN;
1.1 noro 1173: return r;
1174: }
1175:
1176: INLINE int ndl_find_reducer(UINT *dg)
1177: {
1178: RHist r;
1179: int d,k,i;
1180:
1181: d = ndl_hash_value(dg);
1182: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1183: if ( ndl_equal(dg,DL(r)) ) {
1184: if ( k > 0 ) nd_notfirst++;
1185: nd_found++;
1186: return r->index;
1187: }
1188: }
1189: if ( Reverse )
1190: for ( i = nd_psn-1; i >= 0; i-- ) {
1191: r = nd_psh[i];
1192: if ( ndl_reducible(dg,DL(r)) ) {
1193: nd_create++;
1194: nd_append_red(dg,i);
1195: return i;
1196: }
1197: }
1198: else
1199: for ( i = 0; i < nd_psn; i++ ) {
1200: r = nd_psh[i];
1201: if ( ndl_reducible(dg,DL(r)) ) {
1202: nd_create++;
1203: nd_append_red(dg,i);
1204: return i;
1205: }
1206: }
1207: return -1;
1208: }
1209:
1.24 noro 1210: // ret=0,...,nd_psn-1 => reducer found
1211: // ret=nd_psn => reducer not found
1212: // ret=-1 => singular top reducible
1213:
1214: int comp_sig(SIG s1,SIG s2);
1215: void _ndltodl(UINT *ndl,DL dl);
1216:
1217: void print_sig(SIG s)
1218: {
1219: int i;
1220:
1221: fprintf(asir_out,"<<");
1222: for ( i = 0; i < nd_nvar; i++ ) {
1223: fprintf(asir_out,"%d",s->dl->d[i]);
1224: if ( i != nd_nvar-1 ) fprintf(asir_out,",");
1225: }
1226: fprintf(asir_out,">>*e%d",s->pos);
1227: }
1228:
1.35 noro 1229: // assuming increasing order wrt signature
1230:
1.24 noro 1231: INLINE int ndl_find_reducer_s(UINT *dg,SIG sig)
1232: {
1233: RHist r;
1.27 noro 1234: int i,singular,ret,d,k;
1.26 noro 1235: static int wpd,nvar;
1.24 noro 1236: static SIG quo;
1237: static UINT *tmp;
1238:
1.26 noro 1239: if ( !quo || nvar != nd_nvar ) NEWSIG(quo);
1240: if ( wpd != nd_wpd ) {
1.24 noro 1241: wpd = nd_wpd;
1242: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
1243: }
1.27 noro 1244: d = ndl_hash_value(dg);
1.35 noro 1245: #if 1
1.27 noro 1246: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1247: if ( ndl_equal(dg,DL(r)) ) {
1248: return r->index;
1249: }
1250: }
1.35 noro 1251: #endif
1.24 noro 1252: singular = 0;
1253: for ( i = 0; i < nd_psn; i++ ) {
1254: r = nd_psh[i];
1255: if ( ndl_reducible(dg,DL(r)) ) {
1.27 noro 1256: ndl_sub(dg,DL(r),tmp);
1.24 noro 1257: _ndltodl(tmp,DL(quo));
1258: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
1259: quo->pos = nd_psh[i]->sig->pos;
1260: ret = comp_sig(sig,quo);
1261: if ( ret > 0 ) { singular = 0; break; }
1.38 noro 1262: if ( ret == 0 ) { /* fprintf(asir_out,"s"); fflush(asir_out); */ singular = 1; }
1.24 noro 1263: }
1264: }
1265: if ( singular ) return -1;
1.27 noro 1266: else if ( i < nd_psn )
1267: nd_append_red(dg,i);
1268: return i;
1.24 noro 1269: }
1270:
1.1 noro 1271: ND nd_merge(ND p1,ND p2)
1272: {
1273: int n,c;
1274: int t,can,td1,td2;
1275: ND r;
1276: NM m1,m2,mr0,mr,s;
1277:
1278: if ( !p1 ) return p2;
1279: else if ( !p2 ) return p1;
1280: else {
1281: can = 0;
1282: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1283: c = DL_COMPARE(DL(m1),DL(m2));
1284: switch ( c ) {
1285: case 0:
1286: s = m1; m1 = NEXT(m1);
1287: can++; NEXTNM2(mr0,mr,s);
1288: s = m2; m2 = NEXT(m2); FREENM(s);
1289: break;
1290: case 1:
1291: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1292: break;
1293: case -1:
1294: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1295: break;
1296: }
1297: }
1298: if ( !mr0 )
1299: if ( m1 ) mr0 = m1;
1300: else if ( m2 ) mr0 = m2;
1301: else return 0;
1302: else if ( m1 ) NEXT(mr) = m1;
1303: else if ( m2 ) NEXT(mr) = m2;
1304: else NEXT(mr) = 0;
1305: BDY(p1) = mr0;
1306: SG(p1) = MAX(SG(p1),SG(p2));
1307: LEN(p1) = LEN(p1)+LEN(p2)-can;
1308: FREEND(p2);
1309: return p1;
1310: }
1311: }
1312:
1313: ND nd_add(int mod,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:
1.11 noro 1320: Nnd_add++;
1.1 noro 1321: if ( !p1 ) return p2;
1322: else if ( !p2 ) return p1;
1323: else if ( mod == -1 ) return nd_add_sf(p1,p2);
1324: else if ( mod == -2 ) return nd_add_lf(p1,p2);
1325: else if ( !mod ) return nd_add_q(p1,p2);
1326: else {
1327: can = 0;
1328: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1329: c = DL_COMPARE(DL(m1),DL(m2));
1330: switch ( c ) {
1331: case 0:
1332: t = ((CM(m1))+(CM(m2))) - mod;
1333: if ( t < 0 ) t += mod;
1334: s = m1; m1 = NEXT(m1);
1335: if ( t ) {
1336: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1337: } else {
1338: can += 2; FREENM(s);
1339: }
1340: s = m2; m2 = NEXT(m2); FREENM(s);
1341: break;
1342: case 1:
1343: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1344: break;
1345: case -1:
1346: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1347: break;
1348: }
1349: }
1350: if ( !mr0 )
1351: if ( m1 ) mr0 = m1;
1352: else if ( m2 ) mr0 = m2;
1353: else return 0;
1354: else if ( m1 ) NEXT(mr) = m1;
1355: else if ( m2 ) NEXT(mr) = m2;
1356: else NEXT(mr) = 0;
1357: BDY(p1) = mr0;
1358: SG(p1) = MAX(SG(p1),SG(p2));
1359: LEN(p1) = LEN(p1)+LEN(p2)-can;
1360: FREEND(p2);
1361: return p1;
1362: }
1363: }
1364:
1365: /* XXX on opteron, the inlined manipulation of destructive additon of
1366: * two NM seems to make gcc optimizer get confused, so the part is
1367: * done in a function.
1368: */
1369:
1370: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1371: {
1372: NM s;
1373: P t;
1374: int can;
1375:
1376: addp(nd_vc,CP(*m1),CP(*m2),&t);
1377: s = *m1; *m1 = NEXT(*m1);
1378: if ( t ) {
1379: can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
1380: } else {
1381: can = 2; FREENM(s);
1382: }
1383: s = *m2; *m2 = NEXT(*m2); FREENM(s);
1384: return can;
1385: }
1386:
1387: ND nd_add_q(ND p1,ND p2)
1388: {
1389: int n,c,can;
1390: ND r;
1391: NM m1,m2,mr0,mr,s;
1392: P t;
1393:
1394: if ( !p1 ) return p2;
1395: else if ( !p2 ) return p1;
1396: else {
1397: can = 0;
1398: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1399: c = DL_COMPARE(DL(m1),DL(m2));
1400: switch ( c ) {
1401: case 0:
1402: #if defined(__x86_64__)
1403: can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1404: #else
1405: addp(nd_vc,CP(m1),CP(m2),&t);
1406: s = m1; m1 = NEXT(m1);
1407: if ( t ) {
1408: can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
1409: } else {
1410: can += 2; FREENM(s);
1411: }
1412: s = m2; m2 = NEXT(m2); FREENM(s);
1413: #endif
1414: break;
1415: case 1:
1416: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1417: break;
1418: case -1:
1419: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1420: break;
1421: }
1422: }
1423: if ( !mr0 )
1424: if ( m1 ) mr0 = m1;
1425: else if ( m2 ) mr0 = m2;
1426: else return 0;
1427: else if ( m1 ) NEXT(mr) = m1;
1428: else if ( m2 ) NEXT(mr) = m2;
1429: else NEXT(mr) = 0;
1430: BDY(p1) = mr0;
1431: SG(p1) = MAX(SG(p1),SG(p2));
1432: LEN(p1) = LEN(p1)+LEN(p2)-can;
1433: FREEND(p2);
1434: return p1;
1435: }
1436: }
1437:
1438: ND nd_add_sf(ND p1,ND p2)
1439: {
1440: int n,c,can;
1441: ND r;
1442: NM m1,m2,mr0,mr,s;
1443: int t;
1444:
1445: if ( !p1 ) return p2;
1446: else if ( !p2 ) return p1;
1447: else {
1448: can = 0;
1449: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1450: c = DL_COMPARE(DL(m1),DL(m2));
1451: switch ( c ) {
1452: case 0:
1453: t = _addsf(CM(m1),CM(m2));
1454: s = m1; m1 = NEXT(m1);
1455: if ( t ) {
1456: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1457: } else {
1458: can += 2; FREENM(s);
1459: }
1460: s = m2; m2 = NEXT(m2); FREENM(s);
1461: break;
1462: case 1:
1463: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1464: break;
1465: case -1:
1466: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1467: break;
1468: }
1469: }
1470: if ( !mr0 )
1471: if ( m1 ) mr0 = m1;
1472: else if ( m2 ) mr0 = m2;
1473: else return 0;
1474: else if ( m1 ) NEXT(mr) = m1;
1475: else if ( m2 ) NEXT(mr) = m2;
1476: else NEXT(mr) = 0;
1477: BDY(p1) = mr0;
1478: SG(p1) = MAX(SG(p1),SG(p2));
1479: LEN(p1) = LEN(p1)+LEN(p2)-can;
1480: FREEND(p2);
1481: return p1;
1482: }
1483: }
1484:
1485:
1486: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn,Obj *divp)
1487: {
1488: int c,c1,c2;
1489: Z cg,cred,gcd,tq;
1490: P cgp,credp,gcdp;
1491: Obj tr,tr1;
1492:
1493: if ( mod == -1 ) {
1494: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1495: *divp = (Obj)ONE;
1496: } else if ( mod == -2 ) {
1497: Z inv,t;
1498: divlf(ONE,HCZ(p),&inv);
1499: chsgnlf(HCZ(g),&t);
1500: mullf(inv,t,&CZ(mul));
1501: *divp = (Obj)ONE;
1502: } else if ( mod ) {
1503: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1504: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1505: *divp = (Obj)ONE;
1506: } else if ( nd_vc ) {
1507: ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
1508: divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
1509: chsgnp(cgp,&CP(mul));
1510: nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
1511: if ( dn ) {
1512: mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
1513: reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
1514: }
1515: *divp = (Obj)credp;
1516: } else {
1.6 noro 1517: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1518: chsgnz(cg,&CZ(mul));
1.1 noro 1519: nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
1520: if ( dn ) {
1521: mulz(dn->z,cred,&tq); dn->z = tq;
1522: }
1523: *divp = (Obj)cred;
1524: }
1525: return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1526: }
1527:
1528: /* ret=1 : success, ret=0 : overflow */
1.6 noro 1529: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1.1 noro 1530: {
1531: NM m,mrd,tail;
1532: NM mul;
1533: int n,sugar,psugar,sugar0,stat,index;
1534: int c,c1,c2,dummy;
1535: RHist h;
1536: NDV p,red;
1537: Q cg,cred,gcd,tq,qq;
1538: Z iq;
1539: DP dmul;
1540: NODE node;
1541: LIST hist;
1542: double hmag;
1543: P tp,tp1;
1544: Obj tr,tr1,div;
1545: union oNDC hg;
1546: P cont;
1547:
1548: if ( !g ) {
1549: *rp = d;
1550: return 1;
1551: }
1552: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1553:
1554: sugar0 = sugar = SG(g);
1555: n = NV(g);
1556: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1557: if ( d )
1558: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1559: for ( ; g; ) {
1560: index = ndl_find_reducer(HDL(g));
1561: if ( index >= 0 ) {
1562: h = nd_psh[index];
1563: ndl_sub(HDL(g),DL(h),DL(mul));
1564: if ( ndl_check_bound2(index,DL(mul)) ) {
1565: nd_free(g); nd_free(d);
1566: return 0;
1567: }
1568: p = nd_demand ? ndv_load(index) : ps[index];
1569: /* d+g -> div*(d+g)+mul*p */
1.6 noro 1570: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1.1 noro 1571: if ( nd_gentrace ) {
1572: /* Trace=[div,index,mul,ONE] */
1.6 noro 1573: STOZ(index,iq);
1.1 noro 1574: nmtodp(mod,mul,&dmul);
1575: node = mknode(4,div,iq,dmul,ONE);
1576: }
1577: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1578: if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) {
1579: hg = HCU(g);
1580: nd_removecont2(d,g);
1.6 noro 1581: if ( nd_gentrace ) {
1.1 noro 1582: /* overwrite cont : Trace=[div,index,mul,cont] */
1.6 noro 1583: /* exact division */
1.1 noro 1584: cont = ndc_div(mod,hg,HCU(g));
1585: if ( nd_gentrace && !UNIQ(cont) ) ARG3(node) = (pointer)cont;
1586: }
1587: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1588: }
1589: MKLIST(hist,node);
1590: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1591: } else if ( !full ) {
1592: *rp = g;
1593: return 1;
1594: } else {
1595: m = BDY(g);
1596: if ( NEXT(m) ) {
1597: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1598: } else {
1599: FREEND(g); g = 0;
1600: }
1601: if ( d ) {
1602: NEXT(tail)=m; tail=m; LEN(d)++;
1603: } else {
1604: MKND(n,m,1,d); tail = BDY(d);
1605: }
1606: }
1607: }
1608: if ( d ) SG(d) = sugar;
1609: *rp = d;
1610: return 1;
1611: }
1612:
1.24 noro 1613: // ret=1 => success
1614: // ret=0 => overflow
1615: // ret=-1 => singular top reducible
1616:
1617: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1618: {
1619: NM m,mrd,tail;
1620: NM mul;
1621: int n,sugar,psugar,sugar0,stat,index;
1622: int c,c1,c2,dummy;
1623: RHist h;
1624: NDV p,red;
1625: Q cg,cred,gcd,tq,qq;
1626: Z iq;
1627: DP dmul;
1628: NODE node;
1629: LIST hist;
1630: double hmag;
1631: P tp,tp1;
1632: Obj tr,tr1,div;
1633: union oNDC hg;
1634: P cont;
1635: SIG sig;
1636:
1637: if ( !g ) {
1638: *rp = d;
1639: return 1;
1640: }
1641: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1642:
1643: sugar0 = sugar = SG(g);
1644: n = NV(g);
1645: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1646: if ( d )
1647: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1648: sig = g->sig;
1649: for ( ; g; ) {
1650: index = ndl_find_reducer_s(HDL(g),sig);
1651: if ( index >= 0 && index < nd_psn ) {
1652: // reducer found
1653: h = nd_psh[index];
1654: ndl_sub(HDL(g),DL(h),DL(mul));
1655: if ( ndl_check_bound2(index,DL(mul)) ) {
1656: nd_free(g); nd_free(d);
1657: return 0;
1658: }
1659: p = ps[index];
1660: /* d+g -> div*(d+g)+mul*p */
1661: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1662: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1663: if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
1664: hg = HCU(g);
1665: nd_removecont2(d,g);
1666: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1667: }
1668: } else if ( index == -1 ) {
1669: // singular top reducible
1670: return -1;
1671: } else if ( !full ) {
1672: *rp = g;
1673: g->sig = sig;
1674: return 1;
1675: } else {
1676: m = BDY(g);
1677: if ( NEXT(m) ) {
1678: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1679: } else {
1680: FREEND(g); g = 0;
1681: }
1682: if ( d ) {
1683: NEXT(tail)=m; tail=m; LEN(d)++;
1684: } else {
1685: MKND(n,m,1,d); tail = BDY(d);
1686: }
1687: }
1688: }
1689: if ( d ) {
1690: SG(d) = sugar;
1691: d->sig = sig;
1692: }
1693: *rp = d;
1694: return 1;
1695: }
1696:
1.1 noro 1697: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1698: {
1699: int hindex,index;
1700: NDV p;
1701: ND u,d,red;
1702: NODE l;
1703: NM mul,m,mrd,tail;
1704: int sugar,psugar,n,h_reducible;
1705: PGeoBucket bucket;
1706: int c,c1,c2;
1707: Z cg,cred,gcd,zzz;
1708: RHist h;
1709: double hmag,gmag;
1710: int count = 0;
1711: int hcount = 0;
1712:
1713: if ( !g ) {
1714: *rp = 0;
1715: return 1;
1716: }
1717: sugar = SG(g);
1718: n = NV(g);
1.6 noro 1719: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1720: bucket = create_pbucket();
1721: add_pbucket(mod,bucket,g);
1722: d = 0;
1723: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1724: while ( 1 ) {
1725: if ( mod > 0 || mod == -1 )
1726: hindex = head_pbucket(mod,bucket);
1727: else if ( mod == -2 )
1728: hindex = head_pbucket_lf(bucket);
1729: else
1730: hindex = head_pbucket_q(bucket);
1731: if ( hindex < 0 ) {
1732: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1733: if ( d ) SG(d) = sugar;
1734: *rp = d;
1735: return 1;
1736: }
1737: g = bucket->body[hindex];
1738: index = ndl_find_reducer(HDL(g));
1739: if ( index >= 0 ) {
1740: count++;
1741: if ( !d ) hcount++;
1742: h = nd_psh[index];
1743: ndl_sub(HDL(g),DL(h),DL(mul));
1744: if ( ndl_check_bound2(index,DL(mul)) ) {
1745: nd_free(d);
1746: free_pbucket(bucket);
1747: *rp = 0;
1748: return 0;
1749: }
1750: p = ps[index];
1751: if ( mod == -1 )
1752: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1753: else if ( mod == -2 ) {
1754: Z inv,t;
1755: divlf(ONE,HCZ(p),&inv);
1756: chsgnlf(HCZ(g),&t);
1757: mullf(inv,t,&CZ(mul));
1758: } else if ( mod ) {
1759: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1760: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1761: } else {
1.6 noro 1762: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1763: chsgnz(cg,&CZ(mul));
1.1 noro 1764: nd_mul_c_q(d,(P)cred);
1765: mulq_pbucket(bucket,cred);
1766: g = bucket->body[hindex];
1.6 noro 1767: gmag = (double)p_mag((P)HCZ(g));
1.1 noro 1768: }
1769: red = ndv_mul_nm(mod,mul,p);
1770: bucket->body[hindex] = nd_remove_head(g);
1771: red = nd_remove_head(red);
1772: add_pbucket(mod,bucket,red);
1773: psugar = SG(p)+TD(DL(mul));
1774: sugar = MAX(sugar,psugar);
1775: if ( !mod && hmag && (gmag > hmag) ) {
1776: g = normalize_pbucket(mod,bucket);
1777: if ( !g ) {
1778: if ( d ) SG(d) = sugar;
1779: *rp = d;
1780: return 1;
1781: }
1782: nd_removecont2(d,g);
1.6 noro 1783: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1784: add_pbucket(mod,bucket,g);
1785: }
1786: } else if ( !full ) {
1787: g = normalize_pbucket(mod,bucket);
1788: if ( g ) SG(g) = sugar;
1789: *rp = g;
1790: return 1;
1791: } else {
1792: m = BDY(g);
1793: if ( NEXT(m) ) {
1794: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1795: } else {
1796: FREEND(g); g = 0;
1797: }
1798: bucket->body[hindex] = g;
1799: NEXT(m) = 0;
1800: if ( d ) {
1801: NEXT(tail)=m; tail=m; LEN(d)++;
1802: } else {
1803: MKND(n,m,1,d); tail = BDY(d);
1804: }
1805: }
1806: }
1807: }
1808:
1.25 noro 1809: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *rp)
1810: {
1811: int hindex,index;
1812: NDV p;
1813: ND u,d,red;
1814: NODE l;
1815: NM mul,m,mrd,tail;
1816: int sugar,psugar,n,h_reducible;
1817: PGeoBucket bucket;
1818: int c,c1,c2;
1819: Z cg,cred,gcd,zzz;
1820: RHist h;
1821: double hmag,gmag;
1822: int count = 0;
1823: int hcount = 0;
1824: SIG sig;
1825:
1826: if ( !g ) {
1827: *rp = 0;
1828: return 1;
1829: }
1830: sugar = SG(g);
1831: n = NV(g);
1832: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1833: bucket = create_pbucket();
1834: add_pbucket(mod,bucket,g);
1835: d = 0;
1836: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1837: sig = g->sig;
1838: while ( 1 ) {
1839: if ( mod > 0 || mod == -1 )
1840: hindex = head_pbucket(mod,bucket);
1841: else if ( mod == -2 )
1842: hindex = head_pbucket_lf(bucket);
1843: else
1844: hindex = head_pbucket_q(bucket);
1845: if ( hindex < 0 ) {
1846: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1847: if ( d ) {
1848: SG(d) = sugar;
1849: d->sig = sig;
1850: }
1851: *rp = d;
1852: return 1;
1853: }
1854: g = bucket->body[hindex];
1855: index = ndl_find_reducer_s(HDL(g),sig);
1856: if ( index >= 0 && index < nd_psn ) {
1857: count++;
1858: if ( !d ) hcount++;
1859: h = nd_psh[index];
1860: ndl_sub(HDL(g),DL(h),DL(mul));
1861: if ( ndl_check_bound2(index,DL(mul)) ) {
1862: nd_free(d);
1863: free_pbucket(bucket);
1864: *rp = 0;
1865: return 0;
1866: }
1867: p = ps[index];
1868: if ( mod == -1 )
1869: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1870: else if ( mod == -2 ) {
1871: Z inv,t;
1872: divlf(ONE,HCZ(p),&inv);
1873: chsgnlf(HCZ(g),&t);
1874: mullf(inv,t,&CZ(mul));
1875: } else if ( mod ) {
1876: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1877: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1878: } else {
1879: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1880: chsgnz(cg,&CZ(mul));
1881: nd_mul_c_q(d,(P)cred);
1882: mulq_pbucket(bucket,cred);
1883: g = bucket->body[hindex];
1884: gmag = (double)p_mag((P)HCZ(g));
1885: }
1886: red = ndv_mul_nm(mod,mul,p);
1887: bucket->body[hindex] = nd_remove_head(g);
1888: red = nd_remove_head(red);
1889: add_pbucket(mod,bucket,red);
1890: psugar = SG(p)+TD(DL(mul));
1891: sugar = MAX(sugar,psugar);
1892: if ( !mod && hmag && (gmag > hmag) ) {
1893: g = normalize_pbucket(mod,bucket);
1894: if ( !g ) {
1895: if ( d ) {
1896: SG(d) = sugar;
1897: d->sig = sig;
1898: }
1899: *rp = d;
1900: return 1;
1901: }
1902: nd_removecont2(d,g);
1903: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1904: add_pbucket(mod,bucket,g);
1905: }
1906: } else if ( index == -1 ) {
1907: // singular top reducible
1908: return -1;
1909: } else if ( !full ) {
1910: g = normalize_pbucket(mod,bucket);
1911: if ( g ) {
1912: SG(g) = sugar;
1913: g->sig = sig;
1914: }
1915: *rp = g;
1916: return 1;
1917: } else {
1918: m = BDY(g);
1919: if ( NEXT(m) ) {
1920: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1921: } else {
1922: FREEND(g); g = 0;
1923: }
1924: bucket->body[hindex] = g;
1925: NEXT(m) = 0;
1926: if ( d ) {
1927: NEXT(tail)=m; tail=m; LEN(d)++;
1928: } else {
1929: MKND(n,m,1,d); tail = BDY(d);
1930: }
1931: }
1932: }
1933: }
1934:
1.1 noro 1935: /* input : list of NDV, cand : list of NDV */
1936:
1937: int ndv_check_membership(int m,NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1938: {
1939: int n,i,stat;
1940: ND nf,d;
1941: NDV r;
1942: NODE t,s;
1943: union oNDC dn;
1944: Z q;
1945: LIST list;
1946:
1.24 noro 1947: ndv_setup(m,0,cand,nd_gentrace?1:0,1,0);
1.1 noro 1948: n = length(cand);
1949:
1950: if ( nd_gentrace ) { nd_alltracelist = 0; nd_tracelist = 0; }
1951: /* membercheck : list is a subset of Id(cand) ? */
1952: for ( t = input, i = 0; t; t = NEXT(t), i++ ) {
1953: again:
1954: nd_tracelist = 0;
1955: if ( nd_bpe > obpe )
1956: r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
1957: else
1958: r = (NDV)BDY(t);
1959: #if 0
1960: // moved to nd_f4_lf_trace()
1961: if ( m == -2 ) ndv_mod(m,r);
1962: #endif
1963: d = ndvtond(m,r);
1.6 noro 1964: stat = nd_nf(m,0,d,nd_ps,0,&nf);
1.1 noro 1965: if ( !stat ) {
1966: nd_reconstruct(0,0);
1967: goto again;
1968: } else if ( nf ) return 0;
1969: if ( nd_gentrace ) {
1970: nd_tracelist = reverse_node(nd_tracelist);
1971: MKLIST(list,nd_tracelist);
1.6 noro 1972: STOZ(i,q); s = mknode(2,q,list); MKLIST(list,s);
1.1 noro 1973: MKNODE(s,list,nd_alltracelist);
1974: nd_alltracelist = s; nd_tracelist = 0;
1975: }
1976: if ( DP_Print ) { printf("."); fflush(stdout); }
1977: }
1978: if ( DP_Print ) { printf("\n"); }
1979: return 1;
1980: }
1981:
1982: ND nd_remove_head(ND p)
1983: {
1984: NM m;
1985:
1986: m = BDY(p);
1987: if ( !NEXT(m) ) {
1988: FREEND(p); p = 0;
1989: } else {
1990: BDY(p) = NEXT(m); LEN(p)--;
1991: }
1992: FREENM(m);
1993: return p;
1994: }
1995:
1996: ND nd_separate_head(ND p,ND *head)
1997: {
1998: NM m,m0;
1999: ND r;
2000:
2001: m = BDY(p);
2002: if ( !NEXT(m) ) {
2003: *head = p; p = 0;
2004: } else {
2005: m0 = m;
2006: BDY(p) = NEXT(m); LEN(p)--;
2007: NEXT(m0) = 0;
2008: MKND(NV(p),m0,1,r);
2009: *head = r;
2010: }
2011: return p;
2012: }
2013:
2014: PGeoBucket create_pbucket()
2015: {
2016: PGeoBucket g;
2017:
2018: g = CALLOC(1,sizeof(struct oPGeoBucket));
2019: g->m = -1;
2020: return g;
2021: }
2022:
2023: void free_pbucket(PGeoBucket b) {
2024: int i;
2025:
2026: for ( i = 0; i <= b->m; i++ )
2027: if ( b->body[i] ) {
2028: nd_free(b->body[i]);
2029: b->body[i] = 0;
2030: }
2031: GCFREE(b);
2032: }
2033:
1.39 noro 2034: #if 0
1.1 noro 2035: void add_pbucket_symbolic(PGeoBucket g,ND d)
2036: {
2037: int l,i,k,m;
2038:
2039: if ( !d )
2040: return;
2041: l = LEN(d);
2042: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2043: /* 2^(k-1) < l <= 2^k (=m) */
2044: d = nd_merge(g->body[k],d);
2045: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2046: g->body[k] = 0;
2047: d = nd_merge(g->body[k+1],d);
2048: }
2049: g->body[k] = d;
2050: g->m = MAX(g->m,k);
2051: }
1.39 noro 2052: #else
2053: void add_pbucket_symbolic(PGeoBucket g,ND d)
2054: {
2055: int l,i,k,m,m0;
2056:
2057: if ( !d )
2058: return;
2059: m0 = g->m;
2060: while ( 1 ) {
2061: l = LEN(d);
2062: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2063: /* 2^(k-1) < l <= 2^k (=m) */
2064: if ( g->body[k] == 0 ) {
2065: g->body[k] = d;
2066: m0 = MAX(k,m0);
2067: break;
2068: } else {
2069: d = nd_merge(g->body[k],d);
2070: g->body[k] = 0;
2071: }
2072: }
2073: g->m = m0;
2074: }
2075: #endif
1.1 noro 2076:
1.39 noro 2077: #if 0
1.1 noro 2078: void add_pbucket(int mod,PGeoBucket g,ND d)
2079: {
2080: int l,i,k,m;
2081:
2082: if ( !d )
2083: return;
2084: l = LEN(d);
2085: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2086: /* 2^(k-1) < l <= 2^k (=m) */
2087: d = nd_add(mod,g->body[k],d);
2088: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2089: g->body[k] = 0;
2090: d = nd_add(mod,g->body[k+1],d);
2091: }
2092: g->body[k] = d;
2093: g->m = MAX(g->m,k);
2094: }
1.39 noro 2095: #else
2096: void add_pbucket(int mod,PGeoBucket g,ND d)
2097: {
2098: int l,i,k,m,m0;
2099:
2100: m0 = g->m;
2101: while ( d != 0 ) {
2102: l = LEN(d);
2103: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2104: /* 2^(k-1) < l <= 2^k (=m) */
2105: if ( g->body[k] == 0 ) {
2106: g->body[k] = d;
2107: m0 = MAX(k,m0);
2108: break;
2109: } else {
2110: d = nd_add(mod,g->body[k],d);
2111: g->body[k] = 0;
2112: }
2113: }
2114: g->m = m0;
2115: }
2116: #endif
1.1 noro 2117:
2118: void mulq_pbucket(PGeoBucket g,Z c)
2119: {
2120: int k;
2121:
2122: for ( k = 0; k <= g->m; k++ )
2123: nd_mul_c_q(g->body[k],(P)c);
2124: }
2125:
2126: NM remove_head_pbucket_symbolic(PGeoBucket g)
2127: {
2128: int j,i,k,c;
2129: NM head;
2130:
2131: k = g->m;
2132: j = -1;
2133: for ( i = 0; i <= k; i++ ) {
2134: if ( !g->body[i] ) continue;
2135: if ( j < 0 ) j = i;
2136: else {
2137: c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
2138: if ( c > 0 )
2139: j = i;
2140: else if ( c == 0 )
2141: g->body[i] = nd_remove_head(g->body[i]);
2142: }
2143: }
2144: if ( j < 0 ) return 0;
2145: else {
2146: head = BDY(g->body[j]);
2147: if ( !NEXT(head) ) {
2148: FREEND(g->body[j]);
2149: g->body[j] = 0;
2150: } else {
2151: BDY(g->body[j]) = NEXT(head);
2152: LEN(g->body[j])--;
2153: }
2154: return head;
2155: }
2156: }
2157:
2158: int head_pbucket(int mod,PGeoBucket g)
2159: {
2160: int j,i,c,k,nv,sum;
2161: UINT *di,*dj;
2162: ND gi,gj;
2163:
2164: k = g->m;
2165: while ( 1 ) {
2166: j = -1;
2167: for ( i = 0; i <= k; i++ ) {
2168: if ( !(gi = g->body[i]) )
2169: continue;
2170: if ( j < 0 ) {
2171: j = i;
2172: gj = g->body[j];
2173: dj = HDL(gj);
2174: sum = HCM(gj);
2175: } else {
2176: c = DL_COMPARE(HDL(gi),dj);
2177: if ( c > 0 ) {
2178: if ( sum ) HCM(gj) = sum;
2179: else g->body[j] = nd_remove_head(gj);
2180: j = i;
2181: gj = g->body[j];
2182: dj = HDL(gj);
2183: sum = HCM(gj);
2184: } else if ( c == 0 ) {
2185: if ( mod == -1 )
2186: sum = _addsf(sum,HCM(gi));
2187: else {
2188: sum = sum+HCM(gi)-mod;
2189: if ( sum < 0 ) sum += mod;
2190: }
2191: g->body[i] = nd_remove_head(gi);
2192: }
2193: }
2194: }
2195: if ( j < 0 ) return -1;
2196: else if ( sum ) {
2197: HCM(gj) = sum;
2198: return j;
2199: } else
2200: g->body[j] = nd_remove_head(gj);
2201: }
2202: }
2203:
2204: int head_pbucket_q(PGeoBucket g)
2205: {
2206: int j,i,c,k,nv;
2207: Z sum,t;
2208: ND gi,gj;
2209:
2210: k = g->m;
2211: while ( 1 ) {
2212: j = -1;
2213: for ( i = 0; i <= k; i++ ) {
2214: if ( !(gi = g->body[i]) ) continue;
2215: if ( j < 0 ) {
2216: j = i;
2217: gj = g->body[j];
1.6 noro 2218: sum = HCZ(gj);
1.1 noro 2219: } else {
2220: nv = NV(gi);
2221: c = DL_COMPARE(HDL(gi),HDL(gj));
2222: if ( c > 0 ) {
1.6 noro 2223: if ( sum ) HCZ(gj) = sum;
1.1 noro 2224: else g->body[j] = nd_remove_head(gj);
2225: j = i;
2226: gj = g->body[j];
1.6 noro 2227: sum = HCZ(gj);
1.1 noro 2228: } else if ( c == 0 ) {
1.6 noro 2229: addz(sum,HCZ(gi),&t);
1.1 noro 2230: sum = t;
2231: g->body[i] = nd_remove_head(gi);
2232: }
2233: }
2234: }
2235: if ( j < 0 ) return -1;
2236: else if ( sum ) {
1.6 noro 2237: HCZ(gj) = sum;
1.1 noro 2238: return j;
2239: } else
2240: g->body[j] = nd_remove_head(gj);
2241: }
2242: }
2243:
2244: int head_pbucket_lf(PGeoBucket g)
2245: {
2246: int j,i,c,k,nv;
2247: Z sum,t;
2248: ND gi,gj;
2249:
2250: k = g->m;
2251: while ( 1 ) {
2252: j = -1;
2253: for ( i = 0; i <= k; i++ ) {
2254: if ( !(gi = g->body[i]) ) continue;
2255: if ( j < 0 ) {
2256: j = i;
2257: gj = g->body[j];
2258: sum = HCZ(gj);
2259: } else {
2260: nv = NV(gi);
2261: c = DL_COMPARE(HDL(gi),HDL(gj));
2262: if ( c > 0 ) {
2263: if ( sum ) HCZ(gj) = sum;
2264: else g->body[j] = nd_remove_head(gj);
2265: j = i;
2266: gj = g->body[j];
2267: sum = HCZ(gj);
2268: } else if ( c == 0 ) {
2269: addlf(sum,HCZ(gi),&t);
2270: sum = t;
2271: g->body[i] = nd_remove_head(gi);
2272: }
2273: }
2274: }
2275: if ( j < 0 ) return -1;
2276: else if ( sum ) {
2277: HCZ(gj) = sum;
2278: return j;
2279: } else
2280: g->body[j] = nd_remove_head(gj);
2281: }
2282: }
2283:
2284: ND normalize_pbucket(int mod,PGeoBucket g)
2285: {
2286: int i;
2287: ND r,t;
2288:
2289: r = 0;
2290: for ( i = 0; i <= g->m; i++ ) {
2291: r = nd_add(mod,r,g->body[i]);
2292: g->body[i] = 0;
2293: }
2294: g->m = -1;
2295: return r;
2296: }
2297:
2298: #if 0
2299: void register_hcf(NDV p)
2300: {
2301: DCP dc,t;
2302: P hc,h;
2303: int c;
2304: NODE l,l1,prev;
2305:
2306: hc = p->body->c.p;
2307: if ( !nd_vc || NUM(hc) ) return;
2308: fctrp(nd_vc,hc,&dc);
2309: for ( t = dc; t; t = NEXT(t) ) {
2310: h = t->c;
2311: if ( NUM(h) ) continue;
2312: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2313: c = compp(nd_vc,h,(P)BDY(l));
2314: if ( c >= 0 ) break;
2315: }
2316: if ( !l || c > 0 ) {
2317: MKNODE(l1,h,l);
2318: if ( !prev )
2319: nd_hcf = l1;
2320: else
2321: NEXT(prev) = l1;
2322: }
2323: }
2324: }
2325: #else
2326: void register_hcf(NDV p)
2327: {
2328: DCP dc,t;
2329: P hc,h,q;
2330: Q dmy;
2331: int c;
2332: NODE l,l1,prev;
2333:
2334: hc = p->body->c.p;
2335: if ( NUM(hc) ) return;
2336: ptozp(hc,1,&dmy,&h);
2337: #if 1
2338: for ( l = nd_hcf; l; l = NEXT(l) ) {
2339: while ( 1 ) {
2340: if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
2341: else break;
2342: }
2343: }
2344: if ( NUM(h) ) return;
2345: #endif
2346: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2347: c = compp(nd_vc,h,(P)BDY(l));
2348: if ( c >= 0 ) break;
2349: }
2350: if ( !l || c > 0 ) {
2351: MKNODE(l1,h,l);
2352: if ( !prev )
2353: nd_hcf = l1;
2354: else
2355: NEXT(prev) = l1;
2356: }
2357: }
2358: #endif
2359:
2360: int do_diagonalize(int sugar,int m)
2361: {
1.6 noro 2362: int i,nh,stat;
2363: NODE r,g,t;
2364: ND h,nf,s,head;
2365: NDV nfv;
2366: Q q;
2367: P nm,nmp,dn,mnp,dnp,cont,cont1;
2368: union oNDC hc;
2369: NODE node;
2370: LIST l;
2371: Z iq;
1.1 noro 2372:
1.6 noro 2373: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2374: if ( nd_gentrace ) {
2375: /* Trace = [1,index,1,1] */
2376: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2377: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2378: }
2379: if ( nd_demand )
2380: nfv = ndv_load(i);
2381: else
2382: nfv = nd_ps[i];
2383: s = ndvtond(m,nfv);
2384: s = nd_separate_head(s,&head);
2385: stat = nd_nf(m,head,s,nd_ps,1,&nf);
2386: if ( !stat ) return 0;
2387: ndv_free(nfv);
2388: hc = HCU(nf); nd_removecont(m,nf);
2389: /* exact division */
2390: cont = ndc_div(m,hc,HCU(nf));
1.1 noro 2391: if ( nd_gentrace ) finalize_tracelist(i,cont);
1.6 noro 2392: nfv = ndtondv(m,nf);
2393: nd_free(nf);
2394: nd_bound[i] = ndv_compute_bound(nfv);
2395: if ( !m ) register_hcf(nfv);
2396: if ( nd_demand ) {
2397: ndv_save(nfv,i);
2398: ndv_free(nfv);
2399: } else
2400: nd_ps[i] = nfv;
2401: }
2402: return 1;
1.1 noro 2403: }
2404:
2405: LIST compute_splist()
2406: {
2407: NODE g,tn0,tn,node;
2408: LIST l0;
2409: ND_pairs d,t;
2410: int i;
2411: Z i1,i2;
2412:
2413: g = 0; d = 0;
2414: for ( i = 0; i < nd_psn; i++ ) {
2415: d = update_pairs(d,g,i,0);
2416: g = update_base(g,i);
2417: }
2418: for ( t = d, tn0 = 0; t; t = NEXT(t) ) {
2419: NEXTNODE(tn0,tn);
1.6 noro 2420: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 2421: node = mknode(2,i1,i2); MKLIST(l0,node);
2422: BDY(tn) = l0;
2423: }
2424: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
2425: return l0;
2426: }
2427:
2428: /* return value = 0 => input is not a GB */
2429:
2430: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2431: {
1.6 noro 2432: int i,nh,sugar,stat;
2433: NODE r,g,t;
2434: ND_pairs d;
2435: ND_pairs l;
2436: ND h,nf,s,head,nf1;
2437: NDV nfv;
2438: Z q;
2439: union oNDC dn,hc;
2440: int diag_count = 0;
2441: P cont;
2442: LIST list;
1.27 noro 2443: struct oEGT eg1,eg2,eg_update;
1.6 noro 2444:
1.27 noro 2445: init_eg(&eg_update);
1.11 noro 2446: Nnd_add = 0;
1.6 noro 2447: g = 0; d = 0;
2448: for ( i = 0; i < nd_psn; i++ ) {
2449: d = update_pairs(d,g,i,gensyz);
2450: g = update_base(g,i);
2451: }
2452: sugar = 0;
2453: while ( d ) {
1.1 noro 2454: again:
1.6 noro 2455: l = nd_minp(d,&d);
2456: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2457: if ( SG(l) != sugar ) {
2458: if ( ishomo ) {
2459: diag_count = 0;
2460: stat = do_diagonalize(sugar,m);
1.1 noro 2461: if ( !stat ) {
1.6 noro 2462: NEXT(l) = d; d = l;
2463: d = nd_reconstruct(0,d);
2464: goto again;
1.1 noro 2465: }
1.6 noro 2466: }
2467: sugar = SG(l);
2468: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2469: }
2470: stat = nd_sp(m,0,l,&h);
2471: if ( !stat ) {
2472: NEXT(l) = d; d = l;
2473: d = nd_reconstruct(0,d);
2474: goto again;
2475: }
1.1 noro 2476: #if USE_GEOBUCKET
1.39 noro 2477: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf)
2478: :nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2479: #else
1.39 noro 2480: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2481: #endif
1.6 noro 2482: if ( !stat ) {
2483: NEXT(l) = d; d = l;
2484: d = nd_reconstruct(0,d);
2485: goto again;
2486: } else if ( nf ) {
2487: if ( checkonly || gensyz ) return 0;
1.1 noro 2488: if ( nd_newelim ) {
2489: if ( nd_module ) {
2490: if ( MPOS(HDL(nf)) > 1 ) return 0;
2491: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2492: }
1.6 noro 2493: if ( DP_Print ) { printf("+"); fflush(stdout); }
2494: hc = HCU(nf);
2495: nd_removecont(m,nf);
2496: if ( !m && nd_nalg ) {
2497: nd_monic(0,&nf);
2498: nd_removecont(m,nf);
2499: }
2500: if ( nd_gentrace ) {
2501: /* exact division */
1.1 noro 2502: cont = ndc_div(m,hc,HCU(nf));
2503: if ( m || !UNIQ(cont) ) {
1.6 noro 2504: t = mknode(4,NULLP,NULLP,NULLP,cont);
2505: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2506: nd_tracelist = t;
2507: }
2508: }
1.6 noro 2509: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2510: nh = ndv_newps(m,nfv,0);
1.6 noro 2511: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2512: diag_count = 0;
2513: stat = do_diagonalize(sugar,m);
2514: if ( !stat ) {
2515: NEXT(l) = d; d = l;
2516: d = nd_reconstruct(1,d);
2517: goto again;
1.1 noro 2518: }
1.6 noro 2519: }
1.27 noro 2520: get_eg(&eg1);
1.6 noro 2521: d = update_pairs(d,g,nh,0);
1.27 noro 2522: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2523: g = update_base(g,nh);
2524: FREENDP(l);
2525: } else {
2526: if ( nd_gentrace && gensyz ) {
2527: nd_tracelist = reverse_node(nd_tracelist);
2528: MKLIST(list,nd_tracelist);
2529: STOZ(-1,q); t = mknode(2,q,list); MKLIST(list,t);
2530: MKNODE(t,list,nd_alltracelist);
2531: nd_alltracelist = t; nd_tracelist = 0;
2532: }
2533: if ( DP_Print ) { printf("."); fflush(stdout); }
2534: FREENDP(l);
1.36 noro 2535: }
2536: }
2537: conv_ilist(nd_demand,0,g,indp);
2538: if ( !checkonly && DP_Print ) { printf("nd_gb done. Number of nd_add=%d\n",Nnd_add); fflush(stdout); }
2539:
2540: if ( DP_Print )
2541: print_eg("update",&eg_update);
2542: return g;
1.1 noro 2543: }
2544:
1.30 noro 2545: ND_pairs update_pairs_s(ND_pairs d,int t,NODE *syz);
2546: ND_pairs nd_newpairs_s(int t ,NODE *syz);
1.24 noro 2547:
2548: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *nf);
2549: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *nf);
2550:
2551: void _copydl(int n,DL d1,DL d2);
2552: void _subfromdl(int n,DL d1,DL d2);
2553: extern int (*cmpdl)(int n,DL d1,DL d2);
2554:
2555: NODE insert_sig(NODE l,SIG s)
2556: {
2557: int pos;
2558: DL sig;
2559: struct oNODE root;
2560: NODE p,prev,r;
2561: SIG t;
2562:
2563: pos = s->pos; sig = DL(s);
2564: root.next = l; prev = &root;
2565: for ( p = l; p; p = p->next ) {
2566: t = (SIG)p->body;
2567: if ( t->pos == pos ) {
2568: if ( _dl_redble(DL(t),sig,nd_nvar) )
2569: return root.next;
2570: else if ( _dl_redble(sig,DL(t),nd_nvar) )
2571: // remove p
2572: prev->next = p->next;
2573: } else
2574: prev = p;
2575: }
1.27 noro 2576: NEWNODE(r); r->body = (pointer)s; r->next = 0;
2577: for ( p = &root; p->next; p = p->next );
2578: p->next = r;
2579: // r->next = root.next;
2580: // return r;
2581: return root.next;
1.24 noro 2582: }
2583:
2584: ND_pairs remove_spair_s(ND_pairs d,SIG sig)
2585: {
2586: struct oND_pairs root;
2587: ND_pairs prev,p;
2588: SIG spsig;
2589:
2590: root.next = d;
2591: prev = &root; p = d;
2592: while ( p ) {
2593: spsig = p->sig;
1.26 noro 2594: if ( sig->pos == spsig->pos && _dl_redble(DL(sig),DL(spsig),nd_nvar) ) {
1.24 noro 2595: // remove p
2596: prev->next = p->next;
1.26 noro 2597: Nsyz++;
2598: } else
1.24 noro 2599: prev = p;
2600: p = p->next;
2601: }
2602: return (ND_pairs)root.next;
2603: }
2604:
1.29 noro 2605: int _dl_redble_ext(DL,DL,DL,int);
2606:
1.28 noro 2607: int small_lcm(ND_pairs l)
2608: {
2609: SIG sig;
2610: int i;
1.29 noro 2611: NODE t;
1.28 noro 2612: static DL lcm,mul,quo;
2613: static int nvar;
2614:
1.38 noro 2615: if ( nd_sba_largelcm ) return 0;
1.28 noro 2616: if ( nvar < nd_nvar ) {
2617: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(quo,nvar); NEWDL(mul,nvar);
2618: }
2619: sig = l->sig;
2620: _ndltodl(l->lcm,lcm);
1.29 noro 2621: #if 0
1.28 noro 2622: for ( i = 0; i < nd_psn; i++ ) {
2623: if ( sig->pos == nd_psh[i]->sig->pos &&
1.29 noro 2624: _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
1.28 noro 2625: _ndltodl(DL(nd_psh[i]),mul);
2626: _addtodl(nd_nvar,quo,mul);
2627: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2628: break;
2629: }
2630: }
2631: if ( i < nd_psn ) return 1;
2632: else return 0;
1.29 noro 2633: #else
2634: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2635: i = (long)BDY(t);
2636: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2637: _ndltodl(DL(nd_psh[i]),mul);
2638: _addtodl(nd_nvar,quo,mul);
2639: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2640: break;
2641: }
2642: }
2643: if ( t ) return 1;
2644: else return 0;
2645: #endif
1.28 noro 2646: }
2647:
2648: ND_pairs remove_large_lcm(ND_pairs d)
2649: {
2650: struct oND_pairs root;
2651: ND_pairs prev,p;
2652:
2653: root.next = d;
2654: prev = &root; p = d;
2655: while ( p ) {
2656: if ( small_lcm(p) ) {
2657: // remove p
2658: prev->next = p->next;
2659: } else
2660: prev = p;
2661: p = p->next;
2662: }
2663: return (ND_pairs)root.next;
2664: }
2665:
1.26 noro 2666: struct oEGT eg_create,eg_newpairs,eg_merge;
2667:
1.30 noro 2668: NODE conv_ilist_s(int demand,int trace,int **indp);
2669:
1.24 noro 2670: NODE nd_sba_buch(int m,int ishomo,int **indp)
2671: {
1.39 noro 2672: int i,j,nh,sugar,stat,pos;
1.30 noro 2673: NODE r,t,g;
1.24 noro 2674: ND_pairs d;
2675: ND_pairs l;
2676: ND h,nf,s,head,nf1;
2677: NDV nfv;
2678: Z q;
2679: union oNDC dn,hc;
2680: P cont;
2681: LIST list;
2682: SIG sig;
1.29 noro 2683: NODE *syzlist;
1.26 noro 2684: int Nredundant;
1.28 noro 2685: DL lcm,quo,mul;
1.31 noro 2686: struct oEGT eg1,eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.24 noro 2687:
1.27 noro 2688: init_eg(&eg_remove);
1.29 noro 2689: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.26 noro 2690: Nsyz = 0;
1.24 noro 2691: Nnd_add = 0;
1.26 noro 2692: Nredundant = 0;
1.30 noro 2693: d = 0;
1.24 noro 2694: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 2695: d = update_pairs_s(d,i,syzlist);
1.24 noro 2696: }
1.29 noro 2697: for ( i = 0; i < nd_psn; i++ )
2698: for ( j = i+1; j < nd_psn; j++ ) {
2699: NEWSIG(sig); sig->pos = j;
2700: _copydl(nd_nvar,nd_sba_hm[i],sig->dl);
2701: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
2702: }
1.24 noro 2703: sugar = 0;
1.39 noro 2704: pos = 0;
1.26 noro 2705: NEWDL(lcm,nd_nvar); NEWDL(quo,nd_nvar); NEWDL(mul,nd_nvar);
2706: init_eg(&eg_create);
2707: init_eg(&eg_merge);
1.29 noro 2708: init_eg(&eg_large);
1.31 noro 2709: init_eg(&eg_nf);
2710: init_eg(&eg_nfzero);
1.24 noro 2711: while ( d ) {
2712: again:
1.26 noro 2713: if ( DP_Print ) {
2714: int len;
2715: ND_pairs td;
1.28 noro 2716: for ( td = d, len=0; td; td = td->next, len++)
2717: ;
1.26 noro 2718: if ( !(len%100) ) fprintf(asir_out,"(%d)",len);
2719: }
1.24 noro 2720: l = d; d = d->next;
1.28 noro 2721: if ( small_lcm(l) ) {
1.24 noro 2722: if ( DP_Print ) fprintf(asir_out,"M");
1.26 noro 2723: Nredundant++;
1.24 noro 2724: continue;
2725: }
2726: if ( SG(l) != sugar ) {
2727: sugar = SG(l);
2728: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2729: }
1.28 noro 2730: sig = l->sig;
1.39 noro 2731: if ( DP_Print && nd_sba_pot ) {
2732: if ( sig->pos != pos ) {
2733: fprintf(asir_out,"[%d]",sig->pos);
2734: pos = sig->pos;
2735: }
2736: }
1.24 noro 2737: stat = nd_sp(m,0,l,&h);
2738: if ( !stat ) {
2739: NEXT(l) = d; d = l;
2740: d = nd_reconstruct(0,d);
2741: goto again;
2742: }
1.31 noro 2743: get_eg(&eg1);
1.25 noro 2744: #if USE_GEOBUCKET
1.39 noro 2745: 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 2746: #else
1.39 noro 2747: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.24 noro 2748: #endif
1.31 noro 2749: get_eg(&eg2);
1.24 noro 2750: if ( !stat ) {
2751: NEXT(l) = d; d = l;
2752: d = nd_reconstruct(0,d);
2753: goto again;
2754: } else if ( stat == -1 ) {
2755: if ( DP_Print ) { printf("S"); fflush(stdout); }
1.27 noro 2756: FREENDP(l);
1.24 noro 2757: } else if ( nf ) {
2758: if ( DP_Print ) { printf("+"); fflush(stdout); }
1.31 noro 2759: add_eg(&eg_nf,&eg1,&eg2);
1.24 noro 2760: hc = HCU(nf);
2761: nd_removecont(m,nf);
2762: nfv = ndtondv(m,nf); nd_free(nf);
2763: nh = ndv_newps(m,nfv,0);
1.26 noro 2764:
1.30 noro 2765: d = update_pairs_s(d,nh,syzlist);
1.29 noro 2766: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.24 noro 2767: FREENDP(l);
2768: } else {
1.31 noro 2769: add_eg(&eg_nfzero,&eg1,&eg2);
1.24 noro 2770: // syzygy
1.27 noro 2771: get_eg(&eg1);
1.24 noro 2772: d = remove_spair_s(d,sig);
1.27 noro 2773: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 2774: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.24 noro 2775: if ( DP_Print ) { printf("."); fflush(stdout); }
2776: FREENDP(l);
2777: }
2778: }
1.30 noro 2779: g = conv_ilist_s(nd_demand,0,indp);
1.26 noro 2780: if ( DP_Print ) {
1.35 noro 2781: printf("\nnd_sba done. nd_add=%d,Nsyz=%d,Nsamesig=%d,Nredundant=%d\n",Nnd_add,Nsyz,Nsamesig,Nredundant);
1.26 noro 2782: fflush(stdout);
2783: print_eg("create",&eg_create);
2784: print_eg("merge",&eg_merge);
1.27 noro 2785: print_eg("remove",&eg_remove);
1.31 noro 2786: print_eg("nf",&eg_nf);
2787: print_eg("nfzero",&eg_nfzero);
1.27 noro 2788: printf("\n");
1.26 noro 2789: }
1.24 noro 2790: return g;
2791: }
2792:
1.1 noro 2793: /* splist = [[i1,i2],...] */
2794:
2795: int check_splist(int m,NODE splist)
2796: {
2797: NODE t,p;
2798: ND_pairs d,r,l;
2799: int stat;
2800: ND h,nf;
2801:
2802: for ( d = 0, t = splist; t; t = NEXT(t) ) {
2803: p = BDY((LIST)BDY(t));
1.6 noro 2804: NEXTND_pairs(d,r);
2805: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
2806: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 2807: SG(r) = TD(LCM(r)); /* XXX */
2808: }
2809: if ( d ) NEXT(r) = 0;
2810:
1.6 noro 2811: while ( d ) {
1.1 noro 2812: again:
1.6 noro 2813: l = nd_minp(d,&d);
2814: stat = nd_sp(m,0,l,&h);
2815: if ( !stat ) {
2816: NEXT(l) = d; d = l;
2817: d = nd_reconstruct(0,d);
2818: goto again;
2819: }
1.39 noro 2820: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.6 noro 2821: if ( !stat ) {
2822: NEXT(l) = d; d = l;
2823: d = nd_reconstruct(0,d);
2824: goto again;
2825: } else if ( nf ) return 0;
1.1 noro 2826: if ( DP_Print) { printf("."); fflush(stdout); }
1.6 noro 2827: }
1.1 noro 2828: if ( DP_Print) { printf("done.\n"); fflush(stdout); }
2829: return 1;
2830: }
2831:
2832: int check_splist_f4(int m,NODE splist)
2833: {
2834: UINT *s0vect;
1.6 noro 2835: PGeoBucket bucket;
1.1 noro 2836: NODE p,rp0,t;
2837: ND_pairs d,r,l,ll;
2838: int col,stat;
2839:
2840: for ( d = 0, t = splist; t; t = NEXT(t) ) {
2841: p = BDY((LIST)BDY(t));
1.6 noro 2842: NEXTND_pairs(d,r);
2843: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
2844: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 2845: SG(r) = TD(LCM(r)); /* XXX */
2846: }
2847: if ( d ) NEXT(r) = 0;
2848:
1.6 noro 2849: while ( d ) {
2850: l = nd_minsugarp(d,&d);
2851: bucket = create_pbucket();
2852: stat = nd_sp_f4(m,0,l,bucket);
2853: if ( !stat ) {
2854: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
2855: NEXT(ll) = d; d = l;
2856: d = nd_reconstruct(0,d);
2857: continue;
2858: }
2859: if ( bucket->m < 0 ) continue;
2860: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
2861: if ( !col ) {
2862: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
2863: NEXT(ll) = d; d = l;
2864: d = nd_reconstruct(0,d);
2865: continue;
1.1 noro 2866: }
1.6 noro 2867: if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0;
2868: }
2869: return 1;
1.1 noro 2870: }
2871:
2872: int do_diagonalize_trace(int sugar,int m)
2873: {
1.6 noro 2874: int i,nh,stat;
2875: NODE r,g,t;
2876: ND h,nf,nfq,s,head;
2877: NDV nfv,nfqv;
2878: Q q,den,num;
2879: union oNDC hc;
2880: NODE node;
2881: LIST l;
2882: Z iq;
2883: P cont,cont1;
1.1 noro 2884:
1.6 noro 2885: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2886: if ( nd_gentrace ) {
2887: /* Trace = [1,index,1,1] */
2888: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2889: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2890: }
2891: /* for nd_ps */
2892: s = ndvtond(m,nd_ps[i]);
2893: s = nd_separate_head(s,&head);
2894: stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
2895: if ( !stat ) return 0;
2896: nf = nd_add(m,head,nf);
2897: ndv_free(nd_ps[i]);
2898: nd_ps[i] = ndtondv(m,nf);
2899: nd_free(nf);
2900:
2901: /* for nd_ps_trace */
2902: if ( nd_demand )
2903: nfv = ndv_load(i);
2904: else
2905: nfv = nd_ps_trace[i];
2906: s = ndvtond(0,nfv);
2907: s = nd_separate_head(s,&head);
2908: stat = nd_nf(0,head,s,nd_ps_trace,1,&nf);
2909: if ( !stat ) return 0;
2910: ndv_free(nfv);
2911: hc = HCU(nf); nd_removecont(0,nf);
2912: /* exact division */
1.1 noro 2913: cont = ndc_div(0,hc,HCU(nf));
1.6 noro 2914: if ( nd_gentrace ) finalize_tracelist(i,cont);
2915: nfv = ndtondv(0,nf);
2916: nd_free(nf);
2917: nd_bound[i] = ndv_compute_bound(nfv);
2918: register_hcf(nfv);
2919: if ( nd_demand ) {
2920: ndv_save(nfv,i);
2921: ndv_free(nfv);
2922: } else
2923: nd_ps_trace[i] = nfv;
2924: }
2925: return 1;
1.1 noro 2926: }
2927:
2928: static struct oEGT eg_invdalg;
2929: struct oEGT eg_le;
2930:
2931: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
2932: {
2933: NODE tn;
2934: P p1;
2935:
2936: for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
2937: substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
2938: }
2939: *r = p;
2940: }
2941:
2942: NODE nd_gb_trace(int m,int ishomo,int **indp)
2943: {
1.6 noro 2944: int i,nh,sugar,stat;
2945: NODE r,g,t;
2946: ND_pairs d;
2947: ND_pairs l;
2948: ND h,nf,nfq,s,head;
2949: NDV nfv,nfqv;
2950: Z q,den,num;
2951: P hc;
2952: union oNDC dn,hnfq;
2953: struct oEGT eg_monic,egm0,egm1;
2954: int diag_count = 0;
2955: P cont;
2956: LIST list;
2957:
2958: init_eg(&eg_monic);
2959: init_eg(&eg_invdalg);
2960: init_eg(&eg_le);
2961: g = 0; d = 0;
2962: for ( i = 0; i < nd_psn; i++ ) {
2963: d = update_pairs(d,g,i,0);
2964: g = update_base(g,i);
2965: }
2966: sugar = 0;
2967: while ( d ) {
1.1 noro 2968: again:
1.6 noro 2969: l = nd_minp(d,&d);
2970: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2971: if ( SG(l) != sugar ) {
1.1 noro 2972: #if 1
1.6 noro 2973: if ( ishomo ) {
2974: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2975: stat = do_diagonalize_trace(sugar,m);
2976: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2977: diag_count = 0;
1.1 noro 2978: if ( !stat ) {
1.6 noro 2979: NEXT(l) = d; d = l;
2980: d = nd_reconstruct(1,d);
2981: goto again;
1.1 noro 2982: }
1.6 noro 2983: }
2984: #endif
2985: sugar = SG(l);
2986: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2987: }
2988: stat = nd_sp(m,0,l,&h);
2989: if ( !stat ) {
2990: NEXT(l) = d; d = l;
2991: d = nd_reconstruct(1,d);
2992: goto again;
2993: }
1.1 noro 2994: #if USE_GEOBUCKET
1.39 noro 2995: stat = nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2996: #else
1.39 noro 2997: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2998: #endif
1.6 noro 2999: if ( !stat ) {
3000: NEXT(l) = d; d = l;
3001: d = nd_reconstruct(1,d);
3002: goto again;
3003: } else if ( nf ) {
3004: if ( nd_demand ) {
3005: nfqv = ndv_load(nd_psn);
3006: nfq = ndvtond(0,nfqv);
3007: } else
3008: nfq = 0;
3009: if ( !nfq ) {
1.39 noro 3010: if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!nd_top&&!Top,&nfq) ) {
1.6 noro 3011: NEXT(l) = d; d = l;
3012: d = nd_reconstruct(1,d);
3013: goto again;
3014: }
3015: }
3016: if ( nfq ) {
3017: /* m|HC(nfq) => failure */
3018: if ( nd_vc ) {
3019: nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Z)hc;
3020: } else
3021: q = HCZ(nfq);
3022: if ( !remqi((Q)q,m) ) return 0;
3023:
3024: if ( DP_Print ) { printf("+"); fflush(stdout); }
3025: hnfq = HCU(nfq);
3026: if ( nd_nalg ) {
3027: /* m|DN(HC(nf)^(-1)) => failure */
3028: get_eg(&egm0);
3029: if ( !nd_monic(m,&nfq) ) return 0;
3030: get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
3031: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3032: nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
3033: } else {
3034: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3035: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
3036: }
3037: if ( nd_gentrace ) {
3038: /* exact division */
3039: cont = ndc_div(0,hnfq,HCU(nfqv));
3040: if ( !UNIQ(cont) ) {
3041: t = mknode(4,NULLP,NULLP,NULLP,cont);
3042: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
3043: nd_tracelist = t;
3044: }
3045: }
1.24 noro 3046: nh = ndv_newps(0,nfv,nfqv);
1.6 noro 3047: if ( ishomo && ++diag_count == diag_period ) {
3048: diag_count = 0;
3049: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3050: stat = do_diagonalize_trace(sugar,m);
3051: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3052: if ( !stat ) {
1.1 noro 3053: NEXT(l) = d; d = l;
3054: d = nd_reconstruct(1,d);
3055: goto again;
1.6 noro 3056: }
1.1 noro 3057: }
1.6 noro 3058: d = update_pairs(d,g,nh,0);
3059: g = update_base(g,nh);
3060: } else {
3061: if ( DP_Print ) { printf("*"); fflush(stdout); }
3062: }
3063: } else {
3064: if ( DP_Print ) { printf("."); fflush(stdout); }
1.1 noro 3065: }
1.6 noro 3066: FREENDP(l);
3067: }
3068: if ( nd_nalg ) {
3069: if ( DP_Print ) {
3070: print_eg("monic",&eg_monic);
3071: print_eg("invdalg",&eg_invdalg);
3072: print_eg("le",&eg_le);
1.1 noro 3073: }
1.6 noro 3074: }
1.1 noro 3075: conv_ilist(nd_demand,1,g,indp);
1.6 noro 3076: if ( DP_Print ) { printf("nd_gb_trace done.\n"); fflush(stdout); }
3077: return g;
1.1 noro 3078: }
3079:
3080: int ndv_compare(NDV *p1,NDV *p2)
3081: {
3082: return DL_COMPARE(HDL(*p1),HDL(*p2));
3083: }
3084:
3085: int ndv_compare_rev(NDV *p1,NDV *p2)
3086: {
3087: return -DL_COMPARE(HDL(*p1),HDL(*p2));
3088: }
3089:
3090: int ndvi_compare(NDVI p1,NDVI p2)
3091: {
3092: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
3093: }
3094:
3095: int ndvi_compare_rev(NDVI p1,NDVI p2)
3096: {
3097: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3098: }
3099:
3100: NODE ndv_reduceall(int m,NODE f)
3101: {
3102: int i,j,n,stat;
3103: ND nf,g,head;
3104: NODE t,a0,a;
3105: union oNDC dn;
3106: Q q,num,den;
3107: NODE node;
3108: LIST l;
3109: Z iq,jq;
3110: int *perm;
3111: union oNDC hc;
3112: P cont,cont1;
3113:
3114: if ( nd_nora ) return f;
3115: n = length(f);
1.24 noro 3116: ndv_setup(m,0,f,0,1,0);
1.1 noro 3117: perm = (int *)MALLOC(n*sizeof(int));
3118: if ( nd_gentrace ) {
3119: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3120: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3121: }
3122: for ( i = 0; i < n; ) {
3123: if ( nd_gentrace ) {
3124: /* Trace = [1,index,1,1] */
1.6 noro 3125: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3126: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3127: }
3128: g = ndvtond(m,nd_ps[i]);
3129: g = nd_separate_head(g,&head);
1.6 noro 3130: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3131: if ( !stat )
3132: nd_reconstruct(0,0);
3133: else {
3134: if ( DP_Print ) { printf("."); fflush(stdout); }
3135: ndv_free(nd_ps[i]);
3136: hc = HCU(nf); nd_removecont(m,nf);
3137: if ( nd_gentrace ) {
3138: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3139: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3140: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3141: }
1.6 noro 3142: /* exact division */
1.1 noro 3143: cont = ndc_div(m,hc,HCU(nf));
3144: finalize_tracelist(perm[i],cont);
3145: }
3146: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3147: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3148: i++;
3149: }
3150: }
3151: if ( DP_Print ) { printf("\n"); }
3152: for ( a0 = 0, i = 0; i < n; i++ ) {
3153: NEXTNODE(a0,a);
3154: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3155: else {
3156: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3157: BDY(a) = (pointer)nd_ps[j];
3158: }
3159: }
3160: NEXT(a) = 0;
3161: return a0;
3162: }
3163:
3164: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3165: {
3166: ND_pairs d1,nd,cur,head,prev,remove;
3167:
3168: if ( !g ) return d;
3169: /* for testing */
3170: if ( gensyz && nd_gensyz == 2 ) {
3171: d1 = nd_newpairs(g,t);
3172: if ( !d )
3173: return d1;
3174: else {
3175: nd = d;
3176: while ( NEXT(nd) ) nd = NEXT(nd);
3177: NEXT(nd) = d1;
3178: return d;
3179: }
3180: }
3181: d = crit_B(d,t);
3182: d1 = nd_newpairs(g,t);
3183: d1 = crit_M(d1);
3184: d1 = crit_F(d1);
3185: if ( gensyz || do_weyl )
3186: head = d1;
3187: else {
3188: prev = 0; cur = head = d1;
3189: while ( cur ) {
3190: if ( crit_2( cur->i1,cur->i2 ) ) {
3191: remove = cur;
3192: if ( !prev ) head = cur = NEXT(cur);
3193: else cur = NEXT(prev) = NEXT(cur);
3194: FREENDP(remove);
3195: } else {
3196: prev = cur; cur = NEXT(cur);
3197: }
3198: }
3199: }
3200: if ( !d )
3201: return head;
3202: else {
3203: nd = d;
3204: while ( NEXT(nd) ) nd = NEXT(nd);
3205: NEXT(nd) = head;
3206: return d;
3207: }
3208: }
3209:
1.24 noro 3210: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3211:
1.30 noro 3212: ND_pairs update_pairs_s( ND_pairs d, int t,NODE *syz)
1.24 noro 3213: {
3214: ND_pairs d1;
1.26 noro 3215: struct oEGT eg1,eg2,eg3;
1.24 noro 3216:
1.30 noro 3217: if ( !t ) return d;
1.26 noro 3218: get_eg(&eg1);
1.30 noro 3219: d1 = nd_newpairs_s(t,syz);
1.26 noro 3220: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3221: d = merge_pairs_s(d,d1);
1.26 noro 3222: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3223: return d;
3224: }
1.1 noro 3225:
3226: ND_pairs nd_newpairs( NODE g, int t )
3227: {
3228: NODE h;
3229: UINT *dl;
3230: int ts,s,i,t0,min,max;
3231: ND_pairs r,r0;
3232:
3233: dl = DL(nd_psh[t]);
3234: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3235: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3236: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3237: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3238: continue;
3239: if ( nd_gbblock ) {
3240: t0 = (long)BDY(h);
3241: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3242: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3243: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3244: break;
3245: }
3246: if ( nd_gbblock[i] >= 0 )
3247: continue;
3248: }
3249: NEXTND_pairs(r0,r);
3250: r->i1 = (long)BDY(h);
3251: r->i2 = t;
3252: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3253: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3254: SG(r) = MAX(s,ts) + TD(LCM(r));
3255: /* experimental */
3256: if ( nd_sugarweight )
3257: r->sugar2 = ndl_weight2(r->lcm);
3258: }
3259: if ( r0 ) NEXT(r) = 0;
3260: return r0;
3261: }
3262:
1.24 noro 3263: int comp_sig(SIG s1,SIG s2)
3264: {
1.38 noro 3265: if ( nd_sba_pot ) {
3266: if ( s1->pos > s2->pos ) return 1;
3267: else if ( s1->pos < s2->pos ) return -1;
3268: else return (*cmpdl)(nd_nvar,s1->dl,s2->dl);
3269: } else {
3270: static DL m1,m2;
3271: static int nvar;
3272: int ret;
3273:
3274: if ( nvar != nd_nvar ) {
3275: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
3276: }
3277: _adddl(nd_nvar,s1->dl,nd_sba_hm[s1->pos],m1);
3278: _adddl(nd_nvar,s2->dl,nd_sba_hm[s2->pos],m2);
3279: ret = (*cmpdl)(nd_nvar,m1,m2);
3280: if ( ret != 0 ) return ret;
3281: else if ( s1->pos > s2->pos ) return 1;
3282: else if ( s1->pos < s2->pos ) return -1;
3283: else return 0;
1.24 noro 3284: }
3285: }
3286:
3287: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3288: {
3289: int ret,s1,s2;
3290: RHist p1,p2;
3291: static int wpd;
3292: static UINT *lcm;
3293:
3294: sp->i1 = i1;
3295: sp->i2 = i2;
3296: p1 = nd_psh[i1];
3297: p2 = nd_psh[i2];
3298: ndl_lcm(DL(p1),DL(p2),sp->lcm);
3299: s1 = SG(p1)-TD(DL(p1));
3300: s2 = SG(p2)-TD(DL(p2));
3301: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
3302:
1.26 noro 3303: if ( wpd != nd_wpd ) {
1.24 noro 3304: wpd = nd_wpd;
3305: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
3306: }
3307: // DL(sig1) <- sp->lcm
3308: // DL(sig1) -= DL(p1)
3309: // DL(sig1) += DL(p1->sig)
1.27 noro 3310: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 3311: _ndltodl(lcm,DL(sig1));
3312: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
3313: sig1->pos = p1->sig->pos;
3314:
3315: // DL(sig2) <- sp->lcm
3316: // DL(sig2) -= DL(p2)
3317: // DL(sig2) += DL(p2->sig)
1.27 noro 3318: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 3319: _ndltodl(lcm,DL(sig2));
3320: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
3321: sig2->pos = p2->sig->pos;
3322:
3323: ret = comp_sig(sig1,sig2);
3324: if ( ret == 0 ) return 0;
3325: else if ( ret > 0 ) sp->sig = sig1;
3326: else sp->sig = sig2;
3327: return 1;
3328: }
3329:
3330: SIG dup_sig(SIG sig)
3331: {
3332: SIG r;
3333:
3334: if ( !sig ) return 0;
3335: else {
3336: NEWSIG(r);
3337: _copydl(nd_nvar,DL(sig),DL(r));
3338: r->pos = sig->pos;
3339: return r;
3340: }
3341: }
3342:
3343: void dup_ND_pairs(ND_pairs to,ND_pairs from)
3344: {
3345: to->i1 = from->i1;
3346: to->i2 = from->i2;
3347: to->sugar = from->sugar;
3348: to->sugar2 = from->sugar2;
3349: ndl_copy(from->lcm,to->lcm);
3350: to->sig = dup_sig(from->sig);
3351: }
3352:
3353: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
3354: {
3355: struct oND_pairs root;
3356: ND_pairs q1,q2,r0,r;
3357: int ret;
3358:
3359: r = &root;
3360: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
3361: ret = comp_sig(q1->sig,q2->sig);
3362: if ( ret < 0 ) {
3363: r->next = q1; r = q1; q1 = q1->next;
3364: } else if ( ret > 0 ) {
3365: r->next = q2; r = q2; q2 = q2->next;
3366: } else {
3367: ret = DL_COMPARE(q1->lcm,q2->lcm);
1.35 noro 3368: Nsamesig++;
1.24 noro 3369: if ( ret < 0 ) {
3370: r->next = q1; r = q1; q1 = q1->next;
3371: q2 = q2->next;
3372: } else {
3373: r->next = q2; r = q2; q2 = q2->next;
3374: q1 = q1->next;
3375: }
3376: }
3377: }
3378: if ( q1 ) {
3379: r->next = q1;
3380: } else {
3381: r->next = q2;
3382: }
3383: return root.next;
3384: }
3385:
3386: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
3387: {
3388: ND_pairs p,prev;
3389: int ret;
3390:
3391: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
3392: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
3393: break;
3394: }
3395: if ( ret == 0 ) {
3396: ret = DL_COMPARE(s->lcm,p->lcm);
3397: if ( ret < 0 ) {
3398: // replace p with s
3399: s->next = p->next;
3400: if ( prev == 0 ) {
3401: return s;
3402: } else {
3403: prev->next = s;
3404: return l;
3405: }
3406: } else
3407: return l;
3408: } else {
3409: // insert s between prev and p
3410: s->next = p;
3411: if ( prev == 0 ) {
3412: return s;
3413: } else {
3414: prev->next = s;
3415: return l;
3416: }
3417: }
3418: }
3419:
1.29 noro 3420: INLINE int __dl_redble(DL d1,DL d2,int nvar)
3421: {
3422: int i;
3423:
3424: if ( d1->td > d2->td )
3425: return 0;
3426: for ( i = nvar-1; i >= 0; i-- )
3427: if ( d1->d[i] > d2->d[i] )
3428: break;
3429: if ( i >= 0 )
3430: return 0;
3431: else
3432: return 1;
3433: }
3434:
1.30 noro 3435: ND_pairs nd_newpairs_s(int t, NODE *syz)
1.24 noro 3436: {
3437: NODE h,s;
3438: UINT *dl;
1.27 noro 3439: int ts,ret,i;
1.24 noro 3440: ND_pairs r,r0,_sp,sp;
1.29 noro 3441: SIG spsig,tsig;
3442: static int nvar;
3443: static SIG _sig1,_sig2;
1.26 noro 3444: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 3445:
3446: NEWND_pairs(_sp);
1.29 noro 3447: if ( !_sig1 || nvar != nd_nvar ) {
3448: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
3449: }
1.24 noro 3450: r0 = 0;
1.27 noro 3451: for ( i = 0; i < t; i++ ) {
3452: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
1.24 noro 3453: if ( ret ) {
3454: spsig = _sp->sig;
1.29 noro 3455: for ( s = syz[spsig->pos]; s; s = s->next ) {
1.24 noro 3456: tsig = (SIG)s->body;
1.29 noro 3457: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
1.24 noro 3458: break;
3459: }
3460: if ( s == 0 ) {
3461: NEWND_pairs(sp);
3462: dup_ND_pairs(sp,_sp);
3463: r0 = insert_pair_s(r0,sp);
1.26 noro 3464: } else
3465: Nsyz++;
1.24 noro 3466: }
3467: }
3468: return r0;
3469: }
3470:
1.1 noro 3471: /* ipair = [i1,i2],[i1,i2],... */
3472: ND_pairs nd_ipairtospair(NODE ipair)
3473: {
3474: int s1,s2;
3475: NODE tn,t;
3476: ND_pairs r,r0;
3477:
3478: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
3479: NEXTND_pairs(r0,r);
3480: tn = BDY((LIST)BDY(t));
1.6 noro 3481: r->i1 = ZTOS((Q)ARG0(tn));
3482: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 3483: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
3484: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3485: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
3486: SG(r) = MAX(s1,s2) + TD(LCM(r));
3487: /* experimental */
3488: if ( nd_sugarweight )
3489: r->sugar2 = ndl_weight2(r->lcm);
3490: }
3491: if ( r0 ) NEXT(r) = 0;
3492: return r0;
3493: }
3494:
3495: /* kokokara */
3496:
3497: ND_pairs crit_B( ND_pairs d, int s )
3498: {
3499: ND_pairs cur,head,prev,remove;
3500: UINT *t,*tl,*lcm;
3501: int td,tdl;
3502:
3503: if ( !d ) return 0;
3504: t = DL(nd_psh[s]);
3505: prev = 0;
3506: head = cur = d;
3507: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
3508: while ( cur ) {
3509: tl = cur->lcm;
3510: if ( ndl_reducible(tl,t) ) {
3511: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
3512: if ( !ndl_equal(lcm,tl) ) {
3513: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
3514: if (!ndl_equal(lcm,tl)) {
3515: remove = cur;
3516: if ( !prev ) {
3517: head = cur = NEXT(cur);
3518: } else {
3519: cur = NEXT(prev) = NEXT(cur);
3520: }
3521: FREENDP(remove);
3522: } else {
3523: prev = cur; cur = NEXT(cur);
3524: }
3525: } else {
3526: prev = cur; cur = NEXT(cur);
3527: }
3528: } else {
3529: prev = cur; cur = NEXT(cur);
3530: }
3531: }
3532: return head;
3533: }
3534:
3535: ND_pairs crit_M( ND_pairs d1 )
3536: {
3537: ND_pairs e,d2,d3,dd,p;
3538: UINT *id,*jd;
3539:
3540: if ( !d1 ) return d1;
3541: for ( dd = 0, e = d1; e; e = d3 ) {
3542: if ( !(d2 = NEXT(e)) ) {
3543: NEXT(e) = dd;
3544: return e;
3545: }
3546: id = LCM(e);
3547: for ( d3 = 0; d2; d2 = p ) {
3548: p = NEXT(d2);
3549: jd = LCM(d2);
3550: if ( ndl_equal(jd,id) )
3551: ;
3552: else if ( TD(jd) > TD(id) )
3553: if ( ndl_reducible(jd,id) ) continue;
3554: else ;
3555: else if ( ndl_reducible(id,jd) ) goto delit;
3556: NEXT(d2) = d3;
3557: d3 = d2;
3558: }
3559: NEXT(e) = dd;
3560: dd = e;
3561: continue;
3562: /**/
3563: delit: NEXT(d2) = d3;
3564: d3 = d2;
3565: for ( ; p; p = d2 ) {
3566: d2 = NEXT(p);
3567: NEXT(p) = d3;
3568: d3 = p;
3569: }
3570: FREENDP(e);
3571: }
3572: return dd;
3573: }
3574:
3575: ND_pairs crit_F( ND_pairs d1 )
3576: {
3577: ND_pairs rest, head,remove;
3578: ND_pairs last, p, r, w;
3579: int s;
3580:
3581: if ( !d1 ) return d1;
3582: for ( head = last = 0, p = d1; NEXT(p); ) {
3583: r = w = equivalent_pairs(p,&rest);
3584: s = SG(r);
3585: w = NEXT(w);
3586: while ( w ) {
3587: if ( crit_2(w->i1,w->i2) ) {
3588: r = w;
3589: w = NEXT(w);
3590: while ( w ) {
3591: remove = w;
3592: w = NEXT(w);
3593: FREENDP(remove);
3594: }
3595: break;
3596: } else if ( SG(w) < s ) {
3597: FREENDP(r);
3598: r = w;
3599: s = SG(r);
3600: w = NEXT(w);
3601: } else {
3602: remove = w;
3603: w = NEXT(w);
3604: FREENDP(remove);
3605: }
3606: }
3607: if ( last ) NEXT(last) = r;
3608: else head = r;
3609: NEXT(last = r) = 0;
3610: p = rest;
3611: if ( !p ) return head;
3612: }
3613: if ( !last ) return p;
3614: NEXT(last) = p;
3615: return head;
3616: }
3617:
3618: int crit_2( int dp1, int dp2 )
3619: {
3620: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
3621: }
3622:
3623: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
3624: {
3625: ND_pairs w,p,r,s;
3626: UINT *d;
3627:
3628: w = d1;
3629: d = LCM(w);
3630: s = NEXT(w);
3631: NEXT(w) = 0;
3632: for ( r = 0; s; s = p ) {
3633: p = NEXT(s);
3634: if ( ndl_equal(d,LCM(s)) ) {
3635: NEXT(s) = w; w = s;
3636: } else {
3637: NEXT(s) = r; r = s;
3638: }
3639: }
3640: *prest = r;
3641: return w;
3642: }
3643:
3644: NODE update_base(NODE nd,int ndp)
3645: {
3646: UINT *dl, *dln;
3647: NODE last, p, head;
3648:
3649: dl = DL(nd_psh[ndp]);
3650: for ( head = last = 0, p = nd; p; ) {
3651: dln = DL(nd_psh[(long)BDY(p)]);
3652: if ( ndl_reducible( dln, dl ) ) {
3653: p = NEXT(p);
3654: if ( last ) NEXT(last) = p;
3655: } else {
3656: if ( !last ) head = p;
3657: p = NEXT(last = p);
3658: }
3659: }
3660: head = append_one(head,ndp);
3661: return head;
3662: }
3663:
3664: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
3665: {
3666: ND_pairs m,ml,p,l;
3667: UINT *lcm;
3668: int s,td,len,tlen,c,c1;
3669:
3670: if ( !(p = NEXT(m = d)) ) {
3671: *prest = p;
3672: NEXT(m) = 0;
3673: return m;
3674: }
3675: if ( !NoSugar ) {
3676: if ( nd_sugarweight ) {
3677: s = m->sugar2;
3678: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3679: if ( (p->sugar2 < s)
3680: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3681: ml = l; m = p; s = m->sugar2;
3682: }
3683: } else {
3684: s = SG(m);
3685: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3686: if ( (SG(p) < s)
3687: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3688: ml = l; m = p; s = SG(m);
3689: }
3690: }
3691: } else {
3692: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3693: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
3694: ml = l; m = p; s = SG(m);
3695: }
3696: }
3697: if ( !ml ) *prest = NEXT(m);
3698: else {
3699: NEXT(ml) = NEXT(m);
3700: *prest = d;
3701: }
3702: NEXT(m) = 0;
3703: return m;
3704: }
3705:
3706: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
3707: {
3708: int msugar,i;
3709: ND_pairs t,dm0,dm,dr0,dr;
3710:
3711: if ( nd_sugarweight ) {
3712: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
3713: if ( t->sugar2 < msugar ) msugar = t->sugar2;
3714: dm0 = 0; dr0 = 0;
3715: for ( i = 0, t = d; t; t = NEXT(t) )
3716: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
3717: if ( dm0 ) NEXT(dm) = t;
3718: else dm0 = t;
3719: dm = t;
3720: i++;
3721: } else {
3722: if ( dr0 ) NEXT(dr) = t;
3723: else dr0 = t;
3724: dr = t;
3725: }
3726: } else {
3727: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
3728: if ( SG(t) < msugar ) msugar = SG(t);
3729: dm0 = 0; dr0 = 0;
3730: for ( i = 0, t = d; t; t = NEXT(t) )
3731: if ( i < nd_f4_nsp && SG(t) == msugar ) {
3732: if ( dm0 ) NEXT(dm) = t;
3733: else dm0 = t;
3734: dm = t;
3735: i++;
3736: } else {
3737: if ( dr0 ) NEXT(dr) = t;
3738: else dr0 = t;
3739: dr = t;
3740: }
3741: }
3742: NEXT(dm) = 0;
3743: if ( dr0 ) NEXT(dr) = 0;
3744: *prest = dr0;
3745: return dm0;
3746: }
3747:
1.28 noro 3748: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
3749: {
3750: int msugar;
3751: ND_pairs t,last;
3752:
3753: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
3754: if ( SG(t) == msugar ) last = t;
3755: *prest = last->next;
3756: last->next = 0;
3757: return d;
3758: }
3759:
1.1 noro 3760: int nd_tdeg(NDV c)
3761: {
3762: int wmax = 0;
3763: int i,len;
3764: NMV a;
3765:
3766: len = LEN(c);
3767: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
3768: wmax = MAX(TD(DL(a)),wmax);
3769: return wmax;
3770: }
3771:
1.24 noro 3772: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 3773: {
3774: int len;
3775: RHist r;
3776: NDV b;
3777: NODE tn;
3778: LIST l;
3779: Z iq;
3780:
3781: if ( nd_psn == nd_pslen ) {
3782: nd_pslen *= 2;
3783: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
3784: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
3785: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
3786: nd_bound = (UINT **)
3787: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
3788: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
3789: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
3790: }
3791: NEWRHist(r); nd_psh[nd_psn] = r;
3792: nd_ps[nd_psn] = a;
3793: if ( aq ) {
3794: nd_ps_trace[nd_psn] = aq;
3795: if ( !m ) {
3796: register_hcf(aq);
3797: } else if ( m == -2 ) {
3798: /* do nothing */
3799: } else
3800: error("ndv_newps : invalud modulus");
3801: nd_bound[nd_psn] = ndv_compute_bound(aq);
3802: #if 1
3803: SG(r) = SG(aq);
3804: #else
3805: SG(r) = nd_tdeg(aq);
3806: #endif
3807: ndl_copy(HDL(aq),DL(r));
1.24 noro 3808: r->sig = dup_sig(aq->sig);
1.1 noro 3809: } else {
3810: if ( !m ) register_hcf(a);
3811: nd_bound[nd_psn] = ndv_compute_bound(a);
3812: #if 1
3813: SG(r) = SG(a);
3814: #else
3815: SG(r) = nd_tdeg(a);
3816: #endif
3817: ndl_copy(HDL(a),DL(r));
1.24 noro 3818: r->sig = dup_sig(a->sig);
1.1 noro 3819: }
3820: if ( nd_demand ) {
3821: if ( aq ) {
3822: ndv_save(nd_ps_trace[nd_psn],nd_psn);
3823: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3824: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3825: nd_ps_trace[nd_psn] = 0;
3826: } else {
3827: ndv_save(nd_ps[nd_psn],nd_psn);
3828: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
3829: nd_ps[nd_psn] = 0;
3830: }
3831: }
3832: if ( nd_gentrace ) {
3833: /* reverse the tracelist and append it to alltracelist */
3834: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 3835: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 3836: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
3837: }
3838: return nd_psn++;
3839: }
3840:
3841: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
3842: /* return 1 if success, 0 if failure (HC(a mod p)) */
3843:
1.24 noro 3844: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 3845: {
1.6 noro 3846: int i,j,td,len,max;
3847: NODE s,s0,f0,tn;
3848: UINT *d;
3849: RHist r;
3850: NDVI w;
3851: NDV a,am;
3852: union oNDC hc;
3853: NODE node;
3854: P hcp;
3855: Z iq,jq;
3856: LIST l;
3857:
3858: nd_found = 0; nd_notfirst = 0; nd_create = 0;
3859: /* initialize the tracelist */
3860: nd_tracelist = 0;
3861:
3862: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
3863: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
3864: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
3865: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
3866: if ( !dont_sort ) {
3867: /* XXX heuristic */
1.26 noro 3868: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 3869: qsort(w,nd_psn,sizeof(struct oNDVI),
3870: (int (*)(const void *,const void *))ndvi_compare_rev);
3871: else
3872: qsort(w,nd_psn,sizeof(struct oNDVI),
3873: (int (*)(const void *,const void *))ndvi_compare);
3874: }
3875: nd_pslen = 2*nd_psn;
3876: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3877: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3878: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3879: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3880: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
3881: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
3882: nd_hcf = 0;
1.1 noro 3883:
1.6 noro 3884: if ( trace && nd_vc )
3885: makesubst(nd_vc,&nd_subst);
3886: else
3887: nd_subst = 0;
1.1 noro 3888:
1.6 noro 3889: if ( !nd_red )
3890: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
3891: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
3892: for ( i = 0; i < nd_psn; i++ ) {
3893: hc = HCU(w[i].p);
3894: if ( trace ) {
3895: if ( mod == -2 ) {
3896: /* over a large finite field */
3897: /* trace = small modulus */
3898: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
3899: ndv_mod(-2,a);
3900: if ( !dont_removecont) ndv_removecont(-2,a);
3901: am = nd_ps[i] = ndv_dup(trace,w[i].p);
3902: ndv_mod(trace,am);
3903: if ( DL_COMPARE(HDL(am),HDL(a)) )
3904: return 0;
3905: ndv_removecont(trace,am);
3906: } else {
3907: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
3908: if ( !dont_removecont) ndv_removecont(0,a);
3909: register_hcf(a);
3910: am = nd_ps[i] = ndv_dup(mod,a);
3911: ndv_mod(mod,am);
3912: if ( DL_COMPARE(HDL(am),HDL(a)) )
3913: return 0;
3914: ndv_removecont(mod,am);
3915: }
3916: } else {
3917: a = nd_ps[i] = ndv_dup(mod,w[i].p);
3918: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
3919: if ( !mod ) register_hcf(a);
1.1 noro 3920: }
1.6 noro 3921: if ( nd_gentrace ) {
3922: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
3923: /* exact division */
1.1 noro 3924: if ( !dont_removecont )
1.6 noro 3925: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
3926: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
3927: }
3928: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
3929: nd_bound[i] = ndv_compute_bound(a);
3930: nd_psh[i] = r;
3931: if ( nd_demand ) {
3932: if ( trace ) {
3933: ndv_save(nd_ps_trace[i],i);
3934: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
3935: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
3936: nd_ps_trace[i] = 0;
3937: } else {
3938: ndv_save(nd_ps[i],i);
3939: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
3940: nd_ps[i] = 0;
3941: }
1.1 noro 3942: }
1.6 noro 3943: }
1.24 noro 3944: if ( sba ) {
1.27 noro 3945: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 3946: // setup signatures
1.27 noro 3947: for ( i = 0; i < nd_psn; i++ ) {
3948: SIG sig;
1.24 noro 3949:
1.27 noro 3950: NEWSIG(sig); sig->pos = i;
3951: nd_ps[i]->sig = sig;
3952: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
3953: nd_psh[i]->sig = sig;
3954: if ( trace ) {
3955: nd_ps_trace[i]->sig = sig;
3956: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
3957: }
3958: NEWDL(nd_sba_hm[i],nd_nvar);
3959: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
3960: }
1.29 noro 3961: nd_sba_pos = (NODE *)MALLOC(nd_psn*sizeof(NODE));
3962: for ( i = 0; i < nd_psn; i++ ) {
3963: j = nd_psh[i]->sig->pos;
3964: nd_sba_pos[j] = append_one(nd_sba_pos[j],i);
3965: }
1.24 noro 3966: }
1.6 noro 3967: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
3968: return 1;
1.1 noro 3969: }
3970:
3971: struct order_spec *append_block(struct order_spec *spec,
3972: int nv,int nalg,int ord);
3973:
3974: extern VECT current_dl_weight_vector_obj;
3975: static VECT prev_weight_vector_obj;
3976:
3977: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
3978: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
3979: {
3980: NODE alist,t,s,r0,r,arg;
3981: VL tv;
3982: P poly;
3983: DP d;
3984: Alg alpha,dp;
3985: DAlg inv,da,hc;
3986: MP m;
3987: int i,nvar,nalg,n;
3988: NumberField nf;
3989: LIST f1,f2;
3990: struct order_spec *current_spec;
3991: VECT obj,obj0;
3992: VECT tmp;
3993:
3994: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
3995: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
3996:
3997: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
3998: NEXTNODE(alist,t); MKV(tv->v,poly);
3999: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
4000: tv->v = tv->v->priv;
4001: }
4002: NEXT(t) = 0;
4003:
4004: /* simplification, making polynomials monic */
4005: setfield_dalg(alist);
4006: obj_algtodalg((Obj)f,(Obj *)&f1);
4007: for ( t = BDY(f); t; t = NEXT(t) ) {
4008: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
4009: hc = (DAlg)BDY(d)->c;
4010: if ( NID(hc) == N_DA ) {
4011: invdalg(hc,&inv);
4012: for ( m = BDY(d); m; m = NEXT(m) ) {
4013: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
4014: }
4015: }
4016: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
4017: }
4018: obj_dalgtoalg((Obj)f1,(Obj *)&f);
4019:
4020: /* append alg vars to the var list */
4021: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
4022: NEXT(tv) = av;
4023:
4024: /* append a block to ord */
4025: *ord1p = append_block(ord,nvar,nalg,2);
4026:
4027: /* create generator list */
4028: nf = get_numberfield();
4029: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
4030: MKAlg(nf->defpoly[i],dp);
4031: MKNODE(s,dp,t); t = s;
4032: }
4033: MKLIST(f1,t);
4034: *alistp = alist;
4035: algobjtorat((Obj)f1,(Obj *)f1p);
4036:
4037: /* creating a new weight vector */
4038: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
4039: n = nvar+nalg+1;
4040: MKVECT(obj,n);
4041: if ( obj0 && obj0->len == nvar )
4042: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
4043: else
4044: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
4045: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
4046: BDY(obj)[n-1] = (pointer)ONE;
4047: arg = mknode(1,obj);
4048: Pdp_set_weight(arg,&tmp);
4049: }
4050:
4051: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
4052: {
4053: NODE s,t,u0,u;
4054: P p;
4055: VL tv;
4056: Obj obj;
4057: VECT tmp;
4058: NODE arg;
4059:
4060: u0 = 0;
4061: for ( t = r; t; t = NEXT(t) ) {
4062: p = (P)BDY(t);
4063: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
4064: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
4065: }
4066: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
4067: NEXTNODE(u0,u);
4068: BDY(u) = (pointer)p;
4069: }
4070: }
4071: arg = mknode(1,prev_weight_vector_obj);
4072: Pdp_set_weight(arg,&tmp);
4073:
4074: return u0;
4075: }
4076:
4077: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
4078: {
4079: VL tv,fv,vv,vc,av;
4080: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4081: int e,max,nvar,i;
4082: NDV b;
4083: int ishomo,nalg,mrank,trank,wmax,len;
4084: NMV a;
4085: Alg alpha,dp;
4086: P p,zp;
4087: Q dmy;
4088: LIST f1,f2,zpl;
4089: Obj obj;
4090: NumberField nf;
4091: struct order_spec *ord1;
4092: NODE tr,tl1,tl2,tl3,tl4,nzlist;
4093: LIST l1,l2,l3,l4,l5;
4094: int j;
4095: Z jq,bpe,last_nonzero;
4096: int *perm;
4097: EPOS oepos;
4098: int obpe,oadv,ompos,cbpe;
1.15 noro 4099: VECT hvect;
1.1 noro 4100:
4101: nd_module = 0;
4102: if ( !m && Demand ) nd_demand = 1;
4103: else nd_demand = 0;
4104: parse_nd_option(current_option);
4105:
4106: if ( DP_Multiple )
4107: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4108: #if 0
4109: ndv_alloc = 0;
4110: #endif
4111: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4112: if ( m && nd_vc )
4113: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4114: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4115: switch ( ord->id ) {
4116: case 1:
4117: if ( ord->nv != nvar )
4118: error("nd_{gr,f4} : invalid order specification");
4119: break;
4120: default:
4121: break;
4122: }
4123: nd_nalg = 0;
4124: av = 0;
4125: if ( !m ) {
4126: get_algtree((Obj)f,&av);
4127: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4128: nd_ntrans = nvar;
4129: nd_nalg = nalg;
4130: /* #i -> t#i */
4131: if ( nalg ) {
4132: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4133: ord = ord1;
4134: f = f1;
4135: }
4136: nvar += nalg;
4137: }
4138: nd_init_ord(ord);
4139: mrank = 0;
4140: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4141: for ( tv = vv; tv; tv = NEXT(tv) ) {
4142: if ( nd_module ) {
1.16 noro 4143: if ( OID(BDY(t)) == O_DPM ) {
4144: e = dpm_getdeg((DPM)BDY(t),&trank);
4145: max = MAX(e,max);
4146: mrank = MAX(mrank,trank);
4147: } else {
4148: s = BDY((LIST)BDY(t));
4149: trank = length(s);
4150: mrank = MAX(mrank,trank);
4151: for ( ; s; s = NEXT(s) ) {
4152: e = getdeg(tv->v,(P)BDY(s));
4153: max = MAX(e,max);
4154: }
1.1 noro 4155: }
4156: } else {
4157: e = getdeg(tv->v,(P)BDY(t));
4158: max = MAX(e,max);
4159: }
4160: }
4161: nd_setup_parameters(nvar,nd_nzlist?0:max);
4162: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4163: ishomo = 1;
4164: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4165: if ( nd_module ) {
1.16 noro 4166: if ( OID(BDY(t)) == O_DPM ) {
4167: Z cont;
4168: DPM zdpm;
4169:
4170: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4171: else zdpm = (DPM)BDY(t);
4172: b = (pointer)dpmtondv(m,zdpm);
4173: } else {
4174: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4175: else zpl = (LIST)BDY(t);
1.1 noro 4176: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4177: }
1.1 noro 4178: } else {
4179: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4180: else zp = (P)BDY(t);
4181: b = (pointer)ptondv(CO,vv,zp);
4182: }
4183: if ( ishomo )
4184: ishomo = ishomo && ndv_ishomo(b);
4185: if ( m ) ndv_mod(m,b);
4186: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4187: }
4188: if ( fd0 ) NEXT(fd) = 0;
4189:
4190: if ( !ishomo && homo ) {
4191: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4192: b = (NDV)BDY(t); len = LEN(b);
4193: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4194: wmax = MAX(TD(DL(a)),wmax);
4195: }
4196: homogenize_order(ord,nvar,&ord1);
4197: nd_init_ord(ord1);
4198: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4199: for ( t = fd0; t; t = NEXT(t) )
4200: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4201: }
4202:
1.24 noro 4203: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4204: if ( nd_gentrace ) {
4205: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4206: }
4207: if ( nd_splist ) {
4208: *rp = compute_splist();
4209: return;
4210: }
4211: if ( nd_check_splist ) {
4212: if ( f4 ) {
4213: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4214: else *rp = 0;
4215: } else {
4216: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4217: else *rp = 0;
4218: }
4219: return;
4220: }
4221: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
4222: if ( !x ) {
4223: *rp = 0; return;
4224: }
1.15 noro 4225: if ( nd_gentrace ) {
4226: MKVECT(hvect,nd_psn);
4227: for ( i = 0; i < nd_psn; i++ )
4228: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4229: }
1.1 noro 4230: if ( !ishomo && homo ) {
4231: /* dehomogenization */
4232: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4233: nd_init_ord(ord);
4234: nd_setup_parameters(nvar,0);
4235: }
4236: nd_demand = 0;
4237: if ( nd_module && nd_intersect ) {
4238: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 4239: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 4240: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
4241: }
4242: conv_ilist(nd_demand,0,x,0);
4243: goto FINAL;
4244: }
4245: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
4246: x = ndv_reducebase(x,perm);
4247: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4248: x = ndv_reduceall(m,x);
4249: cbpe = nd_bpe;
4250: if ( nd_gentrace && !f4 ) {
4251: tl2 = nd_alltracelist; nd_alltracelist = 0;
4252: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
4253: tl3 = nd_alltracelist; nd_alltracelist = 0;
4254: if ( nd_gensyz ) {
4255: nd_gb(m,0,1,1,0);
4256: tl4 = nd_alltracelist; nd_alltracelist = 0;
4257: } else tl4 = 0;
4258: }
4259: nd_bpe = cbpe;
4260: nd_setup_parameters(nd_nvar,0);
4261: FINAL:
4262: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 4263: NEXTNODE(r0,r);
4264: if ( nd_module ) {
4265: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
4266: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
4267: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
4268: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 4269: }
4270: if ( r0 ) NEXT(r) = 0;
4271: if ( !m && nd_nalg )
4272: r0 = postprocess_algcoef(av,alist,r0);
4273: MKLIST(*rp,r0);
4274: if ( nd_gentrace ) {
4275: if ( f4 ) {
1.6 noro 4276: STOZ(16,bpe);
4277: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 4278: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 4279: } else {
4280: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4281: tl3 = reverse_node(tl3);
4282: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4283: for ( t = tl2; t; t = NEXT(t) ) {
4284: /* s = [i,[*,j,*,*],...] */
4285: s = BDY((LIST)BDY(t));
1.6 noro 4286: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4287: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4288: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4289: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4290: }
4291: }
4292: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4293: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4294: }
4295: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4296: MKLIST(l5,tl4);
1.6 noro 4297: STOZ(nd_bpe,bpe);
1.15 noro 4298: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4299: }
4300: }
4301: #if 0
4302: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
4303: #endif
4304: }
4305:
1.28 noro 4306: NODE nd_sba_f4(int m,int **indp);
4307:
4308: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 4309: {
4310: VL tv,fv,vv,vc,av;
4311: NODE fd,fd0,r,r0,t,x,s,xx;
4312: int e,max,nvar,i;
4313: NDV b;
4314: int ishomo,nalg,wmax,len;
4315: NMV a;
4316: P p,zp;
4317: Q dmy;
4318: struct order_spec *ord1;
4319: int j;
4320: int *perm;
4321: EPOS oepos;
4322: int obpe,oadv,ompos,cbpe;
1.29 noro 4323: struct oEGT eg0,eg1,egconv;
1.24 noro 4324:
4325: nd_module = 0;
4326: nd_demand = 0;
4327: parse_nd_option(current_option);
1.35 noro 4328: Nsamesig = 0;
1.24 noro 4329: if ( DP_Multiple )
4330: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4331: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4332: if ( m && nd_vc )
4333: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4334: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4335: switch ( ord->id ) {
4336: case 1:
4337: if ( ord->nv != nvar )
4338: error("nd_sba : invalid order specification");
4339: break;
4340: default:
4341: break;
4342: }
4343: nd_nalg = 0;
4344: nd_init_ord(ord);
4345: // for SIG comparison
4346: initd(ord);
4347: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
4348: for ( tv = vv; tv; tv = NEXT(tv) ) {
4349: e = getdeg(tv->v,(P)BDY(t));
4350: max = MAX(e,max);
4351: }
4352: }
1.25 noro 4353: nd_setup_parameters(nvar,max);
1.24 noro 4354: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4355: ishomo = 1;
4356: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4357: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
4358: else zp = (P)BDY(t);
4359: b = (pointer)ptondv(CO,vv,zp);
4360: if ( ishomo )
4361: ishomo = ishomo && ndv_ishomo(b);
4362: if ( m ) ndv_mod(m,b);
4363: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4364: }
4365: if ( fd0 ) NEXT(fd) = 0;
4366:
4367: if ( !ishomo && homo ) {
4368: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4369: b = (NDV)BDY(t); len = LEN(b);
4370: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4371: wmax = MAX(TD(DL(a)),wmax);
4372: }
4373: homogenize_order(ord,nvar,&ord1);
4374: nd_init_ord(ord1);
4375: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4376: for ( t = fd0; t; t = NEXT(t) )
4377: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4378: }
4379:
1.39 noro 4380: ndv_setup(m,0,fd0,nd_sba_dontsort,0,1);
1.28 noro 4381: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm);
1.24 noro 4382: if ( !x ) {
4383: *rp = 0; return;
4384: }
4385: if ( !ishomo && homo ) {
4386: /* dehomogenization */
4387: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4388: nd_init_ord(ord);
4389: nd_setup_parameters(nvar,0);
4390: }
4391: nd_demand = 0;
4392: x = ndv_reducebase(x,perm);
4393: x = ndv_reduceall(m,x);
4394: nd_setup_parameters(nd_nvar,0);
1.29 noro 4395: get_eg(&eg0);
1.24 noro 4396: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4397: NEXTNODE(r0,r);
4398: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
1.34 noro 4399: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.24 noro 4400: }
4401: if ( r0 ) NEXT(r) = 0;
4402: MKLIST(*rp,r0);
1.29 noro 4403: get_eg(&eg1); init_eg(&egconv); add_eg(&egconv,&eg0,&eg1);
4404: print_eg("conv",&egconv); fprintf(asir_out,"\n");
1.24 noro 4405: }
4406:
1.1 noro 4407: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
4408: {
4409: VL tv,fv,vv,vc,av;
4410: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4411: int e,max,nvar,i;
4412: NDV b;
4413: int ishomo,nalg;
4414: Alg alpha,dp;
4415: P p,zp;
4416: Q dmy;
4417: LIST f1,f2;
4418: Obj obj;
4419: NumberField nf;
4420: struct order_spec *ord1;
4421: int *perm;
4422:
4423: parse_nd_option(current_option);
4424: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4425: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4426: switch ( ord->id ) {
4427: case 1:
4428: if ( ord->nv != nvar )
4429: error("nd_check : invalid order specification");
4430: break;
4431: default:
4432: break;
4433: }
4434: nd_nalg = 0;
4435: av = 0;
4436: if ( !m ) {
4437: get_algtree((Obj)f,&av);
4438: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4439: nd_ntrans = nvar;
4440: nd_nalg = nalg;
4441: /* #i -> t#i */
4442: if ( nalg ) {
4443: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4444: ord = ord1;
4445: f = f1;
4446: }
4447: nvar += nalg;
4448: }
4449: nd_init_ord(ord);
4450: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4451: for ( tv = vv; tv; tv = NEXT(tv) ) {
4452: e = getdeg(tv->v,(P)BDY(t));
4453: max = MAX(e,max);
4454: }
4455: nd_setup_parameters(nvar,max);
4456: ishomo = 1;
4457: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4458: ptozp((P)BDY(t),1,&dmy,&zp);
4459: b = (pointer)ptondv(CO,vv,zp);
4460: if ( ishomo )
4461: ishomo = ishomo && ndv_ishomo(b);
4462: if ( m ) ndv_mod(m,b);
4463: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4464: }
4465: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 4466: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 4467: for ( x = 0, i = 0; i < nd_psn; i++ )
4468: x = update_base(x,i);
4469: if ( do_check ) {
4470: x = nd_gb(m,ishomo,1,0,&perm);
4471: if ( !x ) {
4472: *rp = 0;
4473: return;
4474: }
4475: } else {
4476: #if 0
4477: /* bug ? */
4478: for ( t = x; t; t = NEXT(t) )
4479: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
4480: #else
4481: conv_ilist(0,0,x,&perm);
4482: #endif
4483: }
4484: x = ndv_reducebase(x,perm);
4485: x = ndv_reduceall(m,x);
4486: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4487: NEXTNODE(r0,r);
4488: BDY(r) = ndvtop(m,CO,vv,BDY(t));
4489: }
4490: if ( r0 ) NEXT(r) = 0;
4491: if ( !m && nd_nalg )
4492: r0 = postprocess_algcoef(av,alist,r0);
4493: MKLIST(*rp,r0);
4494: }
4495:
4496: NDV recompute_trace(NODE trace,NDV *p,int m);
4497: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
4498:
4499: NDV recompute_trace(NODE ti,NDV *p,int mod)
4500: {
4501: int c,c1,c2,i;
4502: NM mul,m,tail;
4503: ND d,r,rm;
4504: NODE sj;
4505: NDV red;
4506: Obj mj;
4507:
4508: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
4509: CM(mul) = 1;
4510: tail = 0;
4511: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
4512: sj = BDY((LIST)BDY(ti));
4513: if ( ARG0(sj) ) {
1.6 noro 4514: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 4515: mj = (Obj)ARG2(sj);
4516: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
4517: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
4518: rm = ndv_mul_nm(mod,mul,red);
4519: if ( !r ) r = rm;
4520: else {
4521: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
4522: if ( d ) {
4523: NEXT(tail) = m; tail = m; LEN(d)++;
4524: } else {
4525: MKND(nd_nvar,m,1,d); tail = BDY(d);
4526: }
4527: }
4528: if ( !m ) return 0; /* failure */
4529: else {
4530: BDY(r) = m;
4531: if ( mod > 0 || mod == -1 ) {
4532: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
4533: DMAR(c1,c2,0,mod,c);
4534: nd_mul_c(mod,rm,c);
4535: } else {
4536: Z t,u;
4537:
4538: chsgnlf(HCZ(r),&t);
4539: divlf(t,HCZ(rm),&u);
4540: nd_mul_c_lf(rm,u);
4541: }
4542: r = nd_add(mod,r,rm);
4543: }
4544: }
4545: }
4546: }
4547: if ( tail ) NEXT(tail) = 0;
4548: d = nd_add(mod,d,r);
4549: nd_mul_c(mod,d,invm(HCM(d),mod));
4550: return ndtondv(mod,d);
4551: }
4552:
4553: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
4554: {
4555: VL tv,fv,vv,vc,av;
4556: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4557: int e,max,nvar,i;
4558: NDV b;
4559: int ishomo,nalg;
4560: Alg alpha,dp;
4561: P p,zp;
4562: Q dmy;
4563: LIST f1,f2;
4564: Obj obj;
4565: NumberField nf;
4566: struct order_spec *ord1;
4567: NODE permtrace,intred,ind,perm,trace,ti;
4568: int len,n,j;
4569: NDV *db,*pb;
4570:
4571: parse_nd_option(current_option);
4572: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4573: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4574: switch ( ord->id ) {
4575: case 1:
4576: if ( ord->nv != nvar )
4577: error("nd_check : invalid order specification");
4578: break;
4579: default:
4580: break;
4581: }
4582: nd_init_ord(ord);
1.6 noro 4583: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 4584: nd_setup_parameters(nvar,0);
4585:
4586: len = length(BDY(f));
4587: db = (NDV *)MALLOC(len*sizeof(NDV *));
4588: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
4589: ptozp((P)BDY(t),1,&dmy,&zp);
4590: b = ptondv(CO,vv,zp);
4591: ndv_mod(m,b);
4592: ndv_mul_c(m,b,invm(HCM(b),m));
4593: db[i] = b;
4594: }
4595:
4596: permtrace = BDY((LIST)ARG2(BDY(tlist)));
4597: intred = BDY((LIST)ARG3(BDY(tlist)));
4598: ind = BDY((LIST)ARG4(BDY(tlist)));
4599: perm = BDY((LIST)ARG0(permtrace));
4600: trace = NEXT(permtrace);
4601:
4602: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 4603: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 4604: if ( j > i ) i = j;
4605: }
4606: n = i+1;
4607: pb = (NDV *)MALLOC(n*sizeof(NDV *));
4608: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
4609: ti = BDY((LIST)BDY(t));
1.6 noro 4610: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 4611: }
4612: for ( t = trace; t; t = NEXT(t) ) {
4613: ti = BDY((LIST)BDY(t));
1.6 noro 4614: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4615: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4616: if ( DP_Print ) {
4617: fprintf(asir_out,"."); fflush(asir_out);
4618: }
4619: }
4620: for ( t = intred; t; t = NEXT(t) ) {
4621: ti = BDY((LIST)BDY(t));
1.6 noro 4622: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4623: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4624: if ( DP_Print ) {
4625: fprintf(asir_out,"*"); fflush(asir_out);
4626: }
4627: }
4628: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
4629: NEXTNODE(r0,r);
1.6 noro 4630: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 4631: ndv_mul_c(m,b,invm(HCM(b),m));
4632: #if 0
1.6 noro 4633: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4634: #else
1.6 noro 4635: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4636: #endif
4637: }
4638: if ( r0 ) NEXT(r) = 0;
4639: MKLIST(*rp,r0);
4640: if ( DP_Print ) fprintf(asir_out,"\n");
4641: }
4642:
1.16 noro 4643: 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 4644: {
4645: VL tv,fv,vv,vc,av;
4646: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
4647: int m,nocheck,nvar,mindex,e,max;
4648: NDV c;
4649: NMV a;
4650: P p,zp;
4651: Q dmy;
4652: EPOS oepos;
4653: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
4654: Alg alpha,dp;
4655: P poly;
4656: LIST f1,f2,zpl;
4657: Obj obj;
4658: NumberField nf;
4659: struct order_spec *ord1;
4660: struct oEGT eg_check,eg0,eg1;
4661: NODE tr,tl1,tl2,tl3,tl4;
4662: LIST l1,l2,l3,l4,l5;
4663: int *perm;
4664: int j,ret;
4665: Z jq,bpe;
1.15 noro 4666: VECT hvect;
1.1 noro 4667:
4668: nd_module = 0;
4669: nd_lf = 0;
4670: parse_nd_option(current_option);
4671: if ( nd_lf ) {
4672: if ( f4 )
4673: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
4674: else
4675: error("nd_gr_trace is not implemented yet over a large finite field");
4676: return;
4677: }
4678: if ( DP_Multiple )
4679: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4680:
4681: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4682: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4683: switch ( ord->id ) {
4684: case 1:
4685: if ( ord->nv != nvar )
4686: error("nd_gr_trace : invalid order specification");
4687: break;
4688: default:
4689: break;
4690: }
4691:
4692: get_algtree((Obj)f,&av);
4693: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4694: nd_ntrans = nvar;
4695: nd_nalg = nalg;
4696: /* #i -> t#i */
4697: if ( nalg ) {
4698: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4699: ord = ord1;
4700: f = f1;
4701: }
4702: nvar += nalg;
4703:
4704: nocheck = 0;
4705: mindex = 0;
4706:
4707: if ( Demand ) nd_demand = 1;
4708: else nd_demand = 0;
4709:
4710: /* setup modulus */
4711: if ( trace < 0 ) {
4712: trace = -trace;
4713: nocheck = 1;
4714: }
4715: m = trace > 1 ? trace : get_lprime(mindex);
4716: nd_init_ord(ord);
4717: mrank = 0;
4718: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4719: for ( tv = vv; tv; tv = NEXT(tv) ) {
4720: if ( nd_module ) {
1.16 noro 4721: if ( OID(BDY(t)) == O_DPM ) {
4722: e = dpm_getdeg((DPM)BDY(t),&trank);
4723: max = MAX(e,max);
4724: mrank = MAX(mrank,trank);
4725: } else {
1.1 noro 4726: s = BDY((LIST)BDY(t));
4727: trank = length(s);
4728: mrank = MAX(mrank,trank);
4729: for ( ; s; s = NEXT(s) ) {
4730: e = getdeg(tv->v,(P)BDY(s));
4731: max = MAX(e,max);
4732: }
1.16 noro 4733: }
1.1 noro 4734: } else {
4735: e = getdeg(tv->v,(P)BDY(t));
4736: max = MAX(e,max);
4737: }
4738: }
4739: nd_setup_parameters(nvar,max);
4740: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4741: ishomo = 1;
4742: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4743: if ( nd_module ) {
1.16 noro 4744: if ( OID(BDY(t)) == O_DPM ) {
4745: Z cont;
4746: DPM zdpm;
4747:
1.17 noro 4748: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 4749: else zdpm = (DPM)BDY(t);
4750: c = (pointer)dpmtondv(m,zdpm);
4751: } else {
4752: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4753: else zpl = (LIST)BDY(t);
1.1 noro 4754: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4755: }
1.1 noro 4756: } else {
1.16 noro 4757: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4758: else zp = (P)BDY(t);
4759: c = (pointer)ptondv(CO,vv,zp);
1.1 noro 4760: }
4761: if ( ishomo )
4762: ishomo = ishomo && ndv_ishomo(c);
4763: if ( c ) {
4764: NEXTNODE(in0,in); BDY(in) = (pointer)c;
4765: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
4766: }
4767: }
4768: if ( in0 ) NEXT(in) = 0;
4769: if ( fd0 ) NEXT(fd) = 0;
4770: if ( !ishomo && homo ) {
4771: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
4772: c = (NDV)BDY(t); len = LEN(c);
4773: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4774: wmax = MAX(TD(DL(a)),wmax);
4775: }
4776: homogenize_order(ord,nvar,&ord1);
4777: nd_init_ord(ord1);
4778: nd_setup_parameters(nvar+1,wmax);
4779: for ( t = fd0; t; t = NEXT(t) )
4780: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4781: }
4782: if ( MaxDeg > 0 ) nocheck = 1;
4783: while ( 1 ) {
4784: tl1 = tl2 = tl3 = tl4 = 0;
4785: if ( Demand )
4786: nd_demand = 1;
1.24 noro 4787: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 4788: if ( nd_gentrace ) {
4789: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4790: }
4791: if ( ret )
4792: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
4793: if ( !ret || !cand ) {
4794: /* failure */
4795: if ( trace > 1 ) { *rp = 0; return; }
4796: else m = get_lprime(++mindex);
4797: continue;
4798: }
1.15 noro 4799: if ( nd_gentrace ) {
4800: MKVECT(hvect,nd_psn);
4801: for ( i = 0; i < nd_psn; i++ )
4802: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4803: }
1.1 noro 4804: if ( !ishomo && homo ) {
4805: /* dehomogenization */
4806: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4807: nd_init_ord(ord);
4808: nd_setup_parameters(nvar,0);
4809: }
4810: nd_demand = 0;
4811: cand = ndv_reducebase(cand,perm);
4812: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4813: cand = ndv_reduceall(0,cand);
4814: cbpe = nd_bpe;
4815: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
4816: get_eg(&eg0);
4817: if ( nocheck )
4818: break;
4819: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
4820: if ( nd_gentrace ) {
4821: tl3 = nd_alltracelist; nd_alltracelist = 0;
4822: } else tl3 = 0;
4823: /* gbcheck : cand is a GB of Id(cand) ? */
4824: if ( nd_vc || nd_gentrace || nd_gensyz )
4825: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
4826: else
4827: ret = nd_f4(0,1,0)!=0;
4828: if ( nd_gentrace && nd_gensyz ) {
4829: tl4 = nd_alltracelist; nd_alltracelist = 0;
4830: } else tl4 = 0;
4831: }
4832: if ( ret ) break;
4833: else if ( trace > 1 ) {
4834: /* failure */
4835: *rp = 0; return;
4836: } else {
4837: /* try the next modulus */
4838: m = get_lprime(++mindex);
4839: /* reset the parameters */
4840: if ( !ishomo && homo ) {
4841: nd_init_ord(ord1);
4842: nd_setup_parameters(nvar+1,wmax);
4843: } else {
4844: nd_init_ord(ord);
4845: nd_setup_parameters(nvar,max);
4846: }
4847: }
4848: }
4849: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
4850: if ( DP_Print )
1.6 noro 4851: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 4852: /* dp->p */
4853: nd_bpe = cbpe;
4854: nd_setup_parameters(nd_nvar,0);
4855: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 4856: if ( nd_module ) {
1.17 noro 4857: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 4858: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 4859: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
4860: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 4861: }
4862: if ( nd_nalg )
4863: cand = postprocess_algcoef(av,alist,cand);
4864: MKLIST(*rp,cand);
4865: if ( nd_gentrace ) {
4866: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4867: tl3 = reverse_node(tl3);
4868: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4869: for ( t = tl2; t; t = NEXT(t) ) {
4870: /* s = [i,[*,j,*,*],...] */
4871: s = BDY((LIST)BDY(t));
1.6 noro 4872: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4873: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4874: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4875: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4876: }
4877: }
4878: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4879: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4880: }
4881: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4882: MKLIST(l5,tl4);
1.6 noro 4883: STOZ(nd_bpe,bpe);
1.15 noro 4884: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4885: }
4886: }
4887:
4888: /* XXX : module element is not considered */
4889:
4890: void dltondl(int n,DL dl,UINT *r)
4891: {
4892: UINT *d;
4893: int i,j,l,s,ord_l;
4894: struct order_pair *op;
4895:
4896: d = (unsigned int *)dl->d;
4897: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
4898: if ( nd_blockmask ) {
4899: l = nd_blockmask->n;
4900: op = nd_blockmask->order_pair;
4901: for ( j = 0, s = 0; j < l; j++ ) {
4902: ord_l = op[j].length;
4903: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
4904: }
4905: TD(r) = ndl_weight(r);
4906: ndl_weight_mask(r);
4907: } else {
4908: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
4909: TD(r) = ndl_weight(r);
4910: }
4911: }
4912:
4913: DL ndltodl(int n,UINT *ndl)
4914: {
4915: DL dl;
4916: int *d;
4917: int i,j,l,s,ord_l;
4918: struct order_pair *op;
4919:
1.33 noro 4920: NEWDL_NOINIT(dl,n);
1.1 noro 4921: dl->td = TD(ndl);
4922: d = dl->d;
4923: if ( nd_blockmask ) {
4924: l = nd_blockmask->n;
4925: op = nd_blockmask->order_pair;
4926: for ( j = 0, s = 0; j < l; j++ ) {
4927: ord_l = op[j].length;
4928: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
4929: }
4930: } else {
4931: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
4932: }
4933: return dl;
4934: }
4935:
1.24 noro 4936: void _ndltodl(UINT *ndl,DL dl)
4937: {
4938: int *d;
4939: int i,j,l,s,ord_l,n;
4940: struct order_pair *op;
4941:
4942: n = nd_nvar;
4943: dl->td = TD(ndl);
4944: d = dl->d;
4945: if ( nd_blockmask ) {
4946: l = nd_blockmask->n;
4947: op = nd_blockmask->order_pair;
4948: for ( j = 0, s = 0; j < l; j++ ) {
4949: ord_l = op[j].length;
4950: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
4951: }
4952: } else {
4953: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
4954: }
4955: }
4956:
1.1 noro 4957: void nmtodp(int mod,NM m,DP *r)
4958: {
4959: DP dp;
4960: MP mr;
4961:
4962: NEWMP(mr);
4963: mr->dl = ndltodl(nd_nvar,DL(m));
4964: mr->c = (Obj)ndctop(mod,m->c);
4965: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
4966: *r = dp;
4967: }
4968:
1.15 noro 4969: void ndltodp(UINT *d,DP *r)
4970: {
4971: DP dp;
4972: MP mr;
4973:
4974: NEWMP(mr);
4975: mr->dl = ndltodl(nd_nvar,d);
4976: mr->c = (Obj)ONE;
4977: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
4978: *r = dp;
4979: }
4980:
1.1 noro 4981: void ndl_print(UINT *dl)
4982: {
4983: int n;
4984: int i,j,l,ord_l,s,s0;
4985: struct order_pair *op;
4986:
4987: n = nd_nvar;
4988: printf("<<");
4989: if ( nd_blockmask ) {
4990: l = nd_blockmask->n;
4991: op = nd_blockmask->order_pair;
4992: for ( j = 0, s = s0 = 0; j < l; j++ ) {
4993: ord_l = op[j].length;
4994: for ( i = 0; i < ord_l; i++, s++ )
4995: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
4996: }
4997: } else {
4998: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
4999: }
5000: printf(">>");
5001: if ( nd_module && MPOS(dl) )
5002: printf("*e%d",MPOS(dl));
5003: }
5004:
5005: void nd_print(ND p)
5006: {
5007: NM m;
5008:
5009: if ( !p )
5010: printf("0\n");
5011: else {
5012: for ( m = BDY(p); m; m = NEXT(m) ) {
5013: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 5014: else printf("+%ld*",CM(m));
1.1 noro 5015: ndl_print(DL(m));
5016: }
5017: printf("\n");
5018: }
5019: }
5020:
5021: void nd_print_q(ND p)
5022: {
5023: NM m;
5024:
5025: if ( !p )
5026: printf("0\n");
5027: else {
5028: for ( m = BDY(p); m; m = NEXT(m) ) {
5029: printf("+");
1.6 noro 5030: printexpr(CO,(Obj)CZ(m));
1.1 noro 5031: printf("*");
5032: ndl_print(DL(m));
5033: }
5034: printf("\n");
5035: }
5036: }
5037:
5038: void ndp_print(ND_pairs d)
5039: {
5040: ND_pairs t;
5041:
5042: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
5043: printf("\n");
5044: }
5045:
5046: void nd_removecont(int mod,ND p)
5047: {
5048: int i,n;
5049: Z *w;
5050: NM m;
5051: struct oVECT v;
5052:
5053: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
5054: else if ( mod == -2 ) {
5055: Z inv;
5056: divlf(ONE,HCZ(p),&inv);
5057: nd_mul_c_lf(p,inv);
5058: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
5059: else {
5060: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
5061: w = (Z *)MALLOC(n*sizeof(Q));
5062: v.len = n;
5063: v.body = (pointer *)w;
1.6 noro 5064: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5065: removecont_array((P *)w,n,1);
1.6 noro 5066: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5067: }
5068: }
5069:
5070: void nd_removecont2(ND p1,ND p2)
5071: {
5072: int i,n1,n2,n;
5073: Z *w;
5074: NM m;
5075: struct oVECT v;
5076:
5077: n1 = nd_length(p1);
5078: n2 = nd_length(p2);
5079: n = n1+n2;
5080: w = (Z *)MALLOC(n*sizeof(Q));
5081: v.len = n;
5082: v.body = (pointer *)w;
5083: i = 0;
5084: if ( p1 )
1.6 noro 5085: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5086: if ( p2 )
1.6 noro 5087: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5088: removecont_array((P *)w,n,1);
5089: i = 0;
5090: if ( p1 )
1.6 noro 5091: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5092: if ( p2 )
1.6 noro 5093: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5094: }
5095:
5096: void ndv_removecont(int mod,NDV p)
5097: {
5098: int i,len,all_p;
5099: Z *c;
5100: P *w;
5101: Z dvr,t;
5102: P g,cont,tp;
5103: NMV m;
5104:
5105: if ( mod == -1 )
5106: ndv_mul_c(mod,p,_invsf(HCM(p)));
5107: else if ( mod == -2 ) {
5108: Z inv;
5109: divlf(ONE,HCZ(p),&inv);
5110: ndv_mul_c_lf(p,inv);
5111: } else if ( mod )
5112: ndv_mul_c(mod,p,invm(HCM(p),mod));
5113: else {
5114: len = p->len;
5115: w = (P *)MALLOC(len*sizeof(P));
5116: c = (Z *)MALLOC(len*sizeof(Q));
5117: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5118: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5119: all_p = all_p && !NUM(w[i]);
5120: }
5121: if ( all_p ) {
5122: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5123: mulp(nd_vc,(P)dvr,g,&cont);
5124: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5125: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5126: }
5127: } else {
5128: sortbynm((Q *)c,len);
5129: qltozl((Q *)c,len,&dvr);
5130: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5131: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5132: }
5133: }
5134: }
5135: }
5136:
5137: /* koko */
5138:
5139: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5140: {
5141: int len,i,max;
5142: NMV m,mr0,mr,t;
5143:
5144: len = p->len;
1.14 noro 5145: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5146: max = MAX(max,TD(DL(m)));
5147: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5148: m = (NMV)((char *)mr0+(len-1)*oadv);
5149: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5150: t = (NMV)MALLOC(nmv_adv);
5151: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5152: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5153: CZ(mr) = CZ(m);
1.1 noro 5154: ndl_copy(DL(t),DL(mr));
5155: }
5156: NV(p)++;
5157: BDY(p) = mr0;
5158: }
5159:
5160: void ndv_dehomogenize(NDV p,struct order_spec *ord)
5161: {
5162: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
5163: int pos;
5164: Q *w;
5165: Q dvr,t;
5166: NMV m,r;
5167:
5168: len = p->len;
5169: newnvar = nd_nvar-1;
5170: newexporigin = nd_get_exporigin(ord);
5171: if ( nd_module ) newmpos = newexporigin-1;
5172: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
5173: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
5174: ndl_dehomogenize(DL(m));
5175: if ( newwpd != nd_wpd ) {
5176: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
5177: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 5178: CZ(r) = CZ(m);
1.1 noro 5179: if ( nd_module ) pos = MPOS(DL(m));
5180: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
5181: adj = nd_exporigin-newexporigin;
5182: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
5183: if ( nd_module ) {
5184: DL(r)[newmpos] = pos;
5185: }
5186: }
5187: }
5188: NV(p)--;
5189: }
5190:
5191: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
5192: {
5193: int i;
5194: P *tpl,*tpl1;
5195: NODE l;
5196: P h,gcd,t;
5197:
5198: tpl = (P *)MALLOC(m*sizeof(P));
5199: tpl1 = (P *)MALLOC(m*sizeof(P));
5200: bcopy(pl,tpl,m*sizeof(P));
5201: gcd = (P)ONE;
5202: for ( l = nd_hcf; l; l = NEXT(l) ) {
5203: h = (P)BDY(l);
5204: while ( 1 ) {
5205: for ( i = 0; i < m; i++ )
5206: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
5207: break;
5208: if ( i == m ) {
5209: bcopy(tpl1,tpl,m*sizeof(P));
5210: mulp(vl,gcd,h,&t); gcd = t;
5211: } else
5212: break;
5213: }
5214: }
5215: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
5216: if ( full ) {
5217: heu_nezgcdnpz(vl,tpl,m,&t);
5218: mulp(vl,gcd,t,pr);
5219: } else
5220: *pr = gcd;
5221: }
5222:
5223: void removecont_array(P *p,int n,int full)
5224: {
5225: int all_p,all_q,i;
5226: Z *c;
5227: P *w;
5228: P t,s;
5229:
5230: for ( all_q = 1, i = 0; i < n; i++ )
5231: all_q = all_q && NUM(p[i]);
5232: if ( all_q ) {
5233: removecont_array_q((Z *)p,n);
5234: } else {
5235: c = (Z *)MALLOC(n*sizeof(Z));
5236: w = (P *)MALLOC(n*sizeof(P));
5237: for ( i = 0; i < n; i++ ) {
5238: ptozp(p[i],1,(Q *)&c[i],&w[i]);
5239: }
5240: removecont_array_q(c,n);
5241: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
5242: for ( i = 0; i < n; i++ ) {
5243: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
5244: }
5245: }
5246: }
5247:
5248: /* c is an int array */
5249:
5250: void removecont_array_q(Z *c,int n)
5251: {
5252: struct oVECT v;
5253: Z d0,d1,a,u,u1,gcd;
5254: int i,j;
5255: Z *q,*r;
5256:
5257: q = (Z *)MALLOC(n*sizeof(Z));
5258: r = (Z *)MALLOC(n*sizeof(Z));
5259: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
5260: gcdvz_estimate(&v,&d0);
5261: for ( i = 0; i < n; i++ ) {
5262: divqrz(c[i],d0,&q[i],&r[i]);
5263: }
5264: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
5265: if ( i < n ) {
5266: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
5267: gcdvz(&v,&d1);
5268: gcdz(d0,d1,&gcd);
1.6 noro 5269: /* exact division */
5270: divsz(d0,gcd,&a);
1.1 noro 5271: for ( i = 0; i < n; i++ ) {
5272: mulz(a,q[i],&u);
5273: if ( r[i] ) {
1.6 noro 5274: /* exact division */
5275: divsz(r[i],gcd,&u1);
1.1 noro 5276: addz(u,u1,&q[i]);
5277: } else
5278: q[i] = u;
5279: }
5280: }
5281: for ( i = 0; i < n; i++ ) c[i] = q[i];
5282: }
5283:
1.4 noro 5284: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
5285:
5286: void mpz_removecont_array(mpz_t *c,int n)
5287: {
5288: mpz_t d0,a,u,u1,gcd;
5289: int i,j;
1.13 noro 5290: static mpz_t *q,*r;
5291: static int c_len = 0;
1.4 noro 5292:
5293: for ( i = 0; i < n; i++ )
5294: if ( mpz_sgn(c[i]) ) break;
5295: if ( i == n ) return;
5296: gcdv_mpz_estimate(d0,c,n);
1.13 noro 5297: if ( n > c_len ) {
5298: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5299: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5300: c_len = n;
5301: }
1.4 noro 5302: for ( i = 0; i < n; i++ ) {
5303: mpz_init(q[i]); mpz_init(r[i]);
5304: mpz_fdiv_qr(q[i],r[i],c[i],d0);
5305: }
5306: for ( i = 0; i < n; i++ )
5307: if ( mpz_sgn(r[i]) ) break;
5308: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
5309: if ( i < n ) {
5310: mpz_gcd(gcd,d0,r[i]);
5311: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
5312: mpz_div(a,d0,gcd);
5313: for ( i = 0; i < n; i++ ) {
5314: mpz_mul(u,a,q[i]);
5315: if ( mpz_sgn(r[i]) ) {
5316: mpz_div(u1,r[i],gcd);
5317: mpz_add(q[i],u,u1);
5318: } else
5319: mpz_set(q[i],u);
5320: }
5321: }
5322: for ( i = 0; i < n; i++ )
5323: mpz_set(c[i],q[i]);
5324: }
5325:
1.1 noro 5326: void nd_mul_c(int mod,ND p,int mul)
5327: {
5328: NM m;
5329: int c,c1;
5330:
5331: if ( !p ) return;
5332: if ( mul == 1 ) return;
5333: if ( mod == -1 )
5334: for ( m = BDY(p); m; m = NEXT(m) )
5335: CM(m) = _mulsf(CM(m),mul);
5336: else
5337: for ( m = BDY(p); m; m = NEXT(m) ) {
5338: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5339: }
5340: }
5341:
5342: void nd_mul_c_lf(ND p,Z mul)
5343: {
5344: NM m;
5345: Z c;
5346:
5347: if ( !p ) return;
5348: if ( UNIZ(mul) ) return;
5349: for ( m = BDY(p); m; m = NEXT(m) ) {
5350: mullf(CZ(m),mul,&c); CZ(m) = c;
5351: }
5352: }
5353:
5354: void nd_mul_c_q(ND p,P mul)
5355: {
5356: NM m;
5357: P c;
5358:
5359: if ( !p ) return;
5360: if ( UNIQ(mul) ) return;
5361: for ( m = BDY(p); m; m = NEXT(m) ) {
5362: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
5363: }
5364: }
5365:
5366: void nd_mul_c_p(VL vl,ND p,P mul)
5367: {
5368: NM m;
5369: P c;
5370:
5371: if ( !p ) return;
5372: for ( m = BDY(p); m; m = NEXT(m) ) {
5373: mulp(vl,CP(m),mul,&c); CP(m) = c;
5374: }
5375: }
5376:
5377: void nd_free(ND p)
5378: {
5379: NM t,s;
5380:
5381: if ( !p ) return;
5382: t = BDY(p);
5383: while ( t ) {
5384: s = NEXT(t);
5385: FREENM(t);
5386: t = s;
5387: }
5388: FREEND(p);
5389: }
5390:
5391: void ndv_free(NDV p)
5392: {
5393: GCFREE(BDY(p));
5394: }
5395:
5396: void nd_append_red(UINT *d,int i)
5397: {
5398: RHist m,m0;
5399: int h;
5400:
5401: NEWRHist(m);
5402: h = ndl_hash_value(d);
5403: m->index = i;
5404: ndl_copy(d,DL(m));
5405: NEXT(m) = nd_red[h];
5406: nd_red[h] = m;
5407: }
5408:
5409: UINT *ndv_compute_bound(NDV p)
5410: {
5411: UINT *d1,*d2,*t;
5412: UINT u;
5413: int i,j,k,l,len,ind;
5414: NMV m;
5415:
5416: if ( !p )
5417: return 0;
5418: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5419: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5420: len = LEN(p);
5421: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
5422: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
5423: ndl_max(DL(m),d1,d2);
5424: t = d1; d1 = d2; d2 = t;
5425: }
5426: l = nd_nvar+31;
5427: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5428: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5429: u = d1[i];
5430: k = (nd_epw-1)*nd_bpe;
5431: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5432: t[ind] = (u>>k)&nd_mask0;
5433: }
5434: for ( ; ind < l; ind++ ) t[ind] = 0;
5435: return t;
5436: }
5437:
5438: UINT *nd_compute_bound(ND p)
5439: {
5440: UINT *d1,*d2,*t;
5441: UINT u;
5442: int i,j,k,l,len,ind;
5443: NM m;
5444:
5445: if ( !p )
5446: return 0;
5447: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5448: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5449: len = LEN(p);
5450: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
5451: for ( m = NEXT(m); m; m = NEXT(m) ) {
5452: ndl_lcm(DL(m),d1,d2);
5453: t = d1; d1 = d2; d2 = t;
5454: }
5455: l = nd_nvar+31;
5456: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5457: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5458: u = d1[i];
5459: k = (nd_epw-1)*nd_bpe;
5460: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5461: t[ind] = (u>>k)&nd_mask0;
5462: }
5463: for ( ; ind < l; ind++ ) t[ind] = 0;
5464: return t;
5465: }
5466:
5467: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
5468: /* of a term. In this case we need additional 1 word. */
5469:
5470: int nd_get_exporigin(struct order_spec *ord)
5471: {
5472: switch ( ord->id ) {
1.21 noro 5473: case 0: case 2: case 256: case 258: case 300:
1.1 noro 5474: return 1+nd_module;
5475: case 1: case 257:
5476: /* block order */
5477: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
5478: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
5479: return ord->ord.block.length+1+nd_module;
5480: case 3: case 259:
5481: #if 0
5482: error("nd_get_exporigin : composite order is not supported yet.");
5483: #else
5484: return 1+nd_module;
5485: #endif
5486: default:
5487: error("nd_get_exporigin : ivalid argument.");
5488: return 0;
5489: }
5490: }
5491:
5492: void nd_setup_parameters(int nvar,int max) {
5493: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
5494: struct order_pair *op;
5495:
5496: nd_nvar = nvar;
5497: if ( max ) {
5498: /* XXX */
5499: if ( do_weyl ) nd_bpe = 32;
5500: else if ( max < 2 ) nd_bpe = 1;
5501: else if ( max < 4 ) nd_bpe = 2;
5502: else if ( max < 8 ) nd_bpe = 3;
5503: else if ( max < 16 ) nd_bpe = 4;
5504: else if ( max < 32 ) nd_bpe = 5;
5505: else if ( max < 64 ) nd_bpe = 6;
5506: else if ( max < 256 ) nd_bpe = 8;
5507: else if ( max < 1024 ) nd_bpe = 10;
5508: else if ( max < 65536 ) nd_bpe = 16;
5509: else nd_bpe = 32;
5510: }
5511: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
5512: UINT t;
5513: int st;
5514: int *v;
5515: /* t = max(weights) */
5516: t = 0;
5517: if ( current_dl_weight_vector )
5518: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
5519: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
5520: if ( t < st ) t = st;
5521: }
5522: if ( nd_matrix )
5523: for ( i = 0; i < nd_matrix_len; i++ )
5524: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
5525: if ( (st=v[j]) < 0 ) st = -st;
5526: if ( t < st ) t = st;
5527: }
5528: /* i = bitsize of t */
5529: for ( i = 0; t; t >>=1, i++ );
5530: /* i += bitsize of nd_nvar */
5531: for ( t = nd_nvar; t; t >>=1, i++);
5532: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
5533: if ( (nd_bpe+i) >= 31 )
5534: error("nd_setup_parameters : too large weight");
5535: }
5536: nd_epw = (sizeof(UINT)*8)/nd_bpe;
5537: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
5538: nd_exporigin = nd_get_exporigin(nd_ord);
5539: wpd = nd_exporigin+elen;
5540: if ( nd_module )
5541: nd_mpos = nd_exporigin-1;
5542: else
5543: nd_mpos = -1;
5544: if ( wpd != nd_wpd ) {
5545: nd_free_private_storage();
5546: nd_wpd = wpd;
5547: }
5548: if ( nd_bpe < 32 ) {
5549: nd_mask0 = (1<<nd_bpe)-1;
5550: } else {
5551: nd_mask0 = 0xffffffff;
5552: }
5553: bzero(nd_mask,sizeof(nd_mask));
5554: nd_mask1 = 0;
5555: for ( i = 0; i < nd_epw; i++ ) {
5556: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
5557: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
5558: }
5559: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
5560: nd_epos = nd_create_epos(nd_ord);
5561: nd_blockmask = nd_create_blockmask(nd_ord);
5562: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
5563: }
5564:
5565: ND_pairs nd_reconstruct(int trace,ND_pairs d)
5566: {
5567: int i,obpe,oadv,h;
5568: static NM prev_nm_free_list;
5569: static ND_pairs prev_ndp_free_list;
5570: RHist mr0,mr;
5571: RHist r;
5572: RHist *old_red;
5573: ND_pairs s0,s,t;
5574: EPOS oepos;
5575:
5576: obpe = nd_bpe;
5577: oadv = nmv_adv;
5578: oepos = nd_epos;
5579: if ( obpe < 2 ) nd_bpe = 2;
5580: else if ( obpe < 3 ) nd_bpe = 3;
5581: else if ( obpe < 4 ) nd_bpe = 4;
5582: else if ( obpe < 5 ) nd_bpe = 5;
5583: else if ( obpe < 6 ) nd_bpe = 6;
5584: else if ( obpe < 8 ) nd_bpe = 8;
5585: else if ( obpe < 10 ) nd_bpe = 10;
5586: else if ( obpe < 16 ) nd_bpe = 16;
5587: else if ( obpe < 32 ) nd_bpe = 32;
5588: else error("nd_reconstruct : exponent too large");
5589:
5590: nd_setup_parameters(nd_nvar,0);
5591: prev_nm_free_list = _nm_free_list;
5592: prev_ndp_free_list = _ndp_free_list;
5593: _nm_free_list = 0;
5594: _ndp_free_list = 0;
5595: for ( i = nd_psn-1; i >= 0; i-- ) {
5596: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
5597: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
5598: }
5599: if ( trace )
5600: for ( i = nd_psn-1; i >= 0; i-- ) {
5601: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
5602: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
5603: }
5604: s0 = 0;
5605: for ( t = d; t; t = NEXT(t) ) {
5606: NEXTND_pairs(s0,s);
5607: s->i1 = t->i1;
5608: s->i2 = t->i2;
1.24 noro 5609: s->sig = t->sig;
1.1 noro 5610: SG(s) = SG(t);
5611: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
5612: }
5613:
5614: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
5615: for ( i = 0; i < REDTAB_LEN; i++ ) {
5616: old_red[i] = nd_red[i];
5617: nd_red[i] = 0;
5618: }
5619: for ( i = 0; i < REDTAB_LEN; i++ )
5620: for ( r = old_red[i]; r; r = NEXT(r) ) {
5621: NEWRHist(mr);
5622: mr->index = r->index;
5623: SG(mr) = SG(r);
5624: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
5625: h = ndl_hash_value(DL(mr));
5626: NEXT(mr) = nd_red[h];
5627: nd_red[h] = mr;
1.24 noro 5628: mr->sig = r->sig;
1.1 noro 5629: }
5630: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
5631: old_red = 0;
5632: for ( i = 0; i < nd_psn; i++ ) {
5633: NEWRHist(r); SG(r) = SG(nd_psh[i]);
5634: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 5635: r->sig = nd_psh[i]->sig;
1.1 noro 5636: nd_psh[i] = r;
5637: }
5638: if ( s0 ) NEXT(s) = 0;
5639: prev_nm_free_list = 0;
5640: prev_ndp_free_list = 0;
5641: #if 0
5642: GC_gcollect();
5643: #endif
5644: return s0;
5645: }
5646:
1.30 noro 5647: void nd_reconstruct_s(int trace,ND_pairs *d)
5648: {
5649: int i,obpe,oadv,h;
5650: static NM prev_nm_free_list;
5651: static ND_pairs prev_ndp_free_list;
5652: RHist mr0,mr;
5653: RHist r;
5654: RHist *old_red;
5655: ND_pairs s0,s,t;
5656: EPOS oepos;
5657:
5658: obpe = nd_bpe;
5659: oadv = nmv_adv;
5660: oepos = nd_epos;
5661: if ( obpe < 2 ) nd_bpe = 2;
5662: else if ( obpe < 3 ) nd_bpe = 3;
5663: else if ( obpe < 4 ) nd_bpe = 4;
5664: else if ( obpe < 5 ) nd_bpe = 5;
5665: else if ( obpe < 6 ) nd_bpe = 6;
5666: else if ( obpe < 8 ) nd_bpe = 8;
5667: else if ( obpe < 10 ) nd_bpe = 10;
5668: else if ( obpe < 16 ) nd_bpe = 16;
5669: else if ( obpe < 32 ) nd_bpe = 32;
5670: else error("nd_reconstruct_s : exponent too large");
5671:
5672: nd_setup_parameters(nd_nvar,0);
5673: prev_nm_free_list = _nm_free_list;
5674: prev_ndp_free_list = _ndp_free_list;
5675: _nm_free_list = 0;
5676: _ndp_free_list = 0;
5677: for ( i = nd_psn-1; i >= 0; i-- ) {
5678: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
5679: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
5680: }
5681: if ( trace )
5682: for ( i = nd_psn-1; i >= 0; i-- ) {
5683: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
5684: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
5685: }
5686:
5687: for ( i = 0; i < nd_nbase; i++ ) {
5688: s0 = 0;
5689: for ( t = d[i]; t; t = NEXT(t) ) {
5690: NEXTND_pairs(s0,s);
5691: s->i1 = t->i1;
5692: s->i2 = t->i2;
5693: s->sig = t->sig;
5694: SG(s) = SG(t);
5695: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
5696: }
5697: d[i] = s0;
5698: }
5699:
5700: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
5701: for ( i = 0; i < REDTAB_LEN; i++ ) {
5702: old_red[i] = nd_red[i];
5703: nd_red[i] = 0;
5704: }
5705: for ( i = 0; i < REDTAB_LEN; i++ )
5706: for ( r = old_red[i]; r; r = NEXT(r) ) {
5707: NEWRHist(mr);
5708: mr->index = r->index;
5709: SG(mr) = SG(r);
5710: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
5711: h = ndl_hash_value(DL(mr));
5712: NEXT(mr) = nd_red[h];
5713: nd_red[h] = mr;
5714: mr->sig = r->sig;
5715: }
5716: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
5717: old_red = 0;
5718: for ( i = 0; i < nd_psn; i++ ) {
5719: NEWRHist(r); SG(r) = SG(nd_psh[i]);
5720: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
5721: r->sig = nd_psh[i]->sig;
5722: nd_psh[i] = r;
5723: }
5724: if ( s0 ) NEXT(s) = 0;
5725: prev_nm_free_list = 0;
5726: prev_ndp_free_list = 0;
5727: #if 0
5728: GC_gcollect();
5729: #endif
5730: }
5731:
1.1 noro 5732: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
5733: {
5734: int n,i,ei,oepw,omask0,j,s,ord_l,l;
5735: struct order_pair *op;
5736:
5737: n = nd_nvar;
5738: oepw = (sizeof(UINT)*8)/obpe;
5739: omask0 = (1<<obpe)-1;
5740: TD(r) = TD(d);
5741: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
5742: if ( nd_blockmask ) {
5743: l = nd_blockmask->n;
5744: op = nd_blockmask->order_pair;
5745: for ( i = 1; i < nd_exporigin; i++ )
5746: r[i] = d[i];
5747: for ( j = 0, s = 0; j < l; j++ ) {
5748: ord_l = op[j].length;
5749: for ( i = 0; i < ord_l; i++, s++ ) {
5750: ei = GET_EXP_OLD(d,s);
5751: PUT_EXP(r,s,ei);
5752: }
5753: }
5754: } else {
5755: for ( i = 0; i < n; i++ ) {
5756: ei = GET_EXP_OLD(d,i);
5757: PUT_EXP(r,i,ei);
5758: }
5759: }
5760: if ( nd_module ) MPOS(r) = MPOS(d);
5761: }
5762:
5763: ND nd_copy(ND p)
5764: {
5765: NM m,mr,mr0;
5766: int c,n;
5767: ND r;
5768:
5769: if ( !p )
5770: return 0;
5771: else {
5772: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
5773: NEXTNM(mr0,mr);
5774: CM(mr) = CM(m);
5775: ndl_copy(DL(m),DL(mr));
5776: }
5777: NEXT(mr) = 0;
5778: MKND(NV(p),mr0,LEN(p),r);
5779: SG(r) = SG(p);
5780: return r;
5781: }
5782: }
5783:
5784: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
5785: {
5786: NM m1,m2;
5787: NDV p1,p2;
5788: ND t1,t2;
5789: UINT *lcm;
5790: P gp,tp;
5791: Z g,t;
5792: Z iq;
5793: int td;
5794: LIST hist;
5795: NODE node;
5796: DP d;
5797:
5798: if ( !mod && nd_demand ) {
5799: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
5800: } else {
5801: if ( trace ) {
5802: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
5803: } else {
5804: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
5805: }
5806: }
5807: lcm = LCM(p);
5808: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
5809: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
5810: FREENM(m1); return 0;
5811: }
5812: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
5813: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
5814: FREENM(m1); FREENM(m2); return 0;
5815: }
5816:
5817: if ( mod == -1 ) {
5818: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
5819: } else if ( mod > 0 ) {
5820: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
5821: } else if ( mod == -2 ) {
5822: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
5823: } else if ( nd_vc ) {
5824: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
5825: divsp(nd_vc,HCP(p2),gp,&CP(m1));
5826: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
5827: } else {
1.6 noro 5828: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 5829: }
5830: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
5831: *rp = nd_add(mod,t1,t2);
5832: if ( nd_gentrace ) {
5833: /* nd_tracelist is initialized */
1.6 noro 5834: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 5835: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 5836: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 5837: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
5838: nd_tracelist = node;
5839: }
1.24 noro 5840: if ( *rp )
5841: (*rp)->sig = p->sig;
1.1 noro 5842: FREENM(m1); FREENM(m2);
5843: return 1;
5844: }
5845:
5846: void ndv_mul_c(int mod,NDV p,int mul)
5847: {
5848: NMV m;
5849: int c,c1,len,i;
5850:
5851: if ( !p ) return;
5852: len = LEN(p);
5853: if ( mod == -1 )
5854: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
5855: CM(m) = _mulsf(CM(m),mul);
5856: else
5857: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
5858: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5859: }
5860: }
5861:
5862: void ndv_mul_c_lf(NDV p,Z mul)
5863: {
5864: NMV m;
5865: Z c;
5866: int len,i;
5867:
5868: if ( !p ) return;
5869: len = LEN(p);
5870: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
5871: mullf(CZ(m),mul,&c); CZ(m) = c;
5872: }
5873: }
5874:
5875: /* for nd_det */
5876: void ndv_mul_c_q(NDV p,Z mul)
5877: {
5878: NMV m;
5879: Z c;
5880: int len,i;
5881:
5882: if ( !p ) return;
5883: len = LEN(p);
5884: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 5885: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 5886: }
5887: }
5888:
5889: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
5890: int n2,i,j,l,n,tlen;
5891: UINT *d0;
5892: NM *tab,*psum;
5893: ND s,r;
5894: NM t;
5895: NMV m1;
5896:
5897: if ( !p ) return 0;
5898: n = NV(p); n2 = n>>1;
5899: d0 = DL(m0);
5900: l = LEN(p);
5901: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
5902: tab = (NM *)MALLOC(tlen*sizeof(NM));
5903: psum = (NM *)MALLOC(tlen*sizeof(NM));
5904: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
5905: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
5906: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
5907: /* m0(NM) * m1(NMV) => tab(NM) */
5908: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
5909: for ( j = 0; j < tlen; j++ ) {
5910: if ( tab[j] ) {
5911: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
5912: }
5913: }
5914: }
5915: for ( i = tlen-1, r = 0; i >= 0; i-- )
5916: if ( psum[i] ) {
5917: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
5918: MKND(n,psum[i],j,s);
5919: r = nd_add(mod,r,s);
5920: }
5921: if ( r ) SG(r) = SG(p)+TD(d0);
5922: return r;
5923: }
5924:
5925: /* product of monomials */
5926: /* XXX block order is not handled correctly */
5927:
5928: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
5929: {
5930: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
5931: UINT *d0,*d1,*d,*dt,*ctab;
5932: Z *ctab_q;
5933: Z q,q1;
5934: UINT c0,c1,c;
5935: NM *p;
5936: NM m,t;
5937: int mpos;
5938:
5939: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
5940: if ( !m0 || !m1 ) return;
5941: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
5942: if ( nd_module )
5943: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
5944:
5945: NEWNM(m); d = DL(m);
5946: if ( mod ) {
5947: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
5948: } else if ( nd_vc )
5949: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
5950: else
1.6 noro 5951: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 5952: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
5953: homo = n&1 ? 1 : 0;
5954: if ( homo ) {
5955: /* offset of h-degree */
5956: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
5957: PUT_EXP(DL(m),n-1,h);
5958: TD(DL(m)) = h;
5959: if ( nd_blockmask ) ndl_weight_mask(DL(m));
5960: }
5961: tab[0] = m;
5962: NEWNM(m); d = DL(m);
5963: for ( i = 0, curlen = 1; i < n2; i++ ) {
5964: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
5965: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
5966: /* xi^a*(Di^k*xi^l)*Di^b */
5967: a += l; b += k;
5968: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
5969: if ( !k || !l ) {
5970: for ( j = 0; j < curlen; j++ )
5971: if ( (t = tab[j]) != 0 ) {
5972: dt = DL(t);
5973: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
5974: if ( nd_blockmask ) ndl_weight_mask(dt);
5975: }
5976: curlen *= k+1;
5977: continue;
5978: }
5979: min = MIN(k,l);
5980: if ( mod ) {
5981: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
5982: mkwcm(k,l,mod,(int *)ctab);
5983: } else {
5984: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
5985: mkwc(k,l,ctab_q);
5986: }
5987: for ( j = min; j >= 0; j-- ) {
5988: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
5989: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
5990: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
5991: if ( homo ) {
5992: TD(d) = s;
5993: PUT_EXP(d,n-1,s-h);
5994: } else TD(d) = h;
5995: if ( nd_blockmask ) ndl_weight_mask(d);
5996: if ( mod ) c = ctab[j];
5997: else q = ctab_q[j];
5998: p = tab+curlen*j;
5999: if ( j == 0 ) {
6000: for ( u = 0; u < curlen; u++, p++ ) {
6001: if ( tab[u] ) {
6002: ndl_addto(DL(tab[u]),d);
6003: if ( mod ) {
6004: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
6005: } else if ( nd_vc )
6006: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
6007: else {
1.6 noro 6008: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 6009: }
6010: }
6011: }
6012: } else {
6013: for ( u = 0; u < curlen; u++, p++ ) {
6014: if ( tab[u] ) {
6015: NEWNM(t);
6016: ndl_add(DL(tab[u]),d,DL(t));
6017: if ( mod ) {
6018: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
6019: } else if ( nd_vc )
6020: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
6021: else
1.6 noro 6022: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 6023: *p = t;
6024: }
6025: }
6026: }
6027: }
6028: curlen *= k+1;
6029: }
6030: FREENM(m);
6031: if ( nd_module ) {
6032: mpos = MPOS(d1);
6033: for ( i = 0; i < tlen; i++ )
6034: if ( tab[i] ) {
6035: d = DL(tab[i]);
6036: MPOS(d) = mpos;
6037: TD(d) = ndl_weight(d);
6038: }
6039: }
6040: }
6041:
6042: ND ndv_mul_nm_symbolic(NM m0,NDV p)
6043: {
6044: NM mr,mr0;
6045: NMV m;
6046: UINT *d,*dt,*dm;
6047: int c,n,td,i,c1,c2,len;
6048: Q q;
6049: ND r;
6050:
6051: if ( !p ) return 0;
6052: else {
6053: n = NV(p); m = BDY(p);
6054: d = DL(m0);
6055: len = LEN(p);
6056: mr0 = 0;
6057: td = TD(d);
6058: c = CM(m0);
6059: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6060: NEXTNM(mr0,mr);
6061: CM(mr) = 1;
6062: ndl_add(DL(m),d,DL(mr));
6063: }
6064: NEXT(mr) = 0;
6065: MKND(NV(p),mr0,len,r);
6066: SG(r) = SG(p) + TD(d);
6067: return r;
6068: }
6069: }
6070:
6071: ND ndv_mul_nm(int mod,NM m0,NDV p)
6072: {
6073: NM mr,mr0;
6074: NMV m;
6075: UINT *d,*dt,*dm;
6076: int c,n,td,i,c1,c2,len;
6077: P q;
6078: ND r;
6079:
6080: if ( !p ) return 0;
6081: else if ( do_weyl ) {
6082: if ( mod < 0 ) {
6083: error("ndv_mul_nm : not implemented (weyl)");
6084: return 0;
6085: } else
6086: return weyl_ndv_mul_nm(mod,m0,p);
6087: } else {
6088: n = NV(p); m = BDY(p);
6089: d = DL(m0);
6090: len = LEN(p);
6091: mr0 = 0;
6092: td = TD(d);
6093: if ( mod == -1 ) {
6094: c = CM(m0);
6095: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6096: NEXTNM(mr0,mr);
6097: CM(mr) = _mulsf(CM(m),c);
6098: ndl_add(DL(m),d,DL(mr));
6099: }
6100: } else if ( mod == -2 ) {
6101: Z cl;
6102: cl = CZ(m0);
6103: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6104: NEXTNM(mr0,mr);
6105: mullf(CZ(m),cl,&CZ(mr));
6106: ndl_add(DL(m),d,DL(mr));
6107: }
6108: } else if ( mod ) {
6109: c = CM(m0);
6110: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6111: NEXTNM(mr0,mr);
6112: c1 = CM(m);
6113: DMAR(c1,c,0,mod,c2);
6114: CM(mr) = c2;
6115: ndl_add(DL(m),d,DL(mr));
6116: }
6117: } else {
6118: q = CP(m0);
6119: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6120: NEXTNM(mr0,mr);
6121: mulp(nd_vc,CP(m),q,&CP(mr));
6122: ndl_add(DL(m),d,DL(mr));
6123: }
6124: }
6125: NEXT(mr) = 0;
6126: MKND(NV(p),mr0,len,r);
6127: SG(r) = SG(p) + TD(d);
6128: return r;
6129: }
6130: }
6131:
6132: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
6133: {
6134: NM mq0,mq;
6135: NMV tm;
6136: Q q;
6137: int i,nv,sg,c,c1,c2,hindex;
6138: ND p,t,r;
6139:
6140: if ( bucket->m < 0 ) return 0;
6141: else {
6142: nv = NV(d);
6143: mq0 = 0;
6144: tm = (NMV)MALLOC(nmv_adv);
6145: while ( 1 ) {
6146: if ( mod > 0 || mod == -1 )
6147: hindex = head_pbucket(mod,bucket);
6148: else if ( mod == -2 )
6149: hindex = head_pbucket_lf(bucket);
6150: else
6151: hindex = head_pbucket_q(bucket);
6152: if ( hindex < 0 ) break;
6153: p = bucket->body[hindex];
6154: NEXTNM(mq0,mq);
6155: ndl_sub(HDL(p),HDL(d),DL(mq));
6156: ndl_copy(DL(mq),DL(tm));
6157: if ( mod ) {
6158: c1 = invm(HCM(d),mod); c2 = HCM(p);
6159: DMAR(c1,c2,0,mod,c); CM(mq) = c;
6160: CM(tm) = mod-c;
6161: } else {
1.6 noro 6162: divsz(HCZ(p),HCZ(d),&CZ(mq));
6163: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 6164: }
6165: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
6166: bucket->body[hindex] = nd_remove_head(p);
6167: t = nd_remove_head(t);
6168: add_pbucket(mod,bucket,t);
6169: }
6170: if ( !mq0 )
6171: r = 0;
6172: else {
6173: NEXT(mq) = 0;
6174: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
6175: MKND(nv,mq0,i,r);
6176: /* XXX */
6177: SG(r) = HTD(r);
6178: }
6179: return r;
6180: }
6181: }
6182:
6183: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6184: {
6185: NMV m,mr,mr0,t;
6186: int len,i,k;
6187:
6188: if ( !p ) return;
6189: m = BDY(p); len = LEN(p);
6190: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
6191: m = (NMV)((char *)mr0+(len-1)*oadv);
6192: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
6193: t = (NMV)MALLOC(nmv_adv);
6194: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 6195: CZ(t) = CZ(m);
1.1 noro 6196: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
6197: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 6198: CZ(mr) = CZ(t);
1.1 noro 6199: ndl_copy(DL(t),DL(mr));
6200: }
6201: BDY(p) = mr0;
6202: }
6203:
6204: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6205: {
6206: NMV m,mr,mr0;
6207: int len,i;
6208: NDV r;
6209:
6210: if ( !p ) return 0;
6211: m = BDY(p); len = LEN(p);
6212: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
6213: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
6214: ndl_zero(DL(mr));
6215: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 6216: CZ(mr) = CZ(m);
1.1 noro 6217: }
6218: MKNDV(NV(p),mr0,len,r);
6219: SG(r) = SG(p);
1.24 noro 6220: r->sig = p->sig;
1.1 noro 6221: return r;
6222: }
6223:
6224: /* duplicate p */
6225:
6226: NDV ndv_dup(int mod,NDV p)
6227: {
6228: NDV d;
6229: NMV t,m,m0;
6230: int i,len;
6231:
6232: if ( !p ) return 0;
6233: len = LEN(p);
6234: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6235: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6236: ndl_copy(DL(t),DL(m));
1.6 noro 6237: CZ(m) = CZ(t);
1.1 noro 6238: }
6239: MKNDV(NV(p),m0,len,d);
6240: SG(d) = SG(p);
6241: return d;
6242: }
6243:
6244: NDV ndv_symbolic(int mod,NDV p)
6245: {
6246: NDV d;
6247: NMV t,m,m0;
6248: int i,len;
6249:
6250: if ( !p ) return 0;
6251: len = LEN(p);
6252: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6253: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6254: ndl_copy(DL(t),DL(m));
1.6 noro 6255: CZ(m) = ONE;
1.1 noro 6256: }
6257: MKNDV(NV(p),m0,len,d);
6258: SG(d) = SG(p);
6259: return d;
6260: }
6261:
6262: ND nd_dup(ND p)
6263: {
6264: ND d;
6265: NM t,m,m0;
6266:
6267: if ( !p ) return 0;
6268: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
6269: NEXTNM(m0,m);
6270: ndl_copy(DL(t),DL(m));
1.6 noro 6271: CZ(m) = CZ(t);
1.1 noro 6272: }
6273: if ( m0 ) NEXT(m) = 0;
6274: MKND(NV(p),m0,LEN(p),d);
6275: SG(d) = SG(p);
6276: return d;
6277: }
6278:
6279: /* XXX if p->len == 0 then it represents 0 */
6280:
6281: void ndv_mod(int mod,NDV p)
6282: {
6283: NMV t,d;
6284: int r,s,u;
6285: int i,len,dlen;
6286: P cp;
6287: Z c;
6288: Obj gfs;
6289:
6290: if ( !p ) return;
6291: len = LEN(p);
6292: dlen = 0;
6293: if ( mod == -1 )
6294: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6295: simp_ff((Obj)CP(t),&gfs);
6296: if ( gfs ) {
6297: r = FTOIF(CONT((GFS)gfs));
6298: CM(d) = r;
6299: ndl_copy(DL(t),DL(d));
6300: NMV_ADV(d);
6301: dlen++;
6302: }
6303: }
6304: else if ( mod == -2 )
6305: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6306: simp_ff((Obj)CP(t),&gfs);
6307: if ( gfs ) {
6308: lmtolf((LM)gfs,&CZ(d));
6309: ndl_copy(DL(t),DL(d));
6310: NMV_ADV(d);
6311: dlen++;
6312: }
6313: }
6314: else
6315: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6316: if ( nd_vc ) {
6317: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
6318: c = (Z)cp;
6319: } else
1.6 noro 6320: c = CZ(t);
1.1 noro 6321: r = remqi((Q)c,mod);
6322: if ( r ) {
6323: CM(d) = r;
6324: ndl_copy(DL(t),DL(d));
6325: NMV_ADV(d);
6326: dlen++;
6327: }
6328: }
6329: LEN(p) = dlen;
6330: }
6331:
6332: NDV ptondv(VL vl,VL dvl,P p)
6333: {
6334: ND nd;
6335:
6336: nd = ptond(vl,dvl,p);
6337: return ndtondv(0,nd);
6338: }
6339:
6340: void pltozpl(LIST l,Q *cont,LIST *pp)
6341: {
1.16 noro 6342: NODE nd,nd1;
6343: int n;
6344: P *pl;
6345: Q *cl;
6346: int i;
6347: P dmy;
6348: Z dvr,inv;
6349: LIST r;
6350:
6351: nd = BDY(l); n = length(nd);
6352: pl = (P *)MALLOC(n*sizeof(P));
6353: cl = (Q *)MALLOC(n*sizeof(Q));
6354: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
6355: ptozp((P)BDY(nd),1,&cl[i],&dmy);
6356: }
6357: qltozl(cl,n,&dvr);
6358: divz(ONE,dvr,&inv);
6359: nd = BDY(l);
6360: for ( i = 0; i < n; i++, nd = NEXT(nd) )
6361: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
6362: nd = 0;
6363: for ( i = n-1; i >= 0; i-- ) {
6364: MKNODE(nd1,pl[i],nd); nd = nd1;
6365: }
6366: MKLIST(r,nd);
6367: *pp = r;
1.1 noro 6368: }
6369:
6370: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
6371:
6372: NDV pltondv(VL vl,VL dvl,LIST p)
6373: {
6374: int i;
6375: NODE t;
6376: ND r,ri;
6377: NM m;
6378:
6379: if ( !nd_module ) error("pltond : module order must be set");
6380: r = 0;
6381: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
6382: ri = ptond(vl,dvl,(P)BDY(t));
6383: if ( ri )
6384: for ( m = BDY(ri); m; m = NEXT(m) ) {
6385: MPOS(DL(m)) = i;
6386: TD(DL(m)) = ndl_weight(DL(m));
6387: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6388: }
6389: r = nd_add(0,r,ri);
6390: }
6391: return ndtondv(0,r);
6392: }
6393:
6394: ND ptond(VL vl,VL dvl,P p)
6395: {
6396: int n,i,j,k,e;
6397: VL tvl;
6398: V v;
6399: DCP dc;
6400: DCP *w;
6401: ND r,s,t,u;
6402: P x;
6403: int c;
6404: UINT *d;
6405: NM m,m0;
6406:
6407: if ( !p )
6408: return 0;
6409: else if ( NUM(p) ) {
6410: NEWNM(m);
6411: ndl_zero(DL(m));
6412: if ( !INT((Q)p) )
6413: error("ptond : input must be integer-coefficient");
1.6 noro 6414: CZ(m) = (Z)p;
1.1 noro 6415: NEXT(m) = 0;
6416: MKND(nd_nvar,m,1,r);
6417: SG(r) = 0;
6418: return r;
6419: } else {
6420: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
6421: w = (DCP *)MALLOC(k*sizeof(DCP));
6422: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
6423: for ( i = 0, tvl = dvl, v = VR(p);
6424: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
6425: if ( !tvl ) {
6426: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
6427: t = ptond(vl,dvl,COEF(w[j]));
6428: pwrp(vl,x,DEG(w[j]),&p);
6429: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
6430: }
6431: return s;
6432: } else {
6433: NEWNM(m0); d = DL(m0);
6434: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 6435: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 6436: TD(d) = MUL_WEIGHT(e,i);
6437: if ( nd_blockmask) ndl_weight_mask(d);
6438: if ( nd_module ) MPOS(d) = 0;
6439: t = ptond(vl,dvl,COEF(w[j]));
6440: for ( m = BDY(t); m; m = NEXT(m) )
6441: ndl_addto(DL(m),d);
6442: SG(t) += TD(d);
6443: s = nd_add(0,s,t);
6444: }
6445: FREENM(m0);
6446: return s;
6447: }
6448: }
6449: }
6450:
6451: P ndvtop(int mod,VL vl,VL dvl,NDV p)
6452: {
6453: VL tvl;
6454: int len,n,j,i,e;
6455: NMV m;
6456: Z q;
6457: P c;
6458: UINT *d;
6459: P s,r,u,t,w;
6460: GFS gfs;
6461:
6462: if ( !p ) return 0;
6463: else {
6464: len = LEN(p);
6465: n = NV(p);
6466: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6467: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
6468: if ( mod == -1 ) {
6469: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6470: } else if ( mod == -2 ) {
6471: c = (P)CZ(m);
6472: } else if ( mod > 0 ) {
1.6 noro 6473: STOZ(CM(m),q); c = (P)q;
1.1 noro 6474: } else
6475: c = CP(m);
6476: d = DL(m);
6477: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6478: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6479: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6480: }
6481: addp(vl,s,t,&u); s = u;
6482: }
6483: return s;
6484: }
6485: }
6486:
6487: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
6488: {
6489: VL tvl;
6490: int len,n,j,i,e;
6491: NMV m;
6492: Z q;
6493: P c;
6494: UINT *d;
6495: P s,r,u,t,w;
6496: GFS gfs;
6497: P *a;
6498: LIST l;
6499: NODE nd,nd1;
6500:
6501: if ( !p ) return 0;
6502: else {
6503: a = (P *)MALLOC((rank+1)*sizeof(P));
6504: for ( i = 0; i <= rank; i++ ) a[i] = 0;
6505: len = LEN(p);
6506: n = NV(p);
6507: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6508: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
6509: if ( mod == -1 ) {
6510: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6511: } else if ( mod ) {
1.6 noro 6512: STOZ(CM(m),q); c = (P)q;
1.1 noro 6513: } else
6514: c = CP(m);
6515: d = DL(m);
6516: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6517: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6518: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6519: }
6520: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
6521: }
6522: nd = 0;
6523: for ( i = rank; i > 0; i-- ) {
6524: MKNODE(nd1,a[i],nd); nd = nd1;
6525: }
6526: MKLIST(l,nd);
6527: return l;
6528: }
6529: }
6530:
6531: NDV ndtondv(int mod,ND p)
6532: {
6533: NDV d;
6534: NMV m,m0;
6535: NM t;
6536: int i,len;
6537:
6538: if ( !p ) return 0;
6539: len = LEN(p);
6540: if ( mod > 0 || mod == -1 )
6541: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6542: else
6543: m0 = m = MALLOC(len*nmv_adv);
6544: #if 0
6545: ndv_alloc += nmv_adv*len;
6546: #endif
6547: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
6548: ndl_copy(DL(t),DL(m));
1.6 noro 6549: CZ(m) = CZ(t);
1.1 noro 6550: }
6551: MKNDV(NV(p),m0,len,d);
6552: SG(d) = SG(p);
1.24 noro 6553: d->sig = p->sig;
1.1 noro 6554: return d;
6555: }
6556:
1.16 noro 6557: static int dmm_comp_nv;
6558:
6559: int dmm_comp(DMM *a,DMM *b)
6560: {
6561: return -compdmm(dmm_comp_nv,*a,*b);
6562: }
6563:
6564: void dmm_sort_by_ord(DMM *a,int len,int nv)
6565: {
6566: dmm_comp_nv = nv;
6567: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
6568: }
6569:
6570: void dpm_sort(DPM p,DPM *rp)
6571: {
6572: DMM t,t1;
6573: int len,i,n;
6574: DMM *a;
6575: DPM d;
6576:
6577: if ( !p ) *rp = 0;
6578: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6579: a = (DMM *)MALLOC(len*sizeof(DMM));
6580: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6581: n = p->nv;
6582: dmm_sort_by_ord(a,len,n);
6583: t = 0;
6584: for ( i = len-1; i >= 0; i-- ) {
6585: NEWDMM(t1);
6586: t1->c = a[i]->c;
6587: t1->dl = a[i]->dl;
6588: t1->pos = a[i]->pos;
6589: t1->next = t;
6590: t = t1;
6591: }
6592: MKDPM(n,t,d);
6593: SG(d) = SG(p);
6594: *rp = d;
6595: }
6596:
1.18 noro 6597: int dpm_comp(DPM *a,DPM *b)
6598: {
1.22 noro 6599: return -compdpm(CO,*a,*b);
1.18 noro 6600: }
6601:
6602: NODE dpm_sort_list(NODE l)
6603: {
6604: int i,len;
6605: NODE t,t1;
6606: DPM *a;
6607:
6608: len = length(l);
6609: a = (DPM *)MALLOC(len*sizeof(DPM));
6610: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
6611: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
6612: t = 0;
6613: for ( i = len-1; i >= 0; i-- ) {
6614: MKNODE(t1,(pointer)a[i],t); t = t1;
6615: }
6616: return t;
6617: }
6618:
1.20 noro 6619: int nmv_comp(NMV a,NMV b)
6620: {
1.21 noro 6621: int t;
6622: t = DL_COMPARE(a->dl,b->dl);
6623: return -t;
1.20 noro 6624: }
6625:
1.16 noro 6626: NDV dpmtondv(int mod,DPM p)
6627: {
6628: NDV d;
6629: NMV m,m0;
6630: DMM t;
6631: DMM *a;
6632: int i,len,n;
6633:
6634: if ( !p ) return 0;
6635: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6636: a = (DMM *)MALLOC(len*sizeof(DMM));
6637: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6638: n = p->nv;
6639: dmm_sort_by_ord(a,len,n);
6640: if ( mod > 0 || mod == -1 )
6641: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6642: else
6643: m0 = m = MALLOC(len*nmv_adv);
6644: #if 0
6645: ndv_alloc += nmv_adv*len;
6646: #endif
6647: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6648: dltondl(n,a[i]->dl,DL(m));
6649: MPOS(DL(m)) = a[i]->pos;
1.20 noro 6650: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 6651: CZ(m) = (Z)a[i]->c;
6652: }
1.20 noro 6653: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 6654: MKNDV(NV(p),m0,len,d);
6655: SG(d) = SG(p);
6656: return d;
6657: }
6658:
1.1 noro 6659: ND ndvtond(int mod,NDV p)
6660: {
6661: ND d;
6662: NM m,m0;
6663: NMV t;
6664: int i,len;
6665:
6666: if ( !p ) return 0;
6667: m0 = 0;
6668: len = p->len;
6669: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6670: NEXTNM(m0,m);
6671: ndl_copy(DL(t),DL(m));
1.6 noro 6672: CZ(m) = CZ(t);
1.1 noro 6673: }
6674: NEXT(m) = 0;
6675: MKND(NV(p),m0,len,d);
6676: SG(d) = SG(p);
1.28 noro 6677: d->sig = p->sig;
1.1 noro 6678: return d;
6679: }
6680:
6681: DP ndvtodp(int mod,NDV p)
6682: {
6683: MP m,m0;
6684: DP d;
6685: NMV t;
6686: int i,len;
6687:
6688: if ( !p ) return 0;
6689: m0 = 0;
6690: len = p->len;
6691: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6692: NEXTMP(m0,m);
6693: m->dl = ndltodl(nd_nvar,DL(t));
6694: m->c = (Obj)ndctop(mod,t->c);
6695: }
6696: NEXT(m) = 0;
6697: MKDP(nd_nvar,m0,d);
6698: SG(d) = SG(p);
6699: return d;
6700: }
6701:
1.16 noro 6702: DPM ndvtodpm(int mod,NDV p)
6703: {
6704: DMM m,m0;
6705: DPM d;
6706: NMV t;
6707: int i,len;
6708:
6709: if ( !p ) return 0;
6710: m0 = 0;
6711: len = p->len;
6712: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6713: NEXTDMM(m0,m);
6714: m->dl = ndltodl(nd_nvar,DL(t));
6715: m->c = (Obj)ndctop(mod,t->c);
6716: m->pos = MPOS(DL(t));
6717: }
6718: NEXT(m) = 0;
6719: MKDPM(nd_nvar,m0,d);
6720: SG(d) = SG(p);
6721: return d;
6722: }
6723:
6724:
1.1 noro 6725: DP ndtodp(int mod,ND p)
6726: {
6727: MP m,m0;
6728: DP d;
6729: NM t;
6730: int i,len;
6731:
6732: if ( !p ) return 0;
6733: m0 = 0;
6734: len = p->len;
6735: for ( t = BDY(p); t; t = NEXT(t) ) {
6736: NEXTMP(m0,m);
6737: m->dl = ndltodl(nd_nvar,DL(t));
6738: m->c = (Obj)ndctop(mod,t->c);
6739: }
6740: NEXT(m) = 0;
6741: MKDP(nd_nvar,m0,d);
6742: SG(d) = SG(p);
6743: return d;
6744: }
6745:
6746: void ndv_print(NDV p)
6747: {
6748: NMV m;
6749: int i,len;
6750:
6751: if ( !p ) printf("0\n");
6752: else {
6753: len = LEN(p);
6754: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6755: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 6756: else printf("+%ld*",CM(m));
1.1 noro 6757: ndl_print(DL(m));
6758: }
6759: printf("\n");
6760: }
6761: }
6762:
6763: void ndv_print_q(NDV p)
6764: {
6765: NMV m;
6766: int i,len;
6767:
6768: if ( !p ) printf("0\n");
6769: else {
6770: len = LEN(p);
6771: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6772: printf("+");
1.6 noro 6773: printexpr(CO,(Obj)CZ(m));
1.1 noro 6774: printf("*");
6775: ndl_print(DL(m));
6776: }
6777: printf("\n");
6778: }
6779: }
6780:
6781: NODE ndv_reducebase(NODE x,int *perm)
6782: {
6783: int len,i,j;
6784: NDVI w;
6785: NODE t,t0;
6786:
6787: len = length(x);
6788: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
6789: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
6790: w[i].p = BDY(t); w[i].i = perm[i];
6791: }
6792: for ( i = 0; i < len; i++ ) {
6793: for ( j = 0; j < i; j++ ) {
6794: if ( w[i].p && w[j].p ) {
6795: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
6796: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
6797: }
6798: }
6799: }
6800: for ( i = j = 0, t0 = 0; i < len; i++ ) {
6801: if ( w[i].p ) {
6802: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
6803: perm[j++] = w[i].i;
6804: }
6805: }
6806: NEXT(t) = 0; x = t0;
6807: return x;
6808: }
6809:
6810: /* XXX incomplete */
6811:
1.21 noro 6812: extern DMMstack dmm_stack;
6813: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 6814:
1.1 noro 6815: void nd_init_ord(struct order_spec *ord)
6816: {
6817: nd_module = (ord->id >= 256);
6818: if ( nd_module ) {
6819: nd_dcomp = -1;
1.21 noro 6820: nd_module_ordtype = ord->module_ordtype;
1.1 noro 6821: nd_pot_nelim = ord->pot_nelim;
6822: nd_poly_weight_len = ord->nv;
6823: nd_poly_weight = ord->top_weight;
6824: nd_module_rank = ord->module_rank;
6825: nd_module_weight = ord->module_top_weight;
6826: }
6827: nd_matrix = 0;
6828: nd_matrix_len = 0;
6829: switch ( ord->id ) {
6830: case 0:
6831: switch ( ord->ord.simple ) {
6832: case 0:
6833: nd_dcomp = 1;
6834: nd_isrlex = 1;
6835: break;
6836: case 1:
6837: nd_dcomp = 1;
6838: nd_isrlex = 0;
6839: break;
6840: case 2:
6841: nd_dcomp = 0;
6842: nd_isrlex = 0;
6843: ndl_compare_function = ndl_lex_compare;
6844: break;
6845: case 11:
6846: /* XXX */
6847: nd_dcomp = 0;
6848: nd_isrlex = 1;
6849: ndl_compare_function = ndl_ww_lex_compare;
6850: break;
6851: default:
6852: error("nd_gr : unsupported order");
6853: }
6854: break;
6855: case 1:
6856: /* block order */
6857: /* XXX */
6858: nd_dcomp = -1;
6859: nd_isrlex = 0;
6860: ndl_compare_function = ndl_block_compare;
6861: break;
6862: case 2:
6863: /* matrix order */
6864: /* XXX */
6865: nd_dcomp = -1;
6866: nd_isrlex = 0;
6867: nd_matrix_len = ord->ord.matrix.row;
6868: nd_matrix = ord->ord.matrix.matrix;
6869: ndl_compare_function = ndl_matrix_compare;
6870: break;
6871: case 3:
6872: /* composite order */
6873: nd_dcomp = -1;
6874: nd_isrlex = 0;
6875: nd_worb_len = ord->ord.composite.length;
6876: nd_worb = ord->ord.composite.w_or_b;
6877: ndl_compare_function = ndl_composite_compare;
6878: break;
6879:
6880: /* module order */
6881: case 256:
6882: switch ( ord->ord.simple ) {
6883: case 0:
1.21 noro 6884: nd_dcomp = 0;
1.1 noro 6885: nd_isrlex = 1;
1.21 noro 6886: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 6887: break;
6888: case 1:
1.21 noro 6889: nd_dcomp = 0;
1.1 noro 6890: nd_isrlex = 0;
6891: ndl_compare_function = ndl_module_glex_compare;
6892: break;
6893: case 2:
1.21 noro 6894: nd_dcomp = 0;
1.1 noro 6895: nd_isrlex = 0;
1.21 noro 6896: ndl_compare_function = ndl_module_compare;
6897: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 6898: break;
6899: default:
1.21 noro 6900: error("nd_init_ord : unsupported order");
1.1 noro 6901: }
6902: break;
6903: case 257:
6904: /* block order */
6905: nd_isrlex = 0;
1.21 noro 6906: ndl_compare_function = ndl_module_compare;
6907: ndl_base_compare_function = ndl_block_compare;
1.1 noro 6908: break;
6909: case 258:
6910: /* matrix order */
6911: nd_isrlex = 0;
6912: nd_matrix_len = ord->ord.matrix.row;
6913: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 6914: ndl_compare_function = ndl_module_compare;
6915: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 6916: break;
6917: case 259:
6918: /* composite order */
6919: nd_isrlex = 0;
6920: nd_worb_len = ord->ord.composite.length;
6921: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 6922: ndl_compare_function = ndl_module_compare;
6923: ndl_base_compare_function = ndl_composite_compare;
6924: break;
6925: case 300:
6926: /* schreyer order */
6927: if ( ord->base->id != 256 )
6928: error("nd_init_ord : unsupported base order");
6929: ndl_compare_function = ndl_module_schreyer_compare;
6930: dmm_stack = ord->dmmstack;
6931: switch ( ord->base->ord.simple ) {
6932: case 0:
6933: nd_isrlex = 1;
6934: ndl_base_compare_function = ndl_glex_compare;
6935: dl_base_compare_function = cmpdl_revgradlex;
6936: break;
6937: case 1:
6938: nd_isrlex = 0;
6939: ndl_base_compare_function = ndl_glex_compare;
6940: dl_base_compare_function = cmpdl_gradlex;
6941: break;
6942: case 2:
6943: nd_isrlex = 0;
6944: ndl_base_compare_function = ndl_lex_compare;
6945: dl_base_compare_function = cmpdl_lex;
6946: break;
6947: default:
6948: error("nd_init_ord : unsupported order");
6949: }
1.1 noro 6950: break;
6951: }
6952: nd_ord = ord;
6953: }
6954:
6955: BlockMask nd_create_blockmask(struct order_spec *ord)
6956: {
6957: int n,i,j,s,l;
6958: UINT *t;
6959: BlockMask bm;
6960:
6961: /* we only create mask table for block order */
6962: if ( ord->id != 1 && ord->id != 257 )
6963: return 0;
6964: n = ord->ord.block.length;
6965: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
6966: bm->n = n;
6967: bm->order_pair = ord->ord.block.order_pair;
6968: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
6969: for ( i = 0, s = 0; i < n; i++ ) {
6970: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
6971: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
6972: l = bm->order_pair[i].length;
6973: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
6974: }
6975: return bm;
6976: }
6977:
6978: EPOS nd_create_epos(struct order_spec *ord)
6979: {
6980: int i,j,l,s,ord_l,ord_o;
6981: EPOS epos;
6982: struct order_pair *op;
6983:
6984: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
6985: switch ( ord->id ) {
1.21 noro 6986: case 0: case 256: case 300:
1.1 noro 6987: if ( nd_isrlex ) {
6988: for ( i = 0; i < nd_nvar; i++ ) {
6989: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
6990: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
6991: }
6992: } else {
6993: for ( i = 0; i < nd_nvar; i++ ) {
6994: epos[i].i = nd_exporigin + i/nd_epw;
6995: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
6996: }
6997: }
6998: break;
6999: case 1: case 257:
7000: /* block order */
7001: l = ord->ord.block.length;
7002: op = ord->ord.block.order_pair;
7003: for ( j = 0, s = 0; j < l; j++ ) {
7004: ord_o = op[j].order;
7005: ord_l = op[j].length;
7006: if ( !ord_o )
7007: for ( i = 0; i < ord_l; i++ ) {
7008: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
7009: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
7010: }
7011: else
7012: for ( i = 0; i < ord_l; i++ ) {
7013: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
7014: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
7015: }
7016: s += ord_l;
7017: }
7018: break;
7019: case 2:
7020: /* matrix order */
7021: case 3:
7022: /* composite order */
7023: default:
7024: for ( i = 0; i < nd_nvar; i++ ) {
7025: epos[i].i = nd_exporigin + i/nd_epw;
7026: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7027: }
7028: break;
7029: }
7030: return epos;
7031: }
7032:
7033: /* external interface */
7034:
7035: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
7036: {
7037: NODE t,in0,in;
7038: ND ndf,nf;
7039: NDV ndvf;
7040: VL vv,tv;
7041: int stat,nvar,max,mrank;
7042: union oNDC dn;
7043: Q cont;
7044: P pp;
7045: LIST ppl;
7046:
7047: if ( !f ) {
7048: *rp = 0;
7049: return;
7050: }
7051: pltovl(v,&vv);
7052: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
7053:
7054: /* max=65536 implies nd_bpe=32 */
7055: max = 65536;
7056:
7057: nd_module = 0;
7058: /* nd_module will be set if ord is a module ordering */
7059: nd_init_ord(ord);
7060: nd_setup_parameters(nvar,max);
7061: if ( nd_module && OID(f) != O_LIST )
7062: error("nd_nf_p : the first argument must be a list");
7063: if ( nd_module ) mrank = length(BDY((LIST)f));
7064: /* conversion to ndv */
7065: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
7066: NEXTNODE(in0,in);
7067: if ( nd_module ) {
7068: if ( !BDY(t) || OID(BDY(t)) != O_LIST
7069: || length(BDY((LIST)BDY(t))) != mrank )
7070: error("nd_nf_p : inconsistent basis element");
7071: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
7072: else ppl = (LIST)BDY(t);
7073: BDY(in) = (pointer)pltondv(CO,vv,ppl);
7074: } else {
7075: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
7076: else pp = (P)BDY(t);
7077: BDY(in) = (pointer)ptondv(CO,vv,pp);
7078: }
7079: if ( m ) ndv_mod(m,(NDV)BDY(in));
7080: }
7081: if ( in0 ) NEXT(in) = 0;
7082:
7083: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
7084: else ndvf = ptondv(CO,vv,(P)f);
7085: if ( m ) ndv_mod(m,ndvf);
7086: ndf = (pointer)ndvtond(m,ndvf);
7087:
7088: /* dont sort, dont removecont */
1.24 noro 7089: ndv_setup(m,0,in0,1,1,0);
1.1 noro 7090: nd_scale=2;
1.6 noro 7091: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 7092: if ( !stat )
7093: error("nd_nf_p : exponent too large");
7094: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
7095: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
7096: }
7097:
7098: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
7099: {
7100: NM m;
7101: UINT *t,*s;
7102: int i;
7103:
7104: for ( i = 0; i < n; i++ ) r[i] = 0;
7105: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7106: t = DL(m);
7107: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7108: r[i] = CM(m);
7109: }
7110: for ( i = 0; !r[i]; i++ );
7111: return i;
7112: }
7113:
7114: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
7115: {
7116: NM m;
7117: UINT *t,*s;
7118: int i;
7119:
7120: for ( i = 0; i < n; i++ ) r[i] = 0;
7121: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7122: t = DL(m);
7123: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7124: r[i] = CZ(m);
1.1 noro 7125: }
7126: for ( i = 0; !r[i]; i++ );
7127: return i;
7128: }
7129:
7130: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
7131: {
7132: NM m;
7133: UINT *t,*s;
7134: int i;
7135:
7136: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
7137: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7138: t = DL(m);
7139: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7140: mpz_set(r[i],BDY(CZ(m)));
7141: }
7142: for ( i = 0; !mpz_sgn(r[i]); i++ );
7143: return i;
7144: }
7145:
7146: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
7147: {
7148: NM m;
7149: unsigned long *v;
7150: int i,j,h,size;
7151: UINT *s,*t;
7152:
7153: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
7154: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
7155: bzero(v,size);
7156: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
7157: t = DL(m);
7158: h = ndl_hash_value(t);
7159: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7160: v[i/BLEN] |= 1L <<(i%BLEN);
7161: }
7162: return v;
7163: }
7164:
7165: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
7166: {
7167: NMV mr;
7168: UINT *d,*t,*s;
7169: int i,j,len,h,head;
7170:
7171: d = DL(m);
7172: len = LEN(p);
7173: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7174: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7175: ndl_add(d,DL(mr),t);
7176: h = ndl_hash_value(t);
7177: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7178: if ( j == 0 ) head = i;
7179: v[i/BLEN] |= 1L <<(i%BLEN);
7180: }
7181: return head;
7182: }
7183:
7184: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
7185: {
7186: NM m;
7187: NMV mr;
7188: UINT *d,*t,*s;
7189: NDV p;
7190: int i,j,len;
7191: Z *r;
7192:
7193: m = pair->mul;
7194: d = DL(m);
7195: p = nd_ps[pair->index];
7196: len = LEN(p);
7197: r = (Z *)CALLOC(n,sizeof(Q));
7198: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7199: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7200: ndl_add(d,DL(mr),t);
7201: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7202: r[i] = CZ(mr);
1.1 noro 7203: }
7204: return r;
7205: }
7206:
1.11 noro 7207: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 7208: {
7209: NM m;
7210: NMV mr;
1.11 noro 7211: UINT *d,*t,*s,*u;
1.1 noro 7212: NDV p;
7213: unsigned char *ivc;
7214: unsigned short *ivs;
7215: UINT *v,*ivi,*s0v;
1.11 noro 7216: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 7217: IndArray r;
7218:
7219: m = pair->mul;
7220: d = DL(m);
7221: if ( trace )
7222: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
7223: else
7224: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
7225:
7226: len = LEN(p);
7227: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7228: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 7229: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
7230: ndl_add(d,DL(mr),t);
7231: st = prev;
7232: ed = n;
7233: while ( ed > st ) {
7234: md = (st+ed)/2;
7235: u = s0+md*nd_wpd;
7236: c = DL_COMPARE(u,t);
7237: if ( c == 0 ) break;
7238: else if ( c > 0 ) st = md;
7239: else ed = md;
7240: }
7241: prev = v[j] = md;
1.1 noro 7242: }
7243: r = (IndArray)MALLOC(sizeof(struct oIndArray));
7244: r->head = v[0];
7245: diff = 0;
7246: for ( i = 1; i < len; i++ ) {
7247: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
7248: }
7249: if ( diff < 256 ) {
7250: r->width = 1;
7251: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
7252: r->index.c = ivc;
7253: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
7254: } else if ( diff < 65536 ) {
7255: r->width = 2;
7256: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
7257: r->index.s = ivs;
7258: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
7259: } else {
7260: r->width = 4;
7261: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
7262: r->index.i = ivi;
7263: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
7264: }
7265: return r;
7266: }
7267:
7268: int compress_array(Z *svect,Z *cvect,int n)
7269: {
7270: int i,j;
7271:
7272: for ( i = j = 0; i < n; i++ )
7273: if ( svect[i] ) cvect[j++] = svect[i];
7274: return j;
7275: }
7276:
7277: void expand_array(Z *svect,Z *cvect,int n)
7278: {
7279: int i,j;
7280:
7281: for ( i = j = 0; j < n; i++ )
7282: if ( svect[i] ) svect[i] = cvect[j++];
7283: }
7284:
1.8 noro 7285: #if 0
1.1 noro 7286: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7287: {
7288: int i,j,k,len,pos,prev,nz;
7289: Z cs,mcs,c1,c2,cr,gcd,t;
7290: IndArray ivect;
7291: unsigned char *ivc;
7292: unsigned short *ivs;
7293: unsigned int *ivi;
7294: NDV redv;
7295: NMV mr;
7296: NODE rp;
7297: int maxrs;
7298: double hmag;
7299: Z *cvect;
1.3 noro 7300: int l;
1.1 noro 7301:
7302: maxrs = 0;
7303: for ( i = 0; i < col && !svect[i]; i++ );
7304: if ( i == col ) return maxrs;
7305: hmag = p_mag((P)svect[i])*nd_scale;
7306: cvect = (Z *)MALLOC(col*sizeof(Q));
7307: for ( i = 0; i < nred; i++ ) {
7308: ivect = imat[i];
7309: k = ivect->head;
7310: if ( svect[k] ) {
7311: maxrs = MAX(maxrs,rp0[i]->sugar);
7312: redv = nd_demand?ndv_load(rp0[i]->index)
7313: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7314: len = LEN(redv); mr = BDY(redv);
1.6 noro 7315: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 7316: chsgnz(cs,&mcs);
7317: if ( !UNIQ(cr) ) {
7318: for ( j = 0; j < col; j++ ) {
7319: mulz(svect[j],cr,&c1); svect[j] = c1;
7320: }
7321: }
7322: svect[k] = 0; prev = k;
7323: switch ( ivect->width ) {
7324: case 1:
7325: ivc = ivect->index.c;
7326: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7327: pos = prev+ivc[j]; prev = pos;
1.6 noro 7328: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7329: }
7330: break;
7331: case 2:
7332: ivs = ivect->index.s;
7333: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7334: pos = prev+ivs[j]; prev = pos;
1.6 noro 7335: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7336: }
7337: break;
7338: case 4:
7339: ivi = ivect->index.i;
7340: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7341: pos = prev+ivi[j]; prev = pos;
1.6 noro 7342: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7343: }
7344: break;
7345: }
7346: for ( j = k+1; j < col && !svect[j]; j++ );
7347: if ( j == col ) break;
7348: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
7349: nz = compress_array(svect,cvect,col);
7350: removecont_array((P *)cvect,nz,1);
7351: expand_array(svect,cvect,nz);
7352: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
7353: }
7354: }
7355: }
7356: nz = compress_array(svect,cvect,col);
7357: removecont_array((P *)cvect,nz,1);
7358: expand_array(svect,cvect,nz);
7359: if ( DP_Print ) {
7360: fprintf(asir_out,"-"); fflush(asir_out);
7361: }
7362: return maxrs;
7363: }
1.4 noro 7364: #else
1.9 noro 7365:
1.4 noro 7366: /* direct mpz version */
7367: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7368: {
7369: int i,j,k,len,pos,prev;
7370: mpz_t cs,cr,gcd;
7371: IndArray ivect;
7372: unsigned char *ivc;
7373: unsigned short *ivs;
7374: unsigned int *ivi;
7375: NDV redv;
7376: NMV mr;
7377: NODE rp;
7378: int maxrs;
7379: double hmag;
7380: int l;
1.13 noro 7381: static mpz_t *svect;
7382: static int svect_len=0;
1.4 noro 7383:
7384: maxrs = 0;
7385: for ( i = 0; i < col && !svect0[i]; i++ );
7386: if ( i == col ) return maxrs;
7387: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 7388: if ( col > svect_len ) {
7389: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
7390: svect_len = col;
7391: }
1.4 noro 7392: for ( i = 0; i < col; i++ ) {
7393: mpz_init(svect[i]);
7394: if ( svect0[i] )
7395: mpz_set(svect[i],BDY(svect0[i]));
7396: else
7397: mpz_set_ui(svect[i],0);
7398: }
7399: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
7400: for ( i = 0; i < nred; i++ ) {
7401: ivect = imat[i];
7402: k = ivect->head;
7403: if ( mpz_sgn(svect[k]) ) {
7404: maxrs = MAX(maxrs,rp0[i]->sugar);
7405: redv = nd_demand?ndv_load(rp0[i]->index)
7406: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7407: len = LEN(redv); mr = BDY(redv);
1.6 noro 7408: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 7409: mpz_div(cs,svect[k],gcd);
1.6 noro 7410: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 7411: mpz_neg(cs,cs);
1.9 noro 7412: if ( MUNIMPZ(cr) )
7413: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
7414: else if ( !UNIMPZ(cr) )
7415: for ( j = 0; j < col; j++ ) {
7416: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
7417: }
1.4 noro 7418: mpz_set_ui(svect[k],0);
7419: prev = k;
7420: switch ( ivect->width ) {
7421: case 1:
7422: ivc = ivect->index.c;
7423: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7424: pos = prev+ivc[j]; prev = pos;
1.6 noro 7425: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7426: }
7427: break;
7428: case 2:
7429: ivs = ivect->index.s;
7430: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7431: pos = prev+ivs[j]; prev = pos;
1.6 noro 7432: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7433: }
7434: break;
7435: case 4:
7436: ivi = ivect->index.i;
7437: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7438: pos = prev+ivi[j]; prev = pos;
1.6 noro 7439: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7440: }
7441: break;
7442: }
7443: for ( j = k+1; j < col && !svect[j]; j++ );
7444: if ( j == col ) break;
7445: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
7446: mpz_removecont_array(svect,col);
7447: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
7448: }
7449: }
7450: }
7451: mpz_removecont_array(svect,col);
7452: if ( DP_Print ) {
7453: fprintf(asir_out,"-"); fflush(asir_out);
7454: }
7455: for ( i = 0; i < col; i++ )
7456: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
7457: else svect0[i] = 0;
7458: return maxrs;
7459: }
7460: #endif
1.1 noro 7461:
1.40 ! noro 7462: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.1 noro 7463: {
7464: int i,j,k,len,pos,prev;
7465: UINT c,c1,c2,c3,up,lo,dmy;
7466: IndArray ivect;
7467: unsigned char *ivc;
7468: unsigned short *ivs;
7469: unsigned int *ivi;
7470: NDV redv;
7471: NMV mr;
7472: NODE rp;
7473: int maxrs;
7474:
7475: maxrs = 0;
7476: for ( i = 0; i < nred; i++ ) {
7477: ivect = imat[i];
7478: k = ivect->head; svect[k] %= m;
1.40 ! noro 7479: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.1 noro 7480: maxrs = MAX(maxrs,rp0[i]->sugar);
7481: c = m-c; redv = nd_ps[rp0[i]->index];
7482: len = LEN(redv); mr = BDY(redv);
7483: svect[k] = 0; prev = k;
7484: switch ( ivect->width ) {
7485: case 1:
7486: ivc = ivect->index.c;
7487: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7488: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.40 ! noro 7489: if ( c1 ) {
! 7490: c2 = svect[pos];
1.1 noro 7491: DMA(c1,c,c2,up,lo);
7492: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7493: } else svect[pos] = lo;
1.40 ! noro 7494: }
1.1 noro 7495: }
7496: break;
7497: case 2:
7498: ivs = ivect->index.s;
7499: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7500: pos = prev+ivs[j]; c1 = CM(mr);
7501: prev = pos;
1.40 ! noro 7502: if ( c1 ) {
! 7503: c2 = svect[pos];
1.1 noro 7504: DMA(c1,c,c2,up,lo);
7505: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7506: } else svect[pos] = lo;
1.40 ! noro 7507: }
1.1 noro 7508: }
7509: break;
7510: case 4:
7511: ivi = ivect->index.i;
7512: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7513: pos = prev+ivi[j]; c1 = CM(mr);
7514: prev = pos;
1.40 ! noro 7515: if ( c1 ) {
! 7516: c2 = svect[pos];
1.1 noro 7517: DMA(c1,c,c2,up,lo);
7518: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7519: } else svect[pos] = lo;
1.40 ! noro 7520: }
1.1 noro 7521: }
7522: break;
7523: }
7524: }
7525: }
7526: for ( i = 0; i < col; i++ )
7527: if ( svect[i] >= (UINT)m ) svect[i] %= m;
7528: return maxrs;
7529: }
7530:
7531: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7532: {
7533: int i,j,k,len,pos,prev;
7534: UINT c,c1,c2,c3,up,lo,dmy;
7535: IndArray ivect;
7536: unsigned char *ivc;
7537: unsigned short *ivs;
7538: unsigned int *ivi;
7539: NDV redv;
7540: NMV mr;
7541: NODE rp;
7542: int maxrs;
7543:
7544: maxrs = 0;
7545: for ( i = 0; i < nred; i++ ) {
7546: ivect = imat[i];
7547: k = ivect->head;
7548: if ( (c = svect[k]) != 0 ) {
7549: maxrs = MAX(maxrs,rp0[i]->sugar);
7550: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
7551: len = LEN(redv); mr = BDY(redv);
7552: svect[k] = 0; prev = k;
7553: switch ( ivect->width ) {
7554: case 1:
7555: ivc = ivect->index.c;
7556: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7557: pos = prev+ivc[j]; prev = pos;
7558: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7559: }
7560: break;
7561: case 2:
7562: ivs = ivect->index.s;
7563: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7564: pos = prev+ivs[j]; prev = pos;
7565: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7566: }
7567: break;
7568: case 4:
7569: ivi = ivect->index.i;
7570: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7571: pos = prev+ivi[j]; prev = pos;
7572: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7573: }
7574: break;
7575: }
7576: }
7577: }
7578: return maxrs;
7579: }
7580:
7581: ND nd_add_lf(ND p1,ND p2)
7582: {
7583: int n,c,can;
7584: ND r;
7585: NM m1,m2,mr0,mr,s;
7586: Z t;
7587:
7588: if ( !p1 ) return p2;
7589: else if ( !p2 ) return p1;
7590: else {
7591: can = 0;
7592: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
7593: c = DL_COMPARE(DL(m1),DL(m2));
7594: switch ( c ) {
7595: case 0:
7596: addlf(CZ(m1),CZ(m2),&t);
7597: s = m1; m1 = NEXT(m1);
7598: if ( t ) {
7599: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
7600: } else {
7601: can += 2; FREENM(s);
7602: }
7603: s = m2; m2 = NEXT(m2); FREENM(s);
7604: break;
7605: case 1:
7606: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
7607: break;
7608: case -1:
7609: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
7610: break;
7611: }
7612: }
7613: if ( !mr0 )
7614: if ( m1 ) mr0 = m1;
7615: else if ( m2 ) mr0 = m2;
7616: else return 0;
7617: else if ( m1 ) NEXT(mr) = m1;
7618: else if ( m2 ) NEXT(mr) = m2;
7619: else NEXT(mr) = 0;
7620: BDY(p1) = mr0;
7621: SG(p1) = MAX(SG(p1),SG(p2));
7622: LEN(p1) = LEN(p1)+LEN(p2)-can;
7623: FREEND(p2);
7624: return p1;
7625: }
7626: }
7627:
7628: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7629: {
7630: int i,j,k,len,pos,prev;
7631: mpz_t c,mc,c1;
7632: IndArray ivect;
7633: unsigned char *ivc;
7634: unsigned short *ivs;
7635: unsigned int *ivi;
7636: NDV redv;
7637: NMV mr;
7638: NODE rp;
7639: int maxrs;
7640:
7641: maxrs = 0;
7642: lf_lazy = 1;
7643: for ( i = 0; i < nred; i++ ) {
7644: ivect = imat[i];
7645: k = ivect->head;
7646: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
7647: if ( mpz_sgn(svect[k]) ) {
7648: maxrs = MAX(maxrs,rp0[i]->sugar);
7649: mpz_neg(svect[k],svect[k]);
7650: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
7651: len = LEN(redv); mr = BDY(redv);
7652: prev = k;
7653: switch ( ivect->width ) {
7654: case 1:
7655: ivc = ivect->index.c;
7656: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7657: pos = prev+ivc[j]; prev = pos;
7658: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7659: }
7660: break;
7661: case 2:
7662: ivs = ivect->index.s;
7663: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7664: pos = prev+ivs[j]; prev = pos;
7665: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7666: }
7667: break;
7668: case 4:
7669: ivi = ivect->index.i;
7670: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7671: pos = prev+ivi[j]; prev = pos;
7672: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7673: }
7674: break;
7675: }
7676: mpz_set_ui(svect[k],0);
7677: }
7678: }
7679: lf_lazy=0;
7680: for ( i = 0; i < col; i++ ) {
7681: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
7682: }
7683: return maxrs;
7684: }
7685:
7686: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
7687: {
7688: int i,j,k,l,rank,s;
7689: mpz_t a,a1,inv;
7690: mpz_t *t,*pivot,*pk;
7691: mpz_t **mat;
7692: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
7693: int size,size1;
7694:
7695: mpz_init(inv);
7696: mpz_init(a);
7697: mat = (mpz_t **)mat0;
7698: size = 0;
7699: for ( rank = 0, j = 0; j < col; j++ ) {
7700: for ( i = rank; i < row; i++ ) {
7701: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
7702: }
7703: for ( i = rank; i < row; i++ )
7704: if ( mpz_sgn(mat[i][j]) )
7705: break;
7706: if ( i == row ) {
7707: colstat[j] = 0;
7708: continue;
7709: } else
7710: colstat[j] = 1;
7711: if ( i != rank ) {
7712: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
7713: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
7714: }
7715: pivot = mat[rank];
7716: s = sugar[rank];
7717: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
7718: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
7719: if ( mpz_sgn(*pk) ) {
7720: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
7721: }
7722: for ( i = rank+1; i < row; i++ ) {
7723: t = mat[i];
7724: if ( mpz_sgn(t[j]) ) {
7725: sugar[i] = MAX(sugar[i],s);
7726: mpz_neg(a,t[j]);
7727: red_by_vect_lf(t+j,pivot+j,a,col-j);
7728: }
7729: }
7730: rank++;
7731: }
7732: for ( j = col-1, l = rank-1; j >= 0; j-- )
7733: if ( colstat[j] ) {
7734: pivot = mat[l];
7735: s = sugar[l];
7736: for ( k = j; k < col; k++ )
7737: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
7738: for ( i = 0; i < l; i++ ) {
7739: t = mat[i];
7740: if ( mpz_sgn(t[j]) ) {
7741: sugar[i] = MAX(sugar[i],s);
7742: mpz_neg(a,t[j]);
7743: red_by_vect_lf(t+j,pivot+j,a,col-j);
7744: }
7745: }
7746: l--;
7747: }
7748: for ( j = 0, l = 0; l < rank; j++ )
7749: if ( colstat[j] ) {
7750: t = mat[l];
7751: for ( k = j; k < col; k++ ) {
7752: mpz_mod(t[k],t[k],BDY(current_mod_lf));
7753: }
7754: l++;
7755: }
7756: return rank;
7757: }
7758:
7759:
7760: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
7761: {
7762: int j,k,len;
7763: UINT *p;
7764: UINT c;
7765: NDV r;
7766: NMV mr0,mr;
7767:
7768: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
7769: if ( !len ) return 0;
7770: else {
7771: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
7772: #if 0
7773: ndv_alloc += nmv_adv*len;
7774: #endif
7775: mr = mr0;
7776: p = s0vect;
7777: for ( j = k = 0; j < col; j++, p += nd_wpd )
7778: if ( !rhead[j] ) {
7779: if ( (c = vect[k++]) != 0 ) {
7780: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
7781: }
7782: }
7783: MKNDV(nd_nvar,mr0,len,r);
7784: return r;
7785: }
7786: }
7787:
1.40 ! noro 7788: NDV vect_to_ndv_s(UINT *vect,int col,UINT *s0vect)
! 7789: {
! 7790: int j,k,len;
! 7791: UINT *p;
! 7792: UINT c;
! 7793: NDV r;
! 7794: NMV mr0,mr;
! 7795:
! 7796: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
! 7797: if ( !len ) return 0;
! 7798: else {
! 7799: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
! 7800: mr = mr0;
! 7801: p = s0vect;
! 7802: for ( j = k = 0; j < col; j++, p += nd_wpd )
! 7803: if ( (c = vect[k++]) != 0 ) {
! 7804: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
! 7805: }
! 7806: MKNDV(nd_nvar,mr0,len,r);
! 7807: return r;
! 7808: }
! 7809: }
! 7810:
1.1 noro 7811: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
7812: {
7813: int j,k,len;
7814: UINT *p;
7815: NDV r;
7816: NMV mr0,mr;
7817:
7818: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
7819: if ( !len ) return 0;
7820: else {
7821: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
7822: mr = mr0;
7823: p = s0vect;
7824: for ( j = 0; j < col; j++, p += nd_wpd )
7825: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
7826: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
7827: }
7828: MKNDV(nd_nvar,mr0,len,r);
7829: return r;
7830: }
7831: }
7832:
7833: /* for preprocessed vector */
7834:
7835: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
7836: {
1.6 noro 7837: int j,k,len;
7838: UINT *p;
7839: Z c;
7840: NDV r;
7841: NMV mr0,mr;
1.1 noro 7842:
1.6 noro 7843: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
7844: if ( !len ) return 0;
7845: else {
7846: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 7847: #if 0
1.6 noro 7848: ndv_alloc += nmv_adv*len;
1.1 noro 7849: #endif
1.6 noro 7850: mr = mr0;
7851: p = s0vect;
7852: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
7853: if ( !rhead[j] ) {
7854: if ( (c = vect[k++]) != 0 ) {
7855: if ( !INT(c) )
7856: error("vect_to_ndv_q : components must be integers");
7857: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
7858: }
7859: }
1.1 noro 7860: }
1.6 noro 7861: MKNDV(nd_nvar,mr0,len,r);
7862: return r;
7863: }
1.1 noro 7864: }
7865:
7866: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
7867: {
7868: int j,k,len;
7869: UINT *p;
7870: mpz_t c;
7871: NDV r;
7872: NMV mr0,mr;
7873:
7874: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
7875: if ( !len ) return 0;
7876: else {
7877: mr0 = (NMV)MALLOC(nmv_adv*len);
7878: #if 0
7879: ndv_alloc += nmv_adv*len;
7880: #endif
7881: mr = mr0;
7882: p = s0vect;
7883: for ( j = k = 0; j < col; j++, p += nd_wpd )
7884: if ( !rhead[j] ) {
7885: c[0] = vect[k++][0];
7886: if ( mpz_sgn(c) ) {
7887: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
7888: }
7889: }
7890: MKNDV(nd_nvar,mr0,len,r);
7891: return r;
7892: }
7893: }
7894:
7895: /* for plain vector */
7896:
7897: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
7898: {
7899: int j,k,len;
7900: UINT *p;
7901: Z c;
7902: NDV r;
7903: NMV mr0,mr;
7904:
7905: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
7906: if ( !len ) return 0;
7907: else {
7908: mr0 = (NMV)MALLOC(nmv_adv*len);
7909: #if 0
7910: ndv_alloc += nmv_adv*len;
7911: #endif
7912: mr = mr0;
7913: p = s0vect;
7914: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
7915: if ( (c = vect[k]) != 0 ) {
7916: if ( !INT(c) )
1.6 noro 7917: error("plain_vect_to_ndv_q : components must be integers");
7918: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 7919: }
7920: MKNDV(nd_nvar,mr0,len,r);
7921: return r;
7922: }
7923: }
7924:
7925: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
7926: {
7927: ND_pairs t;
7928: NODE sp0,sp;
7929: int stat;
7930: ND spol;
7931:
7932: for ( t = l; t; t = NEXT(t) ) {
7933: stat = nd_sp(m,trace,t,&spol);
7934: if ( !stat ) return 0;
7935: if ( spol ) {
7936: add_pbucket_symbolic(bucket,spol);
7937: }
7938: }
7939: return 1;
7940: }
7941:
7942: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
7943: {
7944: NODE rp0,rp;
7945: NM mul,head,s0,s;
7946: int index,col,i,sugar;
7947: RHist h;
7948: UINT *s0v,*p;
7949: NM_ind_pair pair;
7950: ND red;
7951: NDV *ps;
7952:
7953: s0 = 0; rp0 = 0; col = 0;
7954: if ( nd_demand )
7955: ps = trace?nd_ps_trace_sym:nd_ps_sym;
7956: else
7957: ps = trace?nd_ps_trace:nd_ps;
7958: while ( 1 ) {
7959: head = remove_head_pbucket_symbolic(bucket);
7960: if ( !head ) break;
7961: if ( !s0 ) s0 = head;
7962: else NEXT(s) = head;
7963: s = head;
7964: index = ndl_find_reducer(DL(head));
7965: if ( index >= 0 ) {
7966: h = nd_psh[index];
7967: NEWNM(mul);
7968: ndl_sub(DL(head),DL(h),DL(mul));
7969: if ( ndl_check_bound2(index,DL(mul)) )
7970: return 0;
7971: sugar = TD(DL(mul))+SG(ps[index]);
1.28 noro 7972: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 7973: red = ndv_mul_nm_symbolic(mul,ps[index]);
7974: add_pbucket_symbolic(bucket,nd_remove_head(red));
7975: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
7976: }
7977: col++;
7978: }
7979: if ( rp0 ) NEXT(rp) = 0;
7980: NEXT(s) = 0;
7981: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
7982: for ( i = 0, p = s0v, s = s0; i < col;
7983: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
7984: *s0vect = s0v;
7985: *r = rp0;
7986: return col;
7987: }
7988:
7989: void print_ndp(ND_pairs l)
7990: {
7991: ND_pairs t;
7992:
7993: for ( t = l; t; t = NEXT(t) )
7994: printf("[%d,%d] ",t->i1,t->i2);
7995: printf("\n");
7996: }
7997:
7998: NODE nd_f4(int m,int checkonly,int **indp)
7999: {
8000: int i,nh,stat,index,f4red;
8001: NODE r,g,tn0,tn,node;
8002: ND_pairs d,l,t,ll0,ll,lh;
8003: LIST l0,l1;
8004: ND spol,red;
8005: NDV nf,redv;
8006: NM s0,s;
8007: NODE rp0,srp0,nflist,nzlist,nzlist_t;
8008: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
8009: UINT c;
8010: UINT **spmat;
8011: UINT *s0vect,*svect,*p,*v;
8012: int *colstat;
8013: IndArray *imat;
8014: int *rhead;
8015: int spcol,sprow;
8016: int sugar,sugarh;
8017: PGeoBucket bucket;
8018: struct oEGT eg0,eg1,eg_f4;
8019: Z i1,i2,sugarq;
1.12 noro 8020:
8021: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 8022: #if 0
8023: ndv_alloc = 0;
8024: #endif
1.11 noro 8025: Nf4_red=0;
1.1 noro 8026: g = 0; d = 0;
8027: for ( i = 0; i < nd_psn; i++ ) {
8028: d = update_pairs(d,g,i,0);
8029: g = update_base(g,i);
8030: }
8031: nzlist = 0;
8032: nzlist_t = nd_nzlist;
8033: f4red = 1;
8034: nd_last_nonzero = 0;
8035: while ( d ) {
8036: get_eg(&eg0);
8037: l = nd_minsugarp(d,&d);
8038: sugar = nd_sugarweight?l->sugar2:SG(l);
8039: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8040: if ( nzlist_t ) {
8041: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 8042: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 8043: tn = BDY((LIST)ARG1(node));
8044: if ( !tn ) {
8045: nzlist_t = NEXT(nzlist_t);
8046: continue;
8047: }
8048: /* tn = [[i1,i2],...] */
8049: lh = nd_ipairtospair(tn);
8050: }
8051: bucket = create_pbucket();
8052: stat = nd_sp_f4(m,0,l,bucket);
8053: if ( !stat ) {
8054: for ( t = l; NEXT(t); t = NEXT(t) );
8055: NEXT(t) = d; d = l;
8056: d = nd_reconstruct(0,d);
8057: continue;
8058: }
8059: if ( bucket->m < 0 ) continue;
8060: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8061: if ( !col ) {
8062: for ( t = l; NEXT(t); t = NEXT(t) );
8063: NEXT(t) = d; d = l;
8064: d = nd_reconstruct(0,d);
8065: continue;
8066: }
1.12 noro 8067: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 8068: if ( DP_Print )
1.6 noro 8069: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 8070: sugar,eg_f4.exectime);
1.1 noro 8071: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
8072: if ( checkonly && nflist ) return 0;
8073: /* adding new bases */
8074: if ( nflist ) nd_last_nonzero = f4red;
8075: for ( r = nflist; r; r = NEXT(r) ) {
8076: nf = (NDV)BDY(r);
1.38 noro 8077: if ( nd_f4_td ) SG(nf) = nd_tdeg(nf);
1.1 noro 8078: ndv_removecont(m,nf);
8079: if ( !m && nd_nalg ) {
8080: ND nf1;
8081:
8082: nf1 = ndvtond(m,nf);
8083: nd_monic(0,&nf1);
8084: nd_removecont(m,nf1);
8085: nf = ndtondv(m,nf1);
8086: }
1.24 noro 8087: nh = ndv_newps(m,nf,0);
1.1 noro 8088: d = update_pairs(d,g,nh,0);
8089: g = update_base(g,nh);
8090: }
8091: if ( DP_Print ) {
8092: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
8093: }
8094: if ( nd_gentrace ) {
8095: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
8096: NEXTNODE(tn0,tn);
1.6 noro 8097: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 8098: node = mknode(2,i1,i2); MKLIST(l0,node);
8099: BDY(tn) = l0;
8100: }
8101: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 8102: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 8103: MKNODE(node,l1,nzlist); nzlist = node;
8104: }
8105: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
8106: f4red++;
8107: if ( nd_f4red && f4red > nd_f4red ) break;
8108: if ( nd_rank0 && !nflist ) break;
8109: }
8110: if ( nd_gentrace ) {
8111: MKLIST(l0,reverse_node(nzlist));
8112: MKNODE(nd_alltracelist,l0,0);
8113: }
8114: #if 0
8115: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8116: #endif
1.12 noro 8117: if ( DP_Print ) {
8118: fprintf(asir_out,"number of red=%d,",Nf4_red);
8119: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
8120: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
8121: }
1.1 noro 8122: conv_ilist(nd_demand,0,g,indp);
8123: return g;
8124: }
8125:
8126: NODE nd_f4_trace(int m,int **indp)
8127: {
8128: int i,nh,stat,index;
8129: NODE r,g;
8130: ND_pairs d,l,l0,t;
8131: ND spol,red;
8132: NDV nf,redv,nfqv,nfv;
8133: NM s0,s;
8134: NODE rp0,srp0,nflist;
8135: int nsp,nred,col,rank,len,k,j,a;
8136: UINT c;
8137: UINT **spmat;
8138: UINT *s0vect,*svect,*p,*v;
8139: int *colstat;
8140: IndArray *imat;
8141: int *rhead;
8142: int spcol,sprow;
8143: int sugar;
8144: PGeoBucket bucket;
8145: struct oEGT eg0,eg1,eg_f4;
8146:
8147: g = 0; d = 0;
8148: for ( i = 0; i < nd_psn; i++ ) {
8149: d = update_pairs(d,g,i,0);
8150: g = update_base(g,i);
8151: }
8152: while ( d ) {
8153: get_eg(&eg0);
8154: l = nd_minsugarp(d,&d);
8155: sugar = SG(l);
8156: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8157: bucket = create_pbucket();
8158: stat = nd_sp_f4(m,0,l,bucket);
8159: if ( !stat ) {
8160: for ( t = l; NEXT(t); t = NEXT(t) );
8161: NEXT(t) = d; d = l;
8162: d = nd_reconstruct(1,d);
8163: continue;
8164: }
8165: if ( bucket->m < 0 ) continue;
8166: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8167: if ( !col ) {
8168: for ( t = l; NEXT(t); t = NEXT(t) );
8169: NEXT(t) = d; d = l;
8170: d = nd_reconstruct(1,d);
8171: continue;
8172: }
8173: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
8174: if ( DP_Print )
1.3 noro 8175: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 8176: sugar,eg_f4.exectime);
1.1 noro 8177: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
8178: if ( !l0 ) continue;
8179: l = l0;
8180:
8181: /* over Q */
8182: bucket = create_pbucket();
8183: stat = nd_sp_f4(0,1,l,bucket);
8184: if ( !stat ) {
8185: for ( t = l; NEXT(t); t = NEXT(t) );
8186: NEXT(t) = d; d = l;
8187: d = nd_reconstruct(1,d);
8188: continue;
8189: }
8190: if ( bucket->m < 0 ) continue;
8191: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
8192: if ( !col ) {
8193: for ( t = l; NEXT(t); t = NEXT(t) );
8194: NEXT(t) = d; d = l;
8195: d = nd_reconstruct(1,d);
8196: continue;
8197: }
8198: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
8199: /* adding new bases */
8200: for ( r = nflist; r; r = NEXT(r) ) {
8201: nfqv = (NDV)BDY(r);
8202: ndv_removecont(0,nfqv);
1.6 noro 8203: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 8204: if ( nd_nalg ) {
8205: ND nf1;
8206:
8207: nf1 = ndvtond(m,nfqv);
8208: nd_monic(0,&nf1);
8209: nd_removecont(0,nf1);
8210: nfqv = ndtondv(0,nf1); nd_free(nf1);
8211: }
8212: nfv = ndv_dup(0,nfqv);
8213: ndv_mod(m,nfv);
8214: ndv_removecont(m,nfv);
1.24 noro 8215: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 8216: d = update_pairs(d,g,nh,0);
8217: g = update_base(g,nh);
8218: }
8219: }
8220: #if 0
8221: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8222: #endif
8223: conv_ilist(nd_demand,1,g,indp);
8224: return g;
8225: }
8226:
8227: int rref(matrix mat,int *sugar)
8228: {
8229: int row,col,i,j,k,l,s,wcol,wj;
8230: unsigned long bj;
8231: unsigned long **a;
8232: unsigned long *ai,*ak,*as,*t;
8233: int *pivot;
8234:
8235: row = mat->row;
8236: col = mat->col;
8237: a = mat->a;
8238: wcol = (col+BLEN-1)/BLEN;
8239: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
8240: i = 0;
8241: for ( j = 0; j < col; j++ ) {
8242: wj = j/BLEN; bj = 1L<<(j%BLEN);
8243: for ( k = i; k < row; k++ )
8244: if ( a[k][wj] & bj ) break;
8245: if ( k == row ) continue;
8246: pivot[i] = j;
8247: if ( k != i ) {
8248: t = a[i]; a[i] = a[k]; a[k] = t;
8249: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
8250: }
8251: ai = a[i];
8252: for ( k = i+1; k < row; k++ ) {
8253: ak = a[k];
8254: if ( ak[wj] & bj ) {
8255: for ( l = wj; l < wcol; l++ )
8256: ak[l] ^= ai[l];
8257: sugar[k] = MAX(sugar[k],sugar[i]);
8258: }
8259: }
8260: i++;
8261: }
8262: for ( k = i-1; k >= 0; k-- ) {
8263: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
8264: ak = a[k];
8265: for ( s = 0; s < k; s++ ) {
8266: as = a[s];
8267: if ( as[wj] & bj ) {
8268: for ( l = wj; l < wcol; l++ )
8269: as[l] ^= ak[l];
8270: sugar[s] = MAX(sugar[s],sugar[k]);
8271: }
8272: }
8273: }
8274: return i;
8275: }
8276:
8277: void print_matrix(matrix mat)
8278: {
8279: int row,col,i,j;
8280: unsigned long *ai;
8281:
8282: row = mat->row;
8283: col = mat->col;
8284: printf("%d x %d\n",row,col);
8285: for ( i = 0; i < row; i++ ) {
8286: ai = mat->a[i];
8287: for ( j = 0; j < col; j++ ) {
8288: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
8289: else putchar('0');
8290: }
8291: putchar('\n');
8292: }
8293: }
8294:
8295: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
8296:
8297: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
8298: {
8299: int row,col,wcol,wj,i,j;
8300: unsigned long bj;
8301: unsigned long *ai;
8302: unsigned long **a;
8303: int len;
8304: int *pos;
8305:
8306: row = mat->row;
8307: col = mat->col;
8308: wcol = (col+BLEN-1)/BLEN;
8309: pos = (int *)MALLOC(wcol*sizeof(int));
8310: bzero(pos,wcol*sizeof(int));
8311: for ( i = j = 0; i < wcol; i++ )
8312: if ( v[i] ) pos[j++] = i;;
8313: len = j;
8314: wj = rhead/BLEN;
8315: bj = 1L<<rhead%BLEN;
8316: a = mat->a;
8317: for ( i = 0; i < row; i++ ) {
8318: ai = a[i];
8319: if ( ai[wj]&bj ) {
8320: for ( j = 0; j < len; j++ )
8321: ai[pos[j]] ^= v[pos[j]];
8322: sugar[i] = MAX(sugar[i],rsugar);
8323: }
8324: }
8325: }
8326:
8327: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8328: {
8329: int nsp,nred,i,i0,k,rank,row;
8330: NODE r0,rp;
8331: ND_pairs sp;
8332: ND spol;
8333: NM_ind_pair rt;
8334: int *s0hash;
8335: UINT *s;
8336: int *pivot,*sugar,*head;
8337: matrix mat;
8338: NM m;
8339: NODE r;
8340: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
8341: int rhead,rsugar,size;
8342: unsigned long *v;
8343:
8344: get_eg(&eg0);
8345: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8346: nred = length(rp0);
8347: mat = alloc_matrix(nsp,col);
8348: s0hash = (int *)MALLOC(col*sizeof(int));
8349: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
8350: s0hash[i] = ndl_hash_value(s);
8351:
8352: sugar = (int *)MALLOC(nsp*sizeof(int));
8353: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
8354: nd_sp(2,0,sp,&spol);
8355: if ( spol ) {
8356: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
8357: sugar[i] = SG(spol);
8358: i++;
8359: }
8360: }
8361: mat->row = i;
8362: if ( DP_Print ) {
8363: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
8364: }
8365: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
8366: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
8367: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
8368: rt = (NM_ind_pair)BDY(rp);
8369: bzero(v,size);
8370: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
8371: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
8372: red_by_vect_2(mat,sugar,v,rhead,rsugar);
8373: }
8374:
8375: get_eg(&eg1);
8376: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
8377: rank = rref(mat,sugar);
8378:
8379: for ( i = 0, r0 = 0; i < rank; i++ ) {
8380: NEXTNODE(r0,r);
8381: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
8382: SG((NDV)BDY(r)) = sugar[i];
8383: }
8384: if ( r0 ) NEXT(r) = 0;
8385: get_eg(&eg2);
8386: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
8387: if ( DP_Print ) {
8388: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 8389: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 8390: fflush(asir_out);
8391: }
8392: return r0;
8393: }
8394:
8395:
8396: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8397: {
8398: IndArray *imat;
1.11 noro 8399: int nsp,nred,i,start;
1.1 noro 8400: int *rhead;
8401: NODE r0,rp;
8402: ND_pairs sp;
8403: NM_ind_pair *rvect;
8404: UINT *s;
8405: int *s0hash;
1.11 noro 8406: struct oEGT eg0,eg1,eg_conv;
1.1 noro 8407:
8408: if ( m == 2 && nd_rref2 )
8409: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
8410:
8411: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8412: nred = length(rp0);
8413: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
8414: rhead = (int *)MALLOC(col*sizeof(int));
8415: for ( i = 0; i < col; i++ ) rhead[i] = 0;
8416:
8417: /* construction of index arrays */
1.11 noro 8418: get_eg(&eg0);
1.1 noro 8419: if ( DP_Print ) {
1.11 noro 8420: fprintf(asir_out,"%dx%d,",nsp+nred,col);
8421: fflush(asir_out);
1.1 noro 8422: }
8423: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 8424: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 8425: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 8426: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 8427: rhead[imat[i]->head] = 1;
1.11 noro 8428: start = imat[i]->head;
8429: }
1.12 noro 8430: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 8431: if ( DP_Print ) {
8432: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
8433: fflush(asir_out);
1.1 noro 8434: }
8435: if ( m > 0 )
1.7 noro 8436: #if SIZEOF_LONG==8
1.1 noro 8437: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8438: #else
8439: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8440: #endif
8441: else if ( m == -1 )
8442: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8443: else if ( m == -2 )
8444: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8445: else
8446: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8447: return r0;
8448: }
8449:
8450: /* for Fp, 2<=p<2^16 */
8451:
8452: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8453: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8454: {
8455: int spcol,sprow,a;
8456: int i,j,k,l,rank;
8457: NODE r0,r;
8458: ND_pairs sp;
8459: ND spol;
8460: UINT **spmat;
8461: UINT *svect,*v;
8462: int *colstat;
8463: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8464: int maxrs;
8465: int *spsugar;
8466: ND_pairs *spactive;
8467:
8468: spcol = col-nred;
8469: get_eg(&eg0);
8470: /* elimination (1st step) */
8471: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8472: svect = (UINT *)MALLOC(col*sizeof(UINT));
8473: spsugar = (int *)MALLOC(nsp*sizeof(int));
8474: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8475: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8476: nd_sp(m,0,sp,&spol);
8477: if ( !spol ) continue;
8478: nd_to_vect(m,s0vect,col,spol,svect);
8479: if ( m == -1 )
8480: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8481: else
1.40 ! noro 8482: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,0);
1.1 noro 8483: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8484: if ( i < col ) {
8485: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8486: for ( j = k = 0; j < col; j++ )
8487: if ( !rhead[j] ) v[k++] = svect[j];
8488: spsugar[sprow] = MAX(maxrs,SG(spol));
8489: if ( nz )
8490: spactive[sprow] = sp;
8491: sprow++;
8492: }
8493: nd_free(spol);
8494: }
8495: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8496: if ( DP_Print ) {
1.5 noro 8497: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8498: fflush(asir_out);
8499: }
8500: /* free index arrays */
8501: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8502:
8503: /* elimination (2nd step) */
8504: colstat = (int *)MALLOC(spcol*sizeof(int));
8505: if ( m == -1 )
8506: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8507: else
8508: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
8509: r0 = 0;
8510: for ( i = 0; i < rank; i++ ) {
8511: NEXTNODE(r0,r); BDY(r) =
8512: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8513: SG((NDV)BDY(r)) = spsugar[i];
8514: GCFREE(spmat[i]);
8515: }
8516: if ( r0 ) NEXT(r) = 0;
8517:
8518: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8519: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8520: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8521: if ( DP_Print ) {
1.5 noro 8522: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8523: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8524: nsp,nred,sprow,spcol,rank);
1.5 noro 8525: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8526: }
8527: if ( nz ) {
8528: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8529: if ( rank > 0 ) {
8530: NEXT(spactive[rank-1]) = 0;
8531: *nz = spactive[0];
8532: } else
8533: *nz = 0;
8534: }
8535: return r0;
8536: }
8537:
1.40 ! noro 8538: NODE nd_f4_red_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
! 8539: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
! 8540: {
! 8541: int spcol,sprow,a;
! 8542: int i,j,k,l,rank;
! 8543: NODE r0,r;
! 8544: ND_pairs sp;
! 8545: ND spol;
! 8546: UINT **spmat;
! 8547: UINT *svect,*cvect;
! 8548: UINT *v;
! 8549: int *colstat;
! 8550: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
! 8551: int maxrs;
! 8552: int *spsugar;
! 8553: ND_pairs *spactive;
! 8554: SIG *spsig;
! 8555:
! 8556: get_eg(&eg0);
! 8557: /* elimination (1st step) */
! 8558: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
! 8559: spsugar = (int *)MALLOC(nsp*sizeof(int));
! 8560: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
! 8561: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
! 8562: nd_sp(m,0,sp,&spol);
! 8563: if ( !spol ) {
! 8564: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
! 8565: continue;
! 8566: }
! 8567: svect = (UINT *)MALLOC(col*sizeof(UINT));
! 8568: nd_to_vect(m,s0vect,col,spol,svect);
! 8569: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,spol->sig);
! 8570: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
! 8571: if ( i < col ) {
! 8572: spmat[sprow] = svect;
! 8573: spsugar[sprow] = MAX(maxrs,SG(spol));
! 8574: spsig[sprow] = sp->sig;
! 8575: sprow++;
! 8576: } else {
! 8577: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
! 8578: }
! 8579: nd_free(spol);
! 8580: }
! 8581: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
! 8582: if ( DP_Print ) {
! 8583: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
! 8584: fflush(asir_out);
! 8585: }
! 8586: /* free index arrays */
! 8587: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
! 8588:
! 8589: /* elimination (2nd step) */
! 8590: colstat = (int *)MALLOC(col*sizeof(int));
! 8591: rank = nd_gauss_elim_mod_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
! 8592: r0 = 0;
! 8593: for ( i = 0; i < sprow; i++ ) {
! 8594: if ( spsugar[i] >= 0 ) {
! 8595: NEXTNODE(r0,r);
! 8596: BDY(r) = vect_to_ndv_s(spmat[i],col,s0vect);
! 8597: SG((NDV)BDY(r)) = spsugar[i];
! 8598: ((NDV)BDY(r))->sig = spsig[i];
! 8599: } else
! 8600: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
! 8601: GCFREE(spmat[i]);
! 8602: }
! 8603: if ( r0 ) NEXT(r) = 0;
! 8604: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
! 8605: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
! 8606: if ( DP_Print ) {
! 8607: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
! 8608: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
! 8609: nsp,nred,sprow,col,rank);
! 8610: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
! 8611: }
! 8612: return r0;
! 8613: }
! 8614:
1.1 noro 8615:
8616: /* for small finite fields */
8617:
8618: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8619: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8620: {
8621: int spcol,sprow,a;
8622: int i,j,k,l,rank;
8623: NODE r0,r;
8624: ND_pairs sp;
8625: ND spol;
8626: UINT **spmat;
8627: UINT *svect,*v;
8628: int *colstat;
8629: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8630: int maxrs;
8631: int *spsugar;
8632: ND_pairs *spactive;
8633:
8634: spcol = col-nred;
8635: get_eg(&eg0);
8636: /* elimination (1st step) */
8637: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8638: svect = (UINT *)MALLOC(col*sizeof(UINT));
8639: spsugar = (int *)MALLOC(nsp*sizeof(int));
8640: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8641: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8642: nd_sp(m,0,sp,&spol);
8643: if ( !spol ) continue;
8644: nd_to_vect(m,s0vect,col,spol,svect);
8645: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8646: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8647: if ( i < col ) {
8648: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8649: for ( j = k = 0; j < col; j++ )
8650: if ( !rhead[j] ) v[k++] = svect[j];
8651: spsugar[sprow] = MAX(maxrs,SG(spol));
8652: if ( nz )
8653: spactive[sprow] = sp;
8654: sprow++;
8655: }
8656: nd_free(spol);
8657: }
8658: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8659: if ( DP_Print ) {
1.5 noro 8660: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8661: fflush(asir_out);
8662: }
8663: /* free index arrays */
8664: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8665:
8666: /* elimination (2nd step) */
8667: colstat = (int *)MALLOC(spcol*sizeof(int));
8668: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8669: r0 = 0;
8670: for ( i = 0; i < rank; i++ ) {
8671: NEXTNODE(r0,r); BDY(r) =
8672: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8673: SG((NDV)BDY(r)) = spsugar[i];
8674: GCFREE(spmat[i]);
8675: }
8676: if ( r0 ) NEXT(r) = 0;
8677:
8678: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8679: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8680: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8681: if ( DP_Print ) {
1.5 noro 8682: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8683: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8684: nsp,nred,sprow,spcol,rank);
1.5 noro 8685: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8686: }
8687: if ( nz ) {
8688: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8689: if ( rank > 0 ) {
8690: NEXT(spactive[rank-1]) = 0;
8691: *nz = spactive[0];
8692: } else
8693: *nz = 0;
8694: }
8695: return r0;
8696: }
8697:
8698: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
8699: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
8700: {
8701: int spcol,sprow,a;
8702: int i,j,k,l,rank;
8703: NODE r0,r;
8704: ND_pairs sp;
8705: ND spol;
8706: mpz_t **spmat;
8707: mpz_t *svect,*v;
8708: int *colstat;
8709: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8710: int maxrs;
8711: int *spsugar;
8712: pointer *w;
8713:
8714: spcol = col-nred;
8715: get_eg(&eg0);
8716: /* elimination (1st step) */
8717: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
8718: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
8719: spsugar = (int *)MALLOC(nsp*sizeof(int));
8720: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8721: nd_sp(m,trace,sp,&spol);
8722: if ( !spol ) continue;
8723: nd_to_vect_lf(s0vect,col,spol,svect);
8724: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
8725: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
8726: if ( i < col ) {
8727: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
8728: for ( j = k = 0; j < col; j++ )
8729: if ( !rhead[j] ) v[k++][0] = svect[j][0];
8730: spsugar[sprow] = MAX(maxrs,SG(spol));
8731: sprow++;
8732: }
8733: /* nd_free(spol); */
8734: }
8735: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8736: if ( DP_Print ) {
1.5 noro 8737: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8738: fflush(asir_out);
8739: }
8740: /* free index arrays */
8741: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
8742:
8743: /* elimination (2nd step) */
8744: colstat = (int *)MALLOC(spcol*sizeof(int));
8745: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
8746: w = (pointer *)MALLOC(rank*sizeof(pointer));
8747: for ( i = 0; i < rank; i++ ) {
8748: #if 0
8749: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
8750: SG((NDV)w[rank-i-1]) = spsugar[i];
8751: #else
8752: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
8753: SG((NDV)w[i]) = spsugar[i];
8754: #endif
8755: /* GCFREE(spmat[i]); */
8756:
8757: }
8758: #if 0
8759: qsort(w,rank,sizeof(NDV),
8760: (int (*)(const void *,const void *))ndv_compare);
8761: #endif
8762: r0 = 0;
8763: for ( i = 0; i < rank; i++ ) {
8764: NEXTNODE(r0,r); BDY(r) = w[i];
8765: }
8766: if ( r0 ) NEXT(r) = 0;
8767:
8768: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
8769: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8770: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8771: if ( DP_Print ) {
1.5 noro 8772: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8773: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8774: nsp,nred,sprow,spcol,rank);
1.5 noro 8775: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8776: }
8777: return r0;
8778: }
8779:
8780: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
8781: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
8782: {
8783: int spcol,sprow,a;
8784: int i,j,k,l,rank;
8785: NODE r0,r;
8786: ND_pairs sp;
8787: ND spol;
8788: Z **spmat;
8789: Z *svect,*v;
8790: int *colstat;
8791: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8792: int maxrs;
8793: int *spsugar;
8794: pointer *w;
8795:
8796: spcol = col-nred;
8797: get_eg(&eg0);
8798: /* elimination (1st step) */
8799: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
8800: svect = (Z *)MALLOC(col*sizeof(Q));
8801: spsugar = (int *)MALLOC(nsp*sizeof(int));
8802: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8803: nd_sp(0,trace,sp,&spol);
8804: if ( !spol ) continue;
8805: nd_to_vect_q(s0vect,col,spol,svect);
8806: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
8807: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8808: if ( i < col ) {
8809: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
8810: for ( j = k = 0; j < col; j++ )
8811: if ( !rhead[j] ) v[k++] = svect[j];
8812: spsugar[sprow] = MAX(maxrs,SG(spol));
8813: sprow++;
8814: }
8815: /* nd_free(spol); */
8816: }
8817: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8818: if ( DP_Print ) {
1.5 noro 8819: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8820: fflush(asir_out);
8821: }
8822: /* free index arrays */
8823: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
8824:
8825: /* elimination (2nd step) */
8826: colstat = (int *)MALLOC(spcol*sizeof(int));
8827: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
8828: w = (pointer *)MALLOC(rank*sizeof(pointer));
8829: for ( i = 0; i < rank; i++ ) {
8830: #if 0
8831: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
8832: SG((NDV)w[rank-i-1]) = spsugar[i];
8833: #else
8834: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
8835: SG((NDV)w[i]) = spsugar[i];
8836: #endif
8837: /* GCFREE(spmat[i]); */
8838: }
8839: #if 0
8840: qsort(w,rank,sizeof(NDV),
8841: (int (*)(const void *,const void *))ndv_compare);
8842: #endif
8843: r0 = 0;
8844: for ( i = 0; i < rank; i++ ) {
8845: NEXTNODE(r0,r); BDY(r) = w[i];
8846: }
8847: if ( r0 ) NEXT(r) = 0;
8848:
8849: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
8850: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8851: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8852: if ( DP_Print ) {
1.5 noro 8853: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8854: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8855: nsp,nred,sprow,spcol,rank);
1.5 noro 8856: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8857: }
8858: return r0;
8859: }
8860:
8861: FILE *nd_write,*nd_read;
8862:
8863: void nd_send_int(int a) {
8864: write_int(nd_write,(unsigned int *)&a);
8865: }
8866:
8867: void nd_send_intarray(int *p,int len) {
8868: write_intarray(nd_write,(unsigned int *)p,len);
8869: }
8870:
8871: int nd_recv_int() {
8872: int a;
8873:
8874: read_int(nd_read,(unsigned int *)&a);
8875: return a;
8876: }
8877:
8878: void nd_recv_intarray(int *p,int len) {
8879: read_intarray(nd_read,(unsigned int *)p,len);
8880: }
8881:
8882: void nd_send_ndv(NDV p) {
8883: int len,i;
8884: NMV m;
8885:
8886: if ( !p ) nd_send_int(0);
8887: else {
8888: len = LEN(p);
8889: nd_send_int(len);
8890: m = BDY(p);
8891: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
8892: nd_send_int(CM(m));
8893: nd_send_intarray((int *)DL(m),nd_wpd);
8894: }
8895: }
8896: }
8897:
8898: void nd_send_nd(ND p) {
8899: int len,i;
8900: NM m;
8901:
8902: if ( !p ) nd_send_int(0);
8903: else {
8904: len = LEN(p);
8905: nd_send_int(len);
8906: m = BDY(p);
8907: for ( i = 0; i < len; i++, m = NEXT(m) ) {
8908: nd_send_int(CM(m));
8909: nd_send_intarray((int *)DL(m),nd_wpd);
8910: }
8911: }
8912: }
8913:
8914: NDV nd_recv_ndv()
8915: {
8916: int len,i;
8917: NMV m,m0;
8918: NDV r;
8919:
8920: len = nd_recv_int();
8921: if ( !len ) return 0;
8922: else {
8923: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8924: #if 0
8925: ndv_alloc += len*nmv_adv;
8926: #endif
8927: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
8928: CM(m) = nd_recv_int();
8929: nd_recv_intarray((int *)DL(m),nd_wpd);
8930: }
8931: MKNDV(nd_nvar,m0,len,r);
8932: return r;
8933: }
8934: }
8935:
8936: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
8937: {
8938: int i,j,t,c,rank,inv;
8939: int *ci,*ri;
8940: Z dn;
8941: MAT m,nm;
8942:
8943: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
8944: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
8945: for ( i = 0; i < row; i++ )
8946: for ( j = 0; j < col; j++ )
8947: mat0[i][j] = 0;
8948: c = col-rank;
8949: for ( i = 0; i < rank; i++ ) {
8950: mat0[i][ri[i]] = dn;
8951: for ( j = 0; j < c; j++ )
8952: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
8953: }
8954: return rank;
8955: }
8956:
8957: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
8958: {
8959: int i,j,k,l,inv,a,rank,s;
8960: unsigned int *t,*pivot,*pk;
8961: unsigned int **mat;
8962: ND_pairs pair;
8963:
8964: mat = (unsigned int **)mat0;
8965: for ( rank = 0, j = 0; j < col; j++ ) {
8966: for ( i = rank; i < row; i++ )
8967: mat[i][j] %= md;
8968: for ( i = rank; i < row; i++ )
8969: if ( mat[i][j] )
8970: break;
8971: if ( i == row ) {
8972: colstat[j] = 0;
8973: continue;
8974: } else
8975: colstat[j] = 1;
8976: if ( i != rank ) {
8977: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8978: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8979: if ( spactive ) {
8980: pair = spactive[i]; spactive[i] = spactive[rank];
8981: spactive[rank] = pair;
8982: }
8983: }
8984: pivot = mat[rank];
8985: s = sugar[rank];
8986: inv = invm(pivot[j],md);
8987: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8988: if ( *pk ) {
8989: if ( *pk >= (unsigned int)md )
8990: *pk %= md;
8991: DMAR(*pk,inv,0,md,*pk)
8992: }
8993: for ( i = rank+1; i < row; i++ ) {
8994: t = mat[i];
8995: if ( (a = t[j]) != 0 ) {
8996: sugar[i] = MAX(sugar[i],s);
8997: red_by_vect(md,t+j,pivot+j,md-a,col-j);
8998: }
8999: }
9000: rank++;
9001: }
9002: for ( j = col-1, l = rank-1; j >= 0; j-- )
9003: if ( colstat[j] ) {
9004: pivot = mat[l];
9005: s = sugar[l];
9006: for ( i = 0; i < l; i++ ) {
9007: t = mat[i];
9008: t[j] %= md;
9009: if ( (a = t[j]) != 0 ) {
9010: sugar[i] = MAX(sugar[i],s);
9011: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9012: }
9013: }
9014: l--;
9015: }
9016: for ( j = 0, l = 0; l < rank; j++ )
9017: if ( colstat[j] ) {
9018: t = mat[l];
9019: for ( k = j; k < col; k++ )
9020: if ( t[k] >= (unsigned int)md )
9021: t[k] %= md;
9022: l++;
9023: }
9024: return rank;
9025: }
9026:
1.40 ! noro 9027: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
! 9028: {
! 9029: int i,j,k,l,rank,s,imin;
! 9030: UINT inv;
! 9031: UINT a;
! 9032: UINT *t,*pivot,*pk;
! 9033: UINT *ck;
! 9034: UINT *ct;
! 9035: ND_pairs pair;
! 9036: SIG sg;
! 9037: int *used;
! 9038:
! 9039: used = (int *)MALLOC(row*sizeof(int));
! 9040: for ( j = 0; j < col; j++ ) {
! 9041: for ( i = 0; i < row; i++ )
! 9042: a = mat[i][j] %= md;
! 9043: for ( i = 0; i < row; i++ )
! 9044: if ( !used[i] && mat[i][j] ) break;
! 9045: if ( i == row ) {
! 9046: colstat[j] = 0;
! 9047: continue;
! 9048: } else {
! 9049: colstat[j] = 1;
! 9050: used[i] = 1;
! 9051: }
! 9052: /* column j is normalized */
! 9053: s = sugar[i];
! 9054: inv = invm(mat[i][j],md);
! 9055: /* normalize pivot row */
! 9056: for ( k = j, pk = mat[i]+j; k < col; k++, pk++, ck++ ) {
! 9057: DMAR(*pk,inv,0,md,*pk);
! 9058: }
! 9059: for ( k = i+1; k < row; k++ ) {
! 9060: if ( (a = mat[k][j]) != 0 ) {
! 9061: sugar[k] = MAX(sugar[k],s);
! 9062: red_by_vect(md,mat[k]+j,mat[i]+j,(int)(md-a),col-j);
! 9063: Nf4_red++;
! 9064: }
! 9065: }
! 9066: }
! 9067: rank = 0;
! 9068: for ( i = 0; i < row; i++ ) {
! 9069: for ( j = 0; j < col; j++ )
! 9070: if ( mat[i][j] ) break;
! 9071: if ( j == col ) sugar[i] = -1;
! 9072: else rank++;
! 9073: }
! 9074: return rank;
! 9075: }
! 9076:
1.1 noro 9077:
1.7 noro 9078: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 9079: {
1.7 noro 9080: int i,j,k,l,inv,a,rank,s;
9081: unsigned int *t,*pivot,*pk;
9082: unsigned int **mat;
9083:
9084: mat = (unsigned int **)mat0;
9085: for ( rank = 0, j = 0; j < col; j++ ) {
9086: for ( i = rank; i < row; i++ )
9087: if ( mat[i][j] )
9088: break;
9089: if ( i == row ) {
9090: colstat[j] = 0;
9091: continue;
9092: } else
9093: colstat[j] = 1;
9094: if ( i != rank ) {
9095: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9096: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9097: }
9098: pivot = mat[rank];
9099: s = sugar[rank];
9100: inv = _invsf(pivot[j]);
9101: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9102: if ( *pk )
9103: *pk = _mulsf(*pk,inv);
9104: for ( i = rank+1; i < row; i++ ) {
9105: t = mat[i];
9106: if ( (a = t[j]) != 0 ) {
9107: sugar[i] = MAX(sugar[i],s);
9108: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9109: }
9110: }
9111: rank++;
9112: }
9113: for ( j = col-1, l = rank-1; j >= 0; j-- )
9114: if ( colstat[j] ) {
9115: pivot = mat[l];
9116: s = sugar[l];
9117: for ( i = 0; i < l; i++ ) {
9118: t = mat[i];
9119: if ( (a = t[j]) != 0 ) {
9120: sugar[i] = MAX(sugar[i],s);
9121: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9122: }
9123: }
9124: l--;
9125: }
9126: return rank;
9127: }
1.1 noro 9128:
1.7 noro 9129: int ndv_ishomo(NDV p)
9130: {
9131: NMV m;
9132: int len,h;
1.1 noro 9133:
9134: if ( !p ) return 1;
9135: len = LEN(p);
9136: m = BDY(p);
9137: h = TD(DL(m));
9138: NMV_ADV(m);
9139: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 9140: if ( TD(DL(m)) != h ) {
9141: return 0;
9142: }
1.1 noro 9143: return 1;
9144: }
9145:
9146: void ndv_save(NDV p,int index)
9147: {
9148: FILE *s;
9149: char name[BUFSIZ];
9150: short id;
9151: int nv,sugar,len,n,i,td,e,j;
9152: NMV m;
9153: unsigned int *dl;
9154: int mpos;
9155:
9156: sprintf(name,"%s/%d",Demand,index);
9157: s = fopen(name,"w");
9158: savevl(s,0);
9159: if ( !p ) {
9160: saveobj(s,0);
9161: return;
9162: }
9163: id = O_DP;
9164: nv = NV(p);
9165: sugar = SG(p);
9166: len = LEN(p);
9167: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
9168: write_int(s,(unsigned int *)&len);
9169:
9170: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9171: saveobj(s,(Obj)CZ(m));
1.1 noro 9172: dl = DL(m);
9173: td = TD(dl);
9174: write_int(s,(unsigned int *)&td);
9175: for ( j = 0; j < nv; j++ ) {
9176: e = GET_EXP(dl,j);
9177: write_int(s,(unsigned int *)&e);
9178: }
9179: if ( nd_module ) {
9180: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
9181: }
9182: }
9183: fclose(s);
9184: }
9185:
9186: void nd_save_mod(ND p,int index)
9187: {
9188: FILE *s;
9189: char name[BUFSIZ];
9190: int nv,sugar,len,c;
9191: NM m;
9192:
9193: sprintf(name,"%s/%d",Demand,index);
9194: s = fopen(name,"w");
9195: if ( !p ) {
9196: len = 0;
9197: write_int(s,(unsigned int *)&len);
9198: fclose(s);
9199: return;
9200: }
9201: nv = NV(p);
9202: sugar = SG(p);
9203: len = LEN(p);
9204: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
9205: for ( m = BDY(p); m; m = NEXT(m) ) {
9206: c = CM(m); write_int(s,(unsigned int *)&c);
9207: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
9208: }
9209: fclose(s);
9210: }
9211:
9212: NDV ndv_load(int index)
9213: {
9214: FILE *s;
9215: char name[BUFSIZ];
9216: short id;
9217: int nv,sugar,len,n,i,td,e,j;
9218: NDV d;
9219: NMV m0,m;
9220: unsigned int *dl;
9221: Obj obj;
9222: int mpos;
9223:
9224: sprintf(name,"%s/%d",Demand,index);
9225: s = fopen(name,"r");
9226: if ( !s ) return 0;
9227:
9228: skipvl(s);
9229: read_short(s,(unsigned short *)&id);
9230: if ( !id ) return 0;
9231: read_int(s,(unsigned int *)&nv);
9232: read_int(s,(unsigned int *)&sugar);
9233: read_int(s,(unsigned int *)&len);
9234:
9235: m0 = m = MALLOC(len*nmv_adv);
9236: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9237: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 9238: dl = DL(m);
9239: ndl_zero(dl);
9240: read_int(s,(unsigned int *)&td); TD(dl) = td;
9241: for ( j = 0; j < nv; j++ ) {
9242: read_int(s,(unsigned int *)&e);
9243: PUT_EXP(dl,j,e);
9244: }
9245: if ( nd_module ) {
9246: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
9247: }
9248: if ( nd_blockmask ) ndl_weight_mask(dl);
9249: }
9250: fclose(s);
9251: MKNDV(nv,m0,len,d);
9252: SG(d) = sugar;
9253: return d;
9254: }
9255:
9256: ND nd_load_mod(int index)
9257: {
9258: FILE *s;
9259: char name[BUFSIZ];
9260: int nv,sugar,len,i,c;
9261: ND d;
9262: NM m0,m;
9263:
9264: sprintf(name,"%s/%d",Demand,index);
9265: s = fopen(name,"r");
9266: /* if the file does not exist, it means p[index]=0 */
9267: if ( !s ) return 0;
9268:
9269: read_int(s,(unsigned int *)&nv);
9270: if ( !nv ) { fclose(s); return 0; }
9271:
9272: read_int(s,(unsigned int *)&sugar);
9273: read_int(s,(unsigned int *)&len);
9274: for ( m0 = 0, i = 0; i < len; i++ ) {
9275: NEXTNM(m0,m);
9276: read_int(s,(unsigned int *)&c); CM(m) = c;
9277: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
9278: }
9279: NEXT(m) = 0;
9280: MKND(nv,m0,len,d);
9281: SG(d) = sugar;
9282: fclose(s);
9283: return d;
9284: }
9285:
9286: void nd_det(int mod,MAT f,P *rp)
9287: {
9288: VL fv,tv;
9289: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
9290: pointer **m;
9291: P **w;
9292: P mp,r;
9293: NDV **dm;
9294: NDV *t,*mi,*mj;
9295: NDV d,s,mij,mjj;
9296: ND u;
9297: NMV nmv;
9298: UINT *bound;
9299: PGeoBucket bucket;
9300: struct order_spec *ord;
9301: Z dq,dt,ds;
9302: Z mone;
9303: Z gn,qn,dn0,nm,dn;
9304:
9305: create_order_spec(0,0,&ord);
9306: nd_init_ord(ord);
9307: get_vars((Obj)f,&fv);
9308: if ( f->row != f->col )
9309: error("nd_det : non-square matrix");
9310: n = f->row;
9311: m = f->body;
9312: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
9313:
9314: if ( !nvar ) {
9315: if ( !mod )
9316: detp(CO,(P **)m,n,rp);
9317: else {
9318: w = (P **)almat_pointer(n,n);
9319: for ( i = 0; i < n; i++ )
9320: for ( j = 0; j < n; j++ )
9321: ptomp(mod,(P)m[i][j],&w[i][j]);
9322: detmp(CO,mod,w,n,&mp);
9323: mptop(mp,rp);
9324: }
9325: return;
9326: }
9327:
9328: if ( !mod ) {
9329: w = (P **)almat_pointer(n,n);
9330: dq = ONE;
9331: for ( i = 0; i < n; i++ ) {
9332: dn0 = ONE;
9333: for ( j = 0; j < n; j++ ) {
9334: if ( !m[i][j] ) continue;
9335: lgp(m[i][j],&nm,&dn);
1.6 noro 9336: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 9337: }
9338: if ( !UNIZ(dn0) ) {
9339: ds = dn0;
9340: for ( j = 0; j < n; j++ )
9341: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
9342: mulz(dq,ds,&dt); dq = dt;
9343: } else
9344: for ( j = 0; j < n; j++ )
9345: w[i][j] = (P)m[i][j];
9346: }
9347: m = (pointer **)w;
9348: }
9349:
9350: for ( i = 0, max = 1; i < n; i++ )
9351: for ( j = 0; j < n; j++ )
9352: for ( tv = fv; tv; tv = NEXT(tv) ) {
9353: e = getdeg(tv->v,(P)m[i][j]);
9354: max = MAX(e,max);
9355: }
9356: nd_setup_parameters(nvar,max);
9357: dm = (NDV **)almat_pointer(n,n);
9358: for ( i = 0, max = 1; i < n; i++ )
9359: for ( j = 0; j < n; j++ ) {
9360: dm[i][j] = ptondv(CO,fv,m[i][j]);
9361: if ( mod ) ndv_mod(mod,dm[i][j]);
9362: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
9363: }
9364: d = ptondv(CO,fv,(P)ONE);
9365: if ( mod ) ndv_mod(mod,d);
9366: chsgnz(ONE,&mone);
9367: for ( j = 0, sgn = 1; j < n; j++ ) {
9368: if ( DP_Print ) {
9369: fprintf(asir_out,".");
9370: }
9371: for ( i = j; i < n && !dm[i][j]; i++ );
9372: if ( i == n ) {
9373: *rp = 0;
9374: return;
9375: }
9376: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
9377: for ( k = j; k < n; k++ )
9378: for ( l = j; l < n; l++ )
9379: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
9380: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
9381: }
9382: if ( k0 != j ) {
9383: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
9384: sgn = -sgn;
9385: }
9386: if ( l0 != j ) {
9387: for ( k = j; k < n; k++ ) {
9388: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
9389: }
9390: sgn = -sgn;
9391: }
9392: bound = nd_det_compute_bound(dm,n,j);
9393: for ( k = 0; k < nd_nvar; k++ )
9394: if ( bound[k]*2 > nd_mask0 ) break;
9395: if ( k < nd_nvar )
9396: nd_det_reconstruct(dm,n,j,d);
9397:
9398: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
9399: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
9400: mi = dm[i]; mij = mi[j];
9401: if ( mod )
9402: ndv_mul_c(mod,mij,mod-1);
9403: else
9404: ndv_mul_c_q(mij,mone);
9405: for ( k = j+1; k < n; k++ ) {
9406: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
9407: bucket = create_pbucket();
9408: if ( mi[k] ) {
9409: nmv = BDY(mjj); len = LEN(mjj);
9410: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9411: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
9412: add_pbucket(mod,bucket,u);
9413: }
9414: }
9415: if ( mj[k] && mij ) {
9416: nmv = BDY(mij); len = LEN(mij);
9417: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9418: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
9419: add_pbucket(mod,bucket,u);
9420: }
9421: }
9422: u = nd_quo(mod,bucket,d);
9423: mi[k] = ndtondv(mod,u);
9424: }
9425: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
9426: }
9427: d = mjj;
9428: }
9429: if ( DP_Print ) {
9430: fprintf(asir_out,"\n");
9431: }
9432: if ( sgn < 0 ) {
9433: if ( mod )
9434: ndv_mul_c(mod,d,mod-1);
9435: else
9436: ndv_mul_c_q(d,mone);
9437: }
9438: r = ndvtop(mod,CO,fv,d);
9439: if ( !mod && !UNIQ(dq) )
9440: divsp(CO,r,(P)dq,rp);
9441: else
9442: *rp = r;
9443: }
9444:
9445: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
9446: {
9447: NM mr,mr0;
9448: NM tnm;
9449: NMV m;
9450: UINT *d0,*dt,*dm;
9451: int c,n,td,i,c1,c2,len;
9452: Z q;
9453: ND r;
9454:
9455: if ( !p ) return 0;
9456: else {
9457: n = NV(p); m = BDY(p); len = LEN(p);
9458: d0 = DL(m0);
9459: td = TD(d);
9460: mr0 = 0;
9461: NEWNM(tnm);
9462: if ( mod ) {
9463: c = CM(m0);
9464: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9465: ndl_add(DL(m),d0,DL(tnm));
9466: if ( ndl_reducible(DL(tnm),d) ) {
9467: NEXTNM(mr0,mr);
9468: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
9469: ndl_copy(DL(tnm),DL(mr));
9470: }
9471: }
9472: } else {
1.6 noro 9473: q = CZ(m0);
1.1 noro 9474: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9475: ndl_add(DL(m),d0,DL(tnm));
9476: if ( ndl_reducible(DL(tnm),d) ) {
9477: NEXTNM(mr0,mr);
1.6 noro 9478: mulz(CZ(m),q,&CZ(mr));
1.1 noro 9479: ndl_copy(DL(tnm),DL(mr));
9480: }
9481: }
9482: }
9483: if ( !mr0 )
9484: return 0;
9485: else {
9486: NEXT(mr) = 0;
9487: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9488: MKND(NV(p),mr0,len,r);
9489: SG(r) = SG(p) + TD(d0);
9490: return r;
9491: }
9492: }
9493: }
9494:
9495: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
9496: {
9497: int i,obpe,oadv,h,k,l;
9498: static NM prev_nm_free_list;
9499: EPOS oepos;
9500:
9501: obpe = nd_bpe;
9502: oadv = nmv_adv;
9503: oepos = nd_epos;
9504: if ( obpe < 2 ) nd_bpe = 2;
9505: else if ( obpe < 3 ) nd_bpe = 3;
9506: else if ( obpe < 4 ) nd_bpe = 4;
9507: else if ( obpe < 5 ) nd_bpe = 5;
9508: else if ( obpe < 6 ) nd_bpe = 6;
9509: else if ( obpe < 8 ) nd_bpe = 8;
9510: else if ( obpe < 10 ) nd_bpe = 10;
9511: else if ( obpe < 16 ) nd_bpe = 16;
9512: else if ( obpe < 32 ) nd_bpe = 32;
9513: else error("nd_det_reconstruct : exponent too large");
9514:
9515: nd_setup_parameters(nd_nvar,0);
9516: prev_nm_free_list = _nm_free_list;
9517: _nm_free_list = 0;
9518: for ( k = j; k < n; k++ )
9519: for (l = j; l < n; l++ )
9520: ndv_realloc(dm[k][l],obpe,oadv,oepos);
9521: ndv_realloc(d,obpe,oadv,oepos);
9522: prev_nm_free_list = 0;
9523: #if 0
9524: GC_gcollect();
9525: #endif
9526: }
9527:
9528: /* returns a UINT array containing degree bounds */
9529:
9530: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
9531: {
9532: UINT *d0,*d1,*d,*t,*r;
9533: int k,l,i;
9534:
9535: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
9536: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
9537: for ( k = j; k < n; k++ )
9538: for ( l = j; l < n; l++ )
9539: if ( dm[k][l] ) {
9540: d = ndv_compute_bound(dm[k][l]);
9541: for ( i = 0; i < nd_nvar; i++ )
9542: d0[i] = MAX(d0[i],d[i]);
9543: }
9544: return d0;
9545: }
9546:
9547: DL nd_separate_d(UINT *d,UINT *trans)
9548: {
9549: int n,td,i,e,j;
9550: DL a;
9551:
9552: ndl_zero(trans);
9553: td = 0;
9554: for ( i = 0; i < nd_ntrans; i++ ) {
9555: e = GET_EXP(d,i);
9556: PUT_EXP(trans,i,e);
9557: td += MUL_WEIGHT(e,i);
9558: }
9559: if ( nd_ntrans+nd_nalg < nd_nvar ) {
9560: /* homogenized */
9561: i = nd_nvar-1;
9562: e = GET_EXP(d,i);
9563: PUT_EXP(trans,i,e);
9564: td += MUL_WEIGHT(e,i);
9565: }
9566: TD(trans) = td;
9567: if ( nd_blockmask) ndl_weight_mask(trans);
9568: NEWDL(a,nd_nalg);
9569: td = 0;
9570: for ( i = 0; i < nd_nalg; i++ ) {
9571: j = nd_ntrans+i;
9572: e = GET_EXP(d,j);
9573: a->d[i] = e;
9574: td += e;
9575: }
9576: a->td = td;
9577: return a;
9578: }
9579:
9580: int nd_monic(int mod,ND *p)
9581: {
9582: UINT *trans,*t;
9583: DL alg;
9584: MP mp0,mp;
9585: NM m,m0,m1,ma0,ma,mb,mr0,mr;
9586: ND r;
9587: DL dl;
9588: DP nm;
9589: NDV ndv;
9590: DAlg inv,cd;
9591: ND s,c;
9592: Z l,mul;
9593: Z ln;
9594: int n,ntrans,i,e,td,is_lc,len;
9595: NumberField nf;
9596: struct oEGT eg0,eg1;
9597:
9598: if ( !(nf = get_numberfield()) )
9599: error("nd_monic : current_numberfield is not set");
9600:
9601: /* Q coef -> DAlg coef */
9602: NEWNM(ma0); ma = ma0;
9603: m = BDY(*p);
9604: is_lc = 1;
9605: while ( 1 ) {
9606: NEWMP(mp0); mp = mp0;
1.6 noro 9607: mp->c = (Obj)CZ(m);
1.1 noro 9608: mp->dl = nd_separate_d(DL(m),DL(ma));
9609: NEWNM(mb);
9610: for ( m = NEXT(m); m; m = NEXT(m) ) {
9611: alg = nd_separate_d(DL(m),DL(mb));
9612: if ( !ndl_equal(DL(ma),DL(mb)) )
9613: break;
1.6 noro 9614: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 9615: }
9616: NEXT(mp) = 0;
9617: MKDP(nd_nalg,mp0,nm);
9618: MKDAlg(nm,ONE,cd);
9619: if ( is_lc == 1 ) {
9620: /* if the lc is a rational number, we have nothing to do */
9621: if ( !mp0->dl->td )
9622: return 1;
9623:
9624: get_eg(&eg0);
9625: invdalg(cd,&inv);
9626: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
9627: /* check the validity of inv */
9628: if ( mod && !remqi((Q)inv->dn,mod) )
9629: return 0;
9630: CA(ma) = nf->one;
9631: is_lc = 0;
9632: ln = ONE;
9633: } else {
9634: muldalg(cd,inv,&CA(ma));
9635: lcmz(ln,CA(ma)->dn,&ln);
9636: }
9637: if ( m ) {
9638: NEXT(ma) = mb; ma = mb;
9639: } else {
9640: NEXT(ma) = 0;
9641: break;
9642: }
9643: }
9644: /* l = lcm(denoms) */
9645: l = ln;
9646: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 9647: divsz(l,CA(m)->dn,&mul);
1.1 noro 9648: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
9649: NEXTNM(mr0,mr);
1.6 noro 9650: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 9651: dl = mp->dl;
9652: td = TD(DL(m));
9653: ndl_copy(DL(m),DL(mr));
9654: for ( i = 0; i < nd_nalg; i++ ) {
9655: e = dl->d[i];
9656: PUT_EXP(DL(mr),i+nd_ntrans,e);
9657: td += MUL_WEIGHT(e,i+nd_ntrans);
9658: }
9659: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
9660: TD(DL(mr)) = td;
9661: if ( nd_blockmask) ndl_weight_mask(DL(mr));
9662: }
9663: }
9664: NEXT(mr) = 0;
9665: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9666: MKND(NV(*p),mr0,len,r);
9667: /* XXX */
9668: SG(r) = SG(*p);
9669: nd_free(*p);
9670: *p = r;
9671: return 1;
9672: }
9673:
9674: NODE reverse_node(NODE n)
9675: {
9676: NODE t,t1;
9677:
9678: for ( t = 0; n; n = NEXT(n) ) {
9679: MKNODE(t1,BDY(n),t); t = t1;
9680: }
9681: return t;
9682: }
9683:
9684: P ndc_div(int mod,union oNDC a,union oNDC b)
9685: {
9686: union oNDC c;
9687: int inv,t;
9688:
9689: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 9690: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 9691: else if ( mod ) {
9692: inv = invm(b.m,mod);
9693: DMAR(a.m,inv,0,mod,t); c.m = t;
9694: } else if ( nd_vc )
9695: divsp(nd_vc,a.p,b.p,&c.p);
9696: else
9697: divsz(a.z,b.z,&c.z);
9698: return ndctop(mod,c);
9699: }
9700:
9701: P ndctop(int mod,union oNDC c)
9702: {
9703: Z q;
9704: int e;
9705: GFS gfs;
9706:
9707: if ( mod == -1 ) {
9708: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
9709: } else if ( mod == -2 ) {
1.10 noro 9710: q = c.z; return (P)q;
1.1 noro 9711: } else if ( mod > 0 ) {
1.6 noro 9712: STOZ(c.m,q); return (P)q;
1.1 noro 9713: } else
9714: return (P)c.p;
9715: }
9716:
9717: /* [0,0,0,cont] = p -> p/cont */
9718:
9719: void finalize_tracelist(int i,P cont)
9720: {
9721: LIST l;
9722: NODE node;
9723: Z iq;
9724:
9725: if ( !UNIQ(cont) ) {
9726: node = mknode(4,NULLP,NULLP,NULLP,cont);
9727: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
9728: nd_tracelist = node;
9729: }
1.6 noro 9730: STOZ(i,iq);
1.1 noro 9731: nd_tracelist = reverse_node(nd_tracelist);
9732: MKLIST(l,nd_tracelist);
9733: node = mknode(2,iq,l); MKLIST(l,node);
9734: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
9735: nd_alltracelist = node; nd_tracelist = 0;
9736: }
9737:
9738: void conv_ilist(int demand,int trace,NODE g,int **indp)
9739: {
9740: int n,i,j;
9741: int *ind;
9742: NODE t;
9743:
9744: n = length(g);
9745: ind = (int *)MALLOC(n*sizeof(int));
9746: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
9747: j = (long)BDY(t); ind[i] = j;
9748: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
9749: }
9750: if ( indp ) *indp = ind;
9751: }
9752:
1.30 noro 9753: NODE conv_ilist_s(int demand,int trace,int **indp)
9754: {
9755: int n,i,j;
9756: int *ind;
9757: NODE g0,g;
9758:
9759: n = nd_psn;
9760: ind = (int *)MALLOC(n*sizeof(int));
9761: g0 = 0;
9762: for ( i = 0; i < n; i++ ) {
9763: ind[i] = i;
9764: NEXTNODE(g0,g);
9765: BDY(g) = (pointer)(demand?ndv_load(i):(trace?nd_ps_trace[i]:nd_ps[i]));
9766: }
9767: if ( g0 ) NEXT(g) = 0;
9768: if ( indp ) *indp = ind;
9769: return g0;
9770: }
9771:
1.1 noro 9772: void parse_nd_option(NODE opt)
9773: {
1.38 noro 9774: NODE t,p,u;
1.1 noro 9775: int i,s,n;
1.38 noro 9776: char *key;
9777: Obj value;
1.1 noro 9778:
1.38 noro 9779: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_gbblock = 0;
1.1 noro 9780: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
9781: nd_splist = 0; nd_check_splist = 0;
1.38 noro 9782: nd_sugarweight = 0; nd_f4red =0; nd_rank0 = 0;
9783: nd_f4_td = 0; nd_sba_f4step = 2; nd_sba_pot = 0; nd_sba_largelcm = 0;
1.39 noro 9784: nd_sba_dontsort = 0; nd_top = 0;
9785:
1.38 noro 9786: for ( t = opt; t; t = NEXT(t) ) {
9787: p = BDY((LIST)BDY(t));
9788: key = BDY((STRING)BDY(p));
9789: value = (Obj)BDY(NEXT(p));
9790: if ( !strcmp(key,"gentrace") )
9791: nd_gentrace = value?1:0;
9792: else if ( !strcmp(key,"gensyz") )
9793: nd_gensyz = value?1:0;
9794: else if ( !strcmp(key,"nora") )
9795: nd_nora = value?1:0;
9796: else if ( !strcmp(key,"gbblock") ) {
9797: if ( value && OID(value) == O_LIST ) {
1.1 noro 9798: u = BDY((LIST)value);
1.38 noro 9799: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
1.1 noro 9800: for ( i = 0; u; u = NEXT(u) ) {
9801: p = BDY((LIST)BDY(u));
1.6 noro 9802: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
9803: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 9804: }
9805: nd_gbblock[i] = -1;
1.38 noro 9806: } else
9807: nd_gbblock = 0;
1.1 noro 9808: } else if ( !strcmp(key,"newelim") )
9809: nd_newelim = value?1:0;
9810: else if ( !strcmp(key,"intersect") )
9811: nd_intersect = value?1:0;
1.17 noro 9812: else if ( !strcmp(key,"syzgen") )
9813: nd_intersect = ZTOS((Q)value);
1.1 noro 9814: else if ( !strcmp(key,"lf") )
9815: nd_lf = value?1:0;
9816: else if ( !strcmp(key,"trace") ) {
1.38 noro 9817: if ( value ) {
9818: u = BDY((LIST)value);
9819: nd_nzlist = BDY((LIST)ARG2(u));
9820: nd_bpe = ZTOS((Q)ARG3(u));
9821: }
1.1 noro 9822: } else if ( !strcmp(key,"f4red") ) {
1.38 noro 9823: nd_f4red = ZTOS((Q)value);
1.1 noro 9824: } else if ( !strcmp(key,"rank0") ) {
1.38 noro 9825: nd_rank0 = value?1:0;
1.1 noro 9826: } else if ( !strcmp(key,"splist") ) {
1.38 noro 9827: nd_splist = value?1:0;
1.1 noro 9828: } else if ( !strcmp(key,"check_splist") ) {
9829: nd_check_splist = BDY((LIST)value);
9830: } else if ( !strcmp(key,"sugarweight") ) {
9831: u = BDY((LIST)value);
1.38 noro 9832: n = length(u);
9833: nd_sugarweight = MALLOC(n*sizeof(int));
1.1 noro 9834: for ( i = 0; i < n; i++, u = NEXT(u) )
1.38 noro 9835: nd_sugarweight[i] = ZTOS((Q)BDY(u));
9836: } else if ( !strcmp(key,"f4_td") ) {
9837: nd_f4_td = value?1:0;
9838: } else if ( !strcmp(key,"sba_f4step") ) {
9839: nd_sba_f4step = value?ZTOS((Q)value):0;
9840: } else if ( !strcmp(key,"sba_pot") ) {
9841: nd_sba_pot = value?1:0;
9842: } else if ( !strcmp(key,"sba_largelcm") ) {
9843: nd_sba_largelcm = value?1:0;
1.39 noro 9844: } else if ( !strcmp(key,"sba_dontsort") ) {
9845: nd_sba_dontsort = value?1:0;
9846: } else if ( !strcmp(key,"top") ) {
9847: nd_top = value?1:0;
1.1 noro 9848: }
1.38 noro 9849: }
1.1 noro 9850: }
9851:
9852: ND mdptond(DP d);
9853: ND nd_mul_nm(int mod,NM m0,ND p);
9854: ND nd_mul_nm_lf(NM m0,ND p);
9855: ND *btog(NODE ti,ND **p,int nb,int mod);
9856: ND btog_one(NODE ti,ND *p,int nb,int mod);
9857: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
9858: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
9859:
9860: /* d:monomial */
9861: ND mdptond(DP d)
9862: {
9863: NM m;
9864: ND r;
9865:
9866: if ( OID(d) == 1 )
9867: r = ptond(CO,CO,(P)d);
9868: else {
9869: NEWNM(m);
9870: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 9871: CZ(m) = (Z)BDY(d)->c;
1.1 noro 9872: NEXT(m) = 0;
9873: MKND(NV(d),m,1,r);
9874: }
9875: return r;
9876: }
9877:
9878: ND nd_mul_nm(int mod,NM m0,ND p)
9879: {
9880: UINT *d0;
9881: int c0,c1,c;
9882: NM tm,mr,mr0;
9883: ND r;
9884:
9885: if ( !p ) return 0;
9886: d0 = DL(m0);
9887: c0 = CM(m0);
9888: mr0 = 0;
9889: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
9890: NEXTNM(mr0,mr);
9891: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
9892: ndl_add(d0,DL(tm),DL(mr));
9893: }
9894: NEXT(mr) = 0;
9895: MKND(NV(p),mr0,LEN(p),r);
9896: return r;
9897: }
9898:
9899: ND nd_mul_nm_lf(NM m0,ND p)
9900: {
9901: UINT *d0;
9902: Z c0,c1,c;
9903: NM tm,mr,mr0;
9904: ND r;
9905:
9906: if ( !p ) return 0;
9907: d0 = DL(m0);
9908: c0 = CZ(m0);
9909: mr0 = 0;
9910: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
9911: NEXTNM(mr0,mr);
9912: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
9913: ndl_add(d0,DL(tm),DL(mr));
9914: }
9915: NEXT(mr) = 0;
9916: MKND(NV(p),mr0,LEN(p),r);
9917: return r;
9918: }
9919:
9920: ND *btog(NODE ti,ND **p,int nb,int mod)
9921: {
9922: PGeoBucket *r;
9923: int i,ci;
9924: NODE t,s;
9925: ND m,tp;
9926: ND *pi,*rd;
9927: P c;
9928:
9929: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
9930: for ( i = 0; i < nb; i++ )
9931: r[i] = create_pbucket();
9932: for ( t = ti; t; t = NEXT(t) ) {
9933: s = BDY((LIST)BDY(t));
9934: if ( ARG0(s) ) {
9935: m = mdptond((DP)ARG2(s));
1.6 noro 9936: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 9937: if ( (ci = ((MQ)c)->cont) != 0 ) {
9938: HCM(m) = ci;
1.6 noro 9939: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 9940: for ( i = 0; i < nb; i++ ) {
9941: tp = nd_mul_nm(mod,BDY(m),pi[i]);
9942: add_pbucket(mod,r[i],tp);
9943: }
9944: }
9945: ci = 1;
9946: } else {
9947: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
9948: ci = invm(ci,mod);
9949: }
9950: }
9951: rd = (ND *)MALLOC(nb*sizeof(ND));
9952: for ( i = 0; i < nb; i++ )
9953: rd[i] = normalize_pbucket(mod,r[i]);
9954: if ( ci != 1 )
9955: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
9956: return rd;
9957: }
9958:
9959: /* YYY */
9960: ND *btog_lf(NODE ti,ND **p,int nb)
9961: {
9962: PGeoBucket *r;
9963: int i;
9964: NODE t,s;
9965: ND m,tp;
9966: ND *pi,*rd;
9967: LM lm;
9968: Z lf,c;
9969:
9970: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
9971: for ( i = 0; i < nb; i++ )
9972: r[i] = create_pbucket();
9973: for ( t = ti; t; t = NEXT(t) ) {
9974: s = BDY((LIST)BDY(t));
9975: if ( ARG0(s) ) {
9976: m = mdptond((DP)ARG2(s));
1.6 noro 9977: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 9978: if ( lm ) {
9979: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 9980: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 9981: for ( i = 0; i < nb; i++ ) {
9982: tp = nd_mul_nm_lf(BDY(m),pi[i]);
9983: add_pbucket(-2,r[i],tp);
9984: }
9985: }
9986: c = ONE;
9987: } else {
9988: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
9989: }
9990: }
9991: rd = (ND *)MALLOC(nb*sizeof(ND));
9992: for ( i = 0; i < nb; i++ )
9993: rd[i] = normalize_pbucket(-2,r[i]);
9994: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
9995: return rd;
9996: }
9997:
9998: ND btog_one(NODE ti,ND *p,int nb,int mod)
9999: {
10000: PGeoBucket r;
10001: int i,ci,j;
10002: NODE t,s;
10003: ND m,tp;
10004: ND pi,rd;
10005: P c;
10006:
10007: r = create_pbucket();
10008: for ( t = ti; t; t = NEXT(t) ) {
10009: s = BDY((LIST)BDY(t));
10010: if ( ARG0(s) ) {
10011: m = mdptond((DP)ARG2(s));
1.6 noro 10012: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10013: if ( (ci = ((MQ)c)->cont) != 0 ) {
10014: HCM(m) = ci;
1.6 noro 10015: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 10016: if ( !pi ) {
10017: pi = nd_load_mod(j);
10018: tp = nd_mul_nm(mod,BDY(m),pi);
10019: nd_free(pi);
10020: add_pbucket(mod,r,tp);
10021: } else {
10022: tp = nd_mul_nm(mod,BDY(m),pi);
10023: add_pbucket(mod,r,tp);
10024: }
10025: }
10026: ci = 1;
10027: } else {
10028: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10029: ci = invm(ci,mod);
10030: }
10031: }
10032: rd = normalize_pbucket(mod,r);
10033: free_pbucket(r);
10034: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
10035: return rd;
10036: }
10037:
10038: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
10039:
10040: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
10041: {
10042: int i,j,n,m,nb,pi0,pi1,nvar;
10043: VL fv,tv,vv;
10044: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10045: ND **p;
10046: ND *c;
10047: ND u;
10048: P inv;
10049: MAT mat;
10050:
10051: if ( mod == -2 )
10052: return nd_btog_lf(f,v,ord,tlist,rp);
10053:
10054: parse_nd_option(current_option);
10055: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10056: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10057: switch ( ord->id ) {
10058: case 1:
10059: if ( ord->nv != nvar )
10060: error("nd_check : invalid order specification");
10061: break;
10062: default:
10063: break;
10064: }
10065: nd_init_ord(ord);
10066: #if 0
1.6 noro 10067: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10068: #else
10069: nd_bpe = 32;
10070: #endif
10071: nd_setup_parameters(nvar,0);
10072: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10073: intred = BDY((LIST)ARG3(BDY(tlist)));
10074: ind = BDY((LIST)ARG4(BDY(tlist)));
10075: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10076: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10077: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10078: if ( j > i ) i = j;
10079: }
10080: n = i+1;
10081: nb = length(BDY(f));
10082: p = (ND **)MALLOC(n*sizeof(ND *));
10083: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10084: pi = BDY((LIST)BDY(t));
1.6 noro 10085: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10086: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10087: ptomp(mod,(P)ARG2(pi),&inv);
10088: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10089: u = ptond(CO,vv,(P)ONE);
10090: HCM(u) = ((MQ)inv)->cont;
10091: c[pi1] = u;
10092: }
10093: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10094: printf("%d ",i); fflush(stdout);
10095: ti = BDY((LIST)BDY(t));
1.6 noro 10096: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10097: }
10098: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10099: printf("%d ",i); fflush(stdout);
10100: ti = BDY((LIST)BDY(t));
1.6 noro 10101: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10102: }
10103: m = length(ind);
10104: MKMAT(mat,nb,m);
10105: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10106: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10107: BDY(mat)[i][j] = ndtodp(mod,c[i]);
10108: return mat;
10109: }
10110:
10111: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
10112: {
10113: int i,j,n,m,nb,pi0,pi1,nvar;
10114: VL fv,tv,vv;
10115: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10116: ND **p;
10117: ND *c;
10118: ND u;
10119: MAT mat;
10120: LM lm;
10121: Z lf,inv;
10122:
10123: parse_nd_option(current_option);
10124: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10125: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10126: switch ( ord->id ) {
10127: case 1:
10128: if ( ord->nv != nvar )
10129: error("nd_check : invalid order specification");
10130: break;
10131: default:
10132: break;
10133: }
10134: nd_init_ord(ord);
10135: #if 0
1.6 noro 10136: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10137: #else
10138: nd_bpe = 32;
10139: #endif
10140: nd_setup_parameters(nvar,0);
10141: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10142: intred = BDY((LIST)ARG3(BDY(tlist)));
10143: ind = BDY((LIST)ARG4(BDY(tlist)));
10144: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10145: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10146: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10147: if ( j > i ) i = j;
10148: }
10149: n = i+1;
10150: nb = length(BDY(f));
10151: p = (ND **)MALLOC(n*sizeof(ND *));
10152: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10153: pi = BDY((LIST)BDY(t));
1.6 noro 10154: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10155: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10156: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
10157: u = ptond(CO,vv,(P)ONE);
10158: HCZ(u) = inv;
10159: c[pi1] = u;
10160: }
10161: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10162: printf("%d ",i); fflush(stdout);
10163: ti = BDY((LIST)BDY(t));
1.6 noro 10164: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10165: }
10166: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10167: printf("%d ",i); fflush(stdout);
10168: ti = BDY((LIST)BDY(t));
1.6 noro 10169: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10170: }
10171: m = length(ind);
10172: MKMAT(mat,nb,m);
10173: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10174: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10175: BDY(mat)[i][j] = ndtodp(-2,c[i]);
10176: return mat;
10177: }
10178:
10179: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
10180: LIST tlist,int pos,MAT *rp)
10181: {
10182: int i,j,n,m,nb,pi0,pi1,nvar;
10183: VL fv,tv,vv;
10184: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10185: ND *p;
10186: ND *c;
10187: ND u;
10188: P inv;
10189: VECT vect;
10190:
10191: if ( mod == -2 )
10192: error("nd_btog_one : not implemented yet for a large finite field");
10193:
10194: parse_nd_option(current_option);
10195: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10196: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10197: switch ( ord->id ) {
10198: case 1:
10199: if ( ord->nv != nvar )
10200: error("nd_check : invalid order specification");
10201: break;
10202: default:
10203: break;
10204: }
10205: nd_init_ord(ord);
10206: #if 0
1.6 noro 10207: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10208: #else
10209: nd_bpe = 32;
10210: #endif
10211: nd_setup_parameters(nvar,0);
10212: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10213: intred = BDY((LIST)ARG3(BDY(tlist)));
10214: ind = BDY((LIST)ARG4(BDY(tlist)));
10215: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10216: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10217: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10218: if ( j > i ) i = j;
10219: }
10220: n = i+1;
10221: nb = length(BDY(f));
10222: p = (ND *)MALLOC(n*sizeof(ND *));
10223: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10224: pi = BDY((LIST)BDY(t));
1.6 noro 10225: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10226: if ( pi1 == pos ) {
10227: ptomp(mod,(P)ARG2(pi),&inv);
10228: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10229: u = ptond(CO,vv,(P)ONE);
10230: HCM(u) = ((MQ)inv)->cont;
10231: p[pi0] = u;
10232: }
10233: }
10234: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10235: printf("%d ",i); fflush(stdout);
10236: ti = BDY((LIST)BDY(t));
1.6 noro 10237: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10238: if ( Demand ) {
10239: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10240: }
10241: }
10242: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10243: printf("%d ",i); fflush(stdout);
10244: ti = BDY((LIST)BDY(t));
1.6 noro 10245: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10246: if ( Demand ) {
10247: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10248: }
10249: }
10250: m = length(ind);
10251: MKVECT(vect,m);
10252: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 10253: u = p[ZTOS((Q)BDY(t))];
1.1 noro 10254: if ( !u ) {
1.6 noro 10255: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 10256: BDY(vect)[j] = ndtodp(mod,u);
10257: nd_free(u);
10258: } else
10259: BDY(vect)[j] = ndtodp(mod,u);
10260: }
10261: return vect;
10262: }
10263:
10264: void ndv_print_lf(NDV p)
10265: {
10266: NMV m;
10267: int i,len;
10268:
10269: if ( !p ) printf("0\n");
10270: else {
10271: len = LEN(p);
10272: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
10273: printf("+");
10274: mpz_out_str(asir_out,10,BDY(CZ(m)));
10275: printf("*");
10276: ndl_print(DL(m));
10277: }
10278: printf("\n");
10279: }
10280: }
10281:
10282: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
10283: {
10284: VL tv,fv,vv,vc,av;
10285: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
10286: int m,nocheck,nvar,mindex,e,max;
10287: NDV c;
10288: NMV a;
10289: P p,zp;
10290: Q dmy;
10291: EPOS oepos;
10292: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
10293: Alg alpha,dp;
10294: P poly;
10295: LIST f1,f2,zpl;
10296: Obj obj;
10297: NumberField nf;
10298: struct order_spec *ord1;
10299: struct oEGT eg_check,eg0,eg1;
10300: NODE tr,tl1,tl2,tl3,tl4;
10301: LIST l1,l2,l3,l4,l5;
10302: int *perm;
10303: int j,ret;
10304: NODE retn;
10305: Q jq,bpe;
10306:
10307: nd_module = 0;
10308: parse_nd_option(current_option);
10309: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10310: if ( nd_vc )
10311: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
10312: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10313: switch ( ord->id ) {
10314: case 1:
10315: if ( ord->nv != nvar )
10316: error("nd_f4_lf_trace : invalid order specification");
10317: break;
10318: default:
10319: break;
10320: }
10321:
10322: nd_ntrans = nvar;
10323: nd_nalg = 0;
10324:
10325: nocheck = 0;
10326: mindex = 0;
10327:
10328: /* do not use on-demand load/save */
10329: nd_demand = 0;
10330: m = trace > 1 ? trace : get_lprime(mindex);
10331: nd_init_ord(ord);
10332: mrank = 0;
10333: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
10334: for ( tv = vv; tv; tv = NEXT(tv) ) {
10335: if ( nd_module ) {
10336: s = BDY((LIST)BDY(t));
10337: trank = length(s);
10338: mrank = MAX(mrank,trank);
10339: for ( ; s; s = NEXT(s) ) {
10340: e = getdeg(tv->v,(P)BDY(s));
10341: max = MAX(e,max);
10342: }
10343: } else {
10344: e = getdeg(tv->v,(P)BDY(t));
10345: max = MAX(e,max);
10346: }
10347: }
10348: nd_setup_parameters(nvar,max);
10349: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
10350: ishomo = 1;
10351: /* XXX */
10352: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
10353: if ( nd_module ) {
10354: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
10355: } else {
10356: c = (pointer)ptondv(CO,vv,(P)BDY(t));
10357: }
10358: if ( ishomo )
10359: ishomo = ishomo && ndv_ishomo(c);
10360: if ( c ) {
10361: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
10362: ndv_mod(-2,c);
10363: NEXTNODE(in0,in); BDY(in) = (pointer)c;
10364: }
10365: }
10366: if ( in0 ) NEXT(in) = 0;
10367: if ( fd0 ) NEXT(fd) = 0;
10368: if ( !ishomo && homo ) {
10369: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
10370: c = (NDV)BDY(t); len = LEN(c);
10371: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
10372: wmax = MAX(TD(DL(a)),wmax);
10373: }
10374: homogenize_order(ord,nvar,&ord1);
10375: nd_init_ord(ord1);
10376: nd_setup_parameters(nvar+1,wmax);
10377: for ( t = fd0; t; t = NEXT(t) )
10378: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
10379: }
10380: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 10381: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 10382: if ( ret )
10383: cand = nd_f4_lf_trace_main(m,&perm);
10384: if ( !ret || !cand ) {
10385: *rp = 0; return;
10386: }
10387: if ( !ishomo && homo ) {
10388: /* dehomogenization */
10389: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
10390: nd_init_ord(ord);
10391: nd_setup_parameters(nvar,0);
10392: }
10393: cand = ndv_reducebase(cand,perm);
10394: cand = ndv_reduceall(-2,cand);
10395: cbpe = nd_bpe;
10396: get_eg(&eg0);
10397: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
10398: /* gbcheck : cand is a GB of Id(cand) ? */
10399: retn = nd_f4(-2,0,0);
10400: }
10401: if ( !retn ) {
10402: /* failure */
10403: *rp = 0; return;
10404: }
10405: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
10406: if ( DP_Print )
1.5 noro 10407: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 10408: /* dp->p */
10409: nd_bpe = cbpe;
10410: nd_setup_parameters(nd_nvar,0);
10411: for ( r = cand; r; r = NEXT(r) ) {
10412: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
10413: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
10414: }
10415: MKLIST(*rp,cand);
10416: }
10417:
10418: NODE nd_f4_lf_trace_main(int m,int **indp)
10419: {
10420: int i,nh,stat,index;
10421: NODE r,rm,g;
10422: ND_pairs d,l,l0,t;
10423: ND spol,red;
10424: NDV nf,redv,nfqv,nfv;
10425: NM s0,s;
10426: NODE rp0,srp0,nflist,nflist_lf;
10427: int nsp,nred,col,rank,len,k,j,a;
10428: UINT c;
10429: UINT **spmat;
10430: UINT *s0vect,*svect,*p,*v;
10431: int *colstat;
10432: IndArray *imat;
10433: int *rhead;
10434: int spcol,sprow;
10435: int sugar;
10436: PGeoBucket bucket;
10437: struct oEGT eg0,eg1,eg_f4;
10438:
10439: g = 0; d = 0;
10440: for ( i = 0; i < nd_psn; i++ ) {
10441: d = update_pairs(d,g,i,0);
10442: g = update_base(g,i);
10443: }
10444: while ( d ) {
10445: get_eg(&eg0);
10446: l = nd_minsugarp(d,&d);
10447: sugar = SG(l);
10448: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
10449: bucket = create_pbucket();
10450: stat = nd_sp_f4(m,0,l,bucket);
10451: if ( !stat ) {
10452: for ( t = l; NEXT(t); t = NEXT(t) );
10453: NEXT(t) = d; d = l;
10454: d = nd_reconstruct(1,d);
10455: continue;
10456: }
10457: if ( bucket->m < 0 ) continue;
10458: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
10459: if ( !col ) {
10460: for ( t = l; NEXT(t); t = NEXT(t) );
10461: NEXT(t) = d; d = l;
10462: d = nd_reconstruct(1,d);
10463: continue;
10464: }
10465: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
10466: if ( DP_Print )
1.5 noro 10467: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 10468: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
10469: if ( !l0 ) continue;
10470: l = l0;
10471:
10472: /* over LF */
10473: bucket = create_pbucket();
10474: stat = nd_sp_f4(-2,1,l,bucket);
10475: if ( !stat ) {
10476: for ( t = l; NEXT(t); t = NEXT(t) );
10477: NEXT(t) = d; d = l;
10478: d = nd_reconstruct(1,d);
10479: continue;
10480: }
10481: if ( bucket->m < 0 ) continue;
10482: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
10483: if ( !col ) {
10484: for ( t = l; NEXT(t); t = NEXT(t) );
10485: NEXT(t) = d; d = l;
10486: d = nd_reconstruct(1,d);
10487: continue;
10488: }
10489: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
10490: /* adding new bases */
10491: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
10492: nfv = (NDV)BDY(rm);
10493: nfqv = (NDV)BDY(r);
10494: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
10495: ndv_removecont(m,nfv);
10496: ndv_removecont(-2,nfqv);
1.24 noro 10497: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 10498: d = update_pairs(d,g,nh,0);
10499: g = update_base(g,nh);
10500: }
10501: if ( r || rm ) return 0;
10502: }
10503: conv_ilist(nd_demand,1,g,indp);
10504: return g;
10505: }
10506:
1.7 noro 10507: #if SIZEOF_LONG==8
10508:
10509: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
10510: {
10511: int j,k,len;
10512: UINT *p;
10513: UINT c;
10514: NDV r;
10515: NMV mr0,mr;
10516:
10517: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
10518: if ( !len ) return 0;
10519: else {
10520: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
10521: #if 0
10522: ndv_alloc += nmv_adv*len;
10523: #endif
10524: mr = mr0;
10525: p = s0vect;
10526: for ( j = k = 0; j < col; j++, p += nd_wpd )
10527: if ( !rhead[j] ) {
10528: if ( (c = (UINT)vect[k++]) != 0 ) {
10529: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
10530: }
10531: }
10532: MKNDV(nd_nvar,mr0,len,r);
10533: return r;
10534: }
10535: }
10536:
1.28 noro 10537: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
10538: {
10539: int j,k,len;
10540: UINT *p;
10541: UINT c;
10542: NDV r;
10543: NMV mr0,mr;
10544:
10545: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
10546: if ( !len ) return 0;
10547: else {
10548: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
10549: mr = mr0;
10550: p = s0vect;
10551: for ( j = k = 0; j < col; j++, p += nd_wpd )
10552: if ( (c = (UINT)vect[k++]) != 0 ) {
10553: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
10554: }
10555: MKNDV(nd_nvar,mr0,len,r);
10556: return r;
10557: }
10558: }
10559:
1.7 noro 10560: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
10561: {
10562: NM m;
1.11 noro 10563: UINT *t,*s,*u;
10564: int i,st,ed,md,prev,c;
1.7 noro 10565:
10566: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 10567: prev = 0;
10568: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
10569: t = DL(m);
10570: st = prev;
10571: ed = n;
10572: while ( ed > st ) {
10573: md = (st+ed)/2;
10574: u = s0+md*nd_wpd;
10575: c = DL_COMPARE(u,t);
10576: if ( c == 0 ) break;
10577: else if ( c > 0 ) st = md;
10578: else ed = md;
10579: }
10580: r[md] = (mp_limb_t)CM(m);
10581: prev = md;
1.7 noro 10582: }
10583: for ( i = 0; !r[i]; i++ );
10584: return i;
10585: }
10586:
10587: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
10588:
1.28 noro 10589: 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 10590: {
10591: int i,j,k,len,pos,prev;
10592: mp_limb_t a,c,c1,c2;
10593: IndArray ivect;
10594: unsigned char *ivc;
10595: unsigned short *ivs;
10596: unsigned int *ivi;
10597: NDV redv;
10598: NMV mr;
10599: NODE rp;
10600: int maxrs;
10601:
10602: for ( i = 0; i < col; i++ ) cvect[i] = 0;
10603: maxrs = 0;
10604: for ( i = 0; i < nred; i++ ) {
10605: ivect = imat[i];
10606: k = ivect->head;
10607: a = svect[k]; c = cvect[k];
10608: MOD128(a,c,m);
10609: svect[k] = a; cvect[k] = 0;
1.28 noro 10610: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 10611: Nf4_red++;
1.7 noro 10612: maxrs = MAX(maxrs,rp0[i]->sugar);
10613: c = m-c; redv = nd_ps[rp0[i]->index];
10614: len = LEN(redv); mr = BDY(redv);
10615: svect[k] = 0; prev = k;
10616: switch ( ivect->width ) {
10617: case 1:
10618: ivc = ivect->index.c;
10619: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10620: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 10621: c2 = svect[pos]+c1*c;
10622: if ( c2 < svect[pos] ) cvect[pos]++;
10623: svect[pos] = c2;
1.7 noro 10624: }
10625: break;
10626: case 2:
10627: ivs = ivect->index.s;
10628: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10629: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 10630: c2 = svect[pos]+c1*c;
10631: if ( c2 < svect[pos] ) cvect[pos]++;
10632: svect[pos] = c2;
1.7 noro 10633: }
10634: break;
10635: case 4:
10636: ivi = ivect->index.i;
10637: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10638: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 10639: c2 = svect[pos]+c1*c;
10640: if ( c2 < svect[pos] ) cvect[pos]++;
10641: svect[pos] = c2;
1.7 noro 10642: }
10643: break;
10644: }
10645: }
10646: }
10647: for ( i = 0; i < col; i++ ) {
10648: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
10649: }
10650: return maxrs;
10651: }
10652:
10653: /* for Fp, 2^15=<p<2^29 */
10654:
10655: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
10656: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
10657: {
10658: int spcol,sprow,a;
10659: int i,j,k,l,rank;
10660: NODE r0,r;
10661: ND_pairs sp;
10662: ND spol;
10663: mp_limb_t **spmat;
10664: mp_limb_t *svect,*cvect;
10665: mp_limb_t *v;
10666: int *colstat;
10667: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
10668: int maxrs;
10669: int *spsugar;
10670: ND_pairs *spactive;
10671:
10672: spcol = col-nred;
10673: get_eg(&eg0);
10674: /* elimination (1st step) */
10675: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
10676: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10677: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10678: spsugar = (int *)MALLOC(nsp*sizeof(int));
10679: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
10680: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
10681: nd_sp(m,0,sp,&spol);
10682: if ( !spol ) continue;
10683: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 noro 10684: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 10685: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
10686: if ( i < col ) {
10687: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
10688: for ( j = k = 0; j < col; j++ )
10689: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
10690: spsugar[sprow] = MAX(maxrs,SG(spol));
10691: if ( nz )
10692: spactive[sprow] = sp;
10693: sprow++;
10694: }
10695: nd_free(spol);
10696: }
1.12 noro 10697: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 10698: if ( DP_Print ) {
10699: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
10700: fflush(asir_out);
10701: }
10702: /* free index arrays */
10703: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
10704:
10705: /* elimination (2nd step) */
10706: colstat = (int *)MALLOC(spcol*sizeof(int));
10707: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
10708: r0 = 0;
10709: for ( i = 0; i < rank; i++ ) {
10710: NEXTNODE(r0,r); BDY(r) =
10711: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
10712: SG((NDV)BDY(r)) = spsugar[i];
10713: GCFREE(spmat[i]);
10714: }
10715: if ( r0 ) NEXT(r) = 0;
10716:
10717: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 10718: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 10719: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
10720: if ( DP_Print ) {
10721: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
10722: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
10723: nsp,nred,sprow,spcol,rank);
10724: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
10725: }
10726: if ( nz ) {
10727: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
10728: if ( rank > 0 ) {
10729: NEXT(spactive[rank-1]) = 0;
10730: *nz = spactive[0];
10731: } else
10732: *nz = 0;
10733: }
10734: return r0;
10735: }
10736:
10737: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
10738: {
10739: int i,j,k,l,rank,s;
10740: mp_limb_t inv;
10741: mp_limb_t a;
10742: UINT c;
10743: mp_limb_t *t,*pivot,*pk;
10744: UINT *ck;
10745: UINT **cmat;
10746: UINT *ct;
10747: ND_pairs pair;
10748:
10749: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
10750: for ( i = 0; i < row; i++ ) {
10751: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
10752: bzero(cmat[i],col*sizeof(UINT));
10753: }
10754:
10755: for ( rank = 0, j = 0; j < col; j++ ) {
10756: for ( i = rank; i < row; i++ ) {
10757: a = mat[i][j]; c = cmat[i][j];
10758: MOD128(a,c,md);
10759: mat[i][j] = a; cmat[i][j] = 0;
10760: }
10761: for ( i = rank; i < row; i++ )
10762: if ( mat[i][j] )
10763: break;
10764: if ( i == row ) {
10765: colstat[j] = 0;
10766: continue;
10767: } else
10768: colstat[j] = 1;
10769: if ( i != rank ) {
10770: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
10771: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
10772: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
10773: if ( spactive ) {
10774: pair = spactive[i]; spactive[i] = spactive[rank];
10775: spactive[rank] = pair;
10776: }
10777: }
10778: /* column j is normalized */
10779: s = sugar[rank];
10780: inv = invm((UINT)mat[rank][j],md);
10781: /* normalize pivot row */
10782: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
10783: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
10784: }
10785: for ( i = rank+1; i < row; i++ ) {
10786: if ( (a = mat[i][j]) != 0 ) {
10787: sugar[i] = MAX(sugar[i],s);
10788: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 10789: Nf4_red++;
1.7 noro 10790: }
10791: }
10792: rank++;
10793: }
10794: for ( j = col-1, l = rank-1; j >= 0; j-- )
10795: if ( colstat[j] ) {
10796: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
10797: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
10798: }
10799: s = sugar[l];
10800: for ( i = 0; i < l; i++ ) {
10801: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
10802: if ( a ) {
10803: sugar[i] = MAX(sugar[i],s);
10804: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 10805: Nf4_red++;
1.7 noro 10806: }
10807: }
10808: l--;
10809: }
10810: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
10811: GCFREE(cmat);
10812: return rank;
10813: }
10814:
1.28 noro 10815: 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)
10816: {
10817: int i,j,k,l,rank,s,imin;
10818: mp_limb_t inv;
10819: mp_limb_t a;
10820: UINT c;
10821: mp_limb_t *t,*pivot,*pk;
10822: UINT *ck;
10823: UINT **cmat;
10824: UINT *ct;
10825: ND_pairs pair;
10826: SIG sg;
1.31 noro 10827: int *used;
1.28 noro 10828:
1.31 noro 10829: used = (int *)MALLOC(row*sizeof(int));
1.28 noro 10830: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
10831: for ( i = 0; i < row; i++ ) {
10832: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
10833: bzero(cmat[i],col*sizeof(UINT));
10834: }
10835:
1.31 noro 10836: for ( j = 0; j < col; j++ ) {
10837: for ( i = 0; i < row; i++ ) {
1.28 noro 10838: a = mat[i][j]; c = cmat[i][j];
10839: MOD128(a,c,md);
10840: mat[i][j] = a; cmat[i][j] = 0;
10841: }
1.31 noro 10842: for ( i = 0; i < row; i++ )
10843: if ( !used[i] && mat[i][j] ) break;
10844: if ( i == row ) {
1.28 noro 10845: colstat[j] = 0;
10846: continue;
1.31 noro 10847: } else {
1.28 noro 10848: colstat[j] = 1;
1.31 noro 10849: used[i] = 1;
1.28 noro 10850: }
10851: /* column j is normalized */
1.31 noro 10852: s = sugar[i];
10853: inv = invm((UINT)mat[i][j],md);
1.28 noro 10854: /* normalize pivot row */
1.31 noro 10855: for ( k = j, pk = mat[i]+j, ck = cmat[i]+j; k < col; k++, pk++, ck++ ) {
1.28 noro 10856: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
10857: }
1.31 noro 10858: for ( k = i+1; k < row; k++ ) {
10859: if ( (a = mat[k][j]) != 0 ) {
10860: sugar[k] = MAX(sugar[k],s);
10861: red_by_vect64(md,mat[k]+j,cmat[k]+j,mat[i]+j,(int)(md-a),col-j);
1.28 noro 10862: Nf4_red++;
10863: }
10864: }
10865: }
1.31 noro 10866: rank = 0;
10867: for ( i = 0; i < row; i++ ) {
10868: for ( j = 0; j < col; j++ )
10869: if ( mat[i][j] ) break;
10870: if ( j == col ) sugar[i] = -1;
10871: else rank++;
10872: }
1.28 noro 10873: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
10874: GCFREE(cmat);
10875: return rank;
10876: }
10877:
10878: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
10879: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
10880: {
10881: int spcol,sprow,a;
10882: int i,j,k,l,rank;
10883: NODE r0,r;
10884: ND_pairs sp;
10885: ND spol;
10886: mp_limb_t **spmat;
10887: mp_limb_t *svect,*cvect;
10888: mp_limb_t *v;
10889: int *colstat;
10890: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
10891: int maxrs;
10892: int *spsugar;
10893: ND_pairs *spactive;
10894: SIG *spsig;
10895:
10896: get_eg(&eg0);
10897: /* elimination (1st step) */
10898: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
10899: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10900: spsugar = (int *)MALLOC(nsp*sizeof(int));
10901: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
10902: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
10903: nd_sp(m,0,sp,&spol);
10904: if ( !spol ) {
1.29 noro 10905: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 10906: continue;
10907: }
10908: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10909: nd_to_vect64(m,s0vect,col,spol,svect);
10910: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
10911: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
10912: if ( i < col ) {
10913: spmat[sprow] = svect;
10914: spsugar[sprow] = MAX(maxrs,SG(spol));
10915: spsig[sprow] = sp->sig;
10916: sprow++;
10917: } else {
1.29 noro 10918: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 10919: }
10920: nd_free(spol);
10921: }
10922: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
10923: if ( DP_Print ) {
10924: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
10925: fflush(asir_out);
10926: }
10927: /* free index arrays */
10928: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
10929:
10930: /* elimination (2nd step) */
10931: colstat = (int *)MALLOC(col*sizeof(int));
10932: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
10933: r0 = 0;
1.31 noro 10934: for ( i = 0; i < sprow; i++ ) {
10935: if ( spsugar[i] >= 0 ) {
10936: NEXTNODE(r0,r);
10937: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
10938: SG((NDV)BDY(r)) = spsugar[i];
10939: ((NDV)BDY(r))->sig = spsig[i];
10940: } else
10941: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
1.28 noro 10942: GCFREE(spmat[i]);
10943: }
10944: if ( r0 ) NEXT(r) = 0;
10945: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
10946: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
10947: if ( DP_Print ) {
10948: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
10949: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
10950: nsp,nred,sprow,col,rank);
10951: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
10952: }
10953: return r0;
10954: }
1.40 ! noro 10955: #endif
1.28 noro 10956:
10957: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
10958: {
10959: IndArray *imat;
10960: int nsp,nred,i,start;
10961: int *rhead;
10962: NODE r0,rp;
10963: ND_pairs sp;
10964: NM_ind_pair *rvect;
10965: UINT *s;
10966: int *s0hash;
10967: struct oEGT eg0,eg1,eg_conv;
10968:
10969: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
10970: nred = length(rp0);
10971: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
10972: rhead = (int *)MALLOC(col*sizeof(int));
10973: for ( i = 0; i < col; i++ ) rhead[i] = 0;
10974:
10975: /* construction of index arrays */
10976: get_eg(&eg0);
10977: if ( DP_Print ) {
10978: fprintf(asir_out,"%dx%d,",nsp+nred,col);
10979: fflush(asir_out);
10980: }
10981: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
10982: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
10983: rvect[i] = (NM_ind_pair)BDY(rp);
10984: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
10985: rhead[imat[i]->head] = 1;
10986: start = imat[i]->head;
10987: }
10988: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
10989: if ( DP_Print ) {
10990: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
10991: fflush(asir_out);
10992: }
10993: if ( m > 0 )
1.40 ! noro 10994: #if SIZEOF_LONG==8
1.28 noro 10995: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
1.40 ! noro 10996: #else
! 10997: r0 = nd_f4_red_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
! 10998: #endif
1.28 noro 10999: else
11000: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
11001: error("nd_f4_red_q_main_s : not implemented yet");
11002: return r0;
11003: }
11004:
11005: INLINE int ndl_find_reducer_minsig(UINT *dg)
11006: {
11007: RHist r;
11008: int i,singular,ret,d,k,imin;
11009: SIG t;
11010: static int wpd,nvar;
11011: static SIG quo,quomin;
11012: static UINT *tmp;
11013:
11014: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
11015: if ( wpd != nd_wpd ) {
11016: wpd = nd_wpd;
11017: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
11018: }
11019: #if 0
11020: d = ndl_hash_value(dg);
11021: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
11022: if ( ndl_equal(dg,DL(r)) ) {
11023: return r->index;
11024: }
11025: }
11026: #endif
11027: imin = -1;
11028: for ( i = 0; i < nd_psn; i++ ) {
11029: r = nd_psh[i];
11030: if ( ndl_reducible(dg,DL(r)) ) {
11031: ndl_sub(dg,DL(r),tmp);
11032: _ndltodl(tmp,DL(quo));
11033: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
11034: quo->pos = nd_psh[i]->sig->pos;
11035: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
11036: t = quo; quo = quomin; quomin = t;
11037: imin = i;
11038: }
11039: }
11040: }
11041: if ( imin == -1 ) return nd_psn;
11042: else {
11043: #if 0
11044: nd_append_red(dg,i);
11045: #endif
11046: return imin;
11047: }
11048: }
11049:
11050: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
11051: {
11052: NODE rp0,rp;
11053: NM mul,head,s0,s;
11054: int index,col,i,sugar;
11055: RHist h;
11056: UINT *s0v,*p;
11057: NM_ind_pair pair;
11058: ND red;
11059: NDV *ps;
11060: SIG sig;
11061:
11062: s0 = 0; rp0 = 0; col = 0;
11063: if ( nd_demand )
11064: ps = trace?nd_ps_trace_sym:nd_ps_sym;
11065: else
11066: ps = trace?nd_ps_trace:nd_ps;
11067: while ( 1 ) {
11068: head = remove_head_pbucket_symbolic(bucket);
11069: if ( !head ) break;
11070: if ( !s0 ) s0 = head;
11071: else NEXT(s) = head;
11072: s = head;
11073: index = ndl_find_reducer_minsig(DL(head));
11074: if ( index >= 0 && index < nd_psn ) {
11075: h = nd_psh[index];
11076: NEWNM(mul);
11077: ndl_sub(DL(head),DL(h),DL(mul));
11078: if ( ndl_check_bound2(index,DL(mul)) )
11079: return 0;
11080: sugar = TD(DL(mul))+SG(ps[index]);
11081: NEWSIG(sig);
11082: _ndltodl(DL(mul),DL(sig));
11083: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
11084: sig->pos = nd_psh[index]->sig->pos;
11085: MKNM_ind_pair(pair,mul,index,sugar,sig);
11086: red = ndv_mul_nm_symbolic(mul,ps[index]);
11087: add_pbucket_symbolic(bucket,nd_remove_head(red));
11088: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
11089: }
11090: col++;
11091: }
11092: if ( rp0 ) NEXT(rp) = 0;
11093: NEXT(s) = 0;
11094: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
11095: for ( i = 0, p = s0v, s = s0; i < col;
11096: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
11097: *s0vect = s0v;
11098: *r = rp0;
11099:
11100: return col;
11101: }
11102:
11103: NODE nd_sba_f4(int m,int **indp)
11104: {
1.34 noro 11105: int i,nh,stat,index,f4red,f4step;
1.33 noro 11106: int col,rank,len,k,j,a,sugar,nbase,psugar,ms;
11107: NODE r,g,rp0,nflist;
11108: ND_pairs d,l,t;
11109: ND h,nf;
11110: NDV nfv;
11111: union oNDC hc;
11112: UINT *s0vect;
1.28 noro 11113: UINT c;
11114: PGeoBucket bucket;
1.33 noro 11115: NODE *syzlist;
11116: SIG sig;
1.28 noro 11117: struct oEGT eg0,eg1,eg_f4;
1.33 noro 11118: struct oEGT eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.28 noro 11119:
11120: Nf4_red=0;
1.30 noro 11121: d = 0;
1.29 noro 11122: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.28 noro 11123: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 11124: d = update_pairs_s(d,i,syzlist);
1.28 noro 11125: }
1.30 noro 11126: nd_nbase = nd_psn;
1.28 noro 11127: f4red = 1;
1.33 noro 11128: psugar = 0;
1.34 noro 11129: f4step = 0;
1.28 noro 11130: while ( d ) {
1.33 noro 11131: for ( t = d, ms = SG(d); t; t = NEXT(t) )
11132: if ( SG(t) < ms ) ms = SG(t);
1.38 noro 11133: if ( ms == psugar && f4step >= nd_sba_f4step ) {
1.33 noro 11134: again:
11135: l = d; d = d->next;
11136: if ( small_lcm(l) ) {
11137: if ( DP_Print ) fprintf(asir_out,"M");
11138: continue;
11139: }
11140: sig = l->sig;
11141: stat = nd_sp(m,0,l,&h);
11142: if ( !stat ) {
11143: NEXT(l) = d; d = l;
11144: d = nd_reconstruct(0,d);
11145: goto again;
11146: }
11147: get_eg(&eg1);
11148: #if USE_GEOBUCKET
1.39 noro 11149: 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 11150: #else
1.39 noro 11151: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 11152: #endif
11153: get_eg(&eg2);
11154: if ( !stat ) {
11155: NEXT(l) = d; d = l;
11156: d = nd_reconstruct(0,d);
11157: goto again;
11158: } else if ( stat == -1 ) {
11159: if ( DP_Print ) { printf("S"); fflush(stdout); }
11160: FREENDP(l);
11161: } else if ( nf ) {
11162: if ( DP_Print ) { printf("+"); fflush(stdout); }
11163: add_eg(&eg_nf,&eg1,&eg2);
11164: hc = HCU(nf);
11165: nd_removecont(m,nf);
11166: nfv = ndtondv(m,nf); nd_free(nf);
11167: nh = ndv_newps(m,nfv,0);
11168:
1.30 noro 11169: d = update_pairs_s(d,nh,syzlist);
11170: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.33 noro 11171: FREENDP(l);
1.28 noro 11172: } else {
1.33 noro 11173: add_eg(&eg_nfzero,&eg1,&eg2);
11174: // syzygy
11175: get_eg(&eg1);
11176: d = remove_spair_s(d,sig);
11177: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 11178: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.33 noro 11179: if ( DP_Print ) { printf("."); fflush(stdout); }
11180: FREENDP(l);
11181: }
11182: } else {
1.34 noro 11183: if ( ms != psugar ) f4step = 1;
11184: else f4step++;
1.33 noro 11185: again2:
11186: psugar = ms;
11187: l = nd_minsugarp_s(d,&d);
11188: sugar = nd_sugarweight?d->sugar2:SG(d);
11189: bucket = create_pbucket();
11190: stat = nd_sp_f4(m,0,l,bucket);
11191: if ( !stat ) {
11192: for ( t = l; NEXT(t); t = NEXT(t) );
11193: NEXT(t) = d; d = l;
11194: d = nd_reconstruct(0,d);
11195: goto again2;
11196: }
11197: if ( bucket->m < 0 ) continue;
11198: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
11199: if ( !col ) {
1.37 noro 11200: for ( t = l; NEXT(t); t = NEXT(t) )
11201: ;
11202: NEXT(t) = d; d = l;
1.33 noro 11203: d = nd_reconstruct(0,d);
11204: goto again2;
11205: }
1.34 noro 11206: if ( DP_Print ) fprintf(asir_out,"\nsugar=%d,",psugar);
1.33 noro 11207: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,syzlist);
11208: /* adding new bases */
11209: for ( r = nflist; r; r = NEXT(r) ) {
11210: nfv = (NDV)BDY(r);
1.38 noro 11211: if ( nd_f4_td ) SG(nfv) = nd_tdeg(nfv);
1.33 noro 11212: ndv_removecont(m,nfv);
11213: nh = ndv_newps(m,nfv,0);
11214: d = update_pairs_s(d,nh,syzlist);
11215: nd_sba_pos[nfv->sig->pos] = append_one(nd_sba_pos[nfv->sig->pos],nh);
11216: }
11217: for ( i = 0; i < nd_nbase; i++ )
11218: for ( r = syzlist[i]; r; r = NEXT(r) )
11219: d = remove_spair_s(d,(SIG)BDY(r));
11220: d = remove_large_lcm(d);
11221: if ( DP_Print ) {
1.34 noro 11222: fprintf(asir_out,"f4red=%d,gblen=%d",f4red,nd_psn); fflush(asir_out);
1.33 noro 11223: }
11224: f4red++;
1.28 noro 11225: }
11226: }
11227: if ( DP_Print ) {
1.34 noro 11228: fprintf(asir_out,"\nnumber of red=%d,",Nf4_red);
1.28 noro 11229: }
1.30 noro 11230: g = conv_ilist_s(nd_demand,0,indp);
1.28 noro 11231: return g;
11232: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>