Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.44
1.44 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.43 2020/12/05 03:27:20 noro Exp $ */
1.1 noro 2:
3: #include "nd.h"
4:
1.41 noro 5: int Nnd_add,Nf4_red,NcriB,NcriMF,Ncri2,Npairs;
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;
1.41 noro 68: static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect,nd_lf,nd_norb;
69: static int nd_f4_td,nd_sba_f4step,nd_sba_pot,nd_sba_largelcm,nd_sba_dontsort,nd_sba_redundant_check;
1.44 ! noro 70: static int nd_top,nd_sba_syz;
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);
1.43 noro 101: NDV dptondv(int mod,DP p);
1.16 noro 102: NDV dpmtondv(int mod,DPM p);
1.43 noro 103: int dp_getdeg(DP p);
1.16 noro 104: int dpm_getdeg(DPM p,int *rank);
105: void dpm_ptozp(DPM p,Z *cont,DPM *r);
106: int compdmm(int nv,DMM a,DMM b);
1.44 ! noro 107: DPM sigtodpm(SIG s);
! 108: SIG dup_sig(SIG sig);
1.1 noro 109:
110: void Pdp_set_weight(NODE,VECT *);
111: void Pox_cmo_rpc(NODE,Obj *);
112:
113: ND nd_add_lf(ND p1,ND p2);
114: void nd_mul_c_lf(ND p,Z mul);
115: void ndv_mul_c_lf(NDV p,Z mul);
116: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
117: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
118: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
119: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
120: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
121: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred);
122: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat);
1.40 noro 123: 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 124: NODE nd_f4_lf_trace_main(int m,int **indp);
125: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp);
126:
127: extern int lf_lazy;
128: extern Z current_mod_lf;
129:
130: extern int Denominator,DP_Multiple,MaxDeg;
131:
132: #define BLEN (8*sizeof(unsigned long))
133:
134: typedef struct matrix {
135: int row,col;
136: unsigned long **a;
137: } *matrix;
138:
139:
140: void nd_free_private_storage()
141: {
142: _nm_free_list = 0;
143: _ndp_free_list = 0;
144: #if 0
145: GC_gcollect();
146: #endif
147: }
148:
149: void _NM_alloc()
150: {
151: NM p;
152: int i;
153:
154: for ( i = 0; i < 1024; i++ ) {
155: p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
156: p->next = _nm_free_list; _nm_free_list = p;
157: }
158: }
159:
160: matrix alloc_matrix(int row,int col)
161: {
162: unsigned long **a;
163: int i,len,blen;
164: matrix mat;
165:
166: mat = (matrix)MALLOC(sizeof(struct matrix));
167: mat->row = row;
168: mat->col = col;
169: mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *));
170: return mat;
171: }
172:
173:
174: void _ND_alloc()
175: {
176: ND p;
177: int i;
178:
179: for ( i = 0; i < 1024; i++ ) {
180: p = (ND)MALLOC(sizeof(struct oND));
181: p->body = (NM)_nd_free_list; _nd_free_list = p;
182: }
183: }
184:
185: void _NDP_alloc()
186: {
187: ND_pairs p;
188: int i;
189:
190: for ( i = 0; i < 1024; i++ ) {
191: p = (ND_pairs)MALLOC(sizeof(struct oND_pairs)
192: +(nd_wpd-1)*sizeof(UINT));
193: p->next = _ndp_free_list; _ndp_free_list = p;
194: }
195: }
196:
197: INLINE int nd_length(ND p)
198: {
199: NM m;
200: int i;
201:
202: if ( !p )
203: return 0;
204: else {
205: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
206: return i;
207: }
208: }
209:
210: extern int dp_negative_weight;
211:
212: INLINE int ndl_reducible(UINT *d1,UINT *d2)
213: {
214: UINT u1,u2;
215: int i,j;
216:
217: if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
218:
219: if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0;
220: #if USE_UNROLL
221: switch ( nd_bpe ) {
222: case 3:
223: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
224: u1 = d1[i]; u2 = d2[i];
225: if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
226: if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
227: if ( (u1& 0xe00000) < (u2& 0xe00000) ) return 0;
228: if ( (u1& 0x1c0000) < (u2& 0x1c0000) ) return 0;
229: if ( (u1& 0x38000) < (u2& 0x38000) ) return 0;
230: if ( (u1& 0x7000) < (u2& 0x7000) ) return 0;
231: if ( (u1& 0xe00) < (u2& 0xe00) ) return 0;
232: if ( (u1& 0x1c0) < (u2& 0x1c0) ) return 0;
233: if ( (u1& 0x38) < (u2& 0x38) ) return 0;
234: if ( (u1& 0x7) < (u2& 0x7) ) return 0;
235: }
236: return 1;
237: break;
238: case 4:
239: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
240: u1 = d1[i]; u2 = d2[i];
241: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
242: if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
243: if ( (u1& 0xf00000) < (u2& 0xf00000) ) return 0;
244: if ( (u1& 0xf0000) < (u2& 0xf0000) ) return 0;
245: if ( (u1& 0xf000) < (u2& 0xf000) ) return 0;
246: if ( (u1& 0xf00) < (u2& 0xf00) ) return 0;
247: if ( (u1& 0xf0) < (u2& 0xf0) ) return 0;
248: if ( (u1& 0xf) < (u2& 0xf) ) return 0;
249: }
250: return 1;
251: break;
252: case 6:
253: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
254: u1 = d1[i]; u2 = d2[i];
255: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
256: if ( (u1& 0xfc0000) < (u2& 0xfc0000) ) return 0;
257: if ( (u1& 0x3f000) < (u2& 0x3f000) ) return 0;
258: if ( (u1& 0xfc0) < (u2& 0xfc0) ) return 0;
259: if ( (u1& 0x3f) < (u2& 0x3f) ) return 0;
260: }
261: return 1;
262: break;
263: case 8:
264: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
265: u1 = d1[i]; u2 = d2[i];
266: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
267: if ( (u1& 0xff0000) < (u2& 0xff0000) ) return 0;
268: if ( (u1& 0xff00) < (u2& 0xff00) ) return 0;
269: if ( (u1& 0xff) < (u2& 0xff) ) return 0;
270: }
271: return 1;
272: break;
273: case 16:
274: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
275: u1 = d1[i]; u2 = d2[i];
276: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
277: if ( (u1& 0xffff) < (u2& 0xffff) ) return 0;
278: }
279: return 1;
280: break;
281: case 32:
282: for ( i = nd_exporigin; i < nd_wpd; i++ )
283: if ( d1[i] < d2[i] ) return 0;
284: return 1;
285: break;
286: default:
287: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
288: u1 = d1[i]; u2 = d2[i];
289: for ( j = 0; j < nd_epw; j++ )
290: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
291: }
292: return 1;
293: }
294: #else
295: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
296: u1 = d1[i]; u2 = d2[i];
297: for ( j = 0; j < nd_epw; j++ )
298: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
299: }
300: return 1;
301: #endif
302: }
303:
304: /*
305: * If the current order is a block order,
306: * then the last block is length 1 and contains
307: * the homo variable. Otherwise, the original
308: * order is either 0 or 2.
309: */
310:
311: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int ompos,int weight)
312: {
313: int w,i,e,n,omask0;
314:
315: omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
316: n = nd_nvar-1;
317: ndl_zero(r);
318: for ( i = 0; i < n; i++ ) {
319: e = GET_EXP_OLD(d,i);
320: PUT_EXP(r,i,e);
321: }
322: w = TD(d);
323: PUT_EXP(r,nd_nvar-1,weight-w);
324: if ( nd_module ) MPOS(r) = d[ompos];
325: TD(r) = weight;
326: if ( nd_blockmask ) ndl_weight_mask(r);
327: }
328:
329: void ndl_dehomogenize(UINT *d)
330: {
331: UINT mask;
332: UINT h;
333: int i,bits;
334:
335: if ( nd_blockmask ) {
336: h = GET_EXP(d,nd_nvar-1);
337: XOR_EXP(d,nd_nvar-1,h);
338: TD(d) -= h;
339: ndl_weight_mask(d);
340: } else {
341: if ( nd_isrlex ) {
342: if ( nd_bpe == 32 ) {
343: h = d[nd_exporigin];
344: for ( i = nd_exporigin+1; i < nd_wpd; i++ )
345: d[i-1] = d[i];
346: d[i-1] = 0;
347: TD(d) -= h;
348: } else {
349: bits = nd_epw*nd_bpe;
350: mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
351: h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
352: for ( i = nd_exporigin; i < nd_wpd; i++ )
353: d[i] = ((d[i]<<nd_bpe)&mask)
354: |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
355: TD(d) -= h;
356: }
357: } else {
358: h = GET_EXP(d,nd_nvar-1);
359: XOR_EXP(d,nd_nvar-1,h);
360: TD(d) -= h;
361: }
362: }
363: }
364:
365: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
366: {
367: UINT t1,t2,u,u1,u2;
368: int i,j,l;
369:
370: if ( nd_module && (MPOS(d1) != MPOS(d2)) )
371: error("ndl_lcm : inconsistent monomials");
372: #if USE_UNROLL
373: switch ( nd_bpe ) {
374: case 3:
375: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
376: u1 = d1[i]; u2 = d2[i];
377: t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
378: t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
379: t1 = (u1& 0xe00000); t2 = (u2& 0xe00000); u |= t1>t2?t1:t2;
380: t1 = (u1& 0x1c0000); t2 = (u2& 0x1c0000); u |= t1>t2?t1:t2;
381: t1 = (u1& 0x38000); t2 = (u2& 0x38000); u |= t1>t2?t1:t2;
382: t1 = (u1& 0x7000); t2 = (u2& 0x7000); u |= t1>t2?t1:t2;
383: t1 = (u1& 0xe00); t2 = (u2& 0xe00); u |= t1>t2?t1:t2;
384: t1 = (u1& 0x1c0); t2 = (u2& 0x1c0); u |= t1>t2?t1:t2;
385: t1 = (u1& 0x38); t2 = (u2& 0x38); u |= t1>t2?t1:t2;
386: t1 = (u1& 0x7); t2 = (u2& 0x7); u |= t1>t2?t1:t2;
387: d[i] = u;
388: }
389: break;
390: case 4:
391: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
392: u1 = d1[i]; u2 = d2[i];
393: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
394: t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
395: t1 = (u1& 0xf00000); t2 = (u2& 0xf00000); u |= t1>t2?t1:t2;
396: t1 = (u1& 0xf0000); t2 = (u2& 0xf0000); u |= t1>t2?t1:t2;
397: t1 = (u1& 0xf000); t2 = (u2& 0xf000); u |= t1>t2?t1:t2;
398: t1 = (u1& 0xf00); t2 = (u2& 0xf00); u |= t1>t2?t1:t2;
399: t1 = (u1& 0xf0); t2 = (u2& 0xf0); u |= t1>t2?t1:t2;
400: t1 = (u1& 0xf); t2 = (u2& 0xf); u |= t1>t2?t1:t2;
401: d[i] = u;
402: }
403: break;
404: case 6:
405: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
406: u1 = d1[i]; u2 = d2[i];
407: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
408: t1 = (u1& 0xfc0000); t2 = (u2& 0xfc0000); u |= t1>t2?t1:t2;
409: t1 = (u1& 0x3f000); t2 = (u2& 0x3f000); u |= t1>t2?t1:t2;
410: t1 = (u1& 0xfc0); t2 = (u2& 0xfc0); u |= t1>t2?t1:t2;
411: t1 = (u1& 0x3f); t2 = (u2& 0x3f); u |= t1>t2?t1:t2;
412: d[i] = u;
413: }
414: break;
415: case 8:
416: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
417: u1 = d1[i]; u2 = d2[i];
418: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
419: t1 = (u1& 0xff0000); t2 = (u2& 0xff0000); u |= t1>t2?t1:t2;
420: t1 = (u1& 0xff00); t2 = (u2& 0xff00); u |= t1>t2?t1:t2;
421: t1 = (u1& 0xff); t2 = (u2& 0xff); u |= t1>t2?t1:t2;
422: d[i] = u;
423: }
424: break;
425: case 16:
426: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
427: u1 = d1[i]; u2 = d2[i];
428: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
429: t1 = (u1& 0xffff); t2 = (u2& 0xffff); u |= t1>t2?t1:t2;
430: d[i] = u;
431: }
432: break;
433: case 32:
434: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
435: u1 = d1[i]; u2 = d2[i];
436: d[i] = u1>u2?u1:u2;
437: }
438: break;
439: default:
440: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
441: u1 = d1[i]; u2 = d2[i];
442: for ( j = 0, u = 0; j < nd_epw; j++ ) {
443: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
444: }
445: d[i] = u;
446: }
447: break;
448: }
449: #else
450: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
451: u1 = d1[i]; u2 = d2[i];
452: for ( j = 0, u = 0; j < nd_epw; j++ ) {
453: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
454: }
455: d[i] = u;
456: }
457: #endif
458: if ( nd_module ) MPOS(d) = MPOS(d1);
459: TD(d) = ndl_weight(d);
460: if ( nd_blockmask ) ndl_weight_mask(d);
461: }
462:
463: void ndl_max(UINT *d1,unsigned *d2,UINT *d)
464: {
465: UINT t1,t2,u,u1,u2;
466: int i,j,l;
467:
468: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
469: u1 = d1[i]; u2 = d2[i];
470: for ( j = 0, u = 0; j < nd_epw; j++ ) {
471: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
472: }
473: d[i] = u;
474: }
475: }
476:
477: int ndl_weight(UINT *d)
478: {
479: UINT t,u;
480: int i,j;
481:
482: if ( current_dl_weight_vector )
483: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
484: u = GET_EXP(d,i);
485: t += MUL_WEIGHT(u,i);
486: }
487: else
488: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
489: u = d[i];
490: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
491: t += (u&nd_mask0);
492: }
1.20 noro 493: if ( nd_module && nd_module_rank && MPOS(d) )
494: t += nd_module_weight[MPOS(d)-1];
495: for ( i = nd_exporigin; i < nd_wpd; i++ )
496: if ( d[i] && !t )
497: printf("afo\n");
1.1 noro 498: return t;
499: }
500:
501: /* for sugarweight */
502:
503: int ndl_weight2(UINT *d)
504: {
505: int t,u;
506: int i,j;
507:
508: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
509: u = GET_EXP(d,i);
510: t += nd_sugarweight[i]*u;
511: }
1.20 noro 512: if ( nd_module && nd_module_rank && MPOS(d) )
513: t += nd_module_weight[MPOS(d)-1];
1.1 noro 514: return t;
515: }
516:
517: void ndl_weight_mask(UINT *d)
518: {
519: UINT t,u;
520: UINT *mask;
521: int i,j,k,l;
522:
523: l = nd_blockmask->n;
524: for ( k = 0; k < l; k++ ) {
525: mask = nd_blockmask->mask[k];
526: if ( current_dl_weight_vector )
527: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
528: u = GET_EXP_MASK(d,i,mask);
529: t += MUL_WEIGHT(u,i);
530: }
531: else
532: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
533: u = d[i]&mask[i];
534: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
535: t += (u&nd_mask0);
536: }
537: d[k+1] = t;
538: }
539: }
540:
1.21 noro 541: int ndl_glex_compare(UINT *d1,UINT *d2)
542: {
543: if ( TD(d1) > TD(d2) ) return 1;
544: else if ( TD(d1) < TD(d2) ) return -1;
545: else return ndl_lex_compare(d1,d2);
546: }
547:
1.1 noro 548: int ndl_lex_compare(UINT *d1,UINT *d2)
549: {
550: int i;
551:
552: d1 += nd_exporigin;
553: d2 += nd_exporigin;
554: for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
555: if ( *d1 > *d2 )
556: return nd_isrlex ? -1 : 1;
557: else if ( *d1 < *d2 )
558: return nd_isrlex ? 1 : -1;
559: return 0;
560: }
561:
562: int ndl_block_compare(UINT *d1,UINT *d2)
563: {
564: int i,l,j,ord_o,ord_l;
565: struct order_pair *op;
566: UINT t1,t2,m;
567: UINT *mask;
568:
569: l = nd_blockmask->n;
570: op = nd_blockmask->order_pair;
571: for ( j = 0; j < l; j++ ) {
572: mask = nd_blockmask->mask[j];
573: ord_o = op[j].order;
574: if ( ord_o < 2 ) {
575: if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
576: else if ( t1 < t2 ) return -1;
577: }
578: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
579: m = mask[i];
580: t1 = d1[i]&m;
581: t2 = d2[i]&m;
582: if ( t1 > t2 )
583: return !ord_o ? -1 : 1;
584: else if ( t1 < t2 )
585: return !ord_o ? 1 : -1;
586: }
587: }
588: return 0;
589: }
590:
591: int ndl_matrix_compare(UINT *d1,UINT *d2)
592: {
593: int i,j,s,row;
594: int *v;
595: Z **mat;
596: Z *w;
597: Z t1;
598: Z t,t2;
599:
1.6 noro 600: for ( j = 0; j < nd_nvar; j++ )
601: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
1.1 noro 602: if ( nd_top_weight ) {
603: if ( OID(nd_top_weight) == O_VECT ) {
1.6 noro 604: mat = (Z **)&BDY((VECT)nd_top_weight);
605: row = 1;
1.1 noro 606: } else {
607: mat = (Z **)BDY((MAT)nd_top_weight);
1.6 noro 608: row = ((MAT)nd_top_weight)->row;
1.1 noro 609: }
610: for ( i = 0; i < row; i++ ) {
1.6 noro 611: w = mat[i];
1.1 noro 612: for ( j = 0, t = 0; j < nd_nvar; j++ ) {
1.6 noro 613: STOZ(nd_work_vector[j],t1);
1.1 noro 614: mulz(w[j],t1,&t2);
615: addz(t,t2,&t1);
616: t = t1;
617: }
1.6 noro 618: if ( t ) {
619: s = sgnz(t);
1.1 noro 620: if ( s > 0 ) return 1;
621: else if ( s < 0 ) return -1;
1.6 noro 622: }
1.1 noro 623: }
1.6 noro 624: }
625: for ( i = 0; i < nd_matrix_len; i++ ) {
626: v = nd_matrix[i];
627: for ( j = 0, s = 0; j < nd_nvar; j++ )
628: s += v[j]*nd_work_vector[j];
629: if ( s > 0 ) return 1;
630: else if ( s < 0 ) return -1;
631: }
1.1 noro 632: if ( !ndl_equal(d1,d2) )
1.6 noro 633: error("ndl_matrix_compare : invalid matrix");
634: return 0;
1.1 noro 635: }
636:
637: int ndl_composite_compare(UINT *d1,UINT *d2)
638: {
639: int i,j,s,start,end,len,o;
640: int *v;
641: struct sparse_weight *sw;
642:
643: for ( j = 0; j < nd_nvar; j++ )
644: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
645: for ( i = 0; i < nd_worb_len; i++ ) {
646: len = nd_worb[i].length;
647: switch ( nd_worb[i].type ) {
648: case IS_DENSE_WEIGHT:
649: v = nd_worb[i].body.dense_weight;
650: for ( j = 0, s = 0; j < len; j++ )
651: s += v[j]*nd_work_vector[j];
652: if ( s > 0 ) return 1;
653: else if ( s < 0 ) return -1;
654: break;
655: case IS_SPARSE_WEIGHT:
656: sw = nd_worb[i].body.sparse_weight;
657: for ( j = 0, s = 0; j < len; j++ )
658: s += sw[j].value*nd_work_vector[sw[j].pos];
659: if ( s > 0 ) return 1;
660: else if ( s < 0 ) return -1;
661: break;
662: case IS_BLOCK:
663: o = nd_worb[i].body.block.order;
664: start = nd_worb[i].body.block.start;
665: switch ( o ) {
666: case 0:
667: end = start+len;
668: for ( j = start, s = 0; j < end; j++ )
669: s += MUL_WEIGHT(nd_work_vector[j],j);
670: if ( s > 0 ) return 1;
671: else if ( s < 0 ) return -1;
672: for ( j = end-1; j >= start; j-- )
673: if ( nd_work_vector[j] < 0 ) return 1;
674: else if ( nd_work_vector[j] > 0 ) return -1;
675: break;
676: case 1:
677: end = start+len;
678: for ( j = start, s = 0; j < end; j++ )
679: s += MUL_WEIGHT(nd_work_vector[j],j);
680: if ( s > 0 ) return 1;
681: else if ( s < 0 ) return -1;
682: for ( j = start; j < end; j++ )
683: if ( nd_work_vector[j] > 0 ) return 1;
684: else if ( nd_work_vector[j] < 0 ) return -1;
685: break;
686: case 2:
687: end = start+len;
688: for ( j = start; j < end; j++ )
689: if ( nd_work_vector[j] > 0 ) return 1;
690: else if ( nd_work_vector[j] < 0 ) return -1;
691: break;
692: }
693: break;
694: }
695: }
696: return 0;
697: }
698:
699: /* TDH -> WW -> TD-> RL */
700:
701: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
702: {
703: int i,m,e1,e2;
704:
705: if ( TD(d1) > TD(d2) ) return 1;
706: else if ( TD(d1) < TD(d2) ) return -1;
707: m = nd_nvar>>1;
708: for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
709: e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
710: e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
711: }
712: if ( e1 > e2 ) return 1;
713: else if ( e1 < e2 ) return -1;
714: return ndl_lex_compare(d1,d2);
715: }
716:
1.21 noro 717: // common function for module glex and grlex comparison
718: int ndl_module_glex_compare(UINT *d1,UINT *d2)
1.1 noro 719: {
1.21 noro 720: int c;
1.1 noro 721:
1.21 noro 722: switch ( nd_module_ordtype ) {
723: case 0:
724: if ( TD(d1) > TD(d2) ) return 1;
725: else if ( TD(d1) < TD(d2) ) return -1;
726: else if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
727: else if ( MPOS(d1) < MPOS(d2) ) return 1;
728: else if ( MPOS(d1) > MPOS(d2) ) return -1;
729: else return 0;
730: break;
1.1 noro 731:
1.21 noro 732: case 1:
1.19 noro 733: if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) {
734: if ( TD(d1) > TD(d2) ) return 1;
735: else if ( TD(d1) < TD(d2) ) return -1;
736: if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
737: if ( MPOS(d1) < MPOS(d2) ) return 1;
738: else if ( MPOS(d1) > MPOS(d2) ) return -1;
739: }
740: if ( MPOS(d1) < MPOS(d2) ) return 1;
741: else if ( MPOS(d1) > MPOS(d2) ) return -1;
1.21 noro 742: else if ( TD(d1) > TD(d2) ) return 1;
743: else if ( TD(d1) < TD(d2) ) return -1;
744: else return ndl_lex_compare(d1,d2);
745: break;
1.1 noro 746:
1.21 noro 747: case 2: // weight -> POT
748: if ( TD(d1) > TD(d2) ) return 1;
749: else if ( TD(d1) < TD(d2) ) return -1;
750: else if ( MPOS(d1) < MPOS(d2) ) return 1;
751: else if ( MPOS(d1) > MPOS(d2) ) return -1;
752: else return ndl_lex_compare(d1,d2);
753: break;
1.1 noro 754:
1.21 noro 755: default:
756: error("ndl_module_glex_compare : invalid module_ordtype");
1.28 noro 757: return 0;
1.21 noro 758: }
1.1 noro 759: }
760:
1.21 noro 761: // common for module comparison
762: int ndl_module_compare(UINT *d1,UINT *d2)
1.1 noro 763: {
1.21 noro 764: int c;
1.1 noro 765:
1.21 noro 766: switch ( nd_module_ordtype ) {
767: case 0:
1.23 noro 768: if ( (c = (*ndl_base_compare_function)(d1,d2)) != 0 ) return c;
1.21 noro 769: else if ( MPOS(d1) > MPOS(d2) ) return -1;
770: else if ( MPOS(d1) < MPOS(d2) ) return 1;
771: else return 0;
772: break;
1.1 noro 773:
1.21 noro 774: case 1:
775: if ( MPOS(d1) < MPOS(d2) ) return 1;
776: else if ( MPOS(d1) > MPOS(d2) ) return -1;
777: else return (*ndl_base_compare_function)(d1,d2);
778: break;
1.1 noro 779:
1.21 noro 780: case 2: // weight -> POT
781: if ( TD(d1) > TD(d2) ) return 1;
782: else if ( TD(d1) < TD(d2) ) return -1;
783: else if ( MPOS(d1) < MPOS(d2) ) return 1;
784: else if ( MPOS(d1) > MPOS(d2) ) return -1;
785: else return (*ndl_base_compare_function)(d1,d2);
786: break;
1.1 noro 787:
1.21 noro 788: default:
789: error("ndl_module_compare : invalid module_ordtype");
1.28 noro 790: return 0;
1.21 noro 791: }
1.1 noro 792: }
793:
1.21 noro 794: extern DMMstack dmm_stack;
795: void _addtodl(int n,DL d1,DL d2);
1.31 noro 796: void _adddl(int n,DL d1,DL d2,DL d3);
1.21 noro 797: int _eqdl(int n,DL d1,DL d2);
798:
799: int ndl_module_schreyer_compare(UINT *m1,UINT *m2)
800: {
1.44 ! noro 801: int pos1,pos2,t,j,retpot;
1.21 noro 802: DMM *in;
803: DMMstack s;
804: static DL d1=0;
805: static DL d2=0;
806: static int dlen=0;
1.44 ! noro 807: extern int ReversePOT;
1.21 noro 808:
1.44 ! noro 809: if ( ReversePOT ) retpot = -1;
! 810: else retpot = 1;
1.21 noro 811: pos1 = MPOS(m1); pos2 = MPOS(m2);
812: if ( pos1 == pos2 ) return (*ndl_base_compare_function)(m1,m2);
813: if ( nd_nvar > dlen ) {
814: NEWDL(d1,nd_nvar);
815: NEWDL(d2,nd_nvar);
816: dlen = nd_nvar;
817: }
818: d1->td = TD(m1);
819: for ( j = 0; j < nd_nvar; j++ ) d1->d[j] = GET_EXP(m1,j);
820: d2->td = TD(m2);
821: for ( j = 0; j < nd_nvar; j++ ) d2->d[j] = GET_EXP(m2,j);
822: for ( s = dmm_stack; s; s = NEXT(s) ) {
823: in = s->in;
824: _addtodl(nd_nvar,in[pos1]->dl,d1);
825: _addtodl(nd_nvar,in[pos2]->dl,d2);
826: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(nd_nvar,d1,d2)) {
1.44 ! noro 827: if ( pos1 < pos2 ) return retpot;
! 828: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 829: else return 0;
830: }
831: pos1 = in[pos1]->pos;
832: pos2 = in[pos2]->pos;
833: if ( pos1 == pos2 ) return (*dl_base_compare_function)(nd_nvar,d1,d2);
834: }
835: // comparison by the bottom order
836: LAST:
837: switch ( nd_base_ordtype ) {
838: case 0:
839: t = (*dl_base_compare_function)(nd_nvar,d1,d2);
840: if ( t ) return t;
1.44 ! noro 841: else if ( pos1 < pos2 ) return retpot;
! 842: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 843: else return 0;
844: break;
845: case 1:
1.44 ! noro 846: if ( pos1 < pos2 ) return retpot;
! 847: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 848: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
849: break;
850: case 2:
851: if ( d1->td > d2->td ) return 1;
852: else if ( d1->td < d2->td ) return -1;
1.44 ! noro 853: else if ( pos1 < pos2 ) return retpot;
! 854: else if ( pos1 > pos2 ) return -retpot;
1.21 noro 855: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
856: break;
857: default:
858: error("ndl_schreyer_compare : invalid base ordtype");
1.28 noro 859: return 0;
1.21 noro 860: }
1.1 noro 861: }
862:
863: INLINE int ndl_equal(UINT *d1,UINT *d2)
864: {
865: int i;
866:
867: switch ( nd_wpd ) {
868: case 2:
869: if ( TD(d2) != TD(d1) ) return 0;
870: if ( d2[1] != d1[1] ) return 0;
871: return 1;
872: break;
873: case 3:
874: if ( TD(d2) != TD(d1) ) return 0;
875: if ( d2[1] != d1[1] ) return 0;
876: if ( d2[2] != d1[2] ) return 0;
877: return 1;
878: break;
879: default:
880: for ( i = 0; i < nd_wpd; i++ )
881: if ( *d1++ != *d2++ ) return 0;
882: return 1;
883: break;
884: }
885: }
886:
887: INLINE void ndl_copy(UINT *d1,UINT *d2)
888: {
889: int i;
890:
891: switch ( nd_wpd ) {
892: case 2:
893: TD(d2) = TD(d1);
894: d2[1] = d1[1];
895: break;
896: case 3:
897: TD(d2) = TD(d1);
898: d2[1] = d1[1];
899: d2[2] = d1[2];
900: break;
901: default:
902: for ( i = 0; i < nd_wpd; i++ )
903: d2[i] = d1[i];
904: break;
905: }
906: }
907:
908: INLINE void ndl_zero(UINT *d)
909: {
910: int i;
911: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
912: }
913:
914: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
915: {
916: int i;
917:
918: if ( nd_module ) {
919: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
920: error("ndl_add : invalid operation");
921: }
922: #if 1
923: switch ( nd_wpd ) {
924: case 2:
925: TD(d) = TD(d1)+TD(d2);
926: d[1] = d1[1]+d2[1];
927: break;
928: case 3:
929: TD(d) = TD(d1)+TD(d2);
930: d[1] = d1[1]+d2[1];
931: d[2] = d1[2]+d2[2];
932: break;
933: default:
934: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
935: break;
936: }
937: #else
938: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
939: #endif
940: }
941:
942: /* d1 += d2 */
943: INLINE void ndl_addto(UINT *d1,UINT *d2)
944: {
945: int i;
946:
947: if ( nd_module ) {
948: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
949: error("ndl_addto : invalid operation");
950: }
951: #if 1
952: switch ( nd_wpd ) {
953: case 2:
954: TD(d1) += TD(d2);
955: d1[1] += d2[1];
956: break;
957: case 3:
958: TD(d1) += TD(d2);
959: d1[1] += d2[1];
960: d1[2] += d2[2];
961: break;
962: default:
963: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
964: break;
965: }
966: #else
967: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
968: #endif
969: }
970:
971: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
972: {
973: int i;
974:
975: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
976: }
977:
978: int ndl_disjoint(UINT *d1,UINT *d2)
979: {
980: UINT t1,t2,u,u1,u2;
981: int i,j;
982:
983: if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
984: #if USE_UNROLL
985: switch ( nd_bpe ) {
986: case 3:
987: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
988: u1 = d1[i]; u2 = d2[i];
989: t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
990: t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
991: t1 = u1& 0xe00000; t2 = u2& 0xe00000; if ( t1&&t2 ) return 0;
992: t1 = u1& 0x1c0000; t2 = u2& 0x1c0000; if ( t1&&t2 ) return 0;
993: t1 = u1& 0x38000; t2 = u2& 0x38000; if ( t1&&t2 ) return 0;
994: t1 = u1& 0x7000; t2 = u2& 0x7000; if ( t1&&t2 ) return 0;
995: t1 = u1& 0xe00; t2 = u2& 0xe00; if ( t1&&t2 ) return 0;
996: t1 = u1& 0x1c0; t2 = u2& 0x1c0; if ( t1&&t2 ) return 0;
997: t1 = u1& 0x38; t2 = u2& 0x38; if ( t1&&t2 ) return 0;
998: t1 = u1& 0x7; t2 = u2& 0x7; if ( t1&&t2 ) return 0;
999: }
1000: return 1;
1001: break;
1002: case 4:
1003: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1004: u1 = d1[i]; u2 = d2[i];
1005: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
1006: t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
1007: t1 = u1& 0xf00000; t2 = u2& 0xf00000; if ( t1&&t2 ) return 0;
1008: t1 = u1& 0xf0000; t2 = u2& 0xf0000; if ( t1&&t2 ) return 0;
1009: t1 = u1& 0xf000; t2 = u2& 0xf000; if ( t1&&t2 ) return 0;
1010: t1 = u1& 0xf00; t2 = u2& 0xf00; if ( t1&&t2 ) return 0;
1011: t1 = u1& 0xf0; t2 = u2& 0xf0; if ( t1&&t2 ) return 0;
1012: t1 = u1& 0xf; t2 = u2& 0xf; if ( t1&&t2 ) return 0;
1013: }
1014: return 1;
1015: break;
1016: case 6:
1017: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1018: u1 = d1[i]; u2 = d2[i];
1019: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1020: t1 = u1& 0xfc0000; t2 = u2& 0xfc0000; if ( t1&&t2 ) return 0;
1021: t1 = u1& 0x3f000; t2 = u2& 0x3f000; if ( t1&&t2 ) return 0;
1022: t1 = u1& 0xfc0; t2 = u2& 0xfc0; if ( t1&&t2 ) return 0;
1023: t1 = u1& 0x3f; t2 = u2& 0x3f; if ( t1&&t2 ) return 0;
1024: }
1025: return 1;
1026: break;
1027: case 8:
1028: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1029: u1 = d1[i]; u2 = d2[i];
1030: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1031: t1 = u1& 0xff0000; t2 = u2& 0xff0000; if ( t1&&t2 ) return 0;
1032: t1 = u1& 0xff00; t2 = u2& 0xff00; if ( t1&&t2 ) return 0;
1033: t1 = u1& 0xff; t2 = u2& 0xff; if ( t1&&t2 ) return 0;
1034: }
1035: return 1;
1036: break;
1037: case 16:
1038: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1039: u1 = d1[i]; u2 = d2[i];
1040: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1041: t1 = u1& 0xffff; t2 = u2& 0xffff; if ( t1&&t2 ) return 0;
1042: }
1043: return 1;
1044: break;
1045: case 32:
1046: for ( i = nd_exporigin; i < nd_wpd; i++ )
1047: if ( d1[i] && d2[i] ) return 0;
1048: return 1;
1049: break;
1050: default:
1051: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1052: u1 = d1[i]; u2 = d2[i];
1053: for ( j = 0; j < nd_epw; j++ ) {
1054: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1055: u1 >>= nd_bpe; u2 >>= nd_bpe;
1056: }
1057: }
1058: return 1;
1059: break;
1060: }
1061: #else
1062: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1063: u1 = d1[i]; u2 = d2[i];
1064: for ( j = 0; j < nd_epw; j++ ) {
1065: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1066: u1 >>= nd_bpe; u2 >>= nd_bpe;
1067: }
1068: }
1069: return 1;
1070: #endif
1071: }
1072:
1073: int ndl_check_bound(UINT *d1,UINT *d2)
1074: {
1075: UINT u2;
1076: int i,j,ind,k;
1077:
1078: ind = 0;
1079: #if USE_UNROLL
1080: switch ( nd_bpe ) {
1081: case 3:
1082: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1083: u2 = d2[i];
1084: if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
1085: if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
1086: if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
1087: if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
1088: if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
1089: if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
1090: if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
1091: if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
1092: if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
1093: if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
1094: }
1095: return 0;
1096: break;
1097: case 4:
1098: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1099: u2 = d2[i];
1100: if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
1101: if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
1102: if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
1103: if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
1104: if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
1105: if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
1106: if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
1107: if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
1108: }
1109: return 0;
1110: break;
1111: case 6:
1112: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1113: u2 = d2[i];
1114: if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
1115: if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
1116: if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
1117: if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
1118: if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
1119: }
1120: return 0;
1121: break;
1122: case 8:
1123: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1124: u2 = d2[i];
1125: if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
1126: if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
1127: if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
1128: if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
1129: }
1130: return 0;
1131: break;
1132: case 16:
1133: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1134: u2 = d2[i];
1135: if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
1136: if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
1137: }
1138: return 0;
1139: break;
1140: case 32:
1141: for ( i = nd_exporigin; i < nd_wpd; i++ )
1142: if ( d1[i]+d2[i]<d1[i] ) return 1;
1143: return 0;
1144: break;
1145: default:
1146: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1147: u2 = d2[i];
1148: k = (nd_epw-1)*nd_bpe;
1149: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1150: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1151: }
1152: return 0;
1153: break;
1154: }
1155: #else
1156: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1157: u2 = d2[i];
1158: k = (nd_epw-1)*nd_bpe;
1159: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1160: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1161: }
1162: return 0;
1163: #endif
1164: }
1165:
1166: int ndl_check_bound2(int index,UINT *d2)
1167: {
1168: return ndl_check_bound(nd_bound[index],d2);
1169: }
1170:
1171: INLINE int ndl_hash_value(UINT *d)
1172: {
1173: int i;
1.11 noro 1174: UINT r;
1.1 noro 1175:
1176: r = 0;
1177: for ( i = 0; i < nd_wpd; i++ )
1.12 noro 1178: r = (r*1511+d[i]);
1.11 noro 1179: r %= REDTAB_LEN;
1.1 noro 1180: return r;
1181: }
1182:
1183: INLINE int ndl_find_reducer(UINT *dg)
1184: {
1185: RHist r;
1186: int d,k,i;
1187:
1188: d = ndl_hash_value(dg);
1189: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1190: if ( ndl_equal(dg,DL(r)) ) {
1191: if ( k > 0 ) nd_notfirst++;
1192: nd_found++;
1193: return r->index;
1194: }
1195: }
1196: if ( Reverse )
1197: for ( i = nd_psn-1; i >= 0; i-- ) {
1198: r = nd_psh[i];
1199: if ( ndl_reducible(dg,DL(r)) ) {
1200: nd_create++;
1201: nd_append_red(dg,i);
1202: return i;
1203: }
1204: }
1205: else
1206: for ( i = 0; i < nd_psn; i++ ) {
1207: r = nd_psh[i];
1208: if ( ndl_reducible(dg,DL(r)) ) {
1209: nd_create++;
1210: nd_append_red(dg,i);
1211: return i;
1212: }
1213: }
1214: return -1;
1215: }
1216:
1.41 noro 1217: INLINE int ndl_find_reducer_nonsig(UINT *dg)
1218: {
1219: RHist r;
1220: int i;
1221:
1222: for ( i = 0; i < nd_psn; i++ ) {
1223: r = nd_psh[i];
1224: if ( ndl_reducible(dg,DL(r)) ) return i;
1225: }
1226: return -1;
1227: }
1228:
1.24 noro 1229: // ret=0,...,nd_psn-1 => reducer found
1230: // ret=nd_psn => reducer not found
1231: // ret=-1 => singular top reducible
1232:
1233: int comp_sig(SIG s1,SIG s2);
1234: void _ndltodl(UINT *ndl,DL dl);
1235:
1236: void print_sig(SIG s)
1237: {
1238: int i;
1239:
1240: fprintf(asir_out,"<<");
1241: for ( i = 0; i < nd_nvar; i++ ) {
1242: fprintf(asir_out,"%d",s->dl->d[i]);
1243: if ( i != nd_nvar-1 ) fprintf(asir_out,",");
1244: }
1245: fprintf(asir_out,">>*e%d",s->pos);
1246: }
1247:
1.35 noro 1248: // assuming increasing order wrt signature
1249:
1.24 noro 1250: INLINE int ndl_find_reducer_s(UINT *dg,SIG sig)
1251: {
1252: RHist r;
1.27 noro 1253: int i,singular,ret,d,k;
1.26 noro 1254: static int wpd,nvar;
1.24 noro 1255: static SIG quo;
1256: static UINT *tmp;
1257:
1.26 noro 1258: if ( !quo || nvar != nd_nvar ) NEWSIG(quo);
1259: if ( wpd != nd_wpd ) {
1.24 noro 1260: wpd = nd_wpd;
1261: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
1262: }
1.27 noro 1263: d = ndl_hash_value(dg);
1.35 noro 1264: #if 1
1.27 noro 1265: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1266: if ( ndl_equal(dg,DL(r)) ) {
1267: return r->index;
1268: }
1269: }
1.35 noro 1270: #endif
1.24 noro 1271: singular = 0;
1272: for ( i = 0; i < nd_psn; i++ ) {
1273: r = nd_psh[i];
1274: if ( ndl_reducible(dg,DL(r)) ) {
1.27 noro 1275: ndl_sub(dg,DL(r),tmp);
1.24 noro 1276: _ndltodl(tmp,DL(quo));
1277: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
1278: quo->pos = nd_psh[i]->sig->pos;
1279: ret = comp_sig(sig,quo);
1280: if ( ret > 0 ) { singular = 0; break; }
1.38 noro 1281: if ( ret == 0 ) { /* fprintf(asir_out,"s"); fflush(asir_out); */ singular = 1; }
1.24 noro 1282: }
1283: }
1284: if ( singular ) return -1;
1.27 noro 1285: else if ( i < nd_psn )
1286: nd_append_red(dg,i);
1287: return i;
1.24 noro 1288: }
1289:
1.1 noro 1290: ND nd_merge(ND p1,ND p2)
1291: {
1292: int n,c;
1293: int t,can,td1,td2;
1294: ND r;
1295: NM m1,m2,mr0,mr,s;
1296:
1297: if ( !p1 ) return p2;
1298: else if ( !p2 ) return p1;
1299: else {
1300: can = 0;
1301: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1302: c = DL_COMPARE(DL(m1),DL(m2));
1303: switch ( c ) {
1304: case 0:
1305: s = m1; m1 = NEXT(m1);
1306: can++; NEXTNM2(mr0,mr,s);
1307: s = m2; m2 = NEXT(m2); FREENM(s);
1308: break;
1309: case 1:
1310: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1311: break;
1312: case -1:
1313: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1314: break;
1315: }
1316: }
1317: if ( !mr0 )
1318: if ( m1 ) mr0 = m1;
1319: else if ( m2 ) mr0 = m2;
1320: else return 0;
1321: else if ( m1 ) NEXT(mr) = m1;
1322: else if ( m2 ) NEXT(mr) = m2;
1323: else NEXT(mr) = 0;
1324: BDY(p1) = mr0;
1325: SG(p1) = MAX(SG(p1),SG(p2));
1326: LEN(p1) = LEN(p1)+LEN(p2)-can;
1327: FREEND(p2);
1328: return p1;
1329: }
1330: }
1331:
1332: ND nd_add(int mod,ND p1,ND p2)
1333: {
1334: int n,c;
1335: int t,can,td1,td2;
1336: ND r;
1337: NM m1,m2,mr0,mr,s;
1338:
1.11 noro 1339: Nnd_add++;
1.1 noro 1340: if ( !p1 ) return p2;
1341: else if ( !p2 ) return p1;
1342: else if ( mod == -1 ) return nd_add_sf(p1,p2);
1343: else if ( mod == -2 ) return nd_add_lf(p1,p2);
1344: else if ( !mod ) return nd_add_q(p1,p2);
1345: else {
1346: can = 0;
1347: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1348: c = DL_COMPARE(DL(m1),DL(m2));
1349: switch ( c ) {
1350: case 0:
1351: t = ((CM(m1))+(CM(m2))) - mod;
1352: if ( t < 0 ) t += mod;
1353: s = m1; m1 = NEXT(m1);
1354: if ( t ) {
1355: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1356: } else {
1357: can += 2; FREENM(s);
1358: }
1359: s = m2; m2 = NEXT(m2); FREENM(s);
1360: break;
1361: case 1:
1362: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1363: break;
1364: case -1:
1365: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1366: break;
1367: }
1368: }
1369: if ( !mr0 )
1370: if ( m1 ) mr0 = m1;
1371: else if ( m2 ) mr0 = m2;
1372: else return 0;
1373: else if ( m1 ) NEXT(mr) = m1;
1374: else if ( m2 ) NEXT(mr) = m2;
1375: else NEXT(mr) = 0;
1376: BDY(p1) = mr0;
1377: SG(p1) = MAX(SG(p1),SG(p2));
1378: LEN(p1) = LEN(p1)+LEN(p2)-can;
1379: FREEND(p2);
1380: return p1;
1381: }
1382: }
1383:
1384: /* XXX on opteron, the inlined manipulation of destructive additon of
1385: * two NM seems to make gcc optimizer get confused, so the part is
1386: * done in a function.
1387: */
1388:
1389: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1390: {
1391: NM s;
1392: P t;
1393: int can;
1394:
1395: addp(nd_vc,CP(*m1),CP(*m2),&t);
1396: s = *m1; *m1 = NEXT(*m1);
1397: if ( t ) {
1398: can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
1399: } else {
1400: can = 2; FREENM(s);
1401: }
1402: s = *m2; *m2 = NEXT(*m2); FREENM(s);
1403: return can;
1404: }
1405:
1406: ND nd_add_q(ND p1,ND p2)
1407: {
1408: int n,c,can;
1409: ND r;
1410: NM m1,m2,mr0,mr,s;
1411: P t;
1412:
1413: if ( !p1 ) return p2;
1414: else if ( !p2 ) return p1;
1415: else {
1416: can = 0;
1417: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1418: c = DL_COMPARE(DL(m1),DL(m2));
1419: switch ( c ) {
1420: case 0:
1421: #if defined(__x86_64__)
1422: can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1423: #else
1424: addp(nd_vc,CP(m1),CP(m2),&t);
1425: s = m1; m1 = NEXT(m1);
1426: if ( t ) {
1427: can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
1428: } else {
1429: can += 2; FREENM(s);
1430: }
1431: s = m2; m2 = NEXT(m2); FREENM(s);
1432: #endif
1433: break;
1434: case 1:
1435: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1436: break;
1437: case -1:
1438: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1439: break;
1440: }
1441: }
1442: if ( !mr0 )
1443: if ( m1 ) mr0 = m1;
1444: else if ( m2 ) mr0 = m2;
1445: else return 0;
1446: else if ( m1 ) NEXT(mr) = m1;
1447: else if ( m2 ) NEXT(mr) = m2;
1448: else NEXT(mr) = 0;
1449: BDY(p1) = mr0;
1450: SG(p1) = MAX(SG(p1),SG(p2));
1451: LEN(p1) = LEN(p1)+LEN(p2)-can;
1452: FREEND(p2);
1453: return p1;
1454: }
1455: }
1456:
1457: ND nd_add_sf(ND p1,ND p2)
1458: {
1459: int n,c,can;
1460: ND r;
1461: NM m1,m2,mr0,mr,s;
1462: int t;
1463:
1464: if ( !p1 ) return p2;
1465: else if ( !p2 ) return p1;
1466: else {
1467: can = 0;
1468: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1469: c = DL_COMPARE(DL(m1),DL(m2));
1470: switch ( c ) {
1471: case 0:
1472: t = _addsf(CM(m1),CM(m2));
1473: s = m1; m1 = NEXT(m1);
1474: if ( t ) {
1475: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1476: } else {
1477: can += 2; FREENM(s);
1478: }
1479: s = m2; m2 = NEXT(m2); FREENM(s);
1480: break;
1481: case 1:
1482: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1483: break;
1484: case -1:
1485: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1486: break;
1487: }
1488: }
1489: if ( !mr0 )
1490: if ( m1 ) mr0 = m1;
1491: else if ( m2 ) mr0 = m2;
1492: else return 0;
1493: else if ( m1 ) NEXT(mr) = m1;
1494: else if ( m2 ) NEXT(mr) = m2;
1495: else NEXT(mr) = 0;
1496: BDY(p1) = mr0;
1497: SG(p1) = MAX(SG(p1),SG(p2));
1498: LEN(p1) = LEN(p1)+LEN(p2)-can;
1499: FREEND(p2);
1500: return p1;
1501: }
1502: }
1503:
1504:
1505: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn,Obj *divp)
1506: {
1507: int c,c1,c2;
1508: Z cg,cred,gcd,tq;
1509: P cgp,credp,gcdp;
1510: Obj tr,tr1;
1511:
1512: if ( mod == -1 ) {
1513: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1514: *divp = (Obj)ONE;
1515: } else if ( mod == -2 ) {
1516: Z inv,t;
1517: divlf(ONE,HCZ(p),&inv);
1518: chsgnlf(HCZ(g),&t);
1519: mullf(inv,t,&CZ(mul));
1520: *divp = (Obj)ONE;
1521: } else if ( mod ) {
1522: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1523: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1524: *divp = (Obj)ONE;
1525: } else if ( nd_vc ) {
1526: ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
1527: divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
1528: chsgnp(cgp,&CP(mul));
1529: nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
1530: if ( dn ) {
1531: mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
1532: reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
1533: }
1534: *divp = (Obj)credp;
1535: } else {
1.6 noro 1536: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1537: chsgnz(cg,&CZ(mul));
1.1 noro 1538: nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
1539: if ( dn ) {
1540: mulz(dn->z,cred,&tq); dn->z = tq;
1541: }
1542: *divp = (Obj)cred;
1543: }
1544: return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1545: }
1546:
1547: /* ret=1 : success, ret=0 : overflow */
1.6 noro 1548: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1.1 noro 1549: {
1550: NM m,mrd,tail;
1551: NM mul;
1552: int n,sugar,psugar,sugar0,stat,index;
1553: int c,c1,c2,dummy;
1554: RHist h;
1555: NDV p,red;
1556: Q cg,cred,gcd,tq,qq;
1557: Z iq;
1558: DP dmul;
1559: NODE node;
1560: LIST hist;
1561: double hmag;
1562: P tp,tp1;
1563: Obj tr,tr1,div;
1564: union oNDC hg;
1565: P cont;
1566:
1567: if ( !g ) {
1568: *rp = d;
1569: return 1;
1570: }
1571: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1572:
1573: sugar0 = sugar = SG(g);
1574: n = NV(g);
1575: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1576: if ( d )
1577: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1578: for ( ; g; ) {
1579: index = ndl_find_reducer(HDL(g));
1580: if ( index >= 0 ) {
1581: h = nd_psh[index];
1582: ndl_sub(HDL(g),DL(h),DL(mul));
1583: if ( ndl_check_bound2(index,DL(mul)) ) {
1584: nd_free(g); nd_free(d);
1585: return 0;
1586: }
1587: p = nd_demand ? ndv_load(index) : ps[index];
1588: /* d+g -> div*(d+g)+mul*p */
1.6 noro 1589: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1.1 noro 1590: if ( nd_gentrace ) {
1591: /* Trace=[div,index,mul,ONE] */
1.6 noro 1592: STOZ(index,iq);
1.1 noro 1593: nmtodp(mod,mul,&dmul);
1594: node = mknode(4,div,iq,dmul,ONE);
1595: }
1596: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1597: if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) {
1598: hg = HCU(g);
1599: nd_removecont2(d,g);
1.6 noro 1600: if ( nd_gentrace ) {
1.1 noro 1601: /* overwrite cont : Trace=[div,index,mul,cont] */
1.6 noro 1602: /* exact division */
1.1 noro 1603: cont = ndc_div(mod,hg,HCU(g));
1604: if ( nd_gentrace && !UNIQ(cont) ) ARG3(node) = (pointer)cont;
1605: }
1606: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1607: }
1608: MKLIST(hist,node);
1609: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1610: } else if ( !full ) {
1611: *rp = g;
1612: return 1;
1613: } else {
1614: m = BDY(g);
1615: if ( NEXT(m) ) {
1616: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1617: } else {
1618: FREEND(g); g = 0;
1619: }
1620: if ( d ) {
1621: NEXT(tail)=m; tail=m; LEN(d)++;
1622: } else {
1623: MKND(n,m,1,d); tail = BDY(d);
1624: }
1625: }
1626: }
1627: if ( d ) SG(d) = sugar;
1628: *rp = d;
1629: return 1;
1630: }
1631:
1.24 noro 1632: // ret=1 => success
1633: // ret=0 => overflow
1634: // ret=-1 => singular top reducible
1635:
1636: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1637: {
1638: NM m,mrd,tail;
1639: NM mul;
1640: int n,sugar,psugar,sugar0,stat,index;
1641: int c,c1,c2,dummy;
1642: RHist h;
1643: NDV p,red;
1644: Q cg,cred,gcd,tq,qq;
1645: Z iq;
1646: DP dmul;
1647: NODE node;
1648: LIST hist;
1649: double hmag;
1650: P tp,tp1;
1651: Obj tr,tr1,div;
1652: union oNDC hg;
1653: P cont;
1654: SIG sig;
1655:
1656: if ( !g ) {
1657: *rp = d;
1658: return 1;
1659: }
1660: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1661:
1662: sugar0 = sugar = SG(g);
1663: n = NV(g);
1664: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1665: if ( d )
1666: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1667: sig = g->sig;
1668: for ( ; g; ) {
1669: index = ndl_find_reducer_s(HDL(g),sig);
1670: if ( index >= 0 && index < nd_psn ) {
1671: // reducer found
1672: h = nd_psh[index];
1673: ndl_sub(HDL(g),DL(h),DL(mul));
1674: if ( ndl_check_bound2(index,DL(mul)) ) {
1675: nd_free(g); nd_free(d);
1676: return 0;
1677: }
1678: p = ps[index];
1679: /* d+g -> div*(d+g)+mul*p */
1680: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1681: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1682: if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
1683: hg = HCU(g);
1684: nd_removecont2(d,g);
1685: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1686: }
1687: } else if ( index == -1 ) {
1688: // singular top reducible
1689: return -1;
1690: } else if ( !full ) {
1691: *rp = g;
1692: g->sig = sig;
1693: return 1;
1694: } else {
1695: m = BDY(g);
1696: if ( NEXT(m) ) {
1697: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1698: } else {
1699: FREEND(g); g = 0;
1700: }
1701: if ( d ) {
1702: NEXT(tail)=m; tail=m; LEN(d)++;
1703: } else {
1704: MKND(n,m,1,d); tail = BDY(d);
1705: }
1706: }
1707: }
1708: if ( d ) {
1709: SG(d) = sugar;
1710: d->sig = sig;
1711: }
1712: *rp = d;
1713: return 1;
1714: }
1715:
1.1 noro 1716: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1717: {
1718: int hindex,index;
1719: NDV p;
1720: ND u,d,red;
1721: NODE l;
1722: NM mul,m,mrd,tail;
1723: int sugar,psugar,n,h_reducible;
1724: PGeoBucket bucket;
1725: int c,c1,c2;
1726: Z cg,cred,gcd,zzz;
1727: RHist h;
1728: double hmag,gmag;
1729: int count = 0;
1730: int hcount = 0;
1731:
1732: if ( !g ) {
1733: *rp = 0;
1734: return 1;
1735: }
1736: sugar = SG(g);
1737: n = NV(g);
1.6 noro 1738: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1739: bucket = create_pbucket();
1740: add_pbucket(mod,bucket,g);
1741: d = 0;
1742: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1743: while ( 1 ) {
1744: if ( mod > 0 || mod == -1 )
1745: hindex = head_pbucket(mod,bucket);
1746: else if ( mod == -2 )
1747: hindex = head_pbucket_lf(bucket);
1748: else
1749: hindex = head_pbucket_q(bucket);
1750: if ( hindex < 0 ) {
1751: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1752: if ( d ) SG(d) = sugar;
1753: *rp = d;
1754: return 1;
1755: }
1756: g = bucket->body[hindex];
1757: index = ndl_find_reducer(HDL(g));
1758: if ( index >= 0 ) {
1759: count++;
1760: if ( !d ) hcount++;
1761: h = nd_psh[index];
1762: ndl_sub(HDL(g),DL(h),DL(mul));
1763: if ( ndl_check_bound2(index,DL(mul)) ) {
1764: nd_free(d);
1765: free_pbucket(bucket);
1766: *rp = 0;
1767: return 0;
1768: }
1769: p = ps[index];
1770: if ( mod == -1 )
1771: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1772: else if ( mod == -2 ) {
1773: Z inv,t;
1774: divlf(ONE,HCZ(p),&inv);
1775: chsgnlf(HCZ(g),&t);
1776: mullf(inv,t,&CZ(mul));
1777: } else if ( mod ) {
1778: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1779: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1780: } else {
1.6 noro 1781: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1782: chsgnz(cg,&CZ(mul));
1.1 noro 1783: nd_mul_c_q(d,(P)cred);
1784: mulq_pbucket(bucket,cred);
1785: g = bucket->body[hindex];
1.6 noro 1786: gmag = (double)p_mag((P)HCZ(g));
1.1 noro 1787: }
1788: red = ndv_mul_nm(mod,mul,p);
1789: bucket->body[hindex] = nd_remove_head(g);
1790: red = nd_remove_head(red);
1791: add_pbucket(mod,bucket,red);
1792: psugar = SG(p)+TD(DL(mul));
1793: sugar = MAX(sugar,psugar);
1794: if ( !mod && hmag && (gmag > hmag) ) {
1795: g = normalize_pbucket(mod,bucket);
1796: if ( !g ) {
1797: if ( d ) SG(d) = sugar;
1798: *rp = d;
1799: return 1;
1800: }
1801: nd_removecont2(d,g);
1.6 noro 1802: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1803: add_pbucket(mod,bucket,g);
1804: }
1805: } else if ( !full ) {
1806: g = normalize_pbucket(mod,bucket);
1807: if ( g ) SG(g) = sugar;
1808: *rp = g;
1809: return 1;
1810: } else {
1811: m = BDY(g);
1812: if ( NEXT(m) ) {
1813: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1814: } else {
1815: FREEND(g); g = 0;
1816: }
1817: bucket->body[hindex] = g;
1818: NEXT(m) = 0;
1819: if ( d ) {
1820: NEXT(tail)=m; tail=m; LEN(d)++;
1821: } else {
1822: MKND(n,m,1,d); tail = BDY(d);
1823: }
1824: }
1825: }
1826: }
1827:
1.25 noro 1828: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *rp)
1829: {
1830: int hindex,index;
1831: NDV p;
1832: ND u,d,red;
1833: NODE l;
1834: NM mul,m,mrd,tail;
1835: int sugar,psugar,n,h_reducible;
1836: PGeoBucket bucket;
1837: int c,c1,c2;
1838: Z cg,cred,gcd,zzz;
1839: RHist h;
1840: double hmag,gmag;
1841: int count = 0;
1842: int hcount = 0;
1843: SIG sig;
1844:
1845: if ( !g ) {
1846: *rp = 0;
1847: return 1;
1848: }
1849: sugar = SG(g);
1850: n = NV(g);
1851: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1852: bucket = create_pbucket();
1853: add_pbucket(mod,bucket,g);
1854: d = 0;
1855: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1856: sig = g->sig;
1857: while ( 1 ) {
1858: if ( mod > 0 || mod == -1 )
1859: hindex = head_pbucket(mod,bucket);
1860: else if ( mod == -2 )
1861: hindex = head_pbucket_lf(bucket);
1862: else
1863: hindex = head_pbucket_q(bucket);
1864: if ( hindex < 0 ) {
1865: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1866: if ( d ) {
1867: SG(d) = sugar;
1868: d->sig = sig;
1869: }
1870: *rp = d;
1871: return 1;
1872: }
1873: g = bucket->body[hindex];
1874: index = ndl_find_reducer_s(HDL(g),sig);
1875: if ( index >= 0 && index < nd_psn ) {
1876: count++;
1877: if ( !d ) hcount++;
1878: h = nd_psh[index];
1879: ndl_sub(HDL(g),DL(h),DL(mul));
1880: if ( ndl_check_bound2(index,DL(mul)) ) {
1881: nd_free(d);
1882: free_pbucket(bucket);
1883: *rp = 0;
1884: return 0;
1885: }
1886: p = ps[index];
1887: if ( mod == -1 )
1888: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1889: else if ( mod == -2 ) {
1890: Z inv,t;
1891: divlf(ONE,HCZ(p),&inv);
1892: chsgnlf(HCZ(g),&t);
1893: mullf(inv,t,&CZ(mul));
1894: } else if ( mod ) {
1895: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1896: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1897: } else {
1898: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1899: chsgnz(cg,&CZ(mul));
1900: nd_mul_c_q(d,(P)cred);
1901: mulq_pbucket(bucket,cred);
1902: g = bucket->body[hindex];
1903: gmag = (double)p_mag((P)HCZ(g));
1904: }
1905: red = ndv_mul_nm(mod,mul,p);
1906: bucket->body[hindex] = nd_remove_head(g);
1907: red = nd_remove_head(red);
1908: add_pbucket(mod,bucket,red);
1909: psugar = SG(p)+TD(DL(mul));
1910: sugar = MAX(sugar,psugar);
1911: if ( !mod && hmag && (gmag > hmag) ) {
1912: g = normalize_pbucket(mod,bucket);
1913: if ( !g ) {
1914: if ( d ) {
1915: SG(d) = sugar;
1916: d->sig = sig;
1917: }
1918: *rp = d;
1919: return 1;
1920: }
1921: nd_removecont2(d,g);
1922: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1923: add_pbucket(mod,bucket,g);
1924: }
1925: } else if ( index == -1 ) {
1926: // singular top reducible
1927: return -1;
1928: } else if ( !full ) {
1929: g = normalize_pbucket(mod,bucket);
1930: if ( g ) {
1931: SG(g) = sugar;
1932: g->sig = sig;
1933: }
1934: *rp = g;
1935: return 1;
1936: } else {
1937: m = BDY(g);
1938: if ( NEXT(m) ) {
1939: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1940: } else {
1941: FREEND(g); g = 0;
1942: }
1943: bucket->body[hindex] = g;
1944: NEXT(m) = 0;
1945: if ( d ) {
1946: NEXT(tail)=m; tail=m; LEN(d)++;
1947: } else {
1948: MKND(n,m,1,d); tail = BDY(d);
1949: }
1950: }
1951: }
1952: }
1953:
1.1 noro 1954: /* input : list of NDV, cand : list of NDV */
1955:
1956: int ndv_check_membership(int m,NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1957: {
1958: int n,i,stat;
1959: ND nf,d;
1960: NDV r;
1961: NODE t,s;
1962: union oNDC dn;
1963: Z q;
1964: LIST list;
1965:
1.24 noro 1966: ndv_setup(m,0,cand,nd_gentrace?1:0,1,0);
1.1 noro 1967: n = length(cand);
1968:
1969: if ( nd_gentrace ) { nd_alltracelist = 0; nd_tracelist = 0; }
1970: /* membercheck : list is a subset of Id(cand) ? */
1971: for ( t = input, i = 0; t; t = NEXT(t), i++ ) {
1972: again:
1973: nd_tracelist = 0;
1974: if ( nd_bpe > obpe )
1975: r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
1976: else
1977: r = (NDV)BDY(t);
1978: #if 0
1979: // moved to nd_f4_lf_trace()
1980: if ( m == -2 ) ndv_mod(m,r);
1981: #endif
1982: d = ndvtond(m,r);
1.6 noro 1983: stat = nd_nf(m,0,d,nd_ps,0,&nf);
1.1 noro 1984: if ( !stat ) {
1985: nd_reconstruct(0,0);
1986: goto again;
1987: } else if ( nf ) return 0;
1988: if ( nd_gentrace ) {
1989: nd_tracelist = reverse_node(nd_tracelist);
1990: MKLIST(list,nd_tracelist);
1.6 noro 1991: STOZ(i,q); s = mknode(2,q,list); MKLIST(list,s);
1.1 noro 1992: MKNODE(s,list,nd_alltracelist);
1993: nd_alltracelist = s; nd_tracelist = 0;
1994: }
1995: if ( DP_Print ) { printf("."); fflush(stdout); }
1996: }
1997: if ( DP_Print ) { printf("\n"); }
1998: return 1;
1999: }
2000:
2001: ND nd_remove_head(ND p)
2002: {
2003: NM m;
2004:
2005: m = BDY(p);
2006: if ( !NEXT(m) ) {
2007: FREEND(p); p = 0;
2008: } else {
2009: BDY(p) = NEXT(m); LEN(p)--;
2010: }
2011: FREENM(m);
2012: return p;
2013: }
2014:
2015: ND nd_separate_head(ND p,ND *head)
2016: {
2017: NM m,m0;
2018: ND r;
2019:
2020: m = BDY(p);
2021: if ( !NEXT(m) ) {
2022: *head = p; p = 0;
2023: } else {
2024: m0 = m;
2025: BDY(p) = NEXT(m); LEN(p)--;
2026: NEXT(m0) = 0;
2027: MKND(NV(p),m0,1,r);
2028: *head = r;
2029: }
2030: return p;
2031: }
2032:
2033: PGeoBucket create_pbucket()
2034: {
2035: PGeoBucket g;
2036:
2037: g = CALLOC(1,sizeof(struct oPGeoBucket));
2038: g->m = -1;
2039: return g;
2040: }
2041:
2042: void free_pbucket(PGeoBucket b) {
2043: int i;
2044:
2045: for ( i = 0; i <= b->m; i++ )
2046: if ( b->body[i] ) {
2047: nd_free(b->body[i]);
2048: b->body[i] = 0;
2049: }
2050: GCFREE(b);
2051: }
2052:
1.39 noro 2053: #if 0
1.1 noro 2054: void add_pbucket_symbolic(PGeoBucket g,ND d)
2055: {
2056: int l,i,k,m;
2057:
2058: if ( !d )
2059: return;
2060: l = LEN(d);
2061: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2062: /* 2^(k-1) < l <= 2^k (=m) */
2063: d = nd_merge(g->body[k],d);
2064: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2065: g->body[k] = 0;
2066: d = nd_merge(g->body[k+1],d);
2067: }
2068: g->body[k] = d;
2069: g->m = MAX(g->m,k);
2070: }
1.39 noro 2071: #else
2072: void add_pbucket_symbolic(PGeoBucket g,ND d)
2073: {
2074: int l,i,k,m,m0;
2075:
2076: if ( !d )
2077: return;
2078: m0 = g->m;
2079: while ( 1 ) {
2080: l = LEN(d);
2081: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2082: /* 2^(k-1) < l <= 2^k (=m) */
2083: if ( g->body[k] == 0 ) {
2084: g->body[k] = d;
2085: m0 = MAX(k,m0);
2086: break;
2087: } else {
2088: d = nd_merge(g->body[k],d);
2089: g->body[k] = 0;
2090: }
2091: }
2092: g->m = m0;
2093: }
2094: #endif
1.1 noro 2095:
1.39 noro 2096: #if 0
1.1 noro 2097: void add_pbucket(int mod,PGeoBucket g,ND d)
2098: {
2099: int l,i,k,m;
2100:
2101: if ( !d )
2102: return;
2103: l = LEN(d);
2104: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2105: /* 2^(k-1) < l <= 2^k (=m) */
2106: d = nd_add(mod,g->body[k],d);
2107: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2108: g->body[k] = 0;
2109: d = nd_add(mod,g->body[k+1],d);
2110: }
2111: g->body[k] = d;
2112: g->m = MAX(g->m,k);
2113: }
1.39 noro 2114: #else
2115: void add_pbucket(int mod,PGeoBucket g,ND d)
2116: {
2117: int l,i,k,m,m0;
2118:
2119: m0 = g->m;
2120: while ( d != 0 ) {
2121: l = LEN(d);
2122: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2123: /* 2^(k-1) < l <= 2^k (=m) */
2124: if ( g->body[k] == 0 ) {
2125: g->body[k] = d;
2126: m0 = MAX(k,m0);
2127: break;
2128: } else {
2129: d = nd_add(mod,g->body[k],d);
2130: g->body[k] = 0;
2131: }
2132: }
2133: g->m = m0;
2134: }
2135: #endif
1.1 noro 2136:
2137: void mulq_pbucket(PGeoBucket g,Z c)
2138: {
2139: int k;
2140:
2141: for ( k = 0; k <= g->m; k++ )
2142: nd_mul_c_q(g->body[k],(P)c);
2143: }
2144:
2145: NM remove_head_pbucket_symbolic(PGeoBucket g)
2146: {
2147: int j,i,k,c;
2148: NM head;
2149:
2150: k = g->m;
2151: j = -1;
2152: for ( i = 0; i <= k; i++ ) {
2153: if ( !g->body[i] ) continue;
2154: if ( j < 0 ) j = i;
2155: else {
2156: c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
2157: if ( c > 0 )
2158: j = i;
2159: else if ( c == 0 )
2160: g->body[i] = nd_remove_head(g->body[i]);
2161: }
2162: }
2163: if ( j < 0 ) return 0;
2164: else {
2165: head = BDY(g->body[j]);
2166: if ( !NEXT(head) ) {
2167: FREEND(g->body[j]);
2168: g->body[j] = 0;
2169: } else {
2170: BDY(g->body[j]) = NEXT(head);
2171: LEN(g->body[j])--;
2172: }
2173: return head;
2174: }
2175: }
2176:
2177: int head_pbucket(int mod,PGeoBucket g)
2178: {
2179: int j,i,c,k,nv,sum;
2180: UINT *di,*dj;
2181: ND gi,gj;
2182:
2183: k = g->m;
2184: while ( 1 ) {
2185: j = -1;
2186: for ( i = 0; i <= k; i++ ) {
2187: if ( !(gi = g->body[i]) )
2188: continue;
2189: if ( j < 0 ) {
2190: j = i;
2191: gj = g->body[j];
2192: dj = HDL(gj);
2193: sum = HCM(gj);
2194: } else {
2195: c = DL_COMPARE(HDL(gi),dj);
2196: if ( c > 0 ) {
2197: if ( sum ) HCM(gj) = sum;
2198: else g->body[j] = nd_remove_head(gj);
2199: j = i;
2200: gj = g->body[j];
2201: dj = HDL(gj);
2202: sum = HCM(gj);
2203: } else if ( c == 0 ) {
2204: if ( mod == -1 )
2205: sum = _addsf(sum,HCM(gi));
2206: else {
2207: sum = sum+HCM(gi)-mod;
2208: if ( sum < 0 ) sum += mod;
2209: }
2210: g->body[i] = nd_remove_head(gi);
2211: }
2212: }
2213: }
2214: if ( j < 0 ) return -1;
2215: else if ( sum ) {
2216: HCM(gj) = sum;
2217: return j;
2218: } else
2219: g->body[j] = nd_remove_head(gj);
2220: }
2221: }
2222:
2223: int head_pbucket_q(PGeoBucket g)
2224: {
2225: int j,i,c,k,nv;
2226: Z sum,t;
2227: ND gi,gj;
2228:
2229: k = g->m;
2230: while ( 1 ) {
2231: j = -1;
2232: for ( i = 0; i <= k; i++ ) {
2233: if ( !(gi = g->body[i]) ) continue;
2234: if ( j < 0 ) {
2235: j = i;
2236: gj = g->body[j];
1.6 noro 2237: sum = HCZ(gj);
1.1 noro 2238: } else {
2239: nv = NV(gi);
2240: c = DL_COMPARE(HDL(gi),HDL(gj));
2241: if ( c > 0 ) {
1.6 noro 2242: if ( sum ) HCZ(gj) = sum;
1.1 noro 2243: else g->body[j] = nd_remove_head(gj);
2244: j = i;
2245: gj = g->body[j];
1.6 noro 2246: sum = HCZ(gj);
1.1 noro 2247: } else if ( c == 0 ) {
1.6 noro 2248: addz(sum,HCZ(gi),&t);
1.1 noro 2249: sum = t;
2250: g->body[i] = nd_remove_head(gi);
2251: }
2252: }
2253: }
2254: if ( j < 0 ) return -1;
2255: else if ( sum ) {
1.6 noro 2256: HCZ(gj) = sum;
1.1 noro 2257: return j;
2258: } else
2259: g->body[j] = nd_remove_head(gj);
2260: }
2261: }
2262:
2263: int head_pbucket_lf(PGeoBucket g)
2264: {
2265: int j,i,c,k,nv;
2266: Z sum,t;
2267: ND gi,gj;
2268:
2269: k = g->m;
2270: while ( 1 ) {
2271: j = -1;
2272: for ( i = 0; i <= k; i++ ) {
2273: if ( !(gi = g->body[i]) ) continue;
2274: if ( j < 0 ) {
2275: j = i;
2276: gj = g->body[j];
2277: sum = HCZ(gj);
2278: } else {
2279: nv = NV(gi);
2280: c = DL_COMPARE(HDL(gi),HDL(gj));
2281: if ( c > 0 ) {
2282: if ( sum ) HCZ(gj) = sum;
2283: else g->body[j] = nd_remove_head(gj);
2284: j = i;
2285: gj = g->body[j];
2286: sum = HCZ(gj);
2287: } else if ( c == 0 ) {
2288: addlf(sum,HCZ(gi),&t);
2289: sum = t;
2290: g->body[i] = nd_remove_head(gi);
2291: }
2292: }
2293: }
2294: if ( j < 0 ) return -1;
2295: else if ( sum ) {
2296: HCZ(gj) = sum;
2297: return j;
2298: } else
2299: g->body[j] = nd_remove_head(gj);
2300: }
2301: }
2302:
2303: ND normalize_pbucket(int mod,PGeoBucket g)
2304: {
2305: int i;
2306: ND r,t;
2307:
2308: r = 0;
2309: for ( i = 0; i <= g->m; i++ ) {
2310: r = nd_add(mod,r,g->body[i]);
2311: g->body[i] = 0;
2312: }
2313: g->m = -1;
2314: return r;
2315: }
2316:
2317: #if 0
2318: void register_hcf(NDV p)
2319: {
2320: DCP dc,t;
2321: P hc,h;
2322: int c;
2323: NODE l,l1,prev;
2324:
2325: hc = p->body->c.p;
2326: if ( !nd_vc || NUM(hc) ) return;
2327: fctrp(nd_vc,hc,&dc);
2328: for ( t = dc; t; t = NEXT(t) ) {
2329: h = t->c;
2330: if ( NUM(h) ) continue;
2331: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2332: c = compp(nd_vc,h,(P)BDY(l));
2333: if ( c >= 0 ) break;
2334: }
2335: if ( !l || c > 0 ) {
2336: MKNODE(l1,h,l);
2337: if ( !prev )
2338: nd_hcf = l1;
2339: else
2340: NEXT(prev) = l1;
2341: }
2342: }
2343: }
2344: #else
2345: void register_hcf(NDV p)
2346: {
2347: DCP dc,t;
2348: P hc,h,q;
2349: Q dmy;
2350: int c;
2351: NODE l,l1,prev;
2352:
2353: hc = p->body->c.p;
2354: if ( NUM(hc) ) return;
2355: ptozp(hc,1,&dmy,&h);
2356: #if 1
2357: for ( l = nd_hcf; l; l = NEXT(l) ) {
2358: while ( 1 ) {
2359: if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
2360: else break;
2361: }
2362: }
2363: if ( NUM(h) ) return;
2364: #endif
2365: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2366: c = compp(nd_vc,h,(P)BDY(l));
2367: if ( c >= 0 ) break;
2368: }
2369: if ( !l || c > 0 ) {
2370: MKNODE(l1,h,l);
2371: if ( !prev )
2372: nd_hcf = l1;
2373: else
2374: NEXT(prev) = l1;
2375: }
2376: }
2377: #endif
2378:
2379: int do_diagonalize(int sugar,int m)
2380: {
1.6 noro 2381: int i,nh,stat;
2382: NODE r,g,t;
2383: ND h,nf,s,head;
2384: NDV nfv;
2385: Q q;
2386: P nm,nmp,dn,mnp,dnp,cont,cont1;
2387: union oNDC hc;
2388: NODE node;
2389: LIST l;
2390: Z iq;
1.1 noro 2391:
1.6 noro 2392: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2393: if ( nd_gentrace ) {
2394: /* Trace = [1,index,1,1] */
2395: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2396: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2397: }
2398: if ( nd_demand )
2399: nfv = ndv_load(i);
2400: else
2401: nfv = nd_ps[i];
2402: s = ndvtond(m,nfv);
2403: s = nd_separate_head(s,&head);
2404: stat = nd_nf(m,head,s,nd_ps,1,&nf);
2405: if ( !stat ) return 0;
2406: ndv_free(nfv);
2407: hc = HCU(nf); nd_removecont(m,nf);
2408: /* exact division */
2409: cont = ndc_div(m,hc,HCU(nf));
1.1 noro 2410: if ( nd_gentrace ) finalize_tracelist(i,cont);
1.6 noro 2411: nfv = ndtondv(m,nf);
2412: nd_free(nf);
2413: nd_bound[i] = ndv_compute_bound(nfv);
2414: if ( !m ) register_hcf(nfv);
2415: if ( nd_demand ) {
2416: ndv_save(nfv,i);
2417: ndv_free(nfv);
2418: } else
2419: nd_ps[i] = nfv;
2420: }
2421: return 1;
1.1 noro 2422: }
2423:
2424: LIST compute_splist()
2425: {
2426: NODE g,tn0,tn,node;
2427: LIST l0;
2428: ND_pairs d,t;
2429: int i;
2430: Z i1,i2;
2431:
2432: g = 0; d = 0;
2433: for ( i = 0; i < nd_psn; i++ ) {
2434: d = update_pairs(d,g,i,0);
2435: g = update_base(g,i);
2436: }
2437: for ( t = d, tn0 = 0; t; t = NEXT(t) ) {
2438: NEXTNODE(tn0,tn);
1.6 noro 2439: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 2440: node = mknode(2,i1,i2); MKLIST(l0,node);
2441: BDY(tn) = l0;
2442: }
2443: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
2444: return l0;
2445: }
2446:
2447: /* return value = 0 => input is not a GB */
2448:
2449: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2450: {
1.6 noro 2451: int i,nh,sugar,stat;
2452: NODE r,g,t;
2453: ND_pairs d;
2454: ND_pairs l;
2455: ND h,nf,s,head,nf1;
2456: NDV nfv;
2457: Z q;
2458: union oNDC dn,hc;
2459: int diag_count = 0;
1.41 noro 2460: int Nnfnz = 0,Nnfz = 0;
1.6 noro 2461: P cont;
2462: LIST list;
1.27 noro 2463: struct oEGT eg1,eg2,eg_update;
1.6 noro 2464:
1.27 noro 2465: init_eg(&eg_update);
1.11 noro 2466: Nnd_add = 0;
1.6 noro 2467: g = 0; d = 0;
2468: for ( i = 0; i < nd_psn; i++ ) {
2469: d = update_pairs(d,g,i,gensyz);
2470: g = update_base(g,i);
2471: }
2472: sugar = 0;
2473: while ( d ) {
1.1 noro 2474: again:
1.6 noro 2475: l = nd_minp(d,&d);
2476: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2477: if ( SG(l) != sugar ) {
2478: if ( ishomo ) {
2479: diag_count = 0;
2480: stat = do_diagonalize(sugar,m);
1.1 noro 2481: if ( !stat ) {
1.6 noro 2482: NEXT(l) = d; d = l;
2483: d = nd_reconstruct(0,d);
2484: goto again;
1.1 noro 2485: }
1.6 noro 2486: }
2487: sugar = SG(l);
2488: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2489: }
2490: stat = nd_sp(m,0,l,&h);
2491: if ( !stat ) {
2492: NEXT(l) = d; d = l;
2493: d = nd_reconstruct(0,d);
2494: goto again;
2495: }
1.1 noro 2496: #if USE_GEOBUCKET
1.39 noro 2497: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf)
2498: :nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2499: #else
1.39 noro 2500: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 2501: #endif
1.6 noro 2502: if ( !stat ) {
2503: NEXT(l) = d; d = l;
2504: d = nd_reconstruct(0,d);
2505: goto again;
2506: } else if ( nf ) {
1.41 noro 2507: Nnfnz++;
1.6 noro 2508: if ( checkonly || gensyz ) return 0;
1.1 noro 2509: if ( nd_newelim ) {
2510: if ( nd_module ) {
2511: if ( MPOS(HDL(nf)) > 1 ) return 0;
2512: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2513: }
1.6 noro 2514: if ( DP_Print ) { printf("+"); fflush(stdout); }
2515: hc = HCU(nf);
2516: nd_removecont(m,nf);
2517: if ( !m && nd_nalg ) {
2518: nd_monic(0,&nf);
2519: nd_removecont(m,nf);
2520: }
2521: if ( nd_gentrace ) {
2522: /* exact division */
1.1 noro 2523: cont = ndc_div(m,hc,HCU(nf));
2524: if ( m || !UNIQ(cont) ) {
1.6 noro 2525: t = mknode(4,NULLP,NULLP,NULLP,cont);
2526: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2527: nd_tracelist = t;
2528: }
2529: }
1.6 noro 2530: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2531: nh = ndv_newps(m,nfv,0);
1.6 noro 2532: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2533: diag_count = 0;
2534: stat = do_diagonalize(sugar,m);
2535: if ( !stat ) {
2536: NEXT(l) = d; d = l;
2537: d = nd_reconstruct(1,d);
2538: goto again;
1.1 noro 2539: }
1.6 noro 2540: }
1.27 noro 2541: get_eg(&eg1);
1.6 noro 2542: d = update_pairs(d,g,nh,0);
1.27 noro 2543: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2544: g = update_base(g,nh);
2545: FREENDP(l);
1.41 noro 2546: } else {
2547: Nnfz++;
2548: if ( nd_gentrace && gensyz ) {
2549: nd_tracelist = reverse_node(nd_tracelist);
2550: MKLIST(list,nd_tracelist);
2551: STOZ(-1,q); t = mknode(2,q,list); MKLIST(list,t);
2552: MKNODE(t,list,nd_alltracelist);
2553: nd_alltracelist = t; nd_tracelist = 0;
2554: }
2555: if ( DP_Print ) { printf("."); fflush(stdout); }
2556: FREENDP(l);
2557: }
1.36 noro 2558: }
2559: conv_ilist(nd_demand,0,g,indp);
1.41 noro 2560: if ( !checkonly && DP_Print ) {
2561: printf("\nnd_gb done. Nnd_add=%d,Npairs=%d, Nnfnz=%d,Nnfz=%d,",Nnd_add,Npairs,Nnfnz,Nnfz);
2562: printf("Nremoved=%d\n",NcriB+NcriMF+Ncri2);
2563: fflush(asir_out);
2564: }
2565: if ( DP_Print ) {
2566: print_eg("update",&eg_update); fprintf(asir_out,"\n");
2567: }
1.36 noro 2568: return g;
1.1 noro 2569: }
2570:
1.30 noro 2571: ND_pairs update_pairs_s(ND_pairs d,int t,NODE *syz);
2572: ND_pairs nd_newpairs_s(int t ,NODE *syz);
1.24 noro 2573:
2574: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *nf);
2575: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *nf);
2576:
2577: void _copydl(int n,DL d1,DL d2);
2578: void _subfromdl(int n,DL d1,DL d2);
2579: extern int (*cmpdl)(int n,DL d1,DL d2);
2580:
2581: NODE insert_sig(NODE l,SIG s)
2582: {
2583: int pos;
2584: DL sig;
2585: struct oNODE root;
2586: NODE p,prev,r;
2587: SIG t;
2588:
2589: pos = s->pos; sig = DL(s);
2590: root.next = l; prev = &root;
2591: for ( p = l; p; p = p->next ) {
2592: t = (SIG)p->body;
2593: if ( t->pos == pos ) {
2594: if ( _dl_redble(DL(t),sig,nd_nvar) )
2595: return root.next;
2596: else if ( _dl_redble(sig,DL(t),nd_nvar) )
2597: // remove p
2598: prev->next = p->next;
2599: } else
2600: prev = p;
2601: }
1.27 noro 2602: NEWNODE(r); r->body = (pointer)s; r->next = 0;
2603: for ( p = &root; p->next; p = p->next );
2604: p->next = r;
2605: // r->next = root.next;
2606: // return r;
2607: return root.next;
1.24 noro 2608: }
2609:
2610: ND_pairs remove_spair_s(ND_pairs d,SIG sig)
2611: {
2612: struct oND_pairs root;
2613: ND_pairs prev,p;
2614: SIG spsig;
2615:
2616: root.next = d;
2617: prev = &root; p = d;
2618: while ( p ) {
2619: spsig = p->sig;
1.26 noro 2620: if ( sig->pos == spsig->pos && _dl_redble(DL(sig),DL(spsig),nd_nvar) ) {
1.24 noro 2621: // remove p
2622: prev->next = p->next;
1.26 noro 2623: Nsyz++;
2624: } else
1.24 noro 2625: prev = p;
2626: p = p->next;
2627: }
2628: return (ND_pairs)root.next;
2629: }
2630:
1.29 noro 2631: int _dl_redble_ext(DL,DL,DL,int);
2632:
1.28 noro 2633: int small_lcm(ND_pairs l)
2634: {
2635: SIG sig;
2636: int i;
1.29 noro 2637: NODE t;
1.28 noro 2638: static DL lcm,mul,quo;
1.44 ! noro 2639: static int nvar = 0;
1.28 noro 2640:
1.38 noro 2641: if ( nd_sba_largelcm ) return 0;
1.28 noro 2642: if ( nvar < nd_nvar ) {
2643: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(quo,nvar); NEWDL(mul,nvar);
2644: }
2645: sig = l->sig;
2646: _ndltodl(l->lcm,lcm);
1.29 noro 2647: #if 0
1.28 noro 2648: for ( i = 0; i < nd_psn; i++ ) {
2649: if ( sig->pos == nd_psh[i]->sig->pos &&
1.29 noro 2650: _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
1.28 noro 2651: _ndltodl(DL(nd_psh[i]),mul);
2652: _addtodl(nd_nvar,quo,mul);
2653: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2654: break;
2655: }
2656: }
2657: if ( i < nd_psn ) return 1;
2658: else return 0;
1.29 noro 2659: #else
2660: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2661: i = (long)BDY(t);
2662: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2663: _ndltodl(DL(nd_psh[i]),mul);
2664: _addtodl(nd_nvar,quo,mul);
2665: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
2666: break;
2667: }
2668: }
2669: if ( t ) return 1;
2670: else return 0;
2671: #endif
1.28 noro 2672: }
2673:
1.41 noro 2674: ND_pairs find_smallest_lcm(ND_pairs l)
2675: {
2676: SIG sig;
2677: int i,minindex;
2678: NODE t;
2679: ND_pairs r;
2680: struct oSIG sig1;
2681: static DL mul,quo,minlm;
1.44 ! noro 2682: static int nvar = 0;
1.41 noro 2683:
2684: if ( nvar < nd_nvar ) {
2685: nvar = nd_nvar;
2686: NEWDL(quo,nvar); NEWDL(mul,nvar);
2687: NEWDL(minlm,nvar);
2688: }
2689: sig = l->sig;
2690: // find mg s.t. m*s(g)=sig and m*lm(g) is minimal
2691: _ndltodl(l->lcm,minlm); minindex = -1;
2692: for ( t = nd_sba_pos[sig->pos]; t; t = t->next ) {
2693: i = (long)BDY(t);
2694: if ( _dl_redble_ext(DL(nd_psh[i]->sig),DL(sig),quo,nd_nvar) ) {
2695: _ndltodl(DL(nd_psh[i]),mul);
2696: _addtodl(nd_nvar,quo,mul);
2697: if ( (*cmpdl)(nd_nvar,minlm,mul) > 0 ) {
2698: minindex = i;
2699: _copydl(nd_nvar,mul,minlm);
2700: }
2701: }
2702: }
2703: // l->lcm is minimal; return l itself
2704: if ( minindex < 0 ) return l;
2705: for ( i = 0; i < nd_psn; i++ ) {
2706: if ( i == minindex ) continue;
2707: _ndltodl(DL(nd_psh[i]),mul);
2708: if ( _dl_redble_ext(mul,minlm,quo,nd_nvar) ) {
2709: _addtodl(nd_nvar,nd_ps[i]->sig->dl,quo);
2710: sig1.pos = nd_ps[i]->sig->pos;
2711: sig1.dl = quo;
2712: if ( comp_sig(sig,&sig1) > 0 ) {
2713: // printf("X");
2714: NEWND_pairs(r);
2715: r->sig = sig;
2716: r->i1 = minindex;
2717: r->i2 = i;
2718: dltondl(nd_nvar,minlm,r->lcm);
2719: r->next = 0;
2720: return r;
2721: }
2722: }
2723: }
2724: // there is no suitable spair
2725: return 0;
2726: }
2727:
1.28 noro 2728: ND_pairs remove_large_lcm(ND_pairs d)
2729: {
2730: struct oND_pairs root;
2731: ND_pairs prev,p;
2732:
2733: root.next = d;
2734: prev = &root; p = d;
2735: while ( p ) {
1.41 noro 2736: #if 0
1.28 noro 2737: if ( small_lcm(p) ) {
2738: // remove p
2739: prev->next = p->next;
2740: } else
1.41 noro 2741: #else
2742: if ( find_smallest_lcm(p) == 0 ) {
2743: // remove p
2744: prev->next = p->next;
2745: } else
2746: #endif
1.28 noro 2747: prev = p;
2748: p = p->next;
2749: }
2750: return (ND_pairs)root.next;
2751: }
2752:
1.26 noro 2753: struct oEGT eg_create,eg_newpairs,eg_merge;
2754:
1.30 noro 2755: NODE conv_ilist_s(int demand,int trace,int **indp);
2756:
1.44 ! noro 2757: // S(fj*ei-fi*ej)
! 2758:
! 2759: SIG trivial_sig(int i,int j)
! 2760: {
! 2761: static struct oSIG sigi,sigj;
! 2762: static int nvar = 0;
! 2763: SIG sig;
! 2764:
! 2765: if ( nvar != nd_nvar ) {
! 2766: nvar = nd_nvar; NEWDL(sigi.dl,nvar); NEWDL(sigj.dl,nvar);
! 2767: }
! 2768: sigi.pos = i; _copydl(nd_nvar,nd_sba_hm[j],sigi.dl);
! 2769: sigj.pos = j; _copydl(nd_nvar,nd_sba_hm[i],sigj.dl);
! 2770: if ( comp_sig(&sigi,&sigj) > 0 ) sig = dup_sig(&sigi);
! 2771: else sig = dup_sig(&sigj);
! 2772: return sig;
! 2773: }
! 2774:
! 2775: NODE nd_sba_buch(int m,int ishomo,int **indp,NODE *syzp)
1.24 noro 2776: {
1.39 noro 2777: int i,j,nh,sugar,stat,pos;
1.30 noro 2778: NODE r,t,g;
1.24 noro 2779: ND_pairs d;
1.41 noro 2780: ND_pairs l,l1;
1.24 noro 2781: ND h,nf,s,head,nf1;
2782: NDV nfv;
2783: Z q;
2784: union oNDC dn,hc;
2785: P cont;
2786: LIST list;
2787: SIG sig;
1.29 noro 2788: NODE *syzlist;
1.44 ! noro 2789: int ngen;
1.41 noro 2790: int Nnominimal,Nredundant;
1.28 noro 2791: DL lcm,quo,mul;
1.31 noro 2792: struct oEGT eg1,eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.41 noro 2793: int Nnfs=0,Nnfz=0,Nnfnz=0;
1.24 noro 2794:
1.27 noro 2795: init_eg(&eg_remove);
1.29 noro 2796: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.26 noro 2797: Nsyz = 0;
1.24 noro 2798: Nnd_add = 0;
1.41 noro 2799: Nnominimal = 0;
1.26 noro 2800: Nredundant = 0;
1.30 noro 2801: d = 0;
1.44 ! noro 2802: ngen = nd_psn;
1.29 noro 2803: for ( i = 0; i < nd_psn; i++ )
2804: for ( j = i+1; j < nd_psn; j++ ) {
1.44 ! noro 2805: sig = trivial_sig(i,j);
1.29 noro 2806: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
2807: }
1.41 noro 2808: for ( i = 0; i < nd_psn; i++ ) {
2809: d = update_pairs_s(d,i,syzlist);
2810: }
1.24 noro 2811: sugar = 0;
1.39 noro 2812: pos = 0;
1.26 noro 2813: NEWDL(lcm,nd_nvar); NEWDL(quo,nd_nvar); NEWDL(mul,nd_nvar);
2814: init_eg(&eg_create);
2815: init_eg(&eg_merge);
1.29 noro 2816: init_eg(&eg_large);
1.31 noro 2817: init_eg(&eg_nf);
2818: init_eg(&eg_nfzero);
1.24 noro 2819: while ( d ) {
2820: again:
1.26 noro 2821: if ( DP_Print ) {
2822: int len;
2823: ND_pairs td;
1.28 noro 2824: for ( td = d, len=0; td; td = td->next, len++)
2825: ;
1.26 noro 2826: if ( !(len%100) ) fprintf(asir_out,"(%d)",len);
2827: }
1.24 noro 2828: l = d; d = d->next;
1.41 noro 2829: #if 0
1.28 noro 2830: if ( small_lcm(l) ) {
1.24 noro 2831: if ( DP_Print ) fprintf(asir_out,"M");
1.41 noro 2832: Nnominimal++;
1.24 noro 2833: continue;
2834: }
2835: if ( SG(l) != sugar ) {
2836: sugar = SG(l);
2837: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2838: }
1.28 noro 2839: sig = l->sig;
1.39 noro 2840: if ( DP_Print && nd_sba_pot ) {
2841: if ( sig->pos != pos ) {
2842: fprintf(asir_out,"[%d]",sig->pos);
2843: pos = sig->pos;
2844: }
2845: }
1.24 noro 2846: stat = nd_sp(m,0,l,&h);
1.41 noro 2847: #else
2848: l1 = find_smallest_lcm(l);
2849: if ( l1 == 0 ) {
2850: if ( DP_Print ) fprintf(asir_out,"M");
2851: Nnominimal++;
2852: continue;
2853: }
2854: if ( SG(l1) != sugar ) {
2855: sugar = SG(l1);
2856: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2857: }
2858: sig = l1->sig;
2859: if ( DP_Print && nd_sba_pot ) {
2860: if ( sig->pos != pos ) {
2861: fprintf(asir_out,"[%d]",sig->pos);
2862: pos = sig->pos;
2863: }
2864: }
2865: stat = nd_sp(m,0,l1,&h);
2866: #endif
1.24 noro 2867: if ( !stat ) {
2868: NEXT(l) = d; d = l;
2869: d = nd_reconstruct(0,d);
2870: goto again;
2871: }
1.31 noro 2872: get_eg(&eg1);
1.25 noro 2873: #if USE_GEOBUCKET
1.39 noro 2874: 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 2875: #else
1.39 noro 2876: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.24 noro 2877: #endif
1.31 noro 2878: get_eg(&eg2);
1.24 noro 2879: if ( !stat ) {
2880: NEXT(l) = d; d = l;
2881: d = nd_reconstruct(0,d);
2882: goto again;
2883: } else if ( stat == -1 ) {
1.41 noro 2884: Nnfs++;
1.24 noro 2885: if ( DP_Print ) { printf("S"); fflush(stdout); }
1.27 noro 2886: FREENDP(l);
1.24 noro 2887: } else if ( nf ) {
1.41 noro 2888: Nnfnz++;
2889: if ( DP_Print ) {
2890: if ( nd_sba_redundant_check ) {
2891: if ( ndl_find_reducer_nonsig(HDL(nf)) >= 0 ) {
2892: Nredundant++;
2893: printf("R");
2894: } else
2895: printf("+");
2896: } else
2897: printf("+");
2898: fflush(stdout);
2899: }
1.31 noro 2900: add_eg(&eg_nf,&eg1,&eg2);
1.24 noro 2901: hc = HCU(nf);
2902: nd_removecont(m,nf);
2903: nfv = ndtondv(m,nf); nd_free(nf);
2904: nh = ndv_newps(m,nfv,0);
1.26 noro 2905:
1.30 noro 2906: d = update_pairs_s(d,nh,syzlist);
1.29 noro 2907: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.24 noro 2908: FREENDP(l);
2909: } else {
1.41 noro 2910: Nnfz++;
1.31 noro 2911: add_eg(&eg_nfzero,&eg1,&eg2);
1.24 noro 2912: // syzygy
1.27 noro 2913: get_eg(&eg1);
1.24 noro 2914: d = remove_spair_s(d,sig);
1.27 noro 2915: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 2916: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.24 noro 2917: if ( DP_Print ) { printf("."); fflush(stdout); }
2918: FREENDP(l);
2919: }
2920: }
1.30 noro 2921: g = conv_ilist_s(nd_demand,0,indp);
1.26 noro 2922: if ( DP_Print ) {
1.41 noro 2923: printf("\nnd_sba done. nd_add=%d,Nsyz=%d,Nsamesig=%d,Nnominimal=%d\n",Nnd_add,Nsyz,Nsamesig,Nnominimal);
2924: printf("Nnfnz=%d,Nnfz=%d,Nnfsingular=%d\n",Nnfnz,Nnfz,Nnfs);
2925: fflush(stdout);
2926: if ( nd_sba_redundant_check )
2927: printf("Nredundant=%d\n",Nredundant);
1.26 noro 2928: fflush(stdout);
2929: print_eg("create",&eg_create);
2930: print_eg("merge",&eg_merge);
1.27 noro 2931: print_eg("remove",&eg_remove);
1.31 noro 2932: print_eg("nf",&eg_nf);
2933: print_eg("nfzero",&eg_nfzero);
1.27 noro 2934: printf("\n");
1.26 noro 2935: }
1.44 ! noro 2936: if ( nd_sba_syz ) {
! 2937: NODE hsyz,tsyz,prev;
! 2938:
! 2939: hsyz = 0;
! 2940: for ( i = 0; i < ngen; i++ ) {
! 2941: tsyz = syzlist[i];
! 2942: for ( prev = 0; tsyz != 0; prev = tsyz, tsyz = NEXT(tsyz))
! 2943: BDY(tsyz) = (pointer)sigtodpm((SIG)BDY(tsyz));
! 2944: if ( prev != 0 ) {
! 2945: prev->next = hsyz; hsyz = syzlist[i];
! 2946: }
! 2947: }
! 2948: *syzp = hsyz;
! 2949: } else *syzp = 0;
1.24 noro 2950: return g;
2951: }
2952:
1.1 noro 2953: /* splist = [[i1,i2],...] */
2954:
2955: int check_splist(int m,NODE splist)
2956: {
2957: NODE t,p;
2958: ND_pairs d,r,l;
2959: int stat;
2960: ND h,nf;
2961:
2962: for ( d = 0, t = splist; t; t = NEXT(t) ) {
2963: p = BDY((LIST)BDY(t));
1.6 noro 2964: NEXTND_pairs(d,r);
2965: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
2966: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 2967: SG(r) = TD(LCM(r)); /* XXX */
2968: }
2969: if ( d ) NEXT(r) = 0;
2970:
1.6 noro 2971: while ( d ) {
1.1 noro 2972: again:
1.6 noro 2973: l = nd_minp(d,&d);
2974: stat = nd_sp(m,0,l,&h);
2975: if ( !stat ) {
2976: NEXT(l) = d; d = l;
2977: d = nd_reconstruct(0,d);
2978: goto again;
2979: }
1.39 noro 2980: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.6 noro 2981: if ( !stat ) {
2982: NEXT(l) = d; d = l;
2983: d = nd_reconstruct(0,d);
2984: goto again;
2985: } else if ( nf ) return 0;
1.1 noro 2986: if ( DP_Print) { printf("."); fflush(stdout); }
1.6 noro 2987: }
1.1 noro 2988: if ( DP_Print) { printf("done.\n"); fflush(stdout); }
2989: return 1;
2990: }
2991:
2992: int check_splist_f4(int m,NODE splist)
2993: {
2994: UINT *s0vect;
1.6 noro 2995: PGeoBucket bucket;
1.1 noro 2996: NODE p,rp0,t;
2997: ND_pairs d,r,l,ll;
2998: int col,stat;
2999:
3000: for ( d = 0, t = splist; t; t = NEXT(t) ) {
3001: p = BDY((LIST)BDY(t));
1.6 noro 3002: NEXTND_pairs(d,r);
3003: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
3004: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 3005: SG(r) = TD(LCM(r)); /* XXX */
3006: }
3007: if ( d ) NEXT(r) = 0;
3008:
1.6 noro 3009: while ( d ) {
3010: l = nd_minsugarp(d,&d);
3011: bucket = create_pbucket();
3012: stat = nd_sp_f4(m,0,l,bucket);
3013: if ( !stat ) {
3014: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3015: NEXT(ll) = d; d = l;
3016: d = nd_reconstruct(0,d);
3017: continue;
3018: }
3019: if ( bucket->m < 0 ) continue;
3020: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
3021: if ( !col ) {
3022: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
3023: NEXT(ll) = d; d = l;
3024: d = nd_reconstruct(0,d);
3025: continue;
1.1 noro 3026: }
1.6 noro 3027: if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0;
3028: }
3029: return 1;
1.1 noro 3030: }
3031:
3032: int do_diagonalize_trace(int sugar,int m)
3033: {
1.6 noro 3034: int i,nh,stat;
3035: NODE r,g,t;
3036: ND h,nf,nfq,s,head;
3037: NDV nfv,nfqv;
3038: Q q,den,num;
3039: union oNDC hc;
3040: NODE node;
3041: LIST l;
3042: Z iq;
3043: P cont,cont1;
1.1 noro 3044:
1.6 noro 3045: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
3046: if ( nd_gentrace ) {
3047: /* Trace = [1,index,1,1] */
3048: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
3049: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3050: }
3051: /* for nd_ps */
3052: s = ndvtond(m,nd_ps[i]);
3053: s = nd_separate_head(s,&head);
3054: stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
3055: if ( !stat ) return 0;
3056: nf = nd_add(m,head,nf);
3057: ndv_free(nd_ps[i]);
3058: nd_ps[i] = ndtondv(m,nf);
3059: nd_free(nf);
3060:
3061: /* for nd_ps_trace */
3062: if ( nd_demand )
3063: nfv = ndv_load(i);
3064: else
3065: nfv = nd_ps_trace[i];
3066: s = ndvtond(0,nfv);
3067: s = nd_separate_head(s,&head);
3068: stat = nd_nf(0,head,s,nd_ps_trace,1,&nf);
3069: if ( !stat ) return 0;
3070: ndv_free(nfv);
3071: hc = HCU(nf); nd_removecont(0,nf);
3072: /* exact division */
1.1 noro 3073: cont = ndc_div(0,hc,HCU(nf));
1.6 noro 3074: if ( nd_gentrace ) finalize_tracelist(i,cont);
3075: nfv = ndtondv(0,nf);
3076: nd_free(nf);
3077: nd_bound[i] = ndv_compute_bound(nfv);
3078: register_hcf(nfv);
3079: if ( nd_demand ) {
3080: ndv_save(nfv,i);
3081: ndv_free(nfv);
3082: } else
3083: nd_ps_trace[i] = nfv;
3084: }
3085: return 1;
1.1 noro 3086: }
3087:
3088: static struct oEGT eg_invdalg;
3089: struct oEGT eg_le;
3090:
3091: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
3092: {
3093: NODE tn;
3094: P p1;
3095:
3096: for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
3097: substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
3098: }
3099: *r = p;
3100: }
3101:
3102: NODE nd_gb_trace(int m,int ishomo,int **indp)
3103: {
1.6 noro 3104: int i,nh,sugar,stat;
3105: NODE r,g,t;
3106: ND_pairs d;
3107: ND_pairs l;
3108: ND h,nf,nfq,s,head;
3109: NDV nfv,nfqv;
3110: Z q,den,num;
3111: P hc;
3112: union oNDC dn,hnfq;
3113: struct oEGT eg_monic,egm0,egm1;
3114: int diag_count = 0;
3115: P cont;
3116: LIST list;
3117:
3118: init_eg(&eg_monic);
3119: init_eg(&eg_invdalg);
3120: init_eg(&eg_le);
3121: g = 0; d = 0;
3122: for ( i = 0; i < nd_psn; i++ ) {
3123: d = update_pairs(d,g,i,0);
3124: g = update_base(g,i);
3125: }
3126: sugar = 0;
3127: while ( d ) {
1.1 noro 3128: again:
1.6 noro 3129: l = nd_minp(d,&d);
3130: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
3131: if ( SG(l) != sugar ) {
1.1 noro 3132: #if 1
1.6 noro 3133: if ( ishomo ) {
3134: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3135: stat = do_diagonalize_trace(sugar,m);
3136: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3137: diag_count = 0;
1.1 noro 3138: if ( !stat ) {
1.6 noro 3139: NEXT(l) = d; d = l;
3140: d = nd_reconstruct(1,d);
3141: goto again;
1.1 noro 3142: }
1.6 noro 3143: }
3144: #endif
3145: sugar = SG(l);
3146: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
3147: }
3148: stat = nd_sp(m,0,l,&h);
3149: if ( !stat ) {
3150: NEXT(l) = d; d = l;
3151: d = nd_reconstruct(1,d);
3152: goto again;
3153: }
1.1 noro 3154: #if USE_GEOBUCKET
1.39 noro 3155: stat = nd_nf_pbucket(m,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3156: #else
1.39 noro 3157: stat = nd_nf(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.1 noro 3158: #endif
1.6 noro 3159: if ( !stat ) {
3160: NEXT(l) = d; d = l;
3161: d = nd_reconstruct(1,d);
3162: goto again;
3163: } else if ( nf ) {
3164: if ( nd_demand ) {
3165: nfqv = ndv_load(nd_psn);
3166: nfq = ndvtond(0,nfqv);
3167: } else
3168: nfq = 0;
3169: if ( !nfq ) {
1.39 noro 3170: if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!nd_top&&!Top,&nfq) ) {
1.6 noro 3171: NEXT(l) = d; d = l;
3172: d = nd_reconstruct(1,d);
3173: goto again;
3174: }
3175: }
3176: if ( nfq ) {
3177: /* m|HC(nfq) => failure */
3178: if ( nd_vc ) {
3179: nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Z)hc;
3180: } else
3181: q = HCZ(nfq);
3182: if ( !remqi((Q)q,m) ) return 0;
3183:
3184: if ( DP_Print ) { printf("+"); fflush(stdout); }
3185: hnfq = HCU(nfq);
3186: if ( nd_nalg ) {
3187: /* m|DN(HC(nf)^(-1)) => failure */
3188: get_eg(&egm0);
3189: if ( !nd_monic(m,&nfq) ) return 0;
3190: get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
3191: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3192: nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
3193: } else {
3194: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
3195: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
3196: }
3197: if ( nd_gentrace ) {
3198: /* exact division */
3199: cont = ndc_div(0,hnfq,HCU(nfqv));
3200: if ( !UNIQ(cont) ) {
3201: t = mknode(4,NULLP,NULLP,NULLP,cont);
3202: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
3203: nd_tracelist = t;
3204: }
3205: }
1.24 noro 3206: nh = ndv_newps(0,nfv,nfqv);
1.6 noro 3207: if ( ishomo && ++diag_count == diag_period ) {
3208: diag_count = 0;
3209: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3210: stat = do_diagonalize_trace(sugar,m);
3211: if ( DP_Print > 2 ) fprintf(asir_out,"|");
3212: if ( !stat ) {
1.1 noro 3213: NEXT(l) = d; d = l;
3214: d = nd_reconstruct(1,d);
3215: goto again;
1.6 noro 3216: }
1.1 noro 3217: }
1.6 noro 3218: d = update_pairs(d,g,nh,0);
3219: g = update_base(g,nh);
3220: } else {
3221: if ( DP_Print ) { printf("*"); fflush(stdout); }
3222: }
3223: } else {
3224: if ( DP_Print ) { printf("."); fflush(stdout); }
1.1 noro 3225: }
1.6 noro 3226: FREENDP(l);
3227: }
3228: if ( nd_nalg ) {
3229: if ( DP_Print ) {
3230: print_eg("monic",&eg_monic);
3231: print_eg("invdalg",&eg_invdalg);
3232: print_eg("le",&eg_le);
1.1 noro 3233: }
1.6 noro 3234: }
1.1 noro 3235: conv_ilist(nd_demand,1,g,indp);
1.41 noro 3236: if ( DP_Print ) { printf("\nnd_gb_trace done.\n"); fflush(stdout); }
1.6 noro 3237: return g;
1.1 noro 3238: }
3239:
3240: int ndv_compare(NDV *p1,NDV *p2)
3241: {
3242: return DL_COMPARE(HDL(*p1),HDL(*p2));
3243: }
3244:
3245: int ndv_compare_rev(NDV *p1,NDV *p2)
3246: {
3247: return -DL_COMPARE(HDL(*p1),HDL(*p2));
3248: }
3249:
3250: int ndvi_compare(NDVI p1,NDVI p2)
3251: {
3252: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
3253: }
3254:
3255: int ndvi_compare_rev(NDVI p1,NDVI p2)
3256: {
3257: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3258: }
3259:
3260: NODE ndv_reduceall(int m,NODE f)
3261: {
3262: int i,j,n,stat;
3263: ND nf,g,head;
3264: NODE t,a0,a;
3265: union oNDC dn;
3266: Q q,num,den;
3267: NODE node;
3268: LIST l;
3269: Z iq,jq;
3270: int *perm;
3271: union oNDC hc;
3272: P cont,cont1;
3273:
3274: if ( nd_nora ) return f;
3275: n = length(f);
1.24 noro 3276: ndv_setup(m,0,f,0,1,0);
1.1 noro 3277: perm = (int *)MALLOC(n*sizeof(int));
3278: if ( nd_gentrace ) {
3279: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3280: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3281: }
3282: for ( i = 0; i < n; ) {
3283: if ( nd_gentrace ) {
3284: /* Trace = [1,index,1,1] */
1.6 noro 3285: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3286: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3287: }
3288: g = ndvtond(m,nd_ps[i]);
3289: g = nd_separate_head(g,&head);
1.6 noro 3290: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3291: if ( !stat )
3292: nd_reconstruct(0,0);
3293: else {
3294: if ( DP_Print ) { printf("."); fflush(stdout); }
3295: ndv_free(nd_ps[i]);
3296: hc = HCU(nf); nd_removecont(m,nf);
3297: if ( nd_gentrace ) {
3298: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3299: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3300: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3301: }
1.6 noro 3302: /* exact division */
1.1 noro 3303: cont = ndc_div(m,hc,HCU(nf));
3304: finalize_tracelist(perm[i],cont);
3305: }
3306: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3307: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3308: i++;
3309: }
3310: }
3311: if ( DP_Print ) { printf("\n"); }
3312: for ( a0 = 0, i = 0; i < n; i++ ) {
3313: NEXTNODE(a0,a);
3314: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3315: else {
3316: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3317: BDY(a) = (pointer)nd_ps[j];
3318: }
3319: }
3320: NEXT(a) = 0;
3321: return a0;
3322: }
3323:
1.41 noro 3324: int ndplength(ND_pairs d)
3325: {
3326: int i;
3327: for ( i = 0; d; i++ ) d = NEXT(d);
3328: return i;
3329: }
3330:
1.1 noro 3331: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3332: {
3333: ND_pairs d1,nd,cur,head,prev,remove;
1.41 noro 3334: int len0;
1.1 noro 3335:
3336: if ( !g ) return d;
3337: /* for testing */
3338: if ( gensyz && nd_gensyz == 2 ) {
3339: d1 = nd_newpairs(g,t);
3340: if ( !d )
3341: return d1;
3342: else {
3343: nd = d;
3344: while ( NEXT(nd) ) nd = NEXT(nd);
3345: NEXT(nd) = d1;
3346: return d;
3347: }
3348: }
3349: d = crit_B(d,t);
3350: d1 = nd_newpairs(g,t);
1.41 noro 3351: len0 = ndplength(d1);
1.1 noro 3352: d1 = crit_M(d1);
3353: d1 = crit_F(d1);
1.41 noro 3354: NcriMF += len0-ndplength(d1);
1.1 noro 3355: if ( gensyz || do_weyl )
3356: head = d1;
3357: else {
3358: prev = 0; cur = head = d1;
3359: while ( cur ) {
3360: if ( crit_2( cur->i1,cur->i2 ) ) {
3361: remove = cur;
3362: if ( !prev ) head = cur = NEXT(cur);
3363: else cur = NEXT(prev) = NEXT(cur);
1.41 noro 3364: FREENDP(remove); Ncri2++;
1.1 noro 3365: } else {
3366: prev = cur; cur = NEXT(cur);
3367: }
3368: }
3369: }
3370: if ( !d )
3371: return head;
3372: else {
3373: nd = d;
3374: while ( NEXT(nd) ) nd = NEXT(nd);
3375: NEXT(nd) = head;
3376: return d;
3377: }
3378: }
3379:
1.24 noro 3380: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3381:
1.30 noro 3382: ND_pairs update_pairs_s( ND_pairs d, int t,NODE *syz)
1.24 noro 3383: {
3384: ND_pairs d1;
1.26 noro 3385: struct oEGT eg1,eg2,eg3;
1.24 noro 3386:
1.30 noro 3387: if ( !t ) return d;
1.26 noro 3388: get_eg(&eg1);
1.30 noro 3389: d1 = nd_newpairs_s(t,syz);
1.26 noro 3390: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3391: d = merge_pairs_s(d,d1);
1.26 noro 3392: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3393: return d;
3394: }
1.1 noro 3395:
3396: ND_pairs nd_newpairs( NODE g, int t )
3397: {
3398: NODE h;
3399: UINT *dl;
3400: int ts,s,i,t0,min,max;
3401: ND_pairs r,r0;
3402:
3403: dl = DL(nd_psh[t]);
3404: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3405: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3406: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3407: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3408: continue;
3409: if ( nd_gbblock ) {
3410: t0 = (long)BDY(h);
3411: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3412: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3413: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3414: break;
3415: }
3416: if ( nd_gbblock[i] >= 0 )
3417: continue;
3418: }
1.41 noro 3419: NEXTND_pairs(r0,r); Npairs++;
1.1 noro 3420: r->i1 = (long)BDY(h);
3421: r->i2 = t;
3422: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3423: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3424: SG(r) = MAX(s,ts) + TD(LCM(r));
3425: /* experimental */
3426: if ( nd_sugarweight )
3427: r->sugar2 = ndl_weight2(r->lcm);
3428: }
3429: if ( r0 ) NEXT(r) = 0;
3430: return r0;
3431: }
3432:
1.24 noro 3433: int comp_sig(SIG s1,SIG s2)
3434: {
1.38 noro 3435: if ( nd_sba_pot ) {
3436: if ( s1->pos > s2->pos ) return 1;
3437: else if ( s1->pos < s2->pos ) return -1;
3438: else return (*cmpdl)(nd_nvar,s1->dl,s2->dl);
3439: } else {
3440: static DL m1,m2;
1.44 ! noro 3441: static int nvar = 0;
1.38 noro 3442: int ret;
3443:
3444: if ( nvar != nd_nvar ) {
3445: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
3446: }
3447: _adddl(nd_nvar,s1->dl,nd_sba_hm[s1->pos],m1);
3448: _adddl(nd_nvar,s2->dl,nd_sba_hm[s2->pos],m2);
3449: ret = (*cmpdl)(nd_nvar,m1,m2);
3450: if ( ret != 0 ) return ret;
3451: else if ( s1->pos > s2->pos ) return 1;
3452: else if ( s1->pos < s2->pos ) return -1;
3453: else return 0;
1.24 noro 3454: }
3455: }
3456:
3457: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3458: {
3459: int ret,s1,s2;
3460: RHist p1,p2;
3461: static int wpd;
3462: static UINT *lcm;
3463:
3464: sp->i1 = i1;
3465: sp->i2 = i2;
3466: p1 = nd_psh[i1];
3467: p2 = nd_psh[i2];
3468: ndl_lcm(DL(p1),DL(p2),sp->lcm);
3469: s1 = SG(p1)-TD(DL(p1));
3470: s2 = SG(p2)-TD(DL(p2));
3471: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
3472:
1.26 noro 3473: if ( wpd != nd_wpd ) {
1.24 noro 3474: wpd = nd_wpd;
3475: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
3476: }
3477: // DL(sig1) <- sp->lcm
3478: // DL(sig1) -= DL(p1)
3479: // DL(sig1) += DL(p1->sig)
1.27 noro 3480: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 3481: _ndltodl(lcm,DL(sig1));
3482: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
3483: sig1->pos = p1->sig->pos;
3484:
3485: // DL(sig2) <- sp->lcm
3486: // DL(sig2) -= DL(p2)
3487: // DL(sig2) += DL(p2->sig)
1.27 noro 3488: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 3489: _ndltodl(lcm,DL(sig2));
3490: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
3491: sig2->pos = p2->sig->pos;
3492:
3493: ret = comp_sig(sig1,sig2);
3494: if ( ret == 0 ) return 0;
3495: else if ( ret > 0 ) sp->sig = sig1;
3496: else sp->sig = sig2;
3497: return 1;
3498: }
3499:
3500: SIG dup_sig(SIG sig)
3501: {
3502: SIG r;
3503:
3504: if ( !sig ) return 0;
3505: else {
3506: NEWSIG(r);
3507: _copydl(nd_nvar,DL(sig),DL(r));
3508: r->pos = sig->pos;
3509: return r;
3510: }
3511: }
3512:
3513: void dup_ND_pairs(ND_pairs to,ND_pairs from)
3514: {
3515: to->i1 = from->i1;
3516: to->i2 = from->i2;
3517: to->sugar = from->sugar;
3518: to->sugar2 = from->sugar2;
3519: ndl_copy(from->lcm,to->lcm);
3520: to->sig = dup_sig(from->sig);
3521: }
3522:
3523: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
3524: {
3525: struct oND_pairs root;
3526: ND_pairs q1,q2,r0,r;
3527: int ret;
3528:
3529: r = &root;
3530: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
3531: ret = comp_sig(q1->sig,q2->sig);
3532: if ( ret < 0 ) {
3533: r->next = q1; r = q1; q1 = q1->next;
3534: } else if ( ret > 0 ) {
3535: r->next = q2; r = q2; q2 = q2->next;
3536: } else {
3537: ret = DL_COMPARE(q1->lcm,q2->lcm);
1.35 noro 3538: Nsamesig++;
1.24 noro 3539: if ( ret < 0 ) {
3540: r->next = q1; r = q1; q1 = q1->next;
3541: q2 = q2->next;
3542: } else {
3543: r->next = q2; r = q2; q2 = q2->next;
3544: q1 = q1->next;
3545: }
3546: }
3547: }
3548: if ( q1 ) {
3549: r->next = q1;
3550: } else {
3551: r->next = q2;
3552: }
3553: return root.next;
3554: }
3555:
3556: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
3557: {
3558: ND_pairs p,prev;
3559: int ret;
3560:
3561: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
3562: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
3563: break;
3564: }
3565: if ( ret == 0 ) {
3566: ret = DL_COMPARE(s->lcm,p->lcm);
3567: if ( ret < 0 ) {
3568: // replace p with s
3569: s->next = p->next;
3570: if ( prev == 0 ) {
3571: return s;
3572: } else {
3573: prev->next = s;
3574: return l;
3575: }
3576: } else
3577: return l;
3578: } else {
3579: // insert s between prev and p
3580: s->next = p;
3581: if ( prev == 0 ) {
3582: return s;
3583: } else {
3584: prev->next = s;
3585: return l;
3586: }
3587: }
3588: }
3589:
1.29 noro 3590: INLINE int __dl_redble(DL d1,DL d2,int nvar)
3591: {
3592: int i;
3593:
3594: if ( d1->td > d2->td )
3595: return 0;
3596: for ( i = nvar-1; i >= 0; i-- )
3597: if ( d1->d[i] > d2->d[i] )
3598: break;
3599: if ( i >= 0 )
3600: return 0;
3601: else
3602: return 1;
3603: }
3604:
1.30 noro 3605: ND_pairs nd_newpairs_s(int t, NODE *syz)
1.24 noro 3606: {
3607: NODE h,s;
3608: UINT *dl;
1.27 noro 3609: int ts,ret,i;
1.24 noro 3610: ND_pairs r,r0,_sp,sp;
1.29 noro 3611: SIG spsig,tsig;
1.44 ! noro 3612: static int nvar = 0;
1.29 noro 3613: static SIG _sig1,_sig2;
1.26 noro 3614: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 3615:
3616: NEWND_pairs(_sp);
1.29 noro 3617: if ( !_sig1 || nvar != nd_nvar ) {
3618: nvar = nd_nvar; NEWSIG(_sig1); NEWSIG(_sig2);
3619: }
1.24 noro 3620: r0 = 0;
1.27 noro 3621: for ( i = 0; i < t; i++ ) {
3622: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
1.24 noro 3623: if ( ret ) {
3624: spsig = _sp->sig;
1.29 noro 3625: for ( s = syz[spsig->pos]; s; s = s->next ) {
1.24 noro 3626: tsig = (SIG)s->body;
1.29 noro 3627: if ( _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
1.24 noro 3628: break;
3629: }
3630: if ( s == 0 ) {
3631: NEWND_pairs(sp);
3632: dup_ND_pairs(sp,_sp);
3633: r0 = insert_pair_s(r0,sp);
1.26 noro 3634: } else
3635: Nsyz++;
1.24 noro 3636: }
3637: }
3638: return r0;
3639: }
3640:
1.1 noro 3641: /* ipair = [i1,i2],[i1,i2],... */
3642: ND_pairs nd_ipairtospair(NODE ipair)
3643: {
3644: int s1,s2;
3645: NODE tn,t;
3646: ND_pairs r,r0;
3647:
3648: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
3649: NEXTND_pairs(r0,r);
3650: tn = BDY((LIST)BDY(t));
1.6 noro 3651: r->i1 = ZTOS((Q)ARG0(tn));
3652: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 3653: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
3654: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3655: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
3656: SG(r) = MAX(s1,s2) + TD(LCM(r));
3657: /* experimental */
3658: if ( nd_sugarweight )
3659: r->sugar2 = ndl_weight2(r->lcm);
3660: }
3661: if ( r0 ) NEXT(r) = 0;
3662: return r0;
3663: }
3664:
3665: /* kokokara */
3666:
3667: ND_pairs crit_B( ND_pairs d, int s )
3668: {
3669: ND_pairs cur,head,prev,remove;
3670: UINT *t,*tl,*lcm;
3671: int td,tdl;
3672:
3673: if ( !d ) return 0;
3674: t = DL(nd_psh[s]);
3675: prev = 0;
3676: head = cur = d;
3677: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
3678: while ( cur ) {
3679: tl = cur->lcm;
3680: if ( ndl_reducible(tl,t) ) {
3681: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
3682: if ( !ndl_equal(lcm,tl) ) {
3683: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
3684: if (!ndl_equal(lcm,tl)) {
3685: remove = cur;
3686: if ( !prev ) {
3687: head = cur = NEXT(cur);
3688: } else {
3689: cur = NEXT(prev) = NEXT(cur);
3690: }
1.41 noro 3691: FREENDP(remove); NcriB++;
1.1 noro 3692: } else {
3693: prev = cur; cur = NEXT(cur);
3694: }
3695: } else {
3696: prev = cur; cur = NEXT(cur);
3697: }
3698: } else {
3699: prev = cur; cur = NEXT(cur);
3700: }
3701: }
3702: return head;
3703: }
3704:
3705: ND_pairs crit_M( ND_pairs d1 )
3706: {
3707: ND_pairs e,d2,d3,dd,p;
3708: UINT *id,*jd;
3709:
3710: if ( !d1 ) return d1;
3711: for ( dd = 0, e = d1; e; e = d3 ) {
3712: if ( !(d2 = NEXT(e)) ) {
3713: NEXT(e) = dd;
3714: return e;
3715: }
3716: id = LCM(e);
3717: for ( d3 = 0; d2; d2 = p ) {
3718: p = NEXT(d2);
3719: jd = LCM(d2);
3720: if ( ndl_equal(jd,id) )
3721: ;
3722: else if ( TD(jd) > TD(id) )
3723: if ( ndl_reducible(jd,id) ) continue;
3724: else ;
3725: else if ( ndl_reducible(id,jd) ) goto delit;
3726: NEXT(d2) = d3;
3727: d3 = d2;
3728: }
3729: NEXT(e) = dd;
3730: dd = e;
3731: continue;
3732: /**/
3733: delit: NEXT(d2) = d3;
3734: d3 = d2;
3735: for ( ; p; p = d2 ) {
3736: d2 = NEXT(p);
3737: NEXT(p) = d3;
3738: d3 = p;
3739: }
3740: FREENDP(e);
3741: }
3742: return dd;
3743: }
3744:
3745: ND_pairs crit_F( ND_pairs d1 )
3746: {
3747: ND_pairs rest, head,remove;
3748: ND_pairs last, p, r, w;
3749: int s;
3750:
3751: if ( !d1 ) return d1;
3752: for ( head = last = 0, p = d1; NEXT(p); ) {
3753: r = w = equivalent_pairs(p,&rest);
3754: s = SG(r);
3755: w = NEXT(w);
3756: while ( w ) {
3757: if ( crit_2(w->i1,w->i2) ) {
3758: r = w;
3759: w = NEXT(w);
3760: while ( w ) {
3761: remove = w;
3762: w = NEXT(w);
3763: FREENDP(remove);
3764: }
3765: break;
3766: } else if ( SG(w) < s ) {
3767: FREENDP(r);
3768: r = w;
3769: s = SG(r);
3770: w = NEXT(w);
3771: } else {
3772: remove = w;
3773: w = NEXT(w);
3774: FREENDP(remove);
3775: }
3776: }
3777: if ( last ) NEXT(last) = r;
3778: else head = r;
3779: NEXT(last = r) = 0;
3780: p = rest;
3781: if ( !p ) return head;
3782: }
3783: if ( !last ) return p;
3784: NEXT(last) = p;
3785: return head;
3786: }
3787:
3788: int crit_2( int dp1, int dp2 )
3789: {
3790: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
3791: }
3792:
3793: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
3794: {
3795: ND_pairs w,p,r,s;
3796: UINT *d;
3797:
3798: w = d1;
3799: d = LCM(w);
3800: s = NEXT(w);
3801: NEXT(w) = 0;
3802: for ( r = 0; s; s = p ) {
3803: p = NEXT(s);
3804: if ( ndl_equal(d,LCM(s)) ) {
3805: NEXT(s) = w; w = s;
3806: } else {
3807: NEXT(s) = r; r = s;
3808: }
3809: }
3810: *prest = r;
3811: return w;
3812: }
3813:
3814: NODE update_base(NODE nd,int ndp)
3815: {
3816: UINT *dl, *dln;
3817: NODE last, p, head;
3818:
3819: dl = DL(nd_psh[ndp]);
3820: for ( head = last = 0, p = nd; p; ) {
3821: dln = DL(nd_psh[(long)BDY(p)]);
3822: if ( ndl_reducible( dln, dl ) ) {
3823: p = NEXT(p);
3824: if ( last ) NEXT(last) = p;
3825: } else {
3826: if ( !last ) head = p;
3827: p = NEXT(last = p);
3828: }
3829: }
3830: head = append_one(head,ndp);
3831: return head;
3832: }
3833:
3834: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
3835: {
3836: ND_pairs m,ml,p,l;
3837: UINT *lcm;
3838: int s,td,len,tlen,c,c1;
3839:
3840: if ( !(p = NEXT(m = d)) ) {
3841: *prest = p;
3842: NEXT(m) = 0;
3843: return m;
3844: }
3845: if ( !NoSugar ) {
3846: if ( nd_sugarweight ) {
3847: s = m->sugar2;
3848: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3849: if ( (p->sugar2 < s)
3850: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3851: ml = l; m = p; s = m->sugar2;
3852: }
3853: } else {
3854: s = SG(m);
3855: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3856: if ( (SG(p) < s)
3857: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3858: ml = l; m = p; s = SG(m);
3859: }
3860: }
3861: } else {
3862: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3863: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
3864: ml = l; m = p; s = SG(m);
3865: }
3866: }
3867: if ( !ml ) *prest = NEXT(m);
3868: else {
3869: NEXT(ml) = NEXT(m);
3870: *prest = d;
3871: }
3872: NEXT(m) = 0;
3873: return m;
3874: }
3875:
3876: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
3877: {
3878: int msugar,i;
3879: ND_pairs t,dm0,dm,dr0,dr;
3880:
3881: if ( nd_sugarweight ) {
3882: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
3883: if ( t->sugar2 < msugar ) msugar = t->sugar2;
3884: dm0 = 0; dr0 = 0;
3885: for ( i = 0, t = d; t; t = NEXT(t) )
3886: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
3887: if ( dm0 ) NEXT(dm) = t;
3888: else dm0 = t;
3889: dm = t;
3890: i++;
3891: } else {
3892: if ( dr0 ) NEXT(dr) = t;
3893: else dr0 = t;
3894: dr = t;
3895: }
3896: } else {
3897: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
3898: if ( SG(t) < msugar ) msugar = SG(t);
3899: dm0 = 0; dr0 = 0;
3900: for ( i = 0, t = d; t; t = NEXT(t) )
3901: if ( i < nd_f4_nsp && SG(t) == msugar ) {
3902: if ( dm0 ) NEXT(dm) = t;
3903: else dm0 = t;
3904: dm = t;
3905: i++;
3906: } else {
3907: if ( dr0 ) NEXT(dr) = t;
3908: else dr0 = t;
3909: dr = t;
3910: }
3911: }
3912: NEXT(dm) = 0;
3913: if ( dr0 ) NEXT(dr) = 0;
3914: *prest = dr0;
3915: return dm0;
3916: }
3917:
1.28 noro 3918: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
3919: {
3920: int msugar;
3921: ND_pairs t,last;
3922:
3923: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
3924: if ( SG(t) == msugar ) last = t;
3925: *prest = last->next;
3926: last->next = 0;
3927: return d;
3928: }
3929:
1.1 noro 3930: int nd_tdeg(NDV c)
3931: {
3932: int wmax = 0;
3933: int i,len;
3934: NMV a;
3935:
3936: len = LEN(c);
3937: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
3938: wmax = MAX(TD(DL(a)),wmax);
3939: return wmax;
3940: }
3941:
1.24 noro 3942: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 3943: {
3944: int len;
3945: RHist r;
3946: NDV b;
3947: NODE tn;
3948: LIST l;
3949: Z iq;
3950:
3951: if ( nd_psn == nd_pslen ) {
3952: nd_pslen *= 2;
3953: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
3954: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
3955: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
3956: nd_bound = (UINT **)
3957: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
3958: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
3959: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
3960: }
3961: NEWRHist(r); nd_psh[nd_psn] = r;
3962: nd_ps[nd_psn] = a;
3963: if ( aq ) {
3964: nd_ps_trace[nd_psn] = aq;
3965: if ( !m ) {
3966: register_hcf(aq);
3967: } else if ( m == -2 ) {
3968: /* do nothing */
3969: } else
3970: error("ndv_newps : invalud modulus");
3971: nd_bound[nd_psn] = ndv_compute_bound(aq);
3972: #if 1
3973: SG(r) = SG(aq);
3974: #else
3975: SG(r) = nd_tdeg(aq);
3976: #endif
3977: ndl_copy(HDL(aq),DL(r));
1.24 noro 3978: r->sig = dup_sig(aq->sig);
1.1 noro 3979: } else {
3980: if ( !m ) register_hcf(a);
3981: nd_bound[nd_psn] = ndv_compute_bound(a);
3982: #if 1
3983: SG(r) = SG(a);
3984: #else
3985: SG(r) = nd_tdeg(a);
3986: #endif
3987: ndl_copy(HDL(a),DL(r));
1.24 noro 3988: r->sig = dup_sig(a->sig);
1.1 noro 3989: }
3990: if ( nd_demand ) {
3991: if ( aq ) {
3992: ndv_save(nd_ps_trace[nd_psn],nd_psn);
3993: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3994: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3995: nd_ps_trace[nd_psn] = 0;
3996: } else {
3997: ndv_save(nd_ps[nd_psn],nd_psn);
3998: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
3999: nd_ps[nd_psn] = 0;
4000: }
4001: }
4002: if ( nd_gentrace ) {
4003: /* reverse the tracelist and append it to alltracelist */
4004: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 4005: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 4006: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
4007: }
4008: return nd_psn++;
4009: }
4010:
4011: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
4012: /* return 1 if success, 0 if failure (HC(a mod p)) */
4013:
1.24 noro 4014: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 4015: {
1.6 noro 4016: int i,j,td,len,max;
4017: NODE s,s0,f0,tn;
4018: UINT *d;
4019: RHist r;
4020: NDVI w;
4021: NDV a,am;
4022: union oNDC hc;
4023: NODE node;
4024: P hcp;
4025: Z iq,jq;
4026: LIST l;
4027:
4028: nd_found = 0; nd_notfirst = 0; nd_create = 0;
4029: /* initialize the tracelist */
4030: nd_tracelist = 0;
4031:
4032: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
4033: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
4034: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
4035: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
4036: if ( !dont_sort ) {
4037: /* XXX heuristic */
1.26 noro 4038: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 4039: qsort(w,nd_psn,sizeof(struct oNDVI),
4040: (int (*)(const void *,const void *))ndvi_compare_rev);
4041: else
4042: qsort(w,nd_psn,sizeof(struct oNDVI),
4043: (int (*)(const void *,const void *))ndvi_compare);
4044: }
4045: nd_pslen = 2*nd_psn;
4046: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4047: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4048: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4049: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
4050: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
4051: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
4052: nd_hcf = 0;
1.1 noro 4053:
1.6 noro 4054: if ( trace && nd_vc )
4055: makesubst(nd_vc,&nd_subst);
4056: else
4057: nd_subst = 0;
1.1 noro 4058:
1.6 noro 4059: if ( !nd_red )
4060: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
4061: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
4062: for ( i = 0; i < nd_psn; i++ ) {
4063: hc = HCU(w[i].p);
4064: if ( trace ) {
4065: if ( mod == -2 ) {
4066: /* over a large finite field */
4067: /* trace = small modulus */
4068: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
4069: ndv_mod(-2,a);
4070: if ( !dont_removecont) ndv_removecont(-2,a);
4071: am = nd_ps[i] = ndv_dup(trace,w[i].p);
4072: ndv_mod(trace,am);
4073: if ( DL_COMPARE(HDL(am),HDL(a)) )
4074: return 0;
4075: ndv_removecont(trace,am);
4076: } else {
4077: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
4078: if ( !dont_removecont) ndv_removecont(0,a);
4079: register_hcf(a);
4080: am = nd_ps[i] = ndv_dup(mod,a);
4081: ndv_mod(mod,am);
4082: if ( DL_COMPARE(HDL(am),HDL(a)) )
4083: return 0;
4084: ndv_removecont(mod,am);
4085: }
4086: } else {
4087: a = nd_ps[i] = ndv_dup(mod,w[i].p);
4088: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
4089: if ( !mod ) register_hcf(a);
1.1 noro 4090: }
1.6 noro 4091: if ( nd_gentrace ) {
4092: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
4093: /* exact division */
1.1 noro 4094: if ( !dont_removecont )
1.6 noro 4095: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
4096: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
4097: }
4098: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
4099: nd_bound[i] = ndv_compute_bound(a);
4100: nd_psh[i] = r;
4101: if ( nd_demand ) {
4102: if ( trace ) {
4103: ndv_save(nd_ps_trace[i],i);
4104: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4105: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
4106: nd_ps_trace[i] = 0;
4107: } else {
4108: ndv_save(nd_ps[i],i);
4109: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
4110: nd_ps[i] = 0;
4111: }
1.1 noro 4112: }
1.6 noro 4113: }
1.24 noro 4114: if ( sba ) {
1.27 noro 4115: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 4116: // setup signatures
1.27 noro 4117: for ( i = 0; i < nd_psn; i++ ) {
4118: SIG sig;
1.24 noro 4119:
1.27 noro 4120: NEWSIG(sig); sig->pos = i;
4121: nd_ps[i]->sig = sig;
4122: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
4123: nd_psh[i]->sig = sig;
4124: if ( trace ) {
4125: nd_ps_trace[i]->sig = sig;
4126: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
4127: }
4128: NEWDL(nd_sba_hm[i],nd_nvar);
4129: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
4130: }
1.29 noro 4131: nd_sba_pos = (NODE *)MALLOC(nd_psn*sizeof(NODE));
4132: for ( i = 0; i < nd_psn; i++ ) {
4133: j = nd_psh[i]->sig->pos;
4134: nd_sba_pos[j] = append_one(nd_sba_pos[j],i);
4135: }
1.24 noro 4136: }
1.6 noro 4137: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
4138: return 1;
1.1 noro 4139: }
4140:
4141: struct order_spec *append_block(struct order_spec *spec,
4142: int nv,int nalg,int ord);
4143:
4144: extern VECT current_dl_weight_vector_obj;
4145: static VECT prev_weight_vector_obj;
4146:
4147: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
4148: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
4149: {
4150: NODE alist,t,s,r0,r,arg;
4151: VL tv;
4152: P poly;
4153: DP d;
4154: Alg alpha,dp;
4155: DAlg inv,da,hc;
4156: MP m;
4157: int i,nvar,nalg,n;
4158: NumberField nf;
4159: LIST f1,f2;
4160: struct order_spec *current_spec;
4161: VECT obj,obj0;
4162: VECT tmp;
4163:
4164: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
4165: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
4166:
4167: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
4168: NEXTNODE(alist,t); MKV(tv->v,poly);
4169: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
4170: tv->v = tv->v->priv;
4171: }
4172: NEXT(t) = 0;
4173:
4174: /* simplification, making polynomials monic */
4175: setfield_dalg(alist);
4176: obj_algtodalg((Obj)f,(Obj *)&f1);
4177: for ( t = BDY(f); t; t = NEXT(t) ) {
4178: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
4179: hc = (DAlg)BDY(d)->c;
4180: if ( NID(hc) == N_DA ) {
4181: invdalg(hc,&inv);
4182: for ( m = BDY(d); m; m = NEXT(m) ) {
4183: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
4184: }
4185: }
4186: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
4187: }
4188: obj_dalgtoalg((Obj)f1,(Obj *)&f);
4189:
4190: /* append alg vars to the var list */
4191: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
4192: NEXT(tv) = av;
4193:
4194: /* append a block to ord */
4195: *ord1p = append_block(ord,nvar,nalg,2);
4196:
4197: /* create generator list */
4198: nf = get_numberfield();
4199: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
4200: MKAlg(nf->defpoly[i],dp);
4201: MKNODE(s,dp,t); t = s;
4202: }
4203: MKLIST(f1,t);
4204: *alistp = alist;
4205: algobjtorat((Obj)f1,(Obj *)f1p);
4206:
4207: /* creating a new weight vector */
4208: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
4209: n = nvar+nalg+1;
4210: MKVECT(obj,n);
4211: if ( obj0 && obj0->len == nvar )
4212: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
4213: else
4214: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
4215: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
4216: BDY(obj)[n-1] = (pointer)ONE;
4217: arg = mknode(1,obj);
4218: Pdp_set_weight(arg,&tmp);
4219: }
4220:
4221: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
4222: {
4223: NODE s,t,u0,u;
4224: P p;
4225: VL tv;
4226: Obj obj;
4227: VECT tmp;
4228: NODE arg;
4229:
4230: u0 = 0;
4231: for ( t = r; t; t = NEXT(t) ) {
4232: p = (P)BDY(t);
4233: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
4234: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
4235: }
4236: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
4237: NEXTNODE(u0,u);
4238: BDY(u) = (pointer)p;
4239: }
4240: }
4241: arg = mknode(1,prev_weight_vector_obj);
4242: Pdp_set_weight(arg,&tmp);
4243:
4244: return u0;
4245: }
4246:
4247: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
4248: {
4249: VL tv,fv,vv,vc,av;
4250: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4251: int e,max,nvar,i;
4252: NDV b;
4253: int ishomo,nalg,mrank,trank,wmax,len;
4254: NMV a;
4255: Alg alpha,dp;
4256: P p,zp;
4257: Q dmy;
4258: LIST f1,f2,zpl;
4259: Obj obj;
4260: NumberField nf;
4261: struct order_spec *ord1;
4262: NODE tr,tl1,tl2,tl3,tl4,nzlist;
4263: LIST l1,l2,l3,l4,l5;
4264: int j;
4265: Z jq,bpe,last_nonzero;
4266: int *perm;
4267: EPOS oepos;
4268: int obpe,oadv,ompos,cbpe;
1.15 noro 4269: VECT hvect;
1.1 noro 4270:
1.41 noro 4271: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 4272: nd_module = 0;
4273: if ( !m && Demand ) nd_demand = 1;
4274: else nd_demand = 0;
4275: parse_nd_option(current_option);
4276:
4277: if ( DP_Multiple )
4278: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4279: #if 0
4280: ndv_alloc = 0;
4281: #endif
4282: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4283: if ( m && nd_vc )
4284: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4285: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4286: switch ( ord->id ) {
4287: case 1:
4288: if ( ord->nv != nvar )
4289: error("nd_{gr,f4} : invalid order specification");
4290: break;
4291: default:
4292: break;
4293: }
4294: nd_nalg = 0;
4295: av = 0;
4296: if ( !m ) {
4297: get_algtree((Obj)f,&av);
4298: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4299: nd_ntrans = nvar;
4300: nd_nalg = nalg;
4301: /* #i -> t#i */
4302: if ( nalg ) {
4303: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4304: ord = ord1;
4305: f = f1;
4306: }
4307: nvar += nalg;
4308: }
4309: nd_init_ord(ord);
4310: mrank = 0;
4311: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4312: for ( tv = vv; tv; tv = NEXT(tv) ) {
4313: if ( nd_module ) {
1.16 noro 4314: if ( OID(BDY(t)) == O_DPM ) {
4315: e = dpm_getdeg((DPM)BDY(t),&trank);
4316: max = MAX(e,max);
4317: mrank = MAX(mrank,trank);
4318: } else {
4319: s = BDY((LIST)BDY(t));
4320: trank = length(s);
4321: mrank = MAX(mrank,trank);
4322: for ( ; s; s = NEXT(s) ) {
4323: e = getdeg(tv->v,(P)BDY(s));
4324: max = MAX(e,max);
4325: }
1.1 noro 4326: }
4327: } else {
1.43 noro 4328: if ( OID(BDY(t)) == O_DP ) {
4329: e = dp_getdeg((DP)BDY(t));
4330: max = MAX(e,max);
4331: } else {
4332: e = getdeg(tv->v,(P)BDY(t));
4333: max = MAX(e,max);
4334: }
1.1 noro 4335: }
4336: }
4337: nd_setup_parameters(nvar,nd_nzlist?0:max);
4338: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4339: ishomo = 1;
4340: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4341: if ( nd_module ) {
1.16 noro 4342: if ( OID(BDY(t)) == O_DPM ) {
4343: Z cont;
4344: DPM zdpm;
4345:
4346: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4347: else zdpm = (DPM)BDY(t);
4348: b = (pointer)dpmtondv(m,zdpm);
4349: } else {
4350: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4351: else zpl = (LIST)BDY(t);
1.1 noro 4352: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4353: }
1.1 noro 4354: } else {
1.43 noro 4355: if ( OID(BDY(t)) == O_DP ) {
4356: DP zdp;
4357:
4358: if ( !m && !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
4359: else zdp = (DP)BDY(t);
4360: b = (pointer)dptondv(m,zdp);
4361: } else {
4362: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4363: else zp = (P)BDY(t);
4364: b = (pointer)ptondv(CO,vv,zp);
4365: }
1.1 noro 4366: }
4367: if ( ishomo )
4368: ishomo = ishomo && ndv_ishomo(b);
4369: if ( m ) ndv_mod(m,b);
4370: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4371: }
4372: if ( fd0 ) NEXT(fd) = 0;
4373:
4374: if ( !ishomo && homo ) {
4375: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4376: b = (NDV)BDY(t); len = LEN(b);
4377: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4378: wmax = MAX(TD(DL(a)),wmax);
4379: }
4380: homogenize_order(ord,nvar,&ord1);
4381: nd_init_ord(ord1);
4382: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4383: for ( t = fd0; t; t = NEXT(t) )
4384: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4385: }
4386:
1.24 noro 4387: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4388: if ( nd_gentrace ) {
4389: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4390: }
4391: if ( nd_splist ) {
4392: *rp = compute_splist();
4393: return;
4394: }
4395: if ( nd_check_splist ) {
4396: if ( f4 ) {
4397: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4398: else *rp = 0;
4399: } else {
4400: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4401: else *rp = 0;
4402: }
4403: return;
4404: }
4405: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
4406: if ( !x ) {
4407: *rp = 0; return;
4408: }
1.15 noro 4409: if ( nd_gentrace ) {
4410: MKVECT(hvect,nd_psn);
4411: for ( i = 0; i < nd_psn; i++ )
4412: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4413: }
1.1 noro 4414: if ( !ishomo && homo ) {
4415: /* dehomogenization */
4416: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4417: nd_init_ord(ord);
4418: nd_setup_parameters(nvar,0);
4419: }
4420: nd_demand = 0;
4421: if ( nd_module && nd_intersect ) {
4422: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 4423: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 4424: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
4425: }
4426: conv_ilist(nd_demand,0,x,0);
4427: goto FINAL;
4428: }
4429: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
4430: x = ndv_reducebase(x,perm);
4431: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4432: x = ndv_reduceall(m,x);
4433: cbpe = nd_bpe;
4434: if ( nd_gentrace && !f4 ) {
4435: tl2 = nd_alltracelist; nd_alltracelist = 0;
4436: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
4437: tl3 = nd_alltracelist; nd_alltracelist = 0;
4438: if ( nd_gensyz ) {
4439: nd_gb(m,0,1,1,0);
4440: tl4 = nd_alltracelist; nd_alltracelist = 0;
4441: } else tl4 = 0;
4442: }
4443: nd_bpe = cbpe;
4444: nd_setup_parameters(nd_nvar,0);
4445: FINAL:
4446: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 4447: NEXTNODE(r0,r);
4448: if ( nd_module ) {
4449: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
4450: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
4451: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
4452: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 4453: }
4454: if ( r0 ) NEXT(r) = 0;
4455: if ( !m && nd_nalg )
4456: r0 = postprocess_algcoef(av,alist,r0);
4457: MKLIST(*rp,r0);
4458: if ( nd_gentrace ) {
4459: if ( f4 ) {
1.6 noro 4460: STOZ(16,bpe);
4461: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 4462: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 4463: } else {
4464: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4465: tl3 = reverse_node(tl3);
4466: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4467: for ( t = tl2; t; t = NEXT(t) ) {
4468: /* s = [i,[*,j,*,*],...] */
4469: s = BDY((LIST)BDY(t));
1.6 noro 4470: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4471: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4472: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4473: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4474: }
4475: }
4476: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4477: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4478: }
4479: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4480: MKLIST(l5,tl4);
1.6 noro 4481: STOZ(nd_bpe,bpe);
1.15 noro 4482: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4483: }
4484: }
4485: #if 0
4486: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
4487: #endif
4488: }
4489:
1.28 noro 4490: NODE nd_sba_f4(int m,int **indp);
4491:
4492: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 4493: {
4494: VL tv,fv,vv,vc,av;
1.44 ! noro 4495: NODE fd,fd0,r,r0,t,x,s,xx,nd,syz;
1.24 noro 4496: int e,max,nvar,i;
4497: NDV b;
4498: int ishomo,nalg,wmax,len;
4499: NMV a;
4500: P p,zp;
4501: Q dmy;
4502: struct order_spec *ord1;
4503: int j;
4504: int *perm;
4505: EPOS oepos;
4506: int obpe,oadv,ompos,cbpe;
1.29 noro 4507: struct oEGT eg0,eg1,egconv;
1.24 noro 4508:
4509: nd_module = 0;
4510: nd_demand = 0;
4511: parse_nd_option(current_option);
1.35 noro 4512: Nsamesig = 0;
1.24 noro 4513: if ( DP_Multiple )
4514: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4515: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4516: if ( m && nd_vc )
4517: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4518: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4519: switch ( ord->id ) {
4520: case 1:
4521: if ( ord->nv != nvar )
4522: error("nd_sba : invalid order specification");
4523: break;
4524: default:
4525: break;
4526: }
4527: nd_nalg = 0;
4528: nd_init_ord(ord);
4529: // for SIG comparison
4530: initd(ord);
4531: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
4532: for ( tv = vv; tv; tv = NEXT(tv) ) {
1.43 noro 4533: if ( OID(BDY(t)) == O_DP ) {
4534: e = dp_getdeg((DP)BDY(t));
4535: max = MAX(e,max);
4536: } else {
4537: e = getdeg(tv->v,(P)BDY(t));
4538: max = MAX(e,max);
4539: }
1.24 noro 4540: }
4541: }
1.25 noro 4542: nd_setup_parameters(nvar,max);
1.24 noro 4543: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4544: ishomo = 1;
4545: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
1.43 noro 4546: if ( OID(BDY(t)) == O_DP ) {
4547: DP zdp;
4548:
4549: if ( !m ) dp_ptozp((DP)BDY(t),&zdp);
4550: else zdp = (DP)BDY(t);
4551: b = (pointer)dptondv(m,zdp);
4552: } else {
4553: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
4554: else zp = (P)BDY(t);
4555: b = (pointer)ptondv(CO,vv,zp);
4556: }
1.24 noro 4557: if ( ishomo )
4558: ishomo = ishomo && ndv_ishomo(b);
4559: if ( m ) ndv_mod(m,b);
4560: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4561: }
4562: if ( fd0 ) NEXT(fd) = 0;
4563:
4564: if ( !ishomo && homo ) {
4565: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4566: b = (NDV)BDY(t); len = LEN(b);
4567: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4568: wmax = MAX(TD(DL(a)),wmax);
4569: }
4570: homogenize_order(ord,nvar,&ord1);
4571: nd_init_ord(ord1);
1.42 noro 4572: // for SIG comparison
4573: initd(ord1);
1.24 noro 4574: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4575: for ( t = fd0; t; t = NEXT(t) )
4576: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4577: }
4578:
1.39 noro 4579: ndv_setup(m,0,fd0,nd_sba_dontsort,0,1);
1.44 ! noro 4580: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm,&syz);
1.24 noro 4581: if ( !x ) {
4582: *rp = 0; return;
4583: }
4584: if ( !ishomo && homo ) {
4585: /* dehomogenization */
4586: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4587: nd_init_ord(ord);
1.42 noro 4588: // for SIG comparison
4589: initd(ord);
1.24 noro 4590: nd_setup_parameters(nvar,0);
4591: }
4592: nd_demand = 0;
4593: x = ndv_reducebase(x,perm);
4594: x = ndv_reduceall(m,x);
4595: nd_setup_parameters(nd_nvar,0);
1.29 noro 4596: get_eg(&eg0);
1.24 noro 4597: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4598: NEXTNODE(r0,r);
4599: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
1.34 noro 4600: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.24 noro 4601: }
4602: if ( r0 ) NEXT(r) = 0;
1.44 ! noro 4603: if ( nd_sba_syz ) {
! 4604: LIST gb,hsyz;
! 4605: NODE nd;
! 4606:
! 4607: MKLIST(gb,r0);
! 4608: MKLIST(hsyz,syz);
! 4609: nd = mknode(2,gb,hsyz);
! 4610: MKLIST(*rp,nd);
! 4611: } else
! 4612: MKLIST(*rp,r0);
1.29 noro 4613: get_eg(&eg1); init_eg(&egconv); add_eg(&egconv,&eg0,&eg1);
4614: print_eg("conv",&egconv); fprintf(asir_out,"\n");
1.24 noro 4615: }
4616:
1.1 noro 4617: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
4618: {
4619: VL tv,fv,vv,vc,av;
4620: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4621: int e,max,nvar,i;
4622: NDV b;
4623: int ishomo,nalg;
4624: Alg alpha,dp;
4625: P p,zp;
4626: Q dmy;
4627: LIST f1,f2;
4628: Obj obj;
4629: NumberField nf;
4630: struct order_spec *ord1;
4631: int *perm;
4632:
4633: parse_nd_option(current_option);
4634: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4635: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4636: switch ( ord->id ) {
4637: case 1:
4638: if ( ord->nv != nvar )
4639: error("nd_check : invalid order specification");
4640: break;
4641: default:
4642: break;
4643: }
4644: nd_nalg = 0;
4645: av = 0;
4646: if ( !m ) {
4647: get_algtree((Obj)f,&av);
4648: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4649: nd_ntrans = nvar;
4650: nd_nalg = nalg;
4651: /* #i -> t#i */
4652: if ( nalg ) {
4653: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4654: ord = ord1;
4655: f = f1;
4656: }
4657: nvar += nalg;
4658: }
4659: nd_init_ord(ord);
4660: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4661: for ( tv = vv; tv; tv = NEXT(tv) ) {
4662: e = getdeg(tv->v,(P)BDY(t));
4663: max = MAX(e,max);
4664: }
4665: nd_setup_parameters(nvar,max);
4666: ishomo = 1;
4667: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4668: ptozp((P)BDY(t),1,&dmy,&zp);
4669: b = (pointer)ptondv(CO,vv,zp);
4670: if ( ishomo )
4671: ishomo = ishomo && ndv_ishomo(b);
4672: if ( m ) ndv_mod(m,b);
4673: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4674: }
4675: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 4676: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 4677: for ( x = 0, i = 0; i < nd_psn; i++ )
4678: x = update_base(x,i);
4679: if ( do_check ) {
4680: x = nd_gb(m,ishomo,1,0,&perm);
4681: if ( !x ) {
4682: *rp = 0;
4683: return;
4684: }
4685: } else {
4686: #if 0
4687: /* bug ? */
4688: for ( t = x; t; t = NEXT(t) )
4689: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
4690: #else
4691: conv_ilist(0,0,x,&perm);
4692: #endif
4693: }
4694: x = ndv_reducebase(x,perm);
4695: x = ndv_reduceall(m,x);
4696: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4697: NEXTNODE(r0,r);
4698: BDY(r) = ndvtop(m,CO,vv,BDY(t));
4699: }
4700: if ( r0 ) NEXT(r) = 0;
4701: if ( !m && nd_nalg )
4702: r0 = postprocess_algcoef(av,alist,r0);
4703: MKLIST(*rp,r0);
4704: }
4705:
4706: NDV recompute_trace(NODE trace,NDV *p,int m);
4707: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
4708:
4709: NDV recompute_trace(NODE ti,NDV *p,int mod)
4710: {
4711: int c,c1,c2,i;
4712: NM mul,m,tail;
4713: ND d,r,rm;
4714: NODE sj;
4715: NDV red;
4716: Obj mj;
4717:
4718: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
4719: CM(mul) = 1;
4720: tail = 0;
4721: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
4722: sj = BDY((LIST)BDY(ti));
4723: if ( ARG0(sj) ) {
1.6 noro 4724: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 4725: mj = (Obj)ARG2(sj);
4726: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
4727: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
4728: rm = ndv_mul_nm(mod,mul,red);
4729: if ( !r ) r = rm;
4730: else {
4731: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
4732: if ( d ) {
4733: NEXT(tail) = m; tail = m; LEN(d)++;
4734: } else {
4735: MKND(nd_nvar,m,1,d); tail = BDY(d);
4736: }
4737: }
4738: if ( !m ) return 0; /* failure */
4739: else {
4740: BDY(r) = m;
4741: if ( mod > 0 || mod == -1 ) {
4742: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
4743: DMAR(c1,c2,0,mod,c);
4744: nd_mul_c(mod,rm,c);
4745: } else {
4746: Z t,u;
4747:
4748: chsgnlf(HCZ(r),&t);
4749: divlf(t,HCZ(rm),&u);
4750: nd_mul_c_lf(rm,u);
4751: }
4752: r = nd_add(mod,r,rm);
4753: }
4754: }
4755: }
4756: }
4757: if ( tail ) NEXT(tail) = 0;
4758: d = nd_add(mod,d,r);
4759: nd_mul_c(mod,d,invm(HCM(d),mod));
4760: return ndtondv(mod,d);
4761: }
4762:
4763: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
4764: {
4765: VL tv,fv,vv,vc,av;
4766: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4767: int e,max,nvar,i;
4768: NDV b;
4769: int ishomo,nalg;
4770: Alg alpha,dp;
4771: P p,zp;
4772: Q dmy;
4773: LIST f1,f2;
4774: Obj obj;
4775: NumberField nf;
4776: struct order_spec *ord1;
4777: NODE permtrace,intred,ind,perm,trace,ti;
4778: int len,n,j;
4779: NDV *db,*pb;
4780:
4781: parse_nd_option(current_option);
4782: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4783: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4784: switch ( ord->id ) {
4785: case 1:
4786: if ( ord->nv != nvar )
4787: error("nd_check : invalid order specification");
4788: break;
4789: default:
4790: break;
4791: }
4792: nd_init_ord(ord);
1.6 noro 4793: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 4794: nd_setup_parameters(nvar,0);
4795:
4796: len = length(BDY(f));
4797: db = (NDV *)MALLOC(len*sizeof(NDV *));
4798: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
4799: ptozp((P)BDY(t),1,&dmy,&zp);
4800: b = ptondv(CO,vv,zp);
4801: ndv_mod(m,b);
4802: ndv_mul_c(m,b,invm(HCM(b),m));
4803: db[i] = b;
4804: }
4805:
4806: permtrace = BDY((LIST)ARG2(BDY(tlist)));
4807: intred = BDY((LIST)ARG3(BDY(tlist)));
4808: ind = BDY((LIST)ARG4(BDY(tlist)));
4809: perm = BDY((LIST)ARG0(permtrace));
4810: trace = NEXT(permtrace);
4811:
4812: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 4813: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 4814: if ( j > i ) i = j;
4815: }
4816: n = i+1;
4817: pb = (NDV *)MALLOC(n*sizeof(NDV *));
4818: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
4819: ti = BDY((LIST)BDY(t));
1.6 noro 4820: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 4821: }
4822: for ( t = trace; t; t = NEXT(t) ) {
4823: ti = BDY((LIST)BDY(t));
1.6 noro 4824: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4825: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4826: if ( DP_Print ) {
4827: fprintf(asir_out,"."); fflush(asir_out);
4828: }
4829: }
4830: for ( t = intred; t; t = NEXT(t) ) {
4831: ti = BDY((LIST)BDY(t));
1.6 noro 4832: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4833: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4834: if ( DP_Print ) {
4835: fprintf(asir_out,"*"); fflush(asir_out);
4836: }
4837: }
4838: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
4839: NEXTNODE(r0,r);
1.6 noro 4840: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 4841: ndv_mul_c(m,b,invm(HCM(b),m));
4842: #if 0
1.6 noro 4843: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4844: #else
1.6 noro 4845: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4846: #endif
4847: }
4848: if ( r0 ) NEXT(r) = 0;
4849: MKLIST(*rp,r0);
4850: if ( DP_Print ) fprintf(asir_out,"\n");
4851: }
4852:
1.16 noro 4853: 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 4854: {
4855: VL tv,fv,vv,vc,av;
4856: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
4857: int m,nocheck,nvar,mindex,e,max;
4858: NDV c;
4859: NMV a;
4860: P p,zp;
4861: Q dmy;
4862: EPOS oepos;
4863: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
4864: Alg alpha,dp;
4865: P poly;
4866: LIST f1,f2,zpl;
4867: Obj obj;
4868: NumberField nf;
4869: struct order_spec *ord1;
4870: struct oEGT eg_check,eg0,eg1;
4871: NODE tr,tl1,tl2,tl3,tl4;
4872: LIST l1,l2,l3,l4,l5;
4873: int *perm;
4874: int j,ret;
4875: Z jq,bpe;
1.15 noro 4876: VECT hvect;
1.1 noro 4877:
1.41 noro 4878: NcriB = NcriMF = Ncri2 = 0;
1.1 noro 4879: nd_module = 0;
4880: nd_lf = 0;
4881: parse_nd_option(current_option);
4882: if ( nd_lf ) {
4883: if ( f4 )
4884: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
4885: else
4886: error("nd_gr_trace is not implemented yet over a large finite field");
4887: return;
4888: }
4889: if ( DP_Multiple )
4890: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4891:
4892: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4893: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4894: switch ( ord->id ) {
4895: case 1:
4896: if ( ord->nv != nvar )
4897: error("nd_gr_trace : invalid order specification");
4898: break;
4899: default:
4900: break;
4901: }
4902:
4903: get_algtree((Obj)f,&av);
4904: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4905: nd_ntrans = nvar;
4906: nd_nalg = nalg;
4907: /* #i -> t#i */
4908: if ( nalg ) {
4909: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4910: ord = ord1;
4911: f = f1;
4912: }
4913: nvar += nalg;
4914:
4915: nocheck = 0;
4916: mindex = 0;
4917:
4918: if ( Demand ) nd_demand = 1;
4919: else nd_demand = 0;
4920:
4921: /* setup modulus */
4922: if ( trace < 0 ) {
4923: trace = -trace;
4924: nocheck = 1;
4925: }
4926: m = trace > 1 ? trace : get_lprime(mindex);
4927: nd_init_ord(ord);
4928: mrank = 0;
4929: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4930: for ( tv = vv; tv; tv = NEXT(tv) ) {
4931: if ( nd_module ) {
1.16 noro 4932: if ( OID(BDY(t)) == O_DPM ) {
4933: e = dpm_getdeg((DPM)BDY(t),&trank);
4934: max = MAX(e,max);
4935: mrank = MAX(mrank,trank);
4936: } else {
1.1 noro 4937: s = BDY((LIST)BDY(t));
4938: trank = length(s);
4939: mrank = MAX(mrank,trank);
4940: for ( ; s; s = NEXT(s) ) {
4941: e = getdeg(tv->v,(P)BDY(s));
4942: max = MAX(e,max);
4943: }
1.16 noro 4944: }
1.1 noro 4945: } else {
1.43 noro 4946: if ( OID(BDY(t)) == O_DP ) {
4947: e = dp_getdeg((DP)BDY(t));
4948: max = MAX(e,max);
4949: } else {
1.1 noro 4950: e = getdeg(tv->v,(P)BDY(t));
4951: max = MAX(e,max);
1.43 noro 4952: }
1.1 noro 4953: }
4954: }
4955: nd_setup_parameters(nvar,max);
4956: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4957: ishomo = 1;
4958: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4959: if ( nd_module ) {
1.16 noro 4960: if ( OID(BDY(t)) == O_DPM ) {
4961: Z cont;
4962: DPM zdpm;
4963:
1.17 noro 4964: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 4965: else zdpm = (DPM)BDY(t);
4966: c = (pointer)dpmtondv(m,zdpm);
4967: } else {
4968: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4969: else zpl = (LIST)BDY(t);
1.1 noro 4970: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4971: }
1.1 noro 4972: } else {
1.43 noro 4973: if ( OID(BDY(t)) == O_DP ) {
4974: DP zdp;
4975:
4976: if ( !nd_gentrace ) dp_ptozp((DP)BDY(t),&zdp);
4977: else zdp = (DP)BDY(t);
4978: c = (pointer)dptondv(m,zdp);
4979: } else {
4980: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4981: else zp = (P)BDY(t);
4982: c = (pointer)ptondv(CO,vv,zp);
4983: }
1.1 noro 4984: }
4985: if ( ishomo )
4986: ishomo = ishomo && ndv_ishomo(c);
4987: if ( c ) {
4988: NEXTNODE(in0,in); BDY(in) = (pointer)c;
4989: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
4990: }
4991: }
4992: if ( in0 ) NEXT(in) = 0;
4993: if ( fd0 ) NEXT(fd) = 0;
4994: if ( !ishomo && homo ) {
4995: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
4996: c = (NDV)BDY(t); len = LEN(c);
4997: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4998: wmax = MAX(TD(DL(a)),wmax);
4999: }
5000: homogenize_order(ord,nvar,&ord1);
5001: nd_init_ord(ord1);
5002: nd_setup_parameters(nvar+1,wmax);
5003: for ( t = fd0; t; t = NEXT(t) )
5004: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
5005: }
5006: if ( MaxDeg > 0 ) nocheck = 1;
5007: while ( 1 ) {
5008: tl1 = tl2 = tl3 = tl4 = 0;
5009: if ( Demand )
5010: nd_demand = 1;
1.24 noro 5011: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 5012: if ( nd_gentrace ) {
5013: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
5014: }
5015: if ( ret )
5016: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
5017: if ( !ret || !cand ) {
5018: /* failure */
5019: if ( trace > 1 ) { *rp = 0; return; }
5020: else m = get_lprime(++mindex);
5021: continue;
5022: }
1.15 noro 5023: if ( nd_gentrace ) {
5024: MKVECT(hvect,nd_psn);
5025: for ( i = 0; i < nd_psn; i++ )
5026: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
5027: }
1.1 noro 5028: if ( !ishomo && homo ) {
5029: /* dehomogenization */
5030: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
5031: nd_init_ord(ord);
5032: nd_setup_parameters(nvar,0);
5033: }
5034: nd_demand = 0;
5035: cand = ndv_reducebase(cand,perm);
5036: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
5037: cand = ndv_reduceall(0,cand);
5038: cbpe = nd_bpe;
5039: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
5040: get_eg(&eg0);
5041: if ( nocheck )
5042: break;
5043: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
5044: if ( nd_gentrace ) {
5045: tl3 = nd_alltracelist; nd_alltracelist = 0;
5046: } else tl3 = 0;
5047: /* gbcheck : cand is a GB of Id(cand) ? */
5048: if ( nd_vc || nd_gentrace || nd_gensyz )
5049: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
5050: else
5051: ret = nd_f4(0,1,0)!=0;
5052: if ( nd_gentrace && nd_gensyz ) {
5053: tl4 = nd_alltracelist; nd_alltracelist = 0;
5054: } else tl4 = 0;
5055: }
5056: if ( ret ) break;
5057: else if ( trace > 1 ) {
5058: /* failure */
5059: *rp = 0; return;
5060: } else {
5061: /* try the next modulus */
5062: m = get_lprime(++mindex);
5063: /* reset the parameters */
5064: if ( !ishomo && homo ) {
5065: nd_init_ord(ord1);
5066: nd_setup_parameters(nvar+1,wmax);
5067: } else {
5068: nd_init_ord(ord);
5069: nd_setup_parameters(nvar,max);
5070: }
5071: }
5072: }
5073: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
5074: if ( DP_Print )
1.6 noro 5075: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 5076: /* dp->p */
5077: nd_bpe = cbpe;
5078: nd_setup_parameters(nd_nvar,0);
5079: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 5080: if ( nd_module ) {
1.17 noro 5081: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 5082: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 5083: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
5084: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 5085: }
5086: if ( nd_nalg )
5087: cand = postprocess_algcoef(av,alist,cand);
5088: MKLIST(*rp,cand);
5089: if ( nd_gentrace ) {
5090: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
5091: tl3 = reverse_node(tl3);
5092: /* tl2 = [[i,[[*,j,*,*],...]],...] */
5093: for ( t = tl2; t; t = NEXT(t) ) {
5094: /* s = [i,[*,j,*,*],...] */
5095: s = BDY((LIST)BDY(t));
1.6 noro 5096: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 5097: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 5098: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 5099: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
5100: }
5101: }
5102: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 5103: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 5104: }
5105: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
5106: MKLIST(l5,tl4);
1.6 noro 5107: STOZ(nd_bpe,bpe);
1.15 noro 5108: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 5109: }
5110: }
5111:
5112: /* XXX : module element is not considered */
5113:
5114: void dltondl(int n,DL dl,UINT *r)
5115: {
5116: UINT *d;
5117: int i,j,l,s,ord_l;
5118: struct order_pair *op;
5119:
5120: d = (unsigned int *)dl->d;
5121: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
5122: if ( nd_blockmask ) {
5123: l = nd_blockmask->n;
5124: op = nd_blockmask->order_pair;
5125: for ( j = 0, s = 0; j < l; j++ ) {
5126: ord_l = op[j].length;
5127: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
5128: }
5129: TD(r) = ndl_weight(r);
5130: ndl_weight_mask(r);
5131: } else {
5132: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
5133: TD(r) = ndl_weight(r);
5134: }
5135: }
5136:
5137: DL ndltodl(int n,UINT *ndl)
5138: {
5139: DL dl;
5140: int *d;
5141: int i,j,l,s,ord_l;
5142: struct order_pair *op;
5143:
1.33 noro 5144: NEWDL_NOINIT(dl,n);
1.1 noro 5145: dl->td = TD(ndl);
5146: d = dl->d;
5147: if ( nd_blockmask ) {
5148: l = nd_blockmask->n;
5149: op = nd_blockmask->order_pair;
5150: for ( j = 0, s = 0; j < l; j++ ) {
5151: ord_l = op[j].length;
5152: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5153: }
5154: } else {
5155: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5156: }
5157: return dl;
5158: }
5159:
1.24 noro 5160: void _ndltodl(UINT *ndl,DL dl)
5161: {
5162: int *d;
5163: int i,j,l,s,ord_l,n;
5164: struct order_pair *op;
5165:
5166: n = nd_nvar;
5167: dl->td = TD(ndl);
5168: d = dl->d;
5169: if ( nd_blockmask ) {
5170: l = nd_blockmask->n;
5171: op = nd_blockmask->order_pair;
5172: for ( j = 0, s = 0; j < l; j++ ) {
5173: ord_l = op[j].length;
5174: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
5175: }
5176: } else {
5177: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
5178: }
5179: }
5180:
1.1 noro 5181: void nmtodp(int mod,NM m,DP *r)
5182: {
5183: DP dp;
5184: MP mr;
5185:
5186: NEWMP(mr);
5187: mr->dl = ndltodl(nd_nvar,DL(m));
5188: mr->c = (Obj)ndctop(mod,m->c);
5189: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5190: *r = dp;
5191: }
5192:
1.15 noro 5193: void ndltodp(UINT *d,DP *r)
5194: {
5195: DP dp;
5196: MP mr;
5197:
5198: NEWMP(mr);
5199: mr->dl = ndltodl(nd_nvar,d);
5200: mr->c = (Obj)ONE;
5201: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
5202: *r = dp;
5203: }
5204:
1.1 noro 5205: void ndl_print(UINT *dl)
5206: {
5207: int n;
5208: int i,j,l,ord_l,s,s0;
5209: struct order_pair *op;
5210:
5211: n = nd_nvar;
5212: printf("<<");
5213: if ( nd_blockmask ) {
5214: l = nd_blockmask->n;
5215: op = nd_blockmask->order_pair;
5216: for ( j = 0, s = s0 = 0; j < l; j++ ) {
5217: ord_l = op[j].length;
5218: for ( i = 0; i < ord_l; i++, s++ )
5219: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
5220: }
5221: } else {
5222: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
5223: }
5224: printf(">>");
5225: if ( nd_module && MPOS(dl) )
5226: printf("*e%d",MPOS(dl));
5227: }
5228:
5229: void nd_print(ND p)
5230: {
5231: NM m;
5232:
5233: if ( !p )
5234: printf("0\n");
5235: else {
5236: for ( m = BDY(p); m; m = NEXT(m) ) {
5237: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 5238: else printf("+%ld*",CM(m));
1.1 noro 5239: ndl_print(DL(m));
5240: }
5241: printf("\n");
5242: }
5243: }
5244:
5245: void nd_print_q(ND p)
5246: {
5247: NM m;
5248:
5249: if ( !p )
5250: printf("0\n");
5251: else {
5252: for ( m = BDY(p); m; m = NEXT(m) ) {
5253: printf("+");
1.6 noro 5254: printexpr(CO,(Obj)CZ(m));
1.1 noro 5255: printf("*");
5256: ndl_print(DL(m));
5257: }
5258: printf("\n");
5259: }
5260: }
5261:
5262: void ndp_print(ND_pairs d)
5263: {
5264: ND_pairs t;
5265:
5266: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
5267: printf("\n");
5268: }
5269:
5270: void nd_removecont(int mod,ND p)
5271: {
5272: int i,n;
5273: Z *w;
5274: NM m;
5275: struct oVECT v;
5276:
5277: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
5278: else if ( mod == -2 ) {
5279: Z inv;
5280: divlf(ONE,HCZ(p),&inv);
5281: nd_mul_c_lf(p,inv);
5282: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
5283: else {
5284: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
5285: w = (Z *)MALLOC(n*sizeof(Q));
5286: v.len = n;
5287: v.body = (pointer *)w;
1.6 noro 5288: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5289: removecont_array((P *)w,n,1);
1.6 noro 5290: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5291: }
5292: }
5293:
5294: void nd_removecont2(ND p1,ND p2)
5295: {
5296: int i,n1,n2,n;
5297: Z *w;
5298: NM m;
5299: struct oVECT v;
5300:
5301: n1 = nd_length(p1);
5302: n2 = nd_length(p2);
5303: n = n1+n2;
5304: w = (Z *)MALLOC(n*sizeof(Q));
5305: v.len = n;
5306: v.body = (pointer *)w;
5307: i = 0;
5308: if ( p1 )
1.6 noro 5309: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5310: if ( p2 )
1.6 noro 5311: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 5312: removecont_array((P *)w,n,1);
5313: i = 0;
5314: if ( p1 )
1.6 noro 5315: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5316: if ( p2 )
1.6 noro 5317: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 5318: }
5319:
5320: void ndv_removecont(int mod,NDV p)
5321: {
5322: int i,len,all_p;
5323: Z *c;
5324: P *w;
5325: Z dvr,t;
5326: P g,cont,tp;
5327: NMV m;
5328:
5329: if ( mod == -1 )
5330: ndv_mul_c(mod,p,_invsf(HCM(p)));
5331: else if ( mod == -2 ) {
5332: Z inv;
5333: divlf(ONE,HCZ(p),&inv);
5334: ndv_mul_c_lf(p,inv);
5335: } else if ( mod )
5336: ndv_mul_c(mod,p,invm(HCM(p),mod));
5337: else {
5338: len = p->len;
5339: w = (P *)MALLOC(len*sizeof(P));
5340: c = (Z *)MALLOC(len*sizeof(Q));
5341: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5342: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5343: all_p = all_p && !NUM(w[i]);
5344: }
5345: if ( all_p ) {
5346: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5347: mulp(nd_vc,(P)dvr,g,&cont);
5348: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5349: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5350: }
5351: } else {
5352: sortbynm((Q *)c,len);
5353: qltozl((Q *)c,len,&dvr);
5354: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5355: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5356: }
5357: }
5358: }
5359: }
5360:
5361: /* koko */
5362:
5363: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5364: {
5365: int len,i,max;
5366: NMV m,mr0,mr,t;
5367:
5368: len = p->len;
1.14 noro 5369: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5370: max = MAX(max,TD(DL(m)));
5371: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5372: m = (NMV)((char *)mr0+(len-1)*oadv);
5373: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5374: t = (NMV)MALLOC(nmv_adv);
5375: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5376: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5377: CZ(mr) = CZ(m);
1.1 noro 5378: ndl_copy(DL(t),DL(mr));
5379: }
5380: NV(p)++;
5381: BDY(p) = mr0;
5382: }
5383:
5384: void ndv_dehomogenize(NDV p,struct order_spec *ord)
5385: {
5386: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
5387: int pos;
5388: Q *w;
5389: Q dvr,t;
5390: NMV m,r;
5391:
5392: len = p->len;
5393: newnvar = nd_nvar-1;
5394: newexporigin = nd_get_exporigin(ord);
5395: if ( nd_module ) newmpos = newexporigin-1;
5396: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
5397: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
5398: ndl_dehomogenize(DL(m));
5399: if ( newwpd != nd_wpd ) {
5400: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
5401: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 5402: CZ(r) = CZ(m);
1.1 noro 5403: if ( nd_module ) pos = MPOS(DL(m));
5404: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
5405: adj = nd_exporigin-newexporigin;
5406: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
5407: if ( nd_module ) {
5408: DL(r)[newmpos] = pos;
5409: }
5410: }
5411: }
5412: NV(p)--;
5413: }
5414:
5415: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
5416: {
5417: int i;
5418: P *tpl,*tpl1;
5419: NODE l;
5420: P h,gcd,t;
5421:
5422: tpl = (P *)MALLOC(m*sizeof(P));
5423: tpl1 = (P *)MALLOC(m*sizeof(P));
5424: bcopy(pl,tpl,m*sizeof(P));
5425: gcd = (P)ONE;
5426: for ( l = nd_hcf; l; l = NEXT(l) ) {
5427: h = (P)BDY(l);
5428: while ( 1 ) {
5429: for ( i = 0; i < m; i++ )
5430: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
5431: break;
5432: if ( i == m ) {
5433: bcopy(tpl1,tpl,m*sizeof(P));
5434: mulp(vl,gcd,h,&t); gcd = t;
5435: } else
5436: break;
5437: }
5438: }
5439: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
5440: if ( full ) {
5441: heu_nezgcdnpz(vl,tpl,m,&t);
5442: mulp(vl,gcd,t,pr);
5443: } else
5444: *pr = gcd;
5445: }
5446:
5447: void removecont_array(P *p,int n,int full)
5448: {
5449: int all_p,all_q,i;
5450: Z *c;
5451: P *w;
5452: P t,s;
5453:
5454: for ( all_q = 1, i = 0; i < n; i++ )
5455: all_q = all_q && NUM(p[i]);
5456: if ( all_q ) {
5457: removecont_array_q((Z *)p,n);
5458: } else {
5459: c = (Z *)MALLOC(n*sizeof(Z));
5460: w = (P *)MALLOC(n*sizeof(P));
5461: for ( i = 0; i < n; i++ ) {
5462: ptozp(p[i],1,(Q *)&c[i],&w[i]);
5463: }
5464: removecont_array_q(c,n);
5465: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
5466: for ( i = 0; i < n; i++ ) {
5467: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
5468: }
5469: }
5470: }
5471:
5472: /* c is an int array */
5473:
5474: void removecont_array_q(Z *c,int n)
5475: {
5476: struct oVECT v;
5477: Z d0,d1,a,u,u1,gcd;
5478: int i,j;
5479: Z *q,*r;
5480:
5481: q = (Z *)MALLOC(n*sizeof(Z));
5482: r = (Z *)MALLOC(n*sizeof(Z));
5483: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
5484: gcdvz_estimate(&v,&d0);
5485: for ( i = 0; i < n; i++ ) {
5486: divqrz(c[i],d0,&q[i],&r[i]);
5487: }
5488: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
5489: if ( i < n ) {
5490: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
5491: gcdvz(&v,&d1);
5492: gcdz(d0,d1,&gcd);
1.6 noro 5493: /* exact division */
5494: divsz(d0,gcd,&a);
1.1 noro 5495: for ( i = 0; i < n; i++ ) {
5496: mulz(a,q[i],&u);
5497: if ( r[i] ) {
1.6 noro 5498: /* exact division */
5499: divsz(r[i],gcd,&u1);
1.1 noro 5500: addz(u,u1,&q[i]);
5501: } else
5502: q[i] = u;
5503: }
5504: }
5505: for ( i = 0; i < n; i++ ) c[i] = q[i];
5506: }
5507:
1.4 noro 5508: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
5509:
5510: void mpz_removecont_array(mpz_t *c,int n)
5511: {
5512: mpz_t d0,a,u,u1,gcd;
5513: int i,j;
1.13 noro 5514: static mpz_t *q,*r;
5515: static int c_len = 0;
1.4 noro 5516:
5517: for ( i = 0; i < n; i++ )
5518: if ( mpz_sgn(c[i]) ) break;
5519: if ( i == n ) return;
5520: gcdv_mpz_estimate(d0,c,n);
1.13 noro 5521: if ( n > c_len ) {
5522: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5523: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5524: c_len = n;
5525: }
1.4 noro 5526: for ( i = 0; i < n; i++ ) {
5527: mpz_init(q[i]); mpz_init(r[i]);
5528: mpz_fdiv_qr(q[i],r[i],c[i],d0);
5529: }
5530: for ( i = 0; i < n; i++ )
5531: if ( mpz_sgn(r[i]) ) break;
5532: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
5533: if ( i < n ) {
5534: mpz_gcd(gcd,d0,r[i]);
5535: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
5536: mpz_div(a,d0,gcd);
5537: for ( i = 0; i < n; i++ ) {
5538: mpz_mul(u,a,q[i]);
5539: if ( mpz_sgn(r[i]) ) {
5540: mpz_div(u1,r[i],gcd);
5541: mpz_add(q[i],u,u1);
5542: } else
5543: mpz_set(q[i],u);
5544: }
5545: }
5546: for ( i = 0; i < n; i++ )
5547: mpz_set(c[i],q[i]);
5548: }
5549:
1.1 noro 5550: void nd_mul_c(int mod,ND p,int mul)
5551: {
5552: NM m;
5553: int c,c1;
5554:
5555: if ( !p ) return;
5556: if ( mul == 1 ) return;
5557: if ( mod == -1 )
5558: for ( m = BDY(p); m; m = NEXT(m) )
5559: CM(m) = _mulsf(CM(m),mul);
5560: else
5561: for ( m = BDY(p); m; m = NEXT(m) ) {
5562: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5563: }
5564: }
5565:
5566: void nd_mul_c_lf(ND p,Z mul)
5567: {
5568: NM m;
5569: Z c;
5570:
5571: if ( !p ) return;
5572: if ( UNIZ(mul) ) return;
5573: for ( m = BDY(p); m; m = NEXT(m) ) {
5574: mullf(CZ(m),mul,&c); CZ(m) = c;
5575: }
5576: }
5577:
5578: void nd_mul_c_q(ND p,P mul)
5579: {
5580: NM m;
5581: P c;
5582:
5583: if ( !p ) return;
5584: if ( UNIQ(mul) ) return;
5585: for ( m = BDY(p); m; m = NEXT(m) ) {
5586: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
5587: }
5588: }
5589:
5590: void nd_mul_c_p(VL vl,ND p,P mul)
5591: {
5592: NM m;
5593: P c;
5594:
5595: if ( !p ) return;
5596: for ( m = BDY(p); m; m = NEXT(m) ) {
5597: mulp(vl,CP(m),mul,&c); CP(m) = c;
5598: }
5599: }
5600:
5601: void nd_free(ND p)
5602: {
5603: NM t,s;
5604:
5605: if ( !p ) return;
5606: t = BDY(p);
5607: while ( t ) {
5608: s = NEXT(t);
5609: FREENM(t);
5610: t = s;
5611: }
5612: FREEND(p);
5613: }
5614:
5615: void ndv_free(NDV p)
5616: {
5617: GCFREE(BDY(p));
5618: }
5619:
5620: void nd_append_red(UINT *d,int i)
5621: {
5622: RHist m,m0;
5623: int h;
5624:
5625: NEWRHist(m);
5626: h = ndl_hash_value(d);
5627: m->index = i;
5628: ndl_copy(d,DL(m));
5629: NEXT(m) = nd_red[h];
5630: nd_red[h] = m;
5631: }
5632:
5633: UINT *ndv_compute_bound(NDV p)
5634: {
5635: UINT *d1,*d2,*t;
5636: UINT u;
5637: int i,j,k,l,len,ind;
5638: NMV m;
5639:
5640: if ( !p )
5641: return 0;
5642: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5643: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5644: len = LEN(p);
5645: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
5646: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
5647: ndl_max(DL(m),d1,d2);
5648: t = d1; d1 = d2; d2 = t;
5649: }
5650: l = nd_nvar+31;
5651: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5652: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5653: u = d1[i];
5654: k = (nd_epw-1)*nd_bpe;
5655: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5656: t[ind] = (u>>k)&nd_mask0;
5657: }
5658: for ( ; ind < l; ind++ ) t[ind] = 0;
5659: return t;
5660: }
5661:
5662: UINT *nd_compute_bound(ND p)
5663: {
5664: UINT *d1,*d2,*t;
5665: UINT u;
5666: int i,j,k,l,len,ind;
5667: NM m;
5668:
5669: if ( !p )
5670: return 0;
5671: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5672: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5673: len = LEN(p);
5674: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
5675: for ( m = NEXT(m); m; m = NEXT(m) ) {
5676: ndl_lcm(DL(m),d1,d2);
5677: t = d1; d1 = d2; d2 = t;
5678: }
5679: l = nd_nvar+31;
5680: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5681: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5682: u = d1[i];
5683: k = (nd_epw-1)*nd_bpe;
5684: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5685: t[ind] = (u>>k)&nd_mask0;
5686: }
5687: for ( ; ind < l; ind++ ) t[ind] = 0;
5688: return t;
5689: }
5690:
5691: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
5692: /* of a term. In this case we need additional 1 word. */
5693:
5694: int nd_get_exporigin(struct order_spec *ord)
5695: {
5696: switch ( ord->id ) {
1.21 noro 5697: case 0: case 2: case 256: case 258: case 300:
1.1 noro 5698: return 1+nd_module;
5699: case 1: case 257:
5700: /* block order */
5701: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
5702: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
5703: return ord->ord.block.length+1+nd_module;
5704: case 3: case 259:
5705: #if 0
5706: error("nd_get_exporigin : composite order is not supported yet.");
5707: #else
5708: return 1+nd_module;
5709: #endif
5710: default:
5711: error("nd_get_exporigin : ivalid argument.");
5712: return 0;
5713: }
5714: }
5715:
5716: void nd_setup_parameters(int nvar,int max) {
5717: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
5718: struct order_pair *op;
5719:
5720: nd_nvar = nvar;
5721: if ( max ) {
5722: /* XXX */
5723: if ( do_weyl ) nd_bpe = 32;
5724: else if ( max < 2 ) nd_bpe = 1;
5725: else if ( max < 4 ) nd_bpe = 2;
5726: else if ( max < 8 ) nd_bpe = 3;
5727: else if ( max < 16 ) nd_bpe = 4;
5728: else if ( max < 32 ) nd_bpe = 5;
5729: else if ( max < 64 ) nd_bpe = 6;
5730: else if ( max < 256 ) nd_bpe = 8;
5731: else if ( max < 1024 ) nd_bpe = 10;
5732: else if ( max < 65536 ) nd_bpe = 16;
5733: else nd_bpe = 32;
5734: }
5735: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
5736: UINT t;
5737: int st;
5738: int *v;
5739: /* t = max(weights) */
5740: t = 0;
5741: if ( current_dl_weight_vector )
5742: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
5743: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
5744: if ( t < st ) t = st;
5745: }
5746: if ( nd_matrix )
5747: for ( i = 0; i < nd_matrix_len; i++ )
5748: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
5749: if ( (st=v[j]) < 0 ) st = -st;
5750: if ( t < st ) t = st;
5751: }
5752: /* i = bitsize of t */
5753: for ( i = 0; t; t >>=1, i++ );
5754: /* i += bitsize of nd_nvar */
5755: for ( t = nd_nvar; t; t >>=1, i++);
5756: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
5757: if ( (nd_bpe+i) >= 31 )
5758: error("nd_setup_parameters : too large weight");
5759: }
5760: nd_epw = (sizeof(UINT)*8)/nd_bpe;
5761: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
5762: nd_exporigin = nd_get_exporigin(nd_ord);
5763: wpd = nd_exporigin+elen;
5764: if ( nd_module )
5765: nd_mpos = nd_exporigin-1;
5766: else
5767: nd_mpos = -1;
5768: if ( wpd != nd_wpd ) {
5769: nd_free_private_storage();
5770: nd_wpd = wpd;
5771: }
5772: if ( nd_bpe < 32 ) {
5773: nd_mask0 = (1<<nd_bpe)-1;
5774: } else {
5775: nd_mask0 = 0xffffffff;
5776: }
5777: bzero(nd_mask,sizeof(nd_mask));
5778: nd_mask1 = 0;
5779: for ( i = 0; i < nd_epw; i++ ) {
5780: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
5781: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
5782: }
5783: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
5784: nd_epos = nd_create_epos(nd_ord);
5785: nd_blockmask = nd_create_blockmask(nd_ord);
5786: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
5787: }
5788:
5789: ND_pairs nd_reconstruct(int trace,ND_pairs d)
5790: {
5791: int i,obpe,oadv,h;
5792: static NM prev_nm_free_list;
5793: static ND_pairs prev_ndp_free_list;
5794: RHist mr0,mr;
5795: RHist r;
5796: RHist *old_red;
5797: ND_pairs s0,s,t;
5798: EPOS oepos;
5799:
5800: obpe = nd_bpe;
5801: oadv = nmv_adv;
5802: oepos = nd_epos;
5803: if ( obpe < 2 ) nd_bpe = 2;
5804: else if ( obpe < 3 ) nd_bpe = 3;
5805: else if ( obpe < 4 ) nd_bpe = 4;
5806: else if ( obpe < 5 ) nd_bpe = 5;
5807: else if ( obpe < 6 ) nd_bpe = 6;
5808: else if ( obpe < 8 ) nd_bpe = 8;
5809: else if ( obpe < 10 ) nd_bpe = 10;
5810: else if ( obpe < 16 ) nd_bpe = 16;
5811: else if ( obpe < 32 ) nd_bpe = 32;
5812: else error("nd_reconstruct : exponent too large");
5813:
5814: nd_setup_parameters(nd_nvar,0);
5815: prev_nm_free_list = _nm_free_list;
5816: prev_ndp_free_list = _ndp_free_list;
5817: _nm_free_list = 0;
5818: _ndp_free_list = 0;
5819: for ( i = nd_psn-1; i >= 0; i-- ) {
5820: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
5821: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
5822: }
5823: if ( trace )
5824: for ( i = nd_psn-1; i >= 0; i-- ) {
5825: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
5826: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
5827: }
5828: s0 = 0;
5829: for ( t = d; t; t = NEXT(t) ) {
5830: NEXTND_pairs(s0,s);
5831: s->i1 = t->i1;
5832: s->i2 = t->i2;
1.24 noro 5833: s->sig = t->sig;
1.1 noro 5834: SG(s) = SG(t);
5835: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
5836: }
5837:
5838: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
5839: for ( i = 0; i < REDTAB_LEN; i++ ) {
5840: old_red[i] = nd_red[i];
5841: nd_red[i] = 0;
5842: }
5843: for ( i = 0; i < REDTAB_LEN; i++ )
5844: for ( r = old_red[i]; r; r = NEXT(r) ) {
5845: NEWRHist(mr);
5846: mr->index = r->index;
5847: SG(mr) = SG(r);
5848: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
5849: h = ndl_hash_value(DL(mr));
5850: NEXT(mr) = nd_red[h];
5851: nd_red[h] = mr;
1.24 noro 5852: mr->sig = r->sig;
1.1 noro 5853: }
5854: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
5855: old_red = 0;
5856: for ( i = 0; i < nd_psn; i++ ) {
5857: NEWRHist(r); SG(r) = SG(nd_psh[i]);
5858: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 5859: r->sig = nd_psh[i]->sig;
1.1 noro 5860: nd_psh[i] = r;
5861: }
5862: if ( s0 ) NEXT(s) = 0;
5863: prev_nm_free_list = 0;
5864: prev_ndp_free_list = 0;
5865: #if 0
5866: GC_gcollect();
5867: #endif
5868: return s0;
5869: }
5870:
1.30 noro 5871: void nd_reconstruct_s(int trace,ND_pairs *d)
5872: {
5873: int i,obpe,oadv,h;
5874: static NM prev_nm_free_list;
5875: static ND_pairs prev_ndp_free_list;
5876: RHist mr0,mr;
5877: RHist r;
5878: RHist *old_red;
5879: ND_pairs s0,s,t;
5880: EPOS oepos;
5881:
5882: obpe = nd_bpe;
5883: oadv = nmv_adv;
5884: oepos = nd_epos;
5885: if ( obpe < 2 ) nd_bpe = 2;
5886: else if ( obpe < 3 ) nd_bpe = 3;
5887: else if ( obpe < 4 ) nd_bpe = 4;
5888: else if ( obpe < 5 ) nd_bpe = 5;
5889: else if ( obpe < 6 ) nd_bpe = 6;
5890: else if ( obpe < 8 ) nd_bpe = 8;
5891: else if ( obpe < 10 ) nd_bpe = 10;
5892: else if ( obpe < 16 ) nd_bpe = 16;
5893: else if ( obpe < 32 ) nd_bpe = 32;
5894: else error("nd_reconstruct_s : exponent too large");
5895:
5896: nd_setup_parameters(nd_nvar,0);
5897: prev_nm_free_list = _nm_free_list;
5898: prev_ndp_free_list = _ndp_free_list;
5899: _nm_free_list = 0;
5900: _ndp_free_list = 0;
5901: for ( i = nd_psn-1; i >= 0; i-- ) {
5902: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
5903: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
5904: }
5905: if ( trace )
5906: for ( i = nd_psn-1; i >= 0; i-- ) {
5907: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
5908: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
5909: }
5910:
5911: for ( i = 0; i < nd_nbase; i++ ) {
5912: s0 = 0;
5913: for ( t = d[i]; t; t = NEXT(t) ) {
5914: NEXTND_pairs(s0,s);
5915: s->i1 = t->i1;
5916: s->i2 = t->i2;
5917: s->sig = t->sig;
5918: SG(s) = SG(t);
5919: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
5920: }
5921: d[i] = s0;
5922: }
5923:
5924: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
5925: for ( i = 0; i < REDTAB_LEN; i++ ) {
5926: old_red[i] = nd_red[i];
5927: nd_red[i] = 0;
5928: }
5929: for ( i = 0; i < REDTAB_LEN; i++ )
5930: for ( r = old_red[i]; r; r = NEXT(r) ) {
5931: NEWRHist(mr);
5932: mr->index = r->index;
5933: SG(mr) = SG(r);
5934: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
5935: h = ndl_hash_value(DL(mr));
5936: NEXT(mr) = nd_red[h];
5937: nd_red[h] = mr;
5938: mr->sig = r->sig;
5939: }
5940: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
5941: old_red = 0;
5942: for ( i = 0; i < nd_psn; i++ ) {
5943: NEWRHist(r); SG(r) = SG(nd_psh[i]);
5944: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
5945: r->sig = nd_psh[i]->sig;
5946: nd_psh[i] = r;
5947: }
5948: if ( s0 ) NEXT(s) = 0;
5949: prev_nm_free_list = 0;
5950: prev_ndp_free_list = 0;
5951: #if 0
5952: GC_gcollect();
5953: #endif
5954: }
5955:
1.1 noro 5956: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
5957: {
5958: int n,i,ei,oepw,omask0,j,s,ord_l,l;
5959: struct order_pair *op;
5960:
5961: n = nd_nvar;
5962: oepw = (sizeof(UINT)*8)/obpe;
5963: omask0 = (1<<obpe)-1;
5964: TD(r) = TD(d);
5965: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
5966: if ( nd_blockmask ) {
5967: l = nd_blockmask->n;
5968: op = nd_blockmask->order_pair;
5969: for ( i = 1; i < nd_exporigin; i++ )
5970: r[i] = d[i];
5971: for ( j = 0, s = 0; j < l; j++ ) {
5972: ord_l = op[j].length;
5973: for ( i = 0; i < ord_l; i++, s++ ) {
5974: ei = GET_EXP_OLD(d,s);
5975: PUT_EXP(r,s,ei);
5976: }
5977: }
5978: } else {
5979: for ( i = 0; i < n; i++ ) {
5980: ei = GET_EXP_OLD(d,i);
5981: PUT_EXP(r,i,ei);
5982: }
5983: }
5984: if ( nd_module ) MPOS(r) = MPOS(d);
5985: }
5986:
5987: ND nd_copy(ND p)
5988: {
5989: NM m,mr,mr0;
5990: int c,n;
5991: ND r;
5992:
5993: if ( !p )
5994: return 0;
5995: else {
5996: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
5997: NEXTNM(mr0,mr);
5998: CM(mr) = CM(m);
5999: ndl_copy(DL(m),DL(mr));
6000: }
6001: NEXT(mr) = 0;
6002: MKND(NV(p),mr0,LEN(p),r);
6003: SG(r) = SG(p);
6004: return r;
6005: }
6006: }
6007:
6008: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
6009: {
6010: NM m1,m2;
6011: NDV p1,p2;
6012: ND t1,t2;
6013: UINT *lcm;
6014: P gp,tp;
6015: Z g,t;
6016: Z iq;
6017: int td;
6018: LIST hist;
6019: NODE node;
6020: DP d;
6021:
6022: if ( !mod && nd_demand ) {
6023: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
6024: } else {
6025: if ( trace ) {
6026: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
6027: } else {
6028: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
6029: }
6030: }
6031: lcm = LCM(p);
6032: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
6033: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
6034: FREENM(m1); return 0;
6035: }
6036: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
6037: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
6038: FREENM(m1); FREENM(m2); return 0;
6039: }
6040:
6041: if ( mod == -1 ) {
6042: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
6043: } else if ( mod > 0 ) {
6044: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
6045: } else if ( mod == -2 ) {
6046: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
6047: } else if ( nd_vc ) {
6048: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
6049: divsp(nd_vc,HCP(p2),gp,&CP(m1));
6050: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
6051: } else {
1.6 noro 6052: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 6053: }
6054: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
6055: *rp = nd_add(mod,t1,t2);
6056: if ( nd_gentrace ) {
6057: /* nd_tracelist is initialized */
1.6 noro 6058: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6059: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 6060: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 6061: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
6062: nd_tracelist = node;
6063: }
1.24 noro 6064: if ( *rp )
6065: (*rp)->sig = p->sig;
1.1 noro 6066: FREENM(m1); FREENM(m2);
6067: return 1;
6068: }
6069:
6070: void ndv_mul_c(int mod,NDV p,int mul)
6071: {
6072: NMV m;
6073: int c,c1,len,i;
6074:
6075: if ( !p ) return;
6076: len = LEN(p);
6077: if ( mod == -1 )
6078: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
6079: CM(m) = _mulsf(CM(m),mul);
6080: else
6081: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6082: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
6083: }
6084: }
6085:
6086: void ndv_mul_c_lf(NDV p,Z mul)
6087: {
6088: NMV m;
6089: Z c;
6090: int len,i;
6091:
6092: if ( !p ) return;
6093: len = LEN(p);
6094: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6095: mullf(CZ(m),mul,&c); CZ(m) = c;
6096: }
6097: }
6098:
6099: /* for nd_det */
6100: void ndv_mul_c_q(NDV p,Z mul)
6101: {
6102: NMV m;
6103: Z c;
6104: int len,i;
6105:
6106: if ( !p ) return;
6107: len = LEN(p);
6108: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 6109: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 6110: }
6111: }
6112:
6113: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
6114: int n2,i,j,l,n,tlen;
6115: UINT *d0;
6116: NM *tab,*psum;
6117: ND s,r;
6118: NM t;
6119: NMV m1;
6120:
6121: if ( !p ) return 0;
6122: n = NV(p); n2 = n>>1;
6123: d0 = DL(m0);
6124: l = LEN(p);
6125: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
6126: tab = (NM *)MALLOC(tlen*sizeof(NM));
6127: psum = (NM *)MALLOC(tlen*sizeof(NM));
6128: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
6129: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
6130: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
6131: /* m0(NM) * m1(NMV) => tab(NM) */
6132: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
6133: for ( j = 0; j < tlen; j++ ) {
6134: if ( tab[j] ) {
6135: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
6136: }
6137: }
6138: }
6139: for ( i = tlen-1, r = 0; i >= 0; i-- )
6140: if ( psum[i] ) {
6141: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
6142: MKND(n,psum[i],j,s);
6143: r = nd_add(mod,r,s);
6144: }
6145: if ( r ) SG(r) = SG(p)+TD(d0);
6146: return r;
6147: }
6148:
6149: /* product of monomials */
6150: /* XXX block order is not handled correctly */
6151:
6152: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
6153: {
6154: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
6155: UINT *d0,*d1,*d,*dt,*ctab;
6156: Z *ctab_q;
6157: Z q,q1;
6158: UINT c0,c1,c;
6159: NM *p;
6160: NM m,t;
6161: int mpos;
6162:
6163: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
6164: if ( !m0 || !m1 ) return;
6165: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
6166: if ( nd_module )
6167: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
6168:
6169: NEWNM(m); d = DL(m);
6170: if ( mod ) {
6171: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
6172: } else if ( nd_vc )
6173: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
6174: else
1.6 noro 6175: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 6176: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
6177: homo = n&1 ? 1 : 0;
6178: if ( homo ) {
6179: /* offset of h-degree */
6180: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
6181: PUT_EXP(DL(m),n-1,h);
6182: TD(DL(m)) = h;
6183: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6184: }
6185: tab[0] = m;
6186: NEWNM(m); d = DL(m);
6187: for ( i = 0, curlen = 1; i < n2; i++ ) {
6188: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
6189: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
6190: /* xi^a*(Di^k*xi^l)*Di^b */
6191: a += l; b += k;
6192: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
6193: if ( !k || !l ) {
6194: for ( j = 0; j < curlen; j++ )
6195: if ( (t = tab[j]) != 0 ) {
6196: dt = DL(t);
6197: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
6198: if ( nd_blockmask ) ndl_weight_mask(dt);
6199: }
6200: curlen *= k+1;
6201: continue;
6202: }
6203: min = MIN(k,l);
6204: if ( mod ) {
6205: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
6206: mkwcm(k,l,mod,(int *)ctab);
6207: } else {
6208: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
6209: mkwc(k,l,ctab_q);
6210: }
6211: for ( j = min; j >= 0; j-- ) {
6212: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
6213: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
6214: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
6215: if ( homo ) {
6216: TD(d) = s;
6217: PUT_EXP(d,n-1,s-h);
6218: } else TD(d) = h;
6219: if ( nd_blockmask ) ndl_weight_mask(d);
6220: if ( mod ) c = ctab[j];
6221: else q = ctab_q[j];
6222: p = tab+curlen*j;
6223: if ( j == 0 ) {
6224: for ( u = 0; u < curlen; u++, p++ ) {
6225: if ( tab[u] ) {
6226: ndl_addto(DL(tab[u]),d);
6227: if ( mod ) {
6228: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
6229: } else if ( nd_vc )
6230: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
6231: else {
1.6 noro 6232: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 6233: }
6234: }
6235: }
6236: } else {
6237: for ( u = 0; u < curlen; u++, p++ ) {
6238: if ( tab[u] ) {
6239: NEWNM(t);
6240: ndl_add(DL(tab[u]),d,DL(t));
6241: if ( mod ) {
6242: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
6243: } else if ( nd_vc )
6244: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
6245: else
1.6 noro 6246: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 6247: *p = t;
6248: }
6249: }
6250: }
6251: }
6252: curlen *= k+1;
6253: }
6254: FREENM(m);
6255: if ( nd_module ) {
6256: mpos = MPOS(d1);
6257: for ( i = 0; i < tlen; i++ )
6258: if ( tab[i] ) {
6259: d = DL(tab[i]);
6260: MPOS(d) = mpos;
6261: TD(d) = ndl_weight(d);
6262: }
6263: }
6264: }
6265:
6266: ND ndv_mul_nm_symbolic(NM m0,NDV p)
6267: {
6268: NM mr,mr0;
6269: NMV m;
6270: UINT *d,*dt,*dm;
6271: int c,n,td,i,c1,c2,len;
6272: Q q;
6273: ND r;
6274:
6275: if ( !p ) return 0;
6276: else {
6277: n = NV(p); m = BDY(p);
6278: d = DL(m0);
6279: len = LEN(p);
6280: mr0 = 0;
6281: td = TD(d);
6282: c = CM(m0);
6283: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6284: NEXTNM(mr0,mr);
6285: CM(mr) = 1;
6286: ndl_add(DL(m),d,DL(mr));
6287: }
6288: NEXT(mr) = 0;
6289: MKND(NV(p),mr0,len,r);
6290: SG(r) = SG(p) + TD(d);
6291: return r;
6292: }
6293: }
6294:
6295: ND ndv_mul_nm(int mod,NM m0,NDV p)
6296: {
6297: NM mr,mr0;
6298: NMV m;
6299: UINT *d,*dt,*dm;
6300: int c,n,td,i,c1,c2,len;
6301: P q;
6302: ND r;
6303:
6304: if ( !p ) return 0;
6305: else if ( do_weyl ) {
6306: if ( mod < 0 ) {
6307: error("ndv_mul_nm : not implemented (weyl)");
6308: return 0;
6309: } else
6310: return weyl_ndv_mul_nm(mod,m0,p);
6311: } else {
6312: n = NV(p); m = BDY(p);
6313: d = DL(m0);
6314: len = LEN(p);
6315: mr0 = 0;
6316: td = TD(d);
6317: if ( mod == -1 ) {
6318: c = CM(m0);
6319: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6320: NEXTNM(mr0,mr);
6321: CM(mr) = _mulsf(CM(m),c);
6322: ndl_add(DL(m),d,DL(mr));
6323: }
6324: } else if ( mod == -2 ) {
6325: Z cl;
6326: cl = CZ(m0);
6327: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6328: NEXTNM(mr0,mr);
6329: mullf(CZ(m),cl,&CZ(mr));
6330: ndl_add(DL(m),d,DL(mr));
6331: }
6332: } else if ( mod ) {
6333: c = CM(m0);
6334: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6335: NEXTNM(mr0,mr);
6336: c1 = CM(m);
6337: DMAR(c1,c,0,mod,c2);
6338: CM(mr) = c2;
6339: ndl_add(DL(m),d,DL(mr));
6340: }
6341: } else {
6342: q = CP(m0);
6343: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6344: NEXTNM(mr0,mr);
6345: mulp(nd_vc,CP(m),q,&CP(mr));
6346: ndl_add(DL(m),d,DL(mr));
6347: }
6348: }
6349: NEXT(mr) = 0;
6350: MKND(NV(p),mr0,len,r);
6351: SG(r) = SG(p) + TD(d);
6352: return r;
6353: }
6354: }
6355:
6356: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
6357: {
6358: NM mq0,mq;
6359: NMV tm;
6360: Q q;
6361: int i,nv,sg,c,c1,c2,hindex;
6362: ND p,t,r;
6363:
6364: if ( bucket->m < 0 ) return 0;
6365: else {
6366: nv = NV(d);
6367: mq0 = 0;
6368: tm = (NMV)MALLOC(nmv_adv);
6369: while ( 1 ) {
6370: if ( mod > 0 || mod == -1 )
6371: hindex = head_pbucket(mod,bucket);
6372: else if ( mod == -2 )
6373: hindex = head_pbucket_lf(bucket);
6374: else
6375: hindex = head_pbucket_q(bucket);
6376: if ( hindex < 0 ) break;
6377: p = bucket->body[hindex];
6378: NEXTNM(mq0,mq);
6379: ndl_sub(HDL(p),HDL(d),DL(mq));
6380: ndl_copy(DL(mq),DL(tm));
6381: if ( mod ) {
6382: c1 = invm(HCM(d),mod); c2 = HCM(p);
6383: DMAR(c1,c2,0,mod,c); CM(mq) = c;
6384: CM(tm) = mod-c;
6385: } else {
1.6 noro 6386: divsz(HCZ(p),HCZ(d),&CZ(mq));
6387: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 6388: }
6389: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
6390: bucket->body[hindex] = nd_remove_head(p);
6391: t = nd_remove_head(t);
6392: add_pbucket(mod,bucket,t);
6393: }
6394: if ( !mq0 )
6395: r = 0;
6396: else {
6397: NEXT(mq) = 0;
6398: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
6399: MKND(nv,mq0,i,r);
6400: /* XXX */
6401: SG(r) = HTD(r);
6402: }
6403: return r;
6404: }
6405: }
6406:
6407: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6408: {
6409: NMV m,mr,mr0,t;
6410: int len,i,k;
6411:
6412: if ( !p ) return;
6413: m = BDY(p); len = LEN(p);
6414: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
6415: m = (NMV)((char *)mr0+(len-1)*oadv);
6416: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
6417: t = (NMV)MALLOC(nmv_adv);
6418: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 6419: CZ(t) = CZ(m);
1.1 noro 6420: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
6421: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 6422: CZ(mr) = CZ(t);
1.1 noro 6423: ndl_copy(DL(t),DL(mr));
6424: }
6425: BDY(p) = mr0;
6426: }
6427:
6428: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6429: {
6430: NMV m,mr,mr0;
6431: int len,i;
6432: NDV r;
6433:
6434: if ( !p ) return 0;
6435: m = BDY(p); len = LEN(p);
6436: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
6437: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
6438: ndl_zero(DL(mr));
6439: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 6440: CZ(mr) = CZ(m);
1.1 noro 6441: }
6442: MKNDV(NV(p),mr0,len,r);
6443: SG(r) = SG(p);
1.24 noro 6444: r->sig = p->sig;
1.1 noro 6445: return r;
6446: }
6447:
6448: /* duplicate p */
6449:
6450: NDV ndv_dup(int mod,NDV p)
6451: {
6452: NDV d;
6453: NMV t,m,m0;
6454: int i,len;
6455:
6456: if ( !p ) return 0;
6457: len = LEN(p);
6458: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6459: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6460: ndl_copy(DL(t),DL(m));
1.6 noro 6461: CZ(m) = CZ(t);
1.1 noro 6462: }
6463: MKNDV(NV(p),m0,len,d);
6464: SG(d) = SG(p);
6465: return d;
6466: }
6467:
6468: NDV ndv_symbolic(int mod,NDV p)
6469: {
6470: NDV d;
6471: NMV t,m,m0;
6472: int i,len;
6473:
6474: if ( !p ) return 0;
6475: len = LEN(p);
6476: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6477: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6478: ndl_copy(DL(t),DL(m));
1.6 noro 6479: CZ(m) = ONE;
1.1 noro 6480: }
6481: MKNDV(NV(p),m0,len,d);
6482: SG(d) = SG(p);
6483: return d;
6484: }
6485:
6486: ND nd_dup(ND p)
6487: {
6488: ND d;
6489: NM t,m,m0;
6490:
6491: if ( !p ) return 0;
6492: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
6493: NEXTNM(m0,m);
6494: ndl_copy(DL(t),DL(m));
1.6 noro 6495: CZ(m) = CZ(t);
1.1 noro 6496: }
6497: if ( m0 ) NEXT(m) = 0;
6498: MKND(NV(p),m0,LEN(p),d);
6499: SG(d) = SG(p);
6500: return d;
6501: }
6502:
6503: /* XXX if p->len == 0 then it represents 0 */
6504:
6505: void ndv_mod(int mod,NDV p)
6506: {
6507: NMV t,d;
6508: int r,s,u;
6509: int i,len,dlen;
6510: P cp;
6511: Z c;
6512: Obj gfs;
6513:
6514: if ( !p ) return;
6515: len = LEN(p);
6516: dlen = 0;
6517: if ( mod == -1 )
6518: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6519: simp_ff((Obj)CP(t),&gfs);
6520: if ( gfs ) {
6521: r = FTOIF(CONT((GFS)gfs));
6522: CM(d) = r;
6523: ndl_copy(DL(t),DL(d));
6524: NMV_ADV(d);
6525: dlen++;
6526: }
6527: }
6528: else if ( mod == -2 )
6529: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6530: simp_ff((Obj)CP(t),&gfs);
6531: if ( gfs ) {
6532: lmtolf((LM)gfs,&CZ(d));
6533: ndl_copy(DL(t),DL(d));
6534: NMV_ADV(d);
6535: dlen++;
6536: }
6537: }
6538: else
6539: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6540: if ( nd_vc ) {
6541: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
6542: c = (Z)cp;
6543: } else
1.6 noro 6544: c = CZ(t);
1.1 noro 6545: r = remqi((Q)c,mod);
6546: if ( r ) {
6547: CM(d) = r;
6548: ndl_copy(DL(t),DL(d));
6549: NMV_ADV(d);
6550: dlen++;
6551: }
6552: }
6553: LEN(p) = dlen;
6554: }
6555:
6556: NDV ptondv(VL vl,VL dvl,P p)
6557: {
6558: ND nd;
6559:
6560: nd = ptond(vl,dvl,p);
6561: return ndtondv(0,nd);
6562: }
6563:
6564: void pltozpl(LIST l,Q *cont,LIST *pp)
6565: {
1.16 noro 6566: NODE nd,nd1;
6567: int n;
6568: P *pl;
6569: Q *cl;
6570: int i;
6571: P dmy;
6572: Z dvr,inv;
6573: LIST r;
6574:
6575: nd = BDY(l); n = length(nd);
6576: pl = (P *)MALLOC(n*sizeof(P));
6577: cl = (Q *)MALLOC(n*sizeof(Q));
6578: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
6579: ptozp((P)BDY(nd),1,&cl[i],&dmy);
6580: }
6581: qltozl(cl,n,&dvr);
6582: divz(ONE,dvr,&inv);
6583: nd = BDY(l);
6584: for ( i = 0; i < n; i++, nd = NEXT(nd) )
6585: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
6586: nd = 0;
6587: for ( i = n-1; i >= 0; i-- ) {
6588: MKNODE(nd1,pl[i],nd); nd = nd1;
6589: }
6590: MKLIST(r,nd);
6591: *pp = r;
1.1 noro 6592: }
6593:
6594: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
6595:
6596: NDV pltondv(VL vl,VL dvl,LIST p)
6597: {
6598: int i;
6599: NODE t;
6600: ND r,ri;
6601: NM m;
6602:
6603: if ( !nd_module ) error("pltond : module order must be set");
6604: r = 0;
6605: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
6606: ri = ptond(vl,dvl,(P)BDY(t));
6607: if ( ri )
6608: for ( m = BDY(ri); m; m = NEXT(m) ) {
6609: MPOS(DL(m)) = i;
6610: TD(DL(m)) = ndl_weight(DL(m));
6611: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6612: }
6613: r = nd_add(0,r,ri);
6614: }
6615: return ndtondv(0,r);
6616: }
6617:
6618: ND ptond(VL vl,VL dvl,P p)
6619: {
6620: int n,i,j,k,e;
6621: VL tvl;
6622: V v;
6623: DCP dc;
6624: DCP *w;
6625: ND r,s,t,u;
6626: P x;
6627: int c;
6628: UINT *d;
6629: NM m,m0;
6630:
6631: if ( !p )
6632: return 0;
6633: else if ( NUM(p) ) {
6634: NEWNM(m);
6635: ndl_zero(DL(m));
6636: if ( !INT((Q)p) )
6637: error("ptond : input must be integer-coefficient");
1.6 noro 6638: CZ(m) = (Z)p;
1.1 noro 6639: NEXT(m) = 0;
6640: MKND(nd_nvar,m,1,r);
6641: SG(r) = 0;
6642: return r;
6643: } else {
6644: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
6645: w = (DCP *)MALLOC(k*sizeof(DCP));
6646: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
6647: for ( i = 0, tvl = dvl, v = VR(p);
6648: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
6649: if ( !tvl ) {
6650: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
6651: t = ptond(vl,dvl,COEF(w[j]));
6652: pwrp(vl,x,DEG(w[j]),&p);
6653: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
6654: }
6655: return s;
6656: } else {
6657: NEWNM(m0); d = DL(m0);
6658: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 6659: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 6660: TD(d) = MUL_WEIGHT(e,i);
6661: if ( nd_blockmask) ndl_weight_mask(d);
6662: if ( nd_module ) MPOS(d) = 0;
6663: t = ptond(vl,dvl,COEF(w[j]));
6664: for ( m = BDY(t); m; m = NEXT(m) )
6665: ndl_addto(DL(m),d);
6666: SG(t) += TD(d);
6667: s = nd_add(0,s,t);
6668: }
6669: FREENM(m0);
6670: return s;
6671: }
6672: }
6673: }
6674:
6675: P ndvtop(int mod,VL vl,VL dvl,NDV p)
6676: {
6677: VL tvl;
6678: int len,n,j,i,e;
6679: NMV m;
6680: Z q;
6681: P c;
6682: UINT *d;
6683: P s,r,u,t,w;
6684: GFS gfs;
6685:
6686: if ( !p ) return 0;
6687: else {
6688: len = LEN(p);
6689: n = NV(p);
6690: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6691: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
6692: if ( mod == -1 ) {
6693: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6694: } else if ( mod == -2 ) {
6695: c = (P)CZ(m);
6696: } else if ( mod > 0 ) {
1.6 noro 6697: STOZ(CM(m),q); c = (P)q;
1.1 noro 6698: } else
6699: c = CP(m);
6700: d = DL(m);
6701: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6702: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6703: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6704: }
6705: addp(vl,s,t,&u); s = u;
6706: }
6707: return s;
6708: }
6709: }
6710:
6711: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
6712: {
6713: VL tvl;
6714: int len,n,j,i,e;
6715: NMV m;
6716: Z q;
6717: P c;
6718: UINT *d;
6719: P s,r,u,t,w;
6720: GFS gfs;
6721: P *a;
6722: LIST l;
6723: NODE nd,nd1;
6724:
6725: if ( !p ) return 0;
6726: else {
6727: a = (P *)MALLOC((rank+1)*sizeof(P));
6728: for ( i = 0; i <= rank; i++ ) a[i] = 0;
6729: len = LEN(p);
6730: n = NV(p);
6731: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6732: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
6733: if ( mod == -1 ) {
6734: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6735: } else if ( mod ) {
1.6 noro 6736: STOZ(CM(m),q); c = (P)q;
1.1 noro 6737: } else
6738: c = CP(m);
6739: d = DL(m);
6740: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6741: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6742: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6743: }
6744: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
6745: }
6746: nd = 0;
6747: for ( i = rank; i > 0; i-- ) {
6748: MKNODE(nd1,a[i],nd); nd = nd1;
6749: }
6750: MKLIST(l,nd);
6751: return l;
6752: }
6753: }
6754:
6755: NDV ndtondv(int mod,ND p)
6756: {
6757: NDV d;
6758: NMV m,m0;
6759: NM t;
6760: int i,len;
6761:
6762: if ( !p ) return 0;
6763: len = LEN(p);
6764: if ( mod > 0 || mod == -1 )
6765: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6766: else
6767: m0 = m = MALLOC(len*nmv_adv);
6768: #if 0
6769: ndv_alloc += nmv_adv*len;
6770: #endif
6771: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
6772: ndl_copy(DL(t),DL(m));
1.6 noro 6773: CZ(m) = CZ(t);
1.1 noro 6774: }
6775: MKNDV(NV(p),m0,len,d);
6776: SG(d) = SG(p);
1.24 noro 6777: d->sig = p->sig;
1.1 noro 6778: return d;
6779: }
6780:
1.16 noro 6781: static int dmm_comp_nv;
6782:
6783: int dmm_comp(DMM *a,DMM *b)
6784: {
6785: return -compdmm(dmm_comp_nv,*a,*b);
6786: }
6787:
6788: void dmm_sort_by_ord(DMM *a,int len,int nv)
6789: {
6790: dmm_comp_nv = nv;
6791: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
6792: }
6793:
6794: void dpm_sort(DPM p,DPM *rp)
6795: {
6796: DMM t,t1;
6797: int len,i,n;
6798: DMM *a;
6799: DPM d;
6800:
6801: if ( !p ) *rp = 0;
6802: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6803: a = (DMM *)MALLOC(len*sizeof(DMM));
6804: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6805: n = p->nv;
6806: dmm_sort_by_ord(a,len,n);
6807: t = 0;
6808: for ( i = len-1; i >= 0; i-- ) {
6809: NEWDMM(t1);
6810: t1->c = a[i]->c;
6811: t1->dl = a[i]->dl;
6812: t1->pos = a[i]->pos;
6813: t1->next = t;
6814: t = t1;
6815: }
6816: MKDPM(n,t,d);
6817: SG(d) = SG(p);
6818: *rp = d;
6819: }
6820:
1.18 noro 6821: int dpm_comp(DPM *a,DPM *b)
6822: {
1.22 noro 6823: return -compdpm(CO,*a,*b);
1.18 noro 6824: }
6825:
6826: NODE dpm_sort_list(NODE l)
6827: {
6828: int i,len;
6829: NODE t,t1;
6830: DPM *a;
6831:
6832: len = length(l);
6833: a = (DPM *)MALLOC(len*sizeof(DPM));
6834: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
6835: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
6836: t = 0;
6837: for ( i = len-1; i >= 0; i-- ) {
6838: MKNODE(t1,(pointer)a[i],t); t = t1;
6839: }
6840: return t;
6841: }
6842:
1.20 noro 6843: int nmv_comp(NMV a,NMV b)
6844: {
1.21 noro 6845: int t;
6846: t = DL_COMPARE(a->dl,b->dl);
6847: return -t;
1.20 noro 6848: }
6849:
1.43 noro 6850: NDV dptondv(int mod,DP p)
6851: {
6852: NDV d;
6853: NMV m,m0;
6854: MP t;
6855: MP *a;
6856: int i,len,n;
6857:
6858: if ( !p ) return 0;
6859: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6860: n = p->nv;
6861: if ( mod > 0 || mod == -1 )
6862: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6863: else
6864: m0 = m = MALLOC(len*nmv_adv);
6865: for ( i = 0, t = BDY(p); i < len; i++, NMV_ADV(m), t = NEXT(t) ) {
6866: dltondl(n,t->dl,DL(m));
6867: TD(DL(m)) = ndl_weight(DL(m));
6868: CZ(m) = (Z)t->c;
6869: }
6870: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
6871: MKNDV(NV(p),m0,len,d);
6872: SG(d) = SG(p);
6873: return d;
6874: }
6875:
1.16 noro 6876: NDV dpmtondv(int mod,DPM p)
6877: {
6878: NDV d;
6879: NMV m,m0;
6880: DMM t;
6881: DMM *a;
6882: int i,len,n;
6883:
6884: if ( !p ) return 0;
6885: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6886: a = (DMM *)MALLOC(len*sizeof(DMM));
6887: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6888: n = p->nv;
6889: dmm_sort_by_ord(a,len,n);
6890: if ( mod > 0 || mod == -1 )
6891: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6892: else
6893: m0 = m = MALLOC(len*nmv_adv);
6894: #if 0
6895: ndv_alloc += nmv_adv*len;
6896: #endif
6897: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6898: dltondl(n,a[i]->dl,DL(m));
6899: MPOS(DL(m)) = a[i]->pos;
1.20 noro 6900: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 6901: CZ(m) = (Z)a[i]->c;
6902: }
1.20 noro 6903: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 6904: MKNDV(NV(p),m0,len,d);
6905: SG(d) = SG(p);
6906: return d;
6907: }
6908:
1.1 noro 6909: ND ndvtond(int mod,NDV p)
6910: {
6911: ND d;
6912: NM m,m0;
6913: NMV t;
6914: int i,len;
6915:
6916: if ( !p ) return 0;
6917: m0 = 0;
6918: len = p->len;
6919: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6920: NEXTNM(m0,m);
6921: ndl_copy(DL(t),DL(m));
1.6 noro 6922: CZ(m) = CZ(t);
1.1 noro 6923: }
6924: NEXT(m) = 0;
6925: MKND(NV(p),m0,len,d);
6926: SG(d) = SG(p);
1.28 noro 6927: d->sig = p->sig;
1.1 noro 6928: return d;
6929: }
6930:
6931: DP ndvtodp(int mod,NDV p)
6932: {
6933: MP m,m0;
6934: DP d;
6935: NMV t;
6936: int i,len;
6937:
6938: if ( !p ) return 0;
6939: m0 = 0;
6940: len = p->len;
6941: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6942: NEXTMP(m0,m);
6943: m->dl = ndltodl(nd_nvar,DL(t));
6944: m->c = (Obj)ndctop(mod,t->c);
6945: }
6946: NEXT(m) = 0;
6947: MKDP(nd_nvar,m0,d);
6948: SG(d) = SG(p);
6949: return d;
6950: }
6951:
1.44 ! noro 6952: DPM sigtodpm(SIG s)
! 6953: {
! 6954: DMM m;
! 6955: DPM d;
! 6956:
! 6957: NEWDMM(m);
! 6958: m->c = (Obj)ONE;
! 6959: m->dl = s->dl;
! 6960: m->pos = s->pos+1;
! 6961: m->next = 0;
! 6962: MKDPM(nd_nvar,m,d);
! 6963: SG(d) = s->dl->td;
! 6964: return d;
! 6965: }
! 6966:
1.16 noro 6967: DPM ndvtodpm(int mod,NDV p)
6968: {
6969: DMM m,m0;
6970: DPM d;
6971: NMV t;
6972: int i,len;
6973:
6974: if ( !p ) return 0;
6975: m0 = 0;
6976: len = p->len;
6977: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6978: NEXTDMM(m0,m);
6979: m->dl = ndltodl(nd_nvar,DL(t));
6980: m->c = (Obj)ndctop(mod,t->c);
6981: m->pos = MPOS(DL(t));
6982: }
6983: NEXT(m) = 0;
6984: MKDPM(nd_nvar,m0,d);
6985: SG(d) = SG(p);
6986: return d;
6987: }
6988:
6989:
1.1 noro 6990: DP ndtodp(int mod,ND p)
6991: {
6992: MP m,m0;
6993: DP d;
6994: NM t;
6995: int i,len;
6996:
6997: if ( !p ) return 0;
6998: m0 = 0;
6999: len = p->len;
7000: for ( t = BDY(p); t; t = NEXT(t) ) {
7001: NEXTMP(m0,m);
7002: m->dl = ndltodl(nd_nvar,DL(t));
7003: m->c = (Obj)ndctop(mod,t->c);
7004: }
7005: NEXT(m) = 0;
7006: MKDP(nd_nvar,m0,d);
7007: SG(d) = SG(p);
7008: return d;
7009: }
7010:
7011: void ndv_print(NDV p)
7012: {
7013: NMV m;
7014: int i,len;
7015:
7016: if ( !p ) printf("0\n");
7017: else {
7018: len = LEN(p);
7019: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7020: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 noro 7021: else printf("+%ld*",CM(m));
1.1 noro 7022: ndl_print(DL(m));
7023: }
7024: printf("\n");
7025: }
7026: }
7027:
7028: void ndv_print_q(NDV p)
7029: {
7030: NMV m;
7031: int i,len;
7032:
7033: if ( !p ) printf("0\n");
7034: else {
7035: len = LEN(p);
7036: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
7037: printf("+");
1.6 noro 7038: printexpr(CO,(Obj)CZ(m));
1.1 noro 7039: printf("*");
7040: ndl_print(DL(m));
7041: }
7042: printf("\n");
7043: }
7044: }
7045:
7046: NODE ndv_reducebase(NODE x,int *perm)
7047: {
7048: int len,i,j;
7049: NDVI w;
7050: NODE t,t0;
7051:
1.41 noro 7052: if ( nd_norb ) return x;
1.1 noro 7053: len = length(x);
7054: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
7055: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
7056: w[i].p = BDY(t); w[i].i = perm[i];
7057: }
7058: for ( i = 0; i < len; i++ ) {
7059: for ( j = 0; j < i; j++ ) {
7060: if ( w[i].p && w[j].p ) {
7061: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
7062: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
7063: }
7064: }
7065: }
7066: for ( i = j = 0, t0 = 0; i < len; i++ ) {
7067: if ( w[i].p ) {
7068: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
7069: perm[j++] = w[i].i;
7070: }
7071: }
7072: NEXT(t) = 0; x = t0;
7073: return x;
7074: }
7075:
7076: /* XXX incomplete */
7077:
1.21 noro 7078: extern DMMstack dmm_stack;
7079: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 7080:
1.1 noro 7081: void nd_init_ord(struct order_spec *ord)
7082: {
7083: nd_module = (ord->id >= 256);
7084: if ( nd_module ) {
7085: nd_dcomp = -1;
1.21 noro 7086: nd_module_ordtype = ord->module_ordtype;
1.1 noro 7087: nd_pot_nelim = ord->pot_nelim;
7088: nd_poly_weight_len = ord->nv;
7089: nd_poly_weight = ord->top_weight;
7090: nd_module_rank = ord->module_rank;
7091: nd_module_weight = ord->module_top_weight;
7092: }
7093: nd_matrix = 0;
7094: nd_matrix_len = 0;
7095: switch ( ord->id ) {
7096: case 0:
7097: switch ( ord->ord.simple ) {
7098: case 0:
7099: nd_dcomp = 1;
7100: nd_isrlex = 1;
7101: break;
7102: case 1:
7103: nd_dcomp = 1;
7104: nd_isrlex = 0;
7105: break;
7106: case 2:
7107: nd_dcomp = 0;
7108: nd_isrlex = 0;
7109: ndl_compare_function = ndl_lex_compare;
7110: break;
7111: case 11:
7112: /* XXX */
7113: nd_dcomp = 0;
7114: nd_isrlex = 1;
7115: ndl_compare_function = ndl_ww_lex_compare;
7116: break;
7117: default:
7118: error("nd_gr : unsupported order");
7119: }
7120: break;
7121: case 1:
7122: /* block order */
7123: /* XXX */
7124: nd_dcomp = -1;
7125: nd_isrlex = 0;
7126: ndl_compare_function = ndl_block_compare;
7127: break;
7128: case 2:
7129: /* matrix order */
7130: /* XXX */
7131: nd_dcomp = -1;
7132: nd_isrlex = 0;
7133: nd_matrix_len = ord->ord.matrix.row;
7134: nd_matrix = ord->ord.matrix.matrix;
7135: ndl_compare_function = ndl_matrix_compare;
7136: break;
7137: case 3:
7138: /* composite order */
7139: nd_dcomp = -1;
7140: nd_isrlex = 0;
7141: nd_worb_len = ord->ord.composite.length;
7142: nd_worb = ord->ord.composite.w_or_b;
7143: ndl_compare_function = ndl_composite_compare;
7144: break;
7145:
7146: /* module order */
7147: case 256:
7148: switch ( ord->ord.simple ) {
7149: case 0:
1.21 noro 7150: nd_dcomp = 0;
1.1 noro 7151: nd_isrlex = 1;
1.21 noro 7152: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 7153: break;
7154: case 1:
1.21 noro 7155: nd_dcomp = 0;
1.1 noro 7156: nd_isrlex = 0;
7157: ndl_compare_function = ndl_module_glex_compare;
7158: break;
7159: case 2:
1.21 noro 7160: nd_dcomp = 0;
1.1 noro 7161: nd_isrlex = 0;
1.21 noro 7162: ndl_compare_function = ndl_module_compare;
7163: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 7164: break;
7165: default:
1.21 noro 7166: error("nd_init_ord : unsupported order");
1.1 noro 7167: }
7168: break;
7169: case 257:
7170: /* block order */
7171: nd_isrlex = 0;
1.21 noro 7172: ndl_compare_function = ndl_module_compare;
7173: ndl_base_compare_function = ndl_block_compare;
1.1 noro 7174: break;
7175: case 258:
7176: /* matrix order */
7177: nd_isrlex = 0;
7178: nd_matrix_len = ord->ord.matrix.row;
7179: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 7180: ndl_compare_function = ndl_module_compare;
7181: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 7182: break;
7183: case 259:
7184: /* composite order */
7185: nd_isrlex = 0;
7186: nd_worb_len = ord->ord.composite.length;
7187: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 7188: ndl_compare_function = ndl_module_compare;
7189: ndl_base_compare_function = ndl_composite_compare;
7190: break;
7191: case 300:
7192: /* schreyer order */
7193: if ( ord->base->id != 256 )
7194: error("nd_init_ord : unsupported base order");
7195: ndl_compare_function = ndl_module_schreyer_compare;
7196: dmm_stack = ord->dmmstack;
7197: switch ( ord->base->ord.simple ) {
7198: case 0:
7199: nd_isrlex = 1;
7200: ndl_base_compare_function = ndl_glex_compare;
7201: dl_base_compare_function = cmpdl_revgradlex;
7202: break;
7203: case 1:
7204: nd_isrlex = 0;
7205: ndl_base_compare_function = ndl_glex_compare;
7206: dl_base_compare_function = cmpdl_gradlex;
7207: break;
7208: case 2:
7209: nd_isrlex = 0;
7210: ndl_base_compare_function = ndl_lex_compare;
7211: dl_base_compare_function = cmpdl_lex;
7212: break;
7213: default:
7214: error("nd_init_ord : unsupported order");
7215: }
1.1 noro 7216: break;
7217: }
7218: nd_ord = ord;
7219: }
7220:
7221: BlockMask nd_create_blockmask(struct order_spec *ord)
7222: {
7223: int n,i,j,s,l;
7224: UINT *t;
7225: BlockMask bm;
7226:
7227: /* we only create mask table for block order */
7228: if ( ord->id != 1 && ord->id != 257 )
7229: return 0;
7230: n = ord->ord.block.length;
7231: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
7232: bm->n = n;
7233: bm->order_pair = ord->ord.block.order_pair;
7234: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
7235: for ( i = 0, s = 0; i < n; i++ ) {
7236: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
7237: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
7238: l = bm->order_pair[i].length;
7239: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
7240: }
7241: return bm;
7242: }
7243:
7244: EPOS nd_create_epos(struct order_spec *ord)
7245: {
7246: int i,j,l,s,ord_l,ord_o;
7247: EPOS epos;
7248: struct order_pair *op;
7249:
7250: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
7251: switch ( ord->id ) {
1.21 noro 7252: case 0: case 256: case 300:
1.1 noro 7253: if ( nd_isrlex ) {
7254: for ( i = 0; i < nd_nvar; i++ ) {
7255: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
7256: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
7257: }
7258: } else {
7259: for ( i = 0; i < nd_nvar; i++ ) {
7260: epos[i].i = nd_exporigin + i/nd_epw;
7261: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7262: }
7263: }
7264: break;
7265: case 1: case 257:
7266: /* block order */
7267: l = ord->ord.block.length;
7268: op = ord->ord.block.order_pair;
7269: for ( j = 0, s = 0; j < l; j++ ) {
7270: ord_o = op[j].order;
7271: ord_l = op[j].length;
7272: if ( !ord_o )
7273: for ( i = 0; i < ord_l; i++ ) {
7274: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
7275: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
7276: }
7277: else
7278: for ( i = 0; i < ord_l; i++ ) {
7279: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
7280: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
7281: }
7282: s += ord_l;
7283: }
7284: break;
7285: case 2:
7286: /* matrix order */
7287: case 3:
7288: /* composite order */
7289: default:
7290: for ( i = 0; i < nd_nvar; i++ ) {
7291: epos[i].i = nd_exporigin + i/nd_epw;
7292: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
7293: }
7294: break;
7295: }
7296: return epos;
7297: }
7298:
7299: /* external interface */
7300:
7301: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
7302: {
7303: NODE t,in0,in;
7304: ND ndf,nf;
7305: NDV ndvf;
7306: VL vv,tv;
7307: int stat,nvar,max,mrank;
7308: union oNDC dn;
7309: Q cont;
7310: P pp;
7311: LIST ppl;
7312:
7313: if ( !f ) {
7314: *rp = 0;
7315: return;
7316: }
7317: pltovl(v,&vv);
7318: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
7319:
7320: /* max=65536 implies nd_bpe=32 */
7321: max = 65536;
7322:
7323: nd_module = 0;
7324: /* nd_module will be set if ord is a module ordering */
7325: nd_init_ord(ord);
7326: nd_setup_parameters(nvar,max);
7327: if ( nd_module && OID(f) != O_LIST )
7328: error("nd_nf_p : the first argument must be a list");
7329: if ( nd_module ) mrank = length(BDY((LIST)f));
7330: /* conversion to ndv */
7331: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
7332: NEXTNODE(in0,in);
7333: if ( nd_module ) {
7334: if ( !BDY(t) || OID(BDY(t)) != O_LIST
7335: || length(BDY((LIST)BDY(t))) != mrank )
7336: error("nd_nf_p : inconsistent basis element");
7337: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
7338: else ppl = (LIST)BDY(t);
7339: BDY(in) = (pointer)pltondv(CO,vv,ppl);
7340: } else {
7341: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
7342: else pp = (P)BDY(t);
7343: BDY(in) = (pointer)ptondv(CO,vv,pp);
7344: }
7345: if ( m ) ndv_mod(m,(NDV)BDY(in));
7346: }
7347: if ( in0 ) NEXT(in) = 0;
7348:
7349: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
7350: else ndvf = ptondv(CO,vv,(P)f);
7351: if ( m ) ndv_mod(m,ndvf);
7352: ndf = (pointer)ndvtond(m,ndvf);
7353:
7354: /* dont sort, dont removecont */
1.24 noro 7355: ndv_setup(m,0,in0,1,1,0);
1.1 noro 7356: nd_scale=2;
1.6 noro 7357: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 7358: if ( !stat )
7359: error("nd_nf_p : exponent too large");
7360: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
7361: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
7362: }
7363:
7364: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
7365: {
7366: NM m;
7367: UINT *t,*s;
7368: int i;
7369:
7370: for ( i = 0; i < n; i++ ) r[i] = 0;
7371: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7372: t = DL(m);
7373: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7374: r[i] = CM(m);
7375: }
7376: for ( i = 0; !r[i]; i++ );
7377: return i;
7378: }
7379:
7380: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
7381: {
7382: NM m;
7383: UINT *t,*s;
7384: int i;
7385:
7386: for ( i = 0; i < n; i++ ) r[i] = 0;
7387: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7388: t = DL(m);
7389: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7390: r[i] = CZ(m);
1.1 noro 7391: }
7392: for ( i = 0; !r[i]; i++ );
7393: return i;
7394: }
7395:
7396: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
7397: {
7398: NM m;
7399: UINT *t,*s;
7400: int i;
7401:
7402: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
7403: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
7404: t = DL(m);
7405: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
7406: mpz_set(r[i],BDY(CZ(m)));
7407: }
7408: for ( i = 0; !mpz_sgn(r[i]); i++ );
7409: return i;
7410: }
7411:
7412: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
7413: {
7414: NM m;
7415: unsigned long *v;
7416: int i,j,h,size;
7417: UINT *s,*t;
7418:
7419: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
7420: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
7421: bzero(v,size);
7422: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
7423: t = DL(m);
7424: h = ndl_hash_value(t);
7425: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7426: v[i/BLEN] |= 1L <<(i%BLEN);
7427: }
7428: return v;
7429: }
7430:
7431: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
7432: {
7433: NMV mr;
7434: UINT *d,*t,*s;
7435: int i,j,len,h,head;
7436:
7437: d = DL(m);
7438: len = LEN(p);
7439: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7440: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7441: ndl_add(d,DL(mr),t);
7442: h = ndl_hash_value(t);
7443: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
7444: if ( j == 0 ) head = i;
7445: v[i/BLEN] |= 1L <<(i%BLEN);
7446: }
7447: return head;
7448: }
7449:
7450: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
7451: {
7452: NM m;
7453: NMV mr;
7454: UINT *d,*t,*s;
7455: NDV p;
7456: int i,j,len;
7457: Z *r;
7458:
7459: m = pair->mul;
7460: d = DL(m);
7461: p = nd_ps[pair->index];
7462: len = LEN(p);
7463: r = (Z *)CALLOC(n,sizeof(Q));
7464: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7465: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7466: ndl_add(d,DL(mr),t);
7467: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7468: r[i] = CZ(mr);
1.1 noro 7469: }
7470: return r;
7471: }
7472:
1.11 noro 7473: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 7474: {
7475: NM m;
7476: NMV mr;
1.11 noro 7477: UINT *d,*t,*s,*u;
1.1 noro 7478: NDV p;
7479: unsigned char *ivc;
7480: unsigned short *ivs;
7481: UINT *v,*ivi,*s0v;
1.11 noro 7482: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 7483: IndArray r;
7484:
7485: m = pair->mul;
7486: d = DL(m);
7487: if ( trace )
7488: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
7489: else
7490: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
7491:
7492: len = LEN(p);
7493: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7494: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 7495: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
7496: ndl_add(d,DL(mr),t);
7497: st = prev;
7498: ed = n;
7499: while ( ed > st ) {
7500: md = (st+ed)/2;
7501: u = s0+md*nd_wpd;
7502: c = DL_COMPARE(u,t);
7503: if ( c == 0 ) break;
7504: else if ( c > 0 ) st = md;
7505: else ed = md;
7506: }
7507: prev = v[j] = md;
1.1 noro 7508: }
7509: r = (IndArray)MALLOC(sizeof(struct oIndArray));
7510: r->head = v[0];
7511: diff = 0;
7512: for ( i = 1; i < len; i++ ) {
7513: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
7514: }
7515: if ( diff < 256 ) {
7516: r->width = 1;
7517: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
7518: r->index.c = ivc;
7519: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
7520: } else if ( diff < 65536 ) {
7521: r->width = 2;
7522: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
7523: r->index.s = ivs;
7524: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
7525: } else {
7526: r->width = 4;
7527: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
7528: r->index.i = ivi;
7529: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
7530: }
7531: return r;
7532: }
7533:
7534: int compress_array(Z *svect,Z *cvect,int n)
7535: {
7536: int i,j;
7537:
7538: for ( i = j = 0; i < n; i++ )
7539: if ( svect[i] ) cvect[j++] = svect[i];
7540: return j;
7541: }
7542:
7543: void expand_array(Z *svect,Z *cvect,int n)
7544: {
7545: int i,j;
7546:
7547: for ( i = j = 0; j < n; i++ )
7548: if ( svect[i] ) svect[i] = cvect[j++];
7549: }
7550:
1.8 noro 7551: #if 0
1.1 noro 7552: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7553: {
7554: int i,j,k,len,pos,prev,nz;
7555: Z cs,mcs,c1,c2,cr,gcd,t;
7556: IndArray ivect;
7557: unsigned char *ivc;
7558: unsigned short *ivs;
7559: unsigned int *ivi;
7560: NDV redv;
7561: NMV mr;
7562: NODE rp;
7563: int maxrs;
7564: double hmag;
7565: Z *cvect;
1.3 noro 7566: int l;
1.1 noro 7567:
7568: maxrs = 0;
7569: for ( i = 0; i < col && !svect[i]; i++ );
7570: if ( i == col ) return maxrs;
7571: hmag = p_mag((P)svect[i])*nd_scale;
7572: cvect = (Z *)MALLOC(col*sizeof(Q));
7573: for ( i = 0; i < nred; i++ ) {
7574: ivect = imat[i];
7575: k = ivect->head;
7576: if ( svect[k] ) {
7577: maxrs = MAX(maxrs,rp0[i]->sugar);
7578: redv = nd_demand?ndv_load(rp0[i]->index)
7579: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7580: len = LEN(redv); mr = BDY(redv);
1.6 noro 7581: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 7582: chsgnz(cs,&mcs);
7583: if ( !UNIQ(cr) ) {
7584: for ( j = 0; j < col; j++ ) {
7585: mulz(svect[j],cr,&c1); svect[j] = c1;
7586: }
7587: }
7588: svect[k] = 0; prev = k;
7589: switch ( ivect->width ) {
7590: case 1:
7591: ivc = ivect->index.c;
7592: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7593: pos = prev+ivc[j]; prev = pos;
1.6 noro 7594: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7595: }
7596: break;
7597: case 2:
7598: ivs = ivect->index.s;
7599: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7600: pos = prev+ivs[j]; prev = pos;
1.6 noro 7601: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7602: }
7603: break;
7604: case 4:
7605: ivi = ivect->index.i;
7606: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7607: pos = prev+ivi[j]; prev = pos;
1.6 noro 7608: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7609: }
7610: break;
7611: }
7612: for ( j = k+1; j < col && !svect[j]; j++ );
7613: if ( j == col ) break;
7614: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
7615: nz = compress_array(svect,cvect,col);
7616: removecont_array((P *)cvect,nz,1);
7617: expand_array(svect,cvect,nz);
7618: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
7619: }
7620: }
7621: }
7622: nz = compress_array(svect,cvect,col);
7623: removecont_array((P *)cvect,nz,1);
7624: expand_array(svect,cvect,nz);
7625: if ( DP_Print ) {
7626: fprintf(asir_out,"-"); fflush(asir_out);
7627: }
7628: return maxrs;
7629: }
1.4 noro 7630: #else
1.9 noro 7631:
1.4 noro 7632: /* direct mpz version */
7633: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7634: {
7635: int i,j,k,len,pos,prev;
7636: mpz_t cs,cr,gcd;
7637: IndArray ivect;
7638: unsigned char *ivc;
7639: unsigned short *ivs;
7640: unsigned int *ivi;
7641: NDV redv;
7642: NMV mr;
7643: NODE rp;
7644: int maxrs;
7645: double hmag;
7646: int l;
1.13 noro 7647: static mpz_t *svect;
7648: static int svect_len=0;
1.4 noro 7649:
7650: maxrs = 0;
7651: for ( i = 0; i < col && !svect0[i]; i++ );
7652: if ( i == col ) return maxrs;
7653: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 7654: if ( col > svect_len ) {
7655: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
7656: svect_len = col;
7657: }
1.4 noro 7658: for ( i = 0; i < col; i++ ) {
7659: mpz_init(svect[i]);
7660: if ( svect0[i] )
7661: mpz_set(svect[i],BDY(svect0[i]));
7662: else
7663: mpz_set_ui(svect[i],0);
7664: }
7665: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
7666: for ( i = 0; i < nred; i++ ) {
7667: ivect = imat[i];
7668: k = ivect->head;
7669: if ( mpz_sgn(svect[k]) ) {
7670: maxrs = MAX(maxrs,rp0[i]->sugar);
7671: redv = nd_demand?ndv_load(rp0[i]->index)
7672: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7673: len = LEN(redv); mr = BDY(redv);
1.6 noro 7674: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 7675: mpz_div(cs,svect[k],gcd);
1.6 noro 7676: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 7677: mpz_neg(cs,cs);
1.9 noro 7678: if ( MUNIMPZ(cr) )
7679: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
7680: else if ( !UNIMPZ(cr) )
7681: for ( j = 0; j < col; j++ ) {
7682: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
7683: }
1.4 noro 7684: mpz_set_ui(svect[k],0);
7685: prev = k;
7686: switch ( ivect->width ) {
7687: case 1:
7688: ivc = ivect->index.c;
7689: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7690: pos = prev+ivc[j]; prev = pos;
1.6 noro 7691: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7692: }
7693: break;
7694: case 2:
7695: ivs = ivect->index.s;
7696: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7697: pos = prev+ivs[j]; prev = pos;
1.6 noro 7698: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7699: }
7700: break;
7701: case 4:
7702: ivi = ivect->index.i;
7703: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7704: pos = prev+ivi[j]; prev = pos;
1.6 noro 7705: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7706: }
7707: break;
7708: }
7709: for ( j = k+1; j < col && !svect[j]; j++ );
7710: if ( j == col ) break;
7711: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
7712: mpz_removecont_array(svect,col);
7713: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
7714: }
7715: }
7716: }
7717: mpz_removecont_array(svect,col);
7718: if ( DP_Print ) {
7719: fprintf(asir_out,"-"); fflush(asir_out);
7720: }
7721: for ( i = 0; i < col; i++ )
7722: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
7723: else svect0[i] = 0;
7724: return maxrs;
7725: }
7726: #endif
1.1 noro 7727:
1.40 noro 7728: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred,SIG sig)
1.1 noro 7729: {
7730: int i,j,k,len,pos,prev;
7731: UINT c,c1,c2,c3,up,lo,dmy;
7732: IndArray ivect;
7733: unsigned char *ivc;
7734: unsigned short *ivs;
7735: unsigned int *ivi;
7736: NDV redv;
7737: NMV mr;
7738: NODE rp;
7739: int maxrs;
7740:
7741: maxrs = 0;
7742: for ( i = 0; i < nred; i++ ) {
7743: ivect = imat[i];
7744: k = ivect->head; svect[k] %= m;
1.40 noro 7745: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.1 noro 7746: maxrs = MAX(maxrs,rp0[i]->sugar);
7747: c = m-c; redv = nd_ps[rp0[i]->index];
7748: len = LEN(redv); mr = BDY(redv);
7749: svect[k] = 0; prev = k;
7750: switch ( ivect->width ) {
7751: case 1:
7752: ivc = ivect->index.c;
7753: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7754: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.40 noro 7755: if ( c1 ) {
7756: c2 = svect[pos];
1.1 noro 7757: DMA(c1,c,c2,up,lo);
7758: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7759: } else svect[pos] = lo;
1.40 noro 7760: }
1.1 noro 7761: }
7762: break;
7763: case 2:
7764: ivs = ivect->index.s;
7765: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7766: pos = prev+ivs[j]; c1 = CM(mr);
7767: prev = pos;
1.40 noro 7768: if ( c1 ) {
7769: c2 = svect[pos];
1.1 noro 7770: DMA(c1,c,c2,up,lo);
7771: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7772: } else svect[pos] = lo;
1.40 noro 7773: }
1.1 noro 7774: }
7775: break;
7776: case 4:
7777: ivi = ivect->index.i;
7778: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7779: pos = prev+ivi[j]; c1 = CM(mr);
7780: prev = pos;
1.40 noro 7781: if ( c1 ) {
7782: c2 = svect[pos];
1.1 noro 7783: DMA(c1,c,c2,up,lo);
7784: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7785: } else svect[pos] = lo;
1.40 noro 7786: }
1.1 noro 7787: }
7788: break;
7789: }
7790: }
7791: }
7792: for ( i = 0; i < col; i++ )
7793: if ( svect[i] >= (UINT)m ) svect[i] %= m;
7794: return maxrs;
7795: }
7796:
7797: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7798: {
7799: int i,j,k,len,pos,prev;
7800: UINT c,c1,c2,c3,up,lo,dmy;
7801: IndArray ivect;
7802: unsigned char *ivc;
7803: unsigned short *ivs;
7804: unsigned int *ivi;
7805: NDV redv;
7806: NMV mr;
7807: NODE rp;
7808: int maxrs;
7809:
7810: maxrs = 0;
7811: for ( i = 0; i < nred; i++ ) {
7812: ivect = imat[i];
7813: k = ivect->head;
7814: if ( (c = svect[k]) != 0 ) {
7815: maxrs = MAX(maxrs,rp0[i]->sugar);
7816: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
7817: len = LEN(redv); mr = BDY(redv);
7818: svect[k] = 0; prev = k;
7819: switch ( ivect->width ) {
7820: case 1:
7821: ivc = ivect->index.c;
7822: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7823: pos = prev+ivc[j]; prev = pos;
7824: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7825: }
7826: break;
7827: case 2:
7828: ivs = ivect->index.s;
7829: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7830: pos = prev+ivs[j]; prev = pos;
7831: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7832: }
7833: break;
7834: case 4:
7835: ivi = ivect->index.i;
7836: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7837: pos = prev+ivi[j]; prev = pos;
7838: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7839: }
7840: break;
7841: }
7842: }
7843: }
7844: return maxrs;
7845: }
7846:
7847: ND nd_add_lf(ND p1,ND p2)
7848: {
7849: int n,c,can;
7850: ND r;
7851: NM m1,m2,mr0,mr,s;
7852: Z t;
7853:
7854: if ( !p1 ) return p2;
7855: else if ( !p2 ) return p1;
7856: else {
7857: can = 0;
7858: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
7859: c = DL_COMPARE(DL(m1),DL(m2));
7860: switch ( c ) {
7861: case 0:
7862: addlf(CZ(m1),CZ(m2),&t);
7863: s = m1; m1 = NEXT(m1);
7864: if ( t ) {
7865: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
7866: } else {
7867: can += 2; FREENM(s);
7868: }
7869: s = m2; m2 = NEXT(m2); FREENM(s);
7870: break;
7871: case 1:
7872: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
7873: break;
7874: case -1:
7875: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
7876: break;
7877: }
7878: }
7879: if ( !mr0 )
7880: if ( m1 ) mr0 = m1;
7881: else if ( m2 ) mr0 = m2;
7882: else return 0;
7883: else if ( m1 ) NEXT(mr) = m1;
7884: else if ( m2 ) NEXT(mr) = m2;
7885: else NEXT(mr) = 0;
7886: BDY(p1) = mr0;
7887: SG(p1) = MAX(SG(p1),SG(p2));
7888: LEN(p1) = LEN(p1)+LEN(p2)-can;
7889: FREEND(p2);
7890: return p1;
7891: }
7892: }
7893:
7894: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7895: {
7896: int i,j,k,len,pos,prev;
7897: mpz_t c,mc,c1;
7898: IndArray ivect;
7899: unsigned char *ivc;
7900: unsigned short *ivs;
7901: unsigned int *ivi;
7902: NDV redv;
7903: NMV mr;
7904: NODE rp;
7905: int maxrs;
7906:
7907: maxrs = 0;
7908: lf_lazy = 1;
7909: for ( i = 0; i < nred; i++ ) {
7910: ivect = imat[i];
7911: k = ivect->head;
7912: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
7913: if ( mpz_sgn(svect[k]) ) {
7914: maxrs = MAX(maxrs,rp0[i]->sugar);
7915: mpz_neg(svect[k],svect[k]);
7916: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
7917: len = LEN(redv); mr = BDY(redv);
7918: prev = k;
7919: switch ( ivect->width ) {
7920: case 1:
7921: ivc = ivect->index.c;
7922: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7923: pos = prev+ivc[j]; prev = pos;
7924: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7925: }
7926: break;
7927: case 2:
7928: ivs = ivect->index.s;
7929: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7930: pos = prev+ivs[j]; prev = pos;
7931: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7932: }
7933: break;
7934: case 4:
7935: ivi = ivect->index.i;
7936: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7937: pos = prev+ivi[j]; prev = pos;
7938: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7939: }
7940: break;
7941: }
7942: mpz_set_ui(svect[k],0);
7943: }
7944: }
7945: lf_lazy=0;
7946: for ( i = 0; i < col; i++ ) {
7947: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
7948: }
7949: return maxrs;
7950: }
7951:
7952: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
7953: {
7954: int i,j,k,l,rank,s;
7955: mpz_t a,a1,inv;
7956: mpz_t *t,*pivot,*pk;
7957: mpz_t **mat;
7958: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
7959: int size,size1;
7960:
7961: mpz_init(inv);
7962: mpz_init(a);
7963: mat = (mpz_t **)mat0;
7964: size = 0;
7965: for ( rank = 0, j = 0; j < col; j++ ) {
7966: for ( i = rank; i < row; i++ ) {
7967: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
7968: }
7969: for ( i = rank; i < row; i++ )
7970: if ( mpz_sgn(mat[i][j]) )
7971: break;
7972: if ( i == row ) {
7973: colstat[j] = 0;
7974: continue;
7975: } else
7976: colstat[j] = 1;
7977: if ( i != rank ) {
7978: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
7979: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
7980: }
7981: pivot = mat[rank];
7982: s = sugar[rank];
7983: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
7984: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
7985: if ( mpz_sgn(*pk) ) {
7986: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
7987: }
7988: for ( i = rank+1; i < row; i++ ) {
7989: t = mat[i];
7990: if ( mpz_sgn(t[j]) ) {
7991: sugar[i] = MAX(sugar[i],s);
7992: mpz_neg(a,t[j]);
7993: red_by_vect_lf(t+j,pivot+j,a,col-j);
7994: }
7995: }
7996: rank++;
7997: }
7998: for ( j = col-1, l = rank-1; j >= 0; j-- )
7999: if ( colstat[j] ) {
8000: pivot = mat[l];
8001: s = sugar[l];
8002: for ( k = j; k < col; k++ )
8003: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
8004: for ( i = 0; i < l; i++ ) {
8005: t = mat[i];
8006: if ( mpz_sgn(t[j]) ) {
8007: sugar[i] = MAX(sugar[i],s);
8008: mpz_neg(a,t[j]);
8009: red_by_vect_lf(t+j,pivot+j,a,col-j);
8010: }
8011: }
8012: l--;
8013: }
8014: for ( j = 0, l = 0; l < rank; j++ )
8015: if ( colstat[j] ) {
8016: t = mat[l];
8017: for ( k = j; k < col; k++ ) {
8018: mpz_mod(t[k],t[k],BDY(current_mod_lf));
8019: }
8020: l++;
8021: }
8022: return rank;
8023: }
8024:
8025:
8026: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
8027: {
8028: int j,k,len;
8029: UINT *p;
8030: UINT c;
8031: NDV r;
8032: NMV mr0,mr;
8033:
8034: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8035: if ( !len ) return 0;
8036: else {
8037: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8038: #if 0
8039: ndv_alloc += nmv_adv*len;
8040: #endif
8041: mr = mr0;
8042: p = s0vect;
8043: for ( j = k = 0; j < col; j++, p += nd_wpd )
8044: if ( !rhead[j] ) {
8045: if ( (c = vect[k++]) != 0 ) {
8046: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8047: }
8048: }
8049: MKNDV(nd_nvar,mr0,len,r);
8050: return r;
8051: }
8052: }
8053:
1.40 noro 8054: NDV vect_to_ndv_s(UINT *vect,int col,UINT *s0vect)
8055: {
8056: int j,k,len;
8057: UINT *p;
8058: UINT c;
8059: NDV r;
8060: NMV mr0,mr;
8061:
8062: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8063: if ( !len ) return 0;
8064: else {
8065: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8066: mr = mr0;
8067: p = s0vect;
8068: for ( j = k = 0; j < col; j++, p += nd_wpd )
8069: if ( (c = vect[k++]) != 0 ) {
8070: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
8071: }
8072: MKNDV(nd_nvar,mr0,len,r);
8073: return r;
8074: }
8075: }
8076:
1.1 noro 8077: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
8078: {
8079: int j,k,len;
8080: UINT *p;
8081: NDV r;
8082: NMV mr0,mr;
8083:
8084: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
8085: if ( !len ) return 0;
8086: else {
8087: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8088: mr = mr0;
8089: p = s0vect;
8090: for ( j = 0; j < col; j++, p += nd_wpd )
8091: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
8092: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
8093: }
8094: MKNDV(nd_nvar,mr0,len,r);
8095: return r;
8096: }
8097: }
8098:
8099: /* for preprocessed vector */
8100:
8101: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
8102: {
1.6 noro 8103: int j,k,len;
8104: UINT *p;
8105: Z c;
8106: NDV r;
8107: NMV mr0,mr;
1.1 noro 8108:
1.6 noro 8109: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
8110: if ( !len ) return 0;
8111: else {
8112: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 8113: #if 0
1.6 noro 8114: ndv_alloc += nmv_adv*len;
1.1 noro 8115: #endif
1.6 noro 8116: mr = mr0;
8117: p = s0vect;
8118: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
8119: if ( !rhead[j] ) {
8120: if ( (c = vect[k++]) != 0 ) {
8121: if ( !INT(c) )
8122: error("vect_to_ndv_q : components must be integers");
8123: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
8124: }
8125: }
1.1 noro 8126: }
1.6 noro 8127: MKNDV(nd_nvar,mr0,len,r);
8128: return r;
8129: }
1.1 noro 8130: }
8131:
8132: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
8133: {
8134: int j,k,len;
8135: UINT *p;
8136: mpz_t c;
8137: NDV r;
8138: NMV mr0,mr;
8139:
8140: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
8141: if ( !len ) return 0;
8142: else {
8143: mr0 = (NMV)MALLOC(nmv_adv*len);
8144: #if 0
8145: ndv_alloc += nmv_adv*len;
8146: #endif
8147: mr = mr0;
8148: p = s0vect;
8149: for ( j = k = 0; j < col; j++, p += nd_wpd )
8150: if ( !rhead[j] ) {
8151: c[0] = vect[k++][0];
8152: if ( mpz_sgn(c) ) {
8153: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
8154: }
8155: }
8156: MKNDV(nd_nvar,mr0,len,r);
8157: return r;
8158: }
8159: }
8160:
8161: /* for plain vector */
8162:
8163: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
8164: {
8165: int j,k,len;
8166: UINT *p;
8167: Z c;
8168: NDV r;
8169: NMV mr0,mr;
8170:
8171: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
8172: if ( !len ) return 0;
8173: else {
8174: mr0 = (NMV)MALLOC(nmv_adv*len);
8175: #if 0
8176: ndv_alloc += nmv_adv*len;
8177: #endif
8178: mr = mr0;
8179: p = s0vect;
8180: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
8181: if ( (c = vect[k]) != 0 ) {
8182: if ( !INT(c) )
1.6 noro 8183: error("plain_vect_to_ndv_q : components must be integers");
8184: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 8185: }
8186: MKNDV(nd_nvar,mr0,len,r);
8187: return r;
8188: }
8189: }
8190:
8191: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
8192: {
8193: ND_pairs t;
8194: NODE sp0,sp;
8195: int stat;
8196: ND spol;
8197:
8198: for ( t = l; t; t = NEXT(t) ) {
8199: stat = nd_sp(m,trace,t,&spol);
8200: if ( !stat ) return 0;
8201: if ( spol ) {
8202: add_pbucket_symbolic(bucket,spol);
8203: }
8204: }
8205: return 1;
8206: }
8207:
8208: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
8209: {
8210: NODE rp0,rp;
8211: NM mul,head,s0,s;
8212: int index,col,i,sugar;
8213: RHist h;
8214: UINT *s0v,*p;
8215: NM_ind_pair pair;
8216: ND red;
8217: NDV *ps;
8218:
8219: s0 = 0; rp0 = 0; col = 0;
8220: if ( nd_demand )
8221: ps = trace?nd_ps_trace_sym:nd_ps_sym;
8222: else
8223: ps = trace?nd_ps_trace:nd_ps;
8224: while ( 1 ) {
8225: head = remove_head_pbucket_symbolic(bucket);
8226: if ( !head ) break;
8227: if ( !s0 ) s0 = head;
8228: else NEXT(s) = head;
8229: s = head;
8230: index = ndl_find_reducer(DL(head));
8231: if ( index >= 0 ) {
8232: h = nd_psh[index];
8233: NEWNM(mul);
8234: ndl_sub(DL(head),DL(h),DL(mul));
8235: if ( ndl_check_bound2(index,DL(mul)) )
8236: return 0;
8237: sugar = TD(DL(mul))+SG(ps[index]);
1.28 noro 8238: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 8239: red = ndv_mul_nm_symbolic(mul,ps[index]);
8240: add_pbucket_symbolic(bucket,nd_remove_head(red));
8241: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
8242: }
8243: col++;
8244: }
8245: if ( rp0 ) NEXT(rp) = 0;
8246: NEXT(s) = 0;
8247: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
8248: for ( i = 0, p = s0v, s = s0; i < col;
8249: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
8250: *s0vect = s0v;
8251: *r = rp0;
8252: return col;
8253: }
8254:
8255: void print_ndp(ND_pairs l)
8256: {
8257: ND_pairs t;
8258:
8259: for ( t = l; t; t = NEXT(t) )
8260: printf("[%d,%d] ",t->i1,t->i2);
8261: printf("\n");
8262: }
8263:
8264: NODE nd_f4(int m,int checkonly,int **indp)
8265: {
8266: int i,nh,stat,index,f4red;
8267: NODE r,g,tn0,tn,node;
8268: ND_pairs d,l,t,ll0,ll,lh;
8269: LIST l0,l1;
8270: ND spol,red;
8271: NDV nf,redv;
8272: NM s0,s;
8273: NODE rp0,srp0,nflist,nzlist,nzlist_t;
8274: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
8275: UINT c;
8276: UINT **spmat;
8277: UINT *s0vect,*svect,*p,*v;
8278: int *colstat;
8279: IndArray *imat;
8280: int *rhead;
8281: int spcol,sprow;
8282: int sugar,sugarh;
8283: PGeoBucket bucket;
8284: struct oEGT eg0,eg1,eg_f4;
8285: Z i1,i2,sugarq;
1.12 noro 8286:
8287: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 8288: #if 0
8289: ndv_alloc = 0;
8290: #endif
1.11 noro 8291: Nf4_red=0;
1.1 noro 8292: g = 0; d = 0;
8293: for ( i = 0; i < nd_psn; i++ ) {
8294: d = update_pairs(d,g,i,0);
8295: g = update_base(g,i);
8296: }
8297: nzlist = 0;
8298: nzlist_t = nd_nzlist;
8299: f4red = 1;
8300: nd_last_nonzero = 0;
8301: while ( d ) {
8302: get_eg(&eg0);
8303: l = nd_minsugarp(d,&d);
8304: sugar = nd_sugarweight?l->sugar2:SG(l);
8305: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8306: if ( nzlist_t ) {
8307: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 8308: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 8309: tn = BDY((LIST)ARG1(node));
8310: if ( !tn ) {
8311: nzlist_t = NEXT(nzlist_t);
8312: continue;
8313: }
8314: /* tn = [[i1,i2],...] */
8315: lh = nd_ipairtospair(tn);
8316: }
8317: bucket = create_pbucket();
8318: stat = nd_sp_f4(m,0,l,bucket);
8319: if ( !stat ) {
8320: for ( t = l; NEXT(t); t = NEXT(t) );
8321: NEXT(t) = d; d = l;
8322: d = nd_reconstruct(0,d);
8323: continue;
8324: }
8325: if ( bucket->m < 0 ) continue;
8326: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8327: if ( !col ) {
8328: for ( t = l; NEXT(t); t = NEXT(t) );
8329: NEXT(t) = d; d = l;
8330: d = nd_reconstruct(0,d);
8331: continue;
8332: }
1.12 noro 8333: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 8334: if ( DP_Print )
1.6 noro 8335: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 8336: sugar,eg_f4.exectime);
1.1 noro 8337: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
8338: if ( checkonly && nflist ) return 0;
8339: /* adding new bases */
8340: if ( nflist ) nd_last_nonzero = f4red;
8341: for ( r = nflist; r; r = NEXT(r) ) {
8342: nf = (NDV)BDY(r);
1.38 noro 8343: if ( nd_f4_td ) SG(nf) = nd_tdeg(nf);
1.1 noro 8344: ndv_removecont(m,nf);
8345: if ( !m && nd_nalg ) {
8346: ND nf1;
8347:
8348: nf1 = ndvtond(m,nf);
8349: nd_monic(0,&nf1);
8350: nd_removecont(m,nf1);
8351: nf = ndtondv(m,nf1);
8352: }
1.24 noro 8353: nh = ndv_newps(m,nf,0);
1.1 noro 8354: d = update_pairs(d,g,nh,0);
8355: g = update_base(g,nh);
8356: }
8357: if ( DP_Print ) {
8358: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
8359: }
8360: if ( nd_gentrace ) {
8361: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
8362: NEXTNODE(tn0,tn);
1.6 noro 8363: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 8364: node = mknode(2,i1,i2); MKLIST(l0,node);
8365: BDY(tn) = l0;
8366: }
8367: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 8368: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 8369: MKNODE(node,l1,nzlist); nzlist = node;
8370: }
8371: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
8372: f4red++;
8373: if ( nd_f4red && f4red > nd_f4red ) break;
8374: if ( nd_rank0 && !nflist ) break;
8375: }
8376: if ( nd_gentrace ) {
8377: MKLIST(l0,reverse_node(nzlist));
8378: MKNODE(nd_alltracelist,l0,0);
8379: }
8380: #if 0
8381: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8382: #endif
1.12 noro 8383: if ( DP_Print ) {
8384: fprintf(asir_out,"number of red=%d,",Nf4_red);
8385: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
8386: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
1.41 noro 8387: fprintf(asir_out,"number of removed pairs=%d\n,",NcriB+NcriMF+Ncri2);
1.12 noro 8388: }
1.1 noro 8389: conv_ilist(nd_demand,0,g,indp);
8390: return g;
8391: }
8392:
8393: NODE nd_f4_trace(int m,int **indp)
8394: {
8395: int i,nh,stat,index;
8396: NODE r,g;
8397: ND_pairs d,l,l0,t;
8398: ND spol,red;
8399: NDV nf,redv,nfqv,nfv;
8400: NM s0,s;
8401: NODE rp0,srp0,nflist;
8402: int nsp,nred,col,rank,len,k,j,a;
8403: UINT c;
8404: UINT **spmat;
8405: UINT *s0vect,*svect,*p,*v;
8406: int *colstat;
8407: IndArray *imat;
8408: int *rhead;
8409: int spcol,sprow;
8410: int sugar;
8411: PGeoBucket bucket;
8412: struct oEGT eg0,eg1,eg_f4;
8413:
8414: g = 0; d = 0;
8415: for ( i = 0; i < nd_psn; i++ ) {
8416: d = update_pairs(d,g,i,0);
8417: g = update_base(g,i);
8418: }
8419: while ( d ) {
8420: get_eg(&eg0);
8421: l = nd_minsugarp(d,&d);
8422: sugar = SG(l);
8423: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
8424: bucket = create_pbucket();
8425: stat = nd_sp_f4(m,0,l,bucket);
8426: if ( !stat ) {
8427: for ( t = l; NEXT(t); t = NEXT(t) );
8428: NEXT(t) = d; d = l;
8429: d = nd_reconstruct(1,d);
8430: continue;
8431: }
8432: if ( bucket->m < 0 ) continue;
8433: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
8434: if ( !col ) {
8435: for ( t = l; NEXT(t); t = NEXT(t) );
8436: NEXT(t) = d; d = l;
8437: d = nd_reconstruct(1,d);
8438: continue;
8439: }
8440: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
8441: if ( DP_Print )
1.3 noro 8442: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 8443: sugar,eg_f4.exectime);
1.1 noro 8444: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
8445: if ( !l0 ) continue;
8446: l = l0;
8447:
8448: /* over Q */
8449: bucket = create_pbucket();
8450: stat = nd_sp_f4(0,1,l,bucket);
8451: if ( !stat ) {
8452: for ( t = l; NEXT(t); t = NEXT(t) );
8453: NEXT(t) = d; d = l;
8454: d = nd_reconstruct(1,d);
8455: continue;
8456: }
8457: if ( bucket->m < 0 ) continue;
8458: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
8459: if ( !col ) {
8460: for ( t = l; NEXT(t); t = NEXT(t) );
8461: NEXT(t) = d; d = l;
8462: d = nd_reconstruct(1,d);
8463: continue;
8464: }
8465: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
8466: /* adding new bases */
8467: for ( r = nflist; r; r = NEXT(r) ) {
8468: nfqv = (NDV)BDY(r);
8469: ndv_removecont(0,nfqv);
1.6 noro 8470: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 8471: if ( nd_nalg ) {
8472: ND nf1;
8473:
8474: nf1 = ndvtond(m,nfqv);
8475: nd_monic(0,&nf1);
8476: nd_removecont(0,nf1);
8477: nfqv = ndtondv(0,nf1); nd_free(nf1);
8478: }
8479: nfv = ndv_dup(0,nfqv);
8480: ndv_mod(m,nfv);
8481: ndv_removecont(m,nfv);
1.24 noro 8482: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 8483: d = update_pairs(d,g,nh,0);
8484: g = update_base(g,nh);
8485: }
8486: }
8487: #if 0
8488: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
8489: #endif
8490: conv_ilist(nd_demand,1,g,indp);
8491: return g;
8492: }
8493:
8494: int rref(matrix mat,int *sugar)
8495: {
8496: int row,col,i,j,k,l,s,wcol,wj;
8497: unsigned long bj;
8498: unsigned long **a;
8499: unsigned long *ai,*ak,*as,*t;
8500: int *pivot;
8501:
8502: row = mat->row;
8503: col = mat->col;
8504: a = mat->a;
8505: wcol = (col+BLEN-1)/BLEN;
8506: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
8507: i = 0;
8508: for ( j = 0; j < col; j++ ) {
8509: wj = j/BLEN; bj = 1L<<(j%BLEN);
8510: for ( k = i; k < row; k++ )
8511: if ( a[k][wj] & bj ) break;
8512: if ( k == row ) continue;
8513: pivot[i] = j;
8514: if ( k != i ) {
8515: t = a[i]; a[i] = a[k]; a[k] = t;
8516: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
8517: }
8518: ai = a[i];
8519: for ( k = i+1; k < row; k++ ) {
8520: ak = a[k];
8521: if ( ak[wj] & bj ) {
8522: for ( l = wj; l < wcol; l++ )
8523: ak[l] ^= ai[l];
8524: sugar[k] = MAX(sugar[k],sugar[i]);
8525: }
8526: }
8527: i++;
8528: }
8529: for ( k = i-1; k >= 0; k-- ) {
8530: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
8531: ak = a[k];
8532: for ( s = 0; s < k; s++ ) {
8533: as = a[s];
8534: if ( as[wj] & bj ) {
8535: for ( l = wj; l < wcol; l++ )
8536: as[l] ^= ak[l];
8537: sugar[s] = MAX(sugar[s],sugar[k]);
8538: }
8539: }
8540: }
8541: return i;
8542: }
8543:
8544: void print_matrix(matrix mat)
8545: {
8546: int row,col,i,j;
8547: unsigned long *ai;
8548:
8549: row = mat->row;
8550: col = mat->col;
8551: printf("%d x %d\n",row,col);
8552: for ( i = 0; i < row; i++ ) {
8553: ai = mat->a[i];
8554: for ( j = 0; j < col; j++ ) {
8555: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
8556: else putchar('0');
8557: }
8558: putchar('\n');
8559: }
8560: }
8561:
8562: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
8563:
8564: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
8565: {
8566: int row,col,wcol,wj,i,j;
8567: unsigned long bj;
8568: unsigned long *ai;
8569: unsigned long **a;
8570: int len;
8571: int *pos;
8572:
8573: row = mat->row;
8574: col = mat->col;
8575: wcol = (col+BLEN-1)/BLEN;
8576: pos = (int *)MALLOC(wcol*sizeof(int));
8577: bzero(pos,wcol*sizeof(int));
8578: for ( i = j = 0; i < wcol; i++ )
8579: if ( v[i] ) pos[j++] = i;;
8580: len = j;
8581: wj = rhead/BLEN;
8582: bj = 1L<<rhead%BLEN;
8583: a = mat->a;
8584: for ( i = 0; i < row; i++ ) {
8585: ai = a[i];
8586: if ( ai[wj]&bj ) {
8587: for ( j = 0; j < len; j++ )
8588: ai[pos[j]] ^= v[pos[j]];
8589: sugar[i] = MAX(sugar[i],rsugar);
8590: }
8591: }
8592: }
8593:
8594: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8595: {
8596: int nsp,nred,i,i0,k,rank,row;
8597: NODE r0,rp;
8598: ND_pairs sp;
8599: ND spol;
8600: NM_ind_pair rt;
8601: int *s0hash;
8602: UINT *s;
8603: int *pivot,*sugar,*head;
8604: matrix mat;
8605: NM m;
8606: NODE r;
8607: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
8608: int rhead,rsugar,size;
8609: unsigned long *v;
8610:
8611: get_eg(&eg0);
8612: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8613: nred = length(rp0);
8614: mat = alloc_matrix(nsp,col);
8615: s0hash = (int *)MALLOC(col*sizeof(int));
8616: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
8617: s0hash[i] = ndl_hash_value(s);
8618:
8619: sugar = (int *)MALLOC(nsp*sizeof(int));
8620: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
8621: nd_sp(2,0,sp,&spol);
8622: if ( spol ) {
8623: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
8624: sugar[i] = SG(spol);
8625: i++;
8626: }
8627: }
8628: mat->row = i;
8629: if ( DP_Print ) {
8630: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
8631: }
8632: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
8633: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
8634: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
8635: rt = (NM_ind_pair)BDY(rp);
8636: bzero(v,size);
8637: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
8638: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
8639: red_by_vect_2(mat,sugar,v,rhead,rsugar);
8640: }
8641:
8642: get_eg(&eg1);
8643: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
8644: rank = rref(mat,sugar);
8645:
8646: for ( i = 0, r0 = 0; i < rank; i++ ) {
8647: NEXTNODE(r0,r);
8648: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
8649: SG((NDV)BDY(r)) = sugar[i];
8650: }
8651: if ( r0 ) NEXT(r) = 0;
8652: get_eg(&eg2);
8653: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
8654: if ( DP_Print ) {
8655: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 8656: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 8657: fflush(asir_out);
8658: }
8659: return r0;
8660: }
8661:
8662:
8663: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8664: {
8665: IndArray *imat;
1.11 noro 8666: int nsp,nred,i,start;
1.1 noro 8667: int *rhead;
8668: NODE r0,rp;
8669: ND_pairs sp;
8670: NM_ind_pair *rvect;
8671: UINT *s;
8672: int *s0hash;
1.11 noro 8673: struct oEGT eg0,eg1,eg_conv;
1.1 noro 8674:
8675: if ( m == 2 && nd_rref2 )
8676: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
8677:
8678: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8679: nred = length(rp0);
8680: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
8681: rhead = (int *)MALLOC(col*sizeof(int));
8682: for ( i = 0; i < col; i++ ) rhead[i] = 0;
8683:
8684: /* construction of index arrays */
1.11 noro 8685: get_eg(&eg0);
1.1 noro 8686: if ( DP_Print ) {
1.11 noro 8687: fprintf(asir_out,"%dx%d,",nsp+nred,col);
8688: fflush(asir_out);
1.1 noro 8689: }
8690: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 8691: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 8692: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 8693: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 8694: rhead[imat[i]->head] = 1;
1.11 noro 8695: start = imat[i]->head;
8696: }
1.12 noro 8697: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 8698: if ( DP_Print ) {
8699: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
8700: fflush(asir_out);
1.1 noro 8701: }
8702: if ( m > 0 )
1.7 noro 8703: #if SIZEOF_LONG==8
1.1 noro 8704: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8705: #else
8706: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8707: #endif
8708: else if ( m == -1 )
8709: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8710: else if ( m == -2 )
8711: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8712: else
8713: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8714: return r0;
8715: }
8716:
8717: /* for Fp, 2<=p<2^16 */
8718:
8719: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8720: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8721: {
8722: int spcol,sprow,a;
8723: int i,j,k,l,rank;
8724: NODE r0,r;
8725: ND_pairs sp;
8726: ND spol;
8727: UINT **spmat;
8728: UINT *svect,*v;
8729: int *colstat;
8730: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8731: int maxrs;
8732: int *spsugar;
8733: ND_pairs *spactive;
8734:
8735: spcol = col-nred;
8736: get_eg(&eg0);
8737: /* elimination (1st step) */
8738: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8739: svect = (UINT *)MALLOC(col*sizeof(UINT));
8740: spsugar = (int *)MALLOC(nsp*sizeof(int));
8741: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8742: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8743: nd_sp(m,0,sp,&spol);
8744: if ( !spol ) continue;
8745: nd_to_vect(m,s0vect,col,spol,svect);
8746: if ( m == -1 )
8747: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8748: else
1.40 noro 8749: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,0);
1.1 noro 8750: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8751: if ( i < col ) {
8752: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8753: for ( j = k = 0; j < col; j++ )
8754: if ( !rhead[j] ) v[k++] = svect[j];
8755: spsugar[sprow] = MAX(maxrs,SG(spol));
8756: if ( nz )
8757: spactive[sprow] = sp;
8758: sprow++;
8759: }
8760: nd_free(spol);
8761: }
8762: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8763: if ( DP_Print ) {
1.5 noro 8764: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8765: fflush(asir_out);
8766: }
8767: /* free index arrays */
8768: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8769:
8770: /* elimination (2nd step) */
8771: colstat = (int *)MALLOC(spcol*sizeof(int));
8772: if ( m == -1 )
8773: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8774: else
8775: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
8776: r0 = 0;
8777: for ( i = 0; i < rank; i++ ) {
8778: NEXTNODE(r0,r); BDY(r) =
8779: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8780: SG((NDV)BDY(r)) = spsugar[i];
8781: GCFREE(spmat[i]);
8782: }
8783: if ( r0 ) NEXT(r) = 0;
8784:
8785: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8786: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8787: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8788: if ( DP_Print ) {
1.5 noro 8789: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8790: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8791: nsp,nred,sprow,spcol,rank);
1.5 noro 8792: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8793: }
8794: if ( nz ) {
8795: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8796: if ( rank > 0 ) {
8797: NEXT(spactive[rank-1]) = 0;
8798: *nz = spactive[0];
8799: } else
8800: *nz = 0;
8801: }
8802: return r0;
8803: }
8804:
1.40 noro 8805: NODE nd_f4_red_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8806: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
8807: {
8808: int spcol,sprow,a;
8809: int i,j,k,l,rank;
8810: NODE r0,r;
8811: ND_pairs sp;
8812: ND spol;
8813: UINT **spmat;
8814: UINT *svect,*cvect;
8815: UINT *v;
8816: int *colstat;
8817: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8818: int maxrs;
8819: int *spsugar;
8820: ND_pairs *spactive;
8821: SIG *spsig;
8822:
8823: get_eg(&eg0);
8824: /* elimination (1st step) */
8825: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8826: spsugar = (int *)MALLOC(nsp*sizeof(int));
8827: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
8828: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8829: nd_sp(m,0,sp,&spol);
8830: if ( !spol ) {
8831: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
8832: continue;
8833: }
8834: svect = (UINT *)MALLOC(col*sizeof(UINT));
8835: nd_to_vect(m,s0vect,col,spol,svect);
8836: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred,spol->sig);
8837: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8838: if ( i < col ) {
8839: spmat[sprow] = svect;
8840: spsugar[sprow] = MAX(maxrs,SG(spol));
8841: spsig[sprow] = sp->sig;
8842: sprow++;
8843: } else {
8844: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
8845: }
8846: nd_free(spol);
8847: }
8848: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
8849: if ( DP_Print ) {
8850: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
8851: fflush(asir_out);
8852: }
8853: /* free index arrays */
8854: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8855:
8856: /* elimination (2nd step) */
8857: colstat = (int *)MALLOC(col*sizeof(int));
8858: rank = nd_gauss_elim_mod_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
8859: r0 = 0;
8860: for ( i = 0; i < sprow; i++ ) {
8861: if ( spsugar[i] >= 0 ) {
8862: NEXTNODE(r0,r);
8863: BDY(r) = vect_to_ndv_s(spmat[i],col,s0vect);
8864: SG((NDV)BDY(r)) = spsugar[i];
8865: ((NDV)BDY(r))->sig = spsig[i];
8866: } else
8867: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
8868: GCFREE(spmat[i]);
8869: }
8870: if ( r0 ) NEXT(r) = 0;
8871: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
8872: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8873: if ( DP_Print ) {
8874: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
8875: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8876: nsp,nred,sprow,col,rank);
8877: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
8878: }
8879: return r0;
8880: }
8881:
1.1 noro 8882:
8883: /* for small finite fields */
8884:
8885: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8886: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8887: {
8888: int spcol,sprow,a;
8889: int i,j,k,l,rank;
8890: NODE r0,r;
8891: ND_pairs sp;
8892: ND spol;
8893: UINT **spmat;
8894: UINT *svect,*v;
8895: int *colstat;
8896: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8897: int maxrs;
8898: int *spsugar;
8899: ND_pairs *spactive;
8900:
8901: spcol = col-nred;
8902: get_eg(&eg0);
8903: /* elimination (1st step) */
8904: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8905: svect = (UINT *)MALLOC(col*sizeof(UINT));
8906: spsugar = (int *)MALLOC(nsp*sizeof(int));
8907: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8908: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8909: nd_sp(m,0,sp,&spol);
8910: if ( !spol ) continue;
8911: nd_to_vect(m,s0vect,col,spol,svect);
8912: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8913: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8914: if ( i < col ) {
8915: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8916: for ( j = k = 0; j < col; j++ )
8917: if ( !rhead[j] ) v[k++] = svect[j];
8918: spsugar[sprow] = MAX(maxrs,SG(spol));
8919: if ( nz )
8920: spactive[sprow] = sp;
8921: sprow++;
8922: }
8923: nd_free(spol);
8924: }
8925: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8926: if ( DP_Print ) {
1.5 noro 8927: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8928: fflush(asir_out);
8929: }
8930: /* free index arrays */
8931: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8932:
8933: /* elimination (2nd step) */
8934: colstat = (int *)MALLOC(spcol*sizeof(int));
8935: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8936: r0 = 0;
8937: for ( i = 0; i < rank; i++ ) {
8938: NEXTNODE(r0,r); BDY(r) =
8939: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8940: SG((NDV)BDY(r)) = spsugar[i];
8941: GCFREE(spmat[i]);
8942: }
8943: if ( r0 ) NEXT(r) = 0;
8944:
8945: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8946: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8947: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8948: if ( DP_Print ) {
1.5 noro 8949: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8950: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8951: nsp,nred,sprow,spcol,rank);
1.5 noro 8952: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8953: }
8954: if ( nz ) {
8955: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8956: if ( rank > 0 ) {
8957: NEXT(spactive[rank-1]) = 0;
8958: *nz = spactive[0];
8959: } else
8960: *nz = 0;
8961: }
8962: return r0;
8963: }
8964:
8965: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
8966: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
8967: {
8968: int spcol,sprow,a;
8969: int i,j,k,l,rank;
8970: NODE r0,r;
8971: ND_pairs sp;
8972: ND spol;
8973: mpz_t **spmat;
8974: mpz_t *svect,*v;
8975: int *colstat;
8976: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8977: int maxrs;
8978: int *spsugar;
8979: pointer *w;
8980:
8981: spcol = col-nred;
8982: get_eg(&eg0);
8983: /* elimination (1st step) */
8984: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
8985: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
8986: spsugar = (int *)MALLOC(nsp*sizeof(int));
8987: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8988: nd_sp(m,trace,sp,&spol);
8989: if ( !spol ) continue;
8990: nd_to_vect_lf(s0vect,col,spol,svect);
8991: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
8992: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
8993: if ( i < col ) {
8994: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
8995: for ( j = k = 0; j < col; j++ )
8996: if ( !rhead[j] ) v[k++][0] = svect[j][0];
8997: spsugar[sprow] = MAX(maxrs,SG(spol));
8998: sprow++;
8999: }
9000: /* nd_free(spol); */
9001: }
9002: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9003: if ( DP_Print ) {
1.5 noro 9004: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9005: fflush(asir_out);
9006: }
9007: /* free index arrays */
9008: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9009:
9010: /* elimination (2nd step) */
9011: colstat = (int *)MALLOC(spcol*sizeof(int));
9012: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
9013: w = (pointer *)MALLOC(rank*sizeof(pointer));
9014: for ( i = 0; i < rank; i++ ) {
9015: #if 0
9016: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9017: SG((NDV)w[rank-i-1]) = spsugar[i];
9018: #else
9019: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
9020: SG((NDV)w[i]) = spsugar[i];
9021: #endif
9022: /* GCFREE(spmat[i]); */
9023:
9024: }
9025: #if 0
9026: qsort(w,rank,sizeof(NDV),
9027: (int (*)(const void *,const void *))ndv_compare);
9028: #endif
9029: r0 = 0;
9030: for ( i = 0; i < rank; i++ ) {
9031: NEXTNODE(r0,r); BDY(r) = w[i];
9032: }
9033: if ( r0 ) NEXT(r) = 0;
9034:
9035: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9036: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9037: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9038: if ( DP_Print ) {
1.5 noro 9039: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9040: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9041: nsp,nred,sprow,spcol,rank);
1.5 noro 9042: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9043: }
9044: return r0;
9045: }
9046:
9047: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
9048: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
9049: {
9050: int spcol,sprow,a;
9051: int i,j,k,l,rank;
9052: NODE r0,r;
9053: ND_pairs sp;
9054: ND spol;
9055: Z **spmat;
9056: Z *svect,*v;
9057: int *colstat;
9058: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
9059: int maxrs;
9060: int *spsugar;
9061: pointer *w;
9062:
9063: spcol = col-nred;
9064: get_eg(&eg0);
9065: /* elimination (1st step) */
9066: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
9067: svect = (Z *)MALLOC(col*sizeof(Q));
9068: spsugar = (int *)MALLOC(nsp*sizeof(int));
9069: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
9070: nd_sp(0,trace,sp,&spol);
9071: if ( !spol ) continue;
9072: nd_to_vect_q(s0vect,col,spol,svect);
9073: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
9074: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
9075: if ( i < col ) {
9076: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
9077: for ( j = k = 0; j < col; j++ )
9078: if ( !rhead[j] ) v[k++] = svect[j];
9079: spsugar[sprow] = MAX(maxrs,SG(spol));
9080: sprow++;
9081: }
9082: /* nd_free(spol); */
9083: }
9084: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
9085: if ( DP_Print ) {
1.5 noro 9086: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 9087: fflush(asir_out);
9088: }
9089: /* free index arrays */
9090: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
9091:
9092: /* elimination (2nd step) */
9093: colstat = (int *)MALLOC(spcol*sizeof(int));
9094: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
9095: w = (pointer *)MALLOC(rank*sizeof(pointer));
9096: for ( i = 0; i < rank; i++ ) {
9097: #if 0
9098: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9099: SG((NDV)w[rank-i-1]) = spsugar[i];
9100: #else
9101: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
9102: SG((NDV)w[i]) = spsugar[i];
9103: #endif
9104: /* GCFREE(spmat[i]); */
9105: }
9106: #if 0
9107: qsort(w,rank,sizeof(NDV),
9108: (int (*)(const void *,const void *))ndv_compare);
9109: #endif
9110: r0 = 0;
9111: for ( i = 0; i < rank; i++ ) {
9112: NEXTNODE(r0,r); BDY(r) = w[i];
9113: }
9114: if ( r0 ) NEXT(r) = 0;
9115:
9116: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
9117: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
9118: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
9119: if ( DP_Print ) {
1.5 noro 9120: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 9121: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
9122: nsp,nred,sprow,spcol,rank);
1.5 noro 9123: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 9124: }
9125: return r0;
9126: }
9127:
9128: FILE *nd_write,*nd_read;
9129:
9130: void nd_send_int(int a) {
9131: write_int(nd_write,(unsigned int *)&a);
9132: }
9133:
9134: void nd_send_intarray(int *p,int len) {
9135: write_intarray(nd_write,(unsigned int *)p,len);
9136: }
9137:
9138: int nd_recv_int() {
9139: int a;
9140:
9141: read_int(nd_read,(unsigned int *)&a);
9142: return a;
9143: }
9144:
9145: void nd_recv_intarray(int *p,int len) {
9146: read_intarray(nd_read,(unsigned int *)p,len);
9147: }
9148:
9149: void nd_send_ndv(NDV p) {
9150: int len,i;
9151: NMV m;
9152:
9153: if ( !p ) nd_send_int(0);
9154: else {
9155: len = LEN(p);
9156: nd_send_int(len);
9157: m = BDY(p);
9158: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9159: nd_send_int(CM(m));
9160: nd_send_intarray((int *)DL(m),nd_wpd);
9161: }
9162: }
9163: }
9164:
9165: void nd_send_nd(ND p) {
9166: int len,i;
9167: NM m;
9168:
9169: if ( !p ) nd_send_int(0);
9170: else {
9171: len = LEN(p);
9172: nd_send_int(len);
9173: m = BDY(p);
9174: for ( i = 0; i < len; i++, m = NEXT(m) ) {
9175: nd_send_int(CM(m));
9176: nd_send_intarray((int *)DL(m),nd_wpd);
9177: }
9178: }
9179: }
9180:
9181: NDV nd_recv_ndv()
9182: {
9183: int len,i;
9184: NMV m,m0;
9185: NDV r;
9186:
9187: len = nd_recv_int();
9188: if ( !len ) return 0;
9189: else {
9190: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
9191: #if 0
9192: ndv_alloc += len*nmv_adv;
9193: #endif
9194: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9195: CM(m) = nd_recv_int();
9196: nd_recv_intarray((int *)DL(m),nd_wpd);
9197: }
9198: MKNDV(nd_nvar,m0,len,r);
9199: return r;
9200: }
9201: }
9202:
9203: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
9204: {
9205: int i,j,t,c,rank,inv;
9206: int *ci,*ri;
9207: Z dn;
9208: MAT m,nm;
9209:
9210: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
9211: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
9212: for ( i = 0; i < row; i++ )
9213: for ( j = 0; j < col; j++ )
9214: mat0[i][j] = 0;
9215: c = col-rank;
9216: for ( i = 0; i < rank; i++ ) {
9217: mat0[i][ri[i]] = dn;
9218: for ( j = 0; j < c; j++ )
9219: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
9220: }
9221: return rank;
9222: }
9223:
9224: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
9225: {
9226: int i,j,k,l,inv,a,rank,s;
9227: unsigned int *t,*pivot,*pk;
9228: unsigned int **mat;
9229: ND_pairs pair;
9230:
9231: mat = (unsigned int **)mat0;
9232: for ( rank = 0, j = 0; j < col; j++ ) {
9233: for ( i = rank; i < row; i++ )
9234: mat[i][j] %= md;
9235: for ( i = rank; i < row; i++ )
9236: if ( mat[i][j] )
9237: break;
9238: if ( i == row ) {
9239: colstat[j] = 0;
9240: continue;
9241: } else
9242: colstat[j] = 1;
9243: if ( i != rank ) {
9244: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9245: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9246: if ( spactive ) {
9247: pair = spactive[i]; spactive[i] = spactive[rank];
9248: spactive[rank] = pair;
9249: }
9250: }
9251: pivot = mat[rank];
9252: s = sugar[rank];
9253: inv = invm(pivot[j],md);
9254: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9255: if ( *pk ) {
9256: if ( *pk >= (unsigned int)md )
9257: *pk %= md;
9258: DMAR(*pk,inv,0,md,*pk)
9259: }
9260: for ( i = rank+1; i < row; i++ ) {
9261: t = mat[i];
9262: if ( (a = t[j]) != 0 ) {
9263: sugar[i] = MAX(sugar[i],s);
9264: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9265: }
9266: }
9267: rank++;
9268: }
9269: for ( j = col-1, l = rank-1; j >= 0; j-- )
9270: if ( colstat[j] ) {
9271: pivot = mat[l];
9272: s = sugar[l];
9273: for ( i = 0; i < l; i++ ) {
9274: t = mat[i];
9275: t[j] %= md;
9276: if ( (a = t[j]) != 0 ) {
9277: sugar[i] = MAX(sugar[i],s);
9278: red_by_vect(md,t+j,pivot+j,md-a,col-j);
9279: }
9280: }
9281: l--;
9282: }
9283: for ( j = 0, l = 0; l < rank; j++ )
9284: if ( colstat[j] ) {
9285: t = mat[l];
9286: for ( k = j; k < col; k++ )
9287: if ( t[k] >= (unsigned int)md )
9288: t[k] %= md;
9289: l++;
9290: }
9291: return rank;
9292: }
9293:
1.40 noro 9294: int nd_gauss_elim_mod_s(UINT **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat,SIG *sig)
9295: {
9296: int i,j,k,l,rank,s,imin;
9297: UINT inv;
9298: UINT a;
9299: UINT *t,*pivot,*pk;
9300: UINT *ck;
9301: UINT *ct;
9302: ND_pairs pair;
9303: SIG sg;
9304: int *used;
9305:
9306: used = (int *)MALLOC(row*sizeof(int));
9307: for ( j = 0; j < col; j++ ) {
9308: for ( i = 0; i < row; i++ )
9309: a = mat[i][j] %= md;
9310: for ( i = 0; i < row; i++ )
9311: if ( !used[i] && mat[i][j] ) break;
9312: if ( i == row ) {
9313: colstat[j] = 0;
9314: continue;
9315: } else {
9316: colstat[j] = 1;
9317: used[i] = 1;
9318: }
9319: /* column j is normalized */
9320: s = sugar[i];
9321: inv = invm(mat[i][j],md);
9322: /* normalize pivot row */
9323: for ( k = j, pk = mat[i]+j; k < col; k++, pk++, ck++ ) {
9324: DMAR(*pk,inv,0,md,*pk);
9325: }
9326: for ( k = i+1; k < row; k++ ) {
9327: if ( (a = mat[k][j]) != 0 ) {
9328: sugar[k] = MAX(sugar[k],s);
9329: red_by_vect(md,mat[k]+j,mat[i]+j,(int)(md-a),col-j);
9330: Nf4_red++;
9331: }
9332: }
9333: }
9334: rank = 0;
9335: for ( i = 0; i < row; i++ ) {
9336: for ( j = 0; j < col; j++ )
9337: if ( mat[i][j] ) break;
9338: if ( j == col ) sugar[i] = -1;
9339: else rank++;
9340: }
9341: return rank;
9342: }
9343:
1.1 noro 9344:
1.7 noro 9345: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 9346: {
1.7 noro 9347: int i,j,k,l,inv,a,rank,s;
9348: unsigned int *t,*pivot,*pk;
9349: unsigned int **mat;
9350:
9351: mat = (unsigned int **)mat0;
9352: for ( rank = 0, j = 0; j < col; j++ ) {
9353: for ( i = rank; i < row; i++ )
9354: if ( mat[i][j] )
9355: break;
9356: if ( i == row ) {
9357: colstat[j] = 0;
9358: continue;
9359: } else
9360: colstat[j] = 1;
9361: if ( i != rank ) {
9362: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
9363: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
9364: }
9365: pivot = mat[rank];
9366: s = sugar[rank];
9367: inv = _invsf(pivot[j]);
9368: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
9369: if ( *pk )
9370: *pk = _mulsf(*pk,inv);
9371: for ( i = rank+1; i < row; i++ ) {
9372: t = mat[i];
9373: if ( (a = t[j]) != 0 ) {
9374: sugar[i] = MAX(sugar[i],s);
9375: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9376: }
9377: }
9378: rank++;
9379: }
9380: for ( j = col-1, l = rank-1; j >= 0; j-- )
9381: if ( colstat[j] ) {
9382: pivot = mat[l];
9383: s = sugar[l];
9384: for ( i = 0; i < l; i++ ) {
9385: t = mat[i];
9386: if ( (a = t[j]) != 0 ) {
9387: sugar[i] = MAX(sugar[i],s);
9388: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
9389: }
9390: }
9391: l--;
9392: }
9393: return rank;
9394: }
1.1 noro 9395:
1.7 noro 9396: int ndv_ishomo(NDV p)
9397: {
9398: NMV m;
9399: int len,h;
1.1 noro 9400:
9401: if ( !p ) return 1;
9402: len = LEN(p);
9403: m = BDY(p);
9404: h = TD(DL(m));
9405: NMV_ADV(m);
9406: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 9407: if ( TD(DL(m)) != h ) {
9408: return 0;
9409: }
1.1 noro 9410: return 1;
9411: }
9412:
9413: void ndv_save(NDV p,int index)
9414: {
9415: FILE *s;
9416: char name[BUFSIZ];
9417: short id;
9418: int nv,sugar,len,n,i,td,e,j;
9419: NMV m;
9420: unsigned int *dl;
9421: int mpos;
9422:
9423: sprintf(name,"%s/%d",Demand,index);
9424: s = fopen(name,"w");
9425: savevl(s,0);
9426: if ( !p ) {
9427: saveobj(s,0);
9428: return;
9429: }
9430: id = O_DP;
9431: nv = NV(p);
9432: sugar = SG(p);
9433: len = LEN(p);
9434: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
9435: write_int(s,(unsigned int *)&len);
9436:
9437: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9438: saveobj(s,(Obj)CZ(m));
1.1 noro 9439: dl = DL(m);
9440: td = TD(dl);
9441: write_int(s,(unsigned int *)&td);
9442: for ( j = 0; j < nv; j++ ) {
9443: e = GET_EXP(dl,j);
9444: write_int(s,(unsigned int *)&e);
9445: }
9446: if ( nd_module ) {
9447: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
9448: }
9449: }
9450: fclose(s);
9451: }
9452:
9453: void nd_save_mod(ND p,int index)
9454: {
9455: FILE *s;
9456: char name[BUFSIZ];
9457: int nv,sugar,len,c;
9458: NM m;
9459:
9460: sprintf(name,"%s/%d",Demand,index);
9461: s = fopen(name,"w");
9462: if ( !p ) {
9463: len = 0;
9464: write_int(s,(unsigned int *)&len);
9465: fclose(s);
9466: return;
9467: }
9468: nv = NV(p);
9469: sugar = SG(p);
9470: len = LEN(p);
9471: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
9472: for ( m = BDY(p); m; m = NEXT(m) ) {
9473: c = CM(m); write_int(s,(unsigned int *)&c);
9474: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
9475: }
9476: fclose(s);
9477: }
9478:
9479: NDV ndv_load(int index)
9480: {
9481: FILE *s;
9482: char name[BUFSIZ];
9483: short id;
9484: int nv,sugar,len,n,i,td,e,j;
9485: NDV d;
9486: NMV m0,m;
9487: unsigned int *dl;
9488: Obj obj;
9489: int mpos;
9490:
9491: sprintf(name,"%s/%d",Demand,index);
9492: s = fopen(name,"r");
9493: if ( !s ) return 0;
9494:
9495: skipvl(s);
9496: read_short(s,(unsigned short *)&id);
9497: if ( !id ) return 0;
9498: read_int(s,(unsigned int *)&nv);
9499: read_int(s,(unsigned int *)&sugar);
9500: read_int(s,(unsigned int *)&len);
9501:
9502: m0 = m = MALLOC(len*nmv_adv);
9503: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 9504: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 9505: dl = DL(m);
9506: ndl_zero(dl);
9507: read_int(s,(unsigned int *)&td); TD(dl) = td;
9508: for ( j = 0; j < nv; j++ ) {
9509: read_int(s,(unsigned int *)&e);
9510: PUT_EXP(dl,j,e);
9511: }
9512: if ( nd_module ) {
9513: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
9514: }
9515: if ( nd_blockmask ) ndl_weight_mask(dl);
9516: }
9517: fclose(s);
9518: MKNDV(nv,m0,len,d);
9519: SG(d) = sugar;
9520: return d;
9521: }
9522:
9523: ND nd_load_mod(int index)
9524: {
9525: FILE *s;
9526: char name[BUFSIZ];
9527: int nv,sugar,len,i,c;
9528: ND d;
9529: NM m0,m;
9530:
9531: sprintf(name,"%s/%d",Demand,index);
9532: s = fopen(name,"r");
9533: /* if the file does not exist, it means p[index]=0 */
9534: if ( !s ) return 0;
9535:
9536: read_int(s,(unsigned int *)&nv);
9537: if ( !nv ) { fclose(s); return 0; }
9538:
9539: read_int(s,(unsigned int *)&sugar);
9540: read_int(s,(unsigned int *)&len);
9541: for ( m0 = 0, i = 0; i < len; i++ ) {
9542: NEXTNM(m0,m);
9543: read_int(s,(unsigned int *)&c); CM(m) = c;
9544: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
9545: }
9546: NEXT(m) = 0;
9547: MKND(nv,m0,len,d);
9548: SG(d) = sugar;
9549: fclose(s);
9550: return d;
9551: }
9552:
9553: void nd_det(int mod,MAT f,P *rp)
9554: {
9555: VL fv,tv;
9556: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
9557: pointer **m;
9558: P **w;
9559: P mp,r;
9560: NDV **dm;
9561: NDV *t,*mi,*mj;
9562: NDV d,s,mij,mjj;
9563: ND u;
9564: NMV nmv;
9565: UINT *bound;
9566: PGeoBucket bucket;
9567: struct order_spec *ord;
9568: Z dq,dt,ds;
9569: Z mone;
9570: Z gn,qn,dn0,nm,dn;
9571:
9572: create_order_spec(0,0,&ord);
9573: nd_init_ord(ord);
9574: get_vars((Obj)f,&fv);
9575: if ( f->row != f->col )
9576: error("nd_det : non-square matrix");
9577: n = f->row;
9578: m = f->body;
9579: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
9580:
9581: if ( !nvar ) {
9582: if ( !mod )
9583: detp(CO,(P **)m,n,rp);
9584: else {
9585: w = (P **)almat_pointer(n,n);
9586: for ( i = 0; i < n; i++ )
9587: for ( j = 0; j < n; j++ )
9588: ptomp(mod,(P)m[i][j],&w[i][j]);
9589: detmp(CO,mod,w,n,&mp);
9590: mptop(mp,rp);
9591: }
9592: return;
9593: }
9594:
9595: if ( !mod ) {
9596: w = (P **)almat_pointer(n,n);
9597: dq = ONE;
9598: for ( i = 0; i < n; i++ ) {
9599: dn0 = ONE;
9600: for ( j = 0; j < n; j++ ) {
9601: if ( !m[i][j] ) continue;
9602: lgp(m[i][j],&nm,&dn);
1.6 noro 9603: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 9604: }
9605: if ( !UNIZ(dn0) ) {
9606: ds = dn0;
9607: for ( j = 0; j < n; j++ )
9608: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
9609: mulz(dq,ds,&dt); dq = dt;
9610: } else
9611: for ( j = 0; j < n; j++ )
9612: w[i][j] = (P)m[i][j];
9613: }
9614: m = (pointer **)w;
9615: }
9616:
9617: for ( i = 0, max = 1; i < n; i++ )
9618: for ( j = 0; j < n; j++ )
9619: for ( tv = fv; tv; tv = NEXT(tv) ) {
9620: e = getdeg(tv->v,(P)m[i][j]);
9621: max = MAX(e,max);
9622: }
9623: nd_setup_parameters(nvar,max);
9624: dm = (NDV **)almat_pointer(n,n);
9625: for ( i = 0, max = 1; i < n; i++ )
9626: for ( j = 0; j < n; j++ ) {
9627: dm[i][j] = ptondv(CO,fv,m[i][j]);
9628: if ( mod ) ndv_mod(mod,dm[i][j]);
9629: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
9630: }
9631: d = ptondv(CO,fv,(P)ONE);
9632: if ( mod ) ndv_mod(mod,d);
9633: chsgnz(ONE,&mone);
9634: for ( j = 0, sgn = 1; j < n; j++ ) {
9635: if ( DP_Print ) {
9636: fprintf(asir_out,".");
9637: }
9638: for ( i = j; i < n && !dm[i][j]; i++ );
9639: if ( i == n ) {
9640: *rp = 0;
9641: return;
9642: }
9643: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
9644: for ( k = j; k < n; k++ )
9645: for ( l = j; l < n; l++ )
9646: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
9647: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
9648: }
9649: if ( k0 != j ) {
9650: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
9651: sgn = -sgn;
9652: }
9653: if ( l0 != j ) {
9654: for ( k = j; k < n; k++ ) {
9655: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
9656: }
9657: sgn = -sgn;
9658: }
9659: bound = nd_det_compute_bound(dm,n,j);
9660: for ( k = 0; k < nd_nvar; k++ )
9661: if ( bound[k]*2 > nd_mask0 ) break;
9662: if ( k < nd_nvar )
9663: nd_det_reconstruct(dm,n,j,d);
9664:
9665: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
9666: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
9667: mi = dm[i]; mij = mi[j];
9668: if ( mod )
9669: ndv_mul_c(mod,mij,mod-1);
9670: else
9671: ndv_mul_c_q(mij,mone);
9672: for ( k = j+1; k < n; k++ ) {
9673: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
9674: bucket = create_pbucket();
9675: if ( mi[k] ) {
9676: nmv = BDY(mjj); len = LEN(mjj);
9677: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9678: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
9679: add_pbucket(mod,bucket,u);
9680: }
9681: }
9682: if ( mj[k] && mij ) {
9683: nmv = BDY(mij); len = LEN(mij);
9684: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9685: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
9686: add_pbucket(mod,bucket,u);
9687: }
9688: }
9689: u = nd_quo(mod,bucket,d);
9690: mi[k] = ndtondv(mod,u);
9691: }
9692: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
9693: }
9694: d = mjj;
9695: }
9696: if ( DP_Print ) {
9697: fprintf(asir_out,"\n");
9698: }
9699: if ( sgn < 0 ) {
9700: if ( mod )
9701: ndv_mul_c(mod,d,mod-1);
9702: else
9703: ndv_mul_c_q(d,mone);
9704: }
9705: r = ndvtop(mod,CO,fv,d);
9706: if ( !mod && !UNIQ(dq) )
9707: divsp(CO,r,(P)dq,rp);
9708: else
9709: *rp = r;
9710: }
9711:
9712: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
9713: {
9714: NM mr,mr0;
9715: NM tnm;
9716: NMV m;
9717: UINT *d0,*dt,*dm;
9718: int c,n,td,i,c1,c2,len;
9719: Z q;
9720: ND r;
9721:
9722: if ( !p ) return 0;
9723: else {
9724: n = NV(p); m = BDY(p); len = LEN(p);
9725: d0 = DL(m0);
9726: td = TD(d);
9727: mr0 = 0;
9728: NEWNM(tnm);
9729: if ( mod ) {
9730: c = CM(m0);
9731: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9732: ndl_add(DL(m),d0,DL(tnm));
9733: if ( ndl_reducible(DL(tnm),d) ) {
9734: NEXTNM(mr0,mr);
9735: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
9736: ndl_copy(DL(tnm),DL(mr));
9737: }
9738: }
9739: } else {
1.6 noro 9740: q = CZ(m0);
1.1 noro 9741: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9742: ndl_add(DL(m),d0,DL(tnm));
9743: if ( ndl_reducible(DL(tnm),d) ) {
9744: NEXTNM(mr0,mr);
1.6 noro 9745: mulz(CZ(m),q,&CZ(mr));
1.1 noro 9746: ndl_copy(DL(tnm),DL(mr));
9747: }
9748: }
9749: }
9750: if ( !mr0 )
9751: return 0;
9752: else {
9753: NEXT(mr) = 0;
9754: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9755: MKND(NV(p),mr0,len,r);
9756: SG(r) = SG(p) + TD(d0);
9757: return r;
9758: }
9759: }
9760: }
9761:
9762: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
9763: {
9764: int i,obpe,oadv,h,k,l;
9765: static NM prev_nm_free_list;
9766: EPOS oepos;
9767:
9768: obpe = nd_bpe;
9769: oadv = nmv_adv;
9770: oepos = nd_epos;
9771: if ( obpe < 2 ) nd_bpe = 2;
9772: else if ( obpe < 3 ) nd_bpe = 3;
9773: else if ( obpe < 4 ) nd_bpe = 4;
9774: else if ( obpe < 5 ) nd_bpe = 5;
9775: else if ( obpe < 6 ) nd_bpe = 6;
9776: else if ( obpe < 8 ) nd_bpe = 8;
9777: else if ( obpe < 10 ) nd_bpe = 10;
9778: else if ( obpe < 16 ) nd_bpe = 16;
9779: else if ( obpe < 32 ) nd_bpe = 32;
9780: else error("nd_det_reconstruct : exponent too large");
9781:
9782: nd_setup_parameters(nd_nvar,0);
9783: prev_nm_free_list = _nm_free_list;
9784: _nm_free_list = 0;
9785: for ( k = j; k < n; k++ )
9786: for (l = j; l < n; l++ )
9787: ndv_realloc(dm[k][l],obpe,oadv,oepos);
9788: ndv_realloc(d,obpe,oadv,oepos);
9789: prev_nm_free_list = 0;
9790: #if 0
9791: GC_gcollect();
9792: #endif
9793: }
9794:
9795: /* returns a UINT array containing degree bounds */
9796:
9797: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
9798: {
9799: UINT *d0,*d1,*d,*t,*r;
9800: int k,l,i;
9801:
9802: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
9803: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
9804: for ( k = j; k < n; k++ )
9805: for ( l = j; l < n; l++ )
9806: if ( dm[k][l] ) {
9807: d = ndv_compute_bound(dm[k][l]);
9808: for ( i = 0; i < nd_nvar; i++ )
9809: d0[i] = MAX(d0[i],d[i]);
9810: }
9811: return d0;
9812: }
9813:
9814: DL nd_separate_d(UINT *d,UINT *trans)
9815: {
9816: int n,td,i,e,j;
9817: DL a;
9818:
9819: ndl_zero(trans);
9820: td = 0;
9821: for ( i = 0; i < nd_ntrans; i++ ) {
9822: e = GET_EXP(d,i);
9823: PUT_EXP(trans,i,e);
9824: td += MUL_WEIGHT(e,i);
9825: }
9826: if ( nd_ntrans+nd_nalg < nd_nvar ) {
9827: /* homogenized */
9828: i = nd_nvar-1;
9829: e = GET_EXP(d,i);
9830: PUT_EXP(trans,i,e);
9831: td += MUL_WEIGHT(e,i);
9832: }
9833: TD(trans) = td;
9834: if ( nd_blockmask) ndl_weight_mask(trans);
9835: NEWDL(a,nd_nalg);
9836: td = 0;
9837: for ( i = 0; i < nd_nalg; i++ ) {
9838: j = nd_ntrans+i;
9839: e = GET_EXP(d,j);
9840: a->d[i] = e;
9841: td += e;
9842: }
9843: a->td = td;
9844: return a;
9845: }
9846:
9847: int nd_monic(int mod,ND *p)
9848: {
9849: UINT *trans,*t;
9850: DL alg;
9851: MP mp0,mp;
9852: NM m,m0,m1,ma0,ma,mb,mr0,mr;
9853: ND r;
9854: DL dl;
9855: DP nm;
9856: NDV ndv;
9857: DAlg inv,cd;
9858: ND s,c;
9859: Z l,mul;
9860: Z ln;
9861: int n,ntrans,i,e,td,is_lc,len;
9862: NumberField nf;
9863: struct oEGT eg0,eg1;
9864:
9865: if ( !(nf = get_numberfield()) )
9866: error("nd_monic : current_numberfield is not set");
9867:
9868: /* Q coef -> DAlg coef */
9869: NEWNM(ma0); ma = ma0;
9870: m = BDY(*p);
9871: is_lc = 1;
9872: while ( 1 ) {
9873: NEWMP(mp0); mp = mp0;
1.6 noro 9874: mp->c = (Obj)CZ(m);
1.1 noro 9875: mp->dl = nd_separate_d(DL(m),DL(ma));
9876: NEWNM(mb);
9877: for ( m = NEXT(m); m; m = NEXT(m) ) {
9878: alg = nd_separate_d(DL(m),DL(mb));
9879: if ( !ndl_equal(DL(ma),DL(mb)) )
9880: break;
1.6 noro 9881: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 9882: }
9883: NEXT(mp) = 0;
9884: MKDP(nd_nalg,mp0,nm);
9885: MKDAlg(nm,ONE,cd);
9886: if ( is_lc == 1 ) {
9887: /* if the lc is a rational number, we have nothing to do */
9888: if ( !mp0->dl->td )
9889: return 1;
9890:
9891: get_eg(&eg0);
9892: invdalg(cd,&inv);
9893: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
9894: /* check the validity of inv */
9895: if ( mod && !remqi((Q)inv->dn,mod) )
9896: return 0;
9897: CA(ma) = nf->one;
9898: is_lc = 0;
9899: ln = ONE;
9900: } else {
9901: muldalg(cd,inv,&CA(ma));
9902: lcmz(ln,CA(ma)->dn,&ln);
9903: }
9904: if ( m ) {
9905: NEXT(ma) = mb; ma = mb;
9906: } else {
9907: NEXT(ma) = 0;
9908: break;
9909: }
9910: }
9911: /* l = lcm(denoms) */
9912: l = ln;
9913: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 9914: divsz(l,CA(m)->dn,&mul);
1.1 noro 9915: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
9916: NEXTNM(mr0,mr);
1.6 noro 9917: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 9918: dl = mp->dl;
9919: td = TD(DL(m));
9920: ndl_copy(DL(m),DL(mr));
9921: for ( i = 0; i < nd_nalg; i++ ) {
9922: e = dl->d[i];
9923: PUT_EXP(DL(mr),i+nd_ntrans,e);
9924: td += MUL_WEIGHT(e,i+nd_ntrans);
9925: }
9926: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
9927: TD(DL(mr)) = td;
9928: if ( nd_blockmask) ndl_weight_mask(DL(mr));
9929: }
9930: }
9931: NEXT(mr) = 0;
9932: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9933: MKND(NV(*p),mr0,len,r);
9934: /* XXX */
9935: SG(r) = SG(*p);
9936: nd_free(*p);
9937: *p = r;
9938: return 1;
9939: }
9940:
9941: NODE reverse_node(NODE n)
9942: {
9943: NODE t,t1;
9944:
9945: for ( t = 0; n; n = NEXT(n) ) {
9946: MKNODE(t1,BDY(n),t); t = t1;
9947: }
9948: return t;
9949: }
9950:
9951: P ndc_div(int mod,union oNDC a,union oNDC b)
9952: {
9953: union oNDC c;
9954: int inv,t;
9955:
9956: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 9957: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 9958: else if ( mod ) {
9959: inv = invm(b.m,mod);
9960: DMAR(a.m,inv,0,mod,t); c.m = t;
9961: } else if ( nd_vc )
9962: divsp(nd_vc,a.p,b.p,&c.p);
9963: else
9964: divsz(a.z,b.z,&c.z);
9965: return ndctop(mod,c);
9966: }
9967:
9968: P ndctop(int mod,union oNDC c)
9969: {
9970: Z q;
9971: int e;
9972: GFS gfs;
9973:
9974: if ( mod == -1 ) {
9975: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
9976: } else if ( mod == -2 ) {
1.10 noro 9977: q = c.z; return (P)q;
1.1 noro 9978: } else if ( mod > 0 ) {
1.6 noro 9979: STOZ(c.m,q); return (P)q;
1.1 noro 9980: } else
9981: return (P)c.p;
9982: }
9983:
9984: /* [0,0,0,cont] = p -> p/cont */
9985:
9986: void finalize_tracelist(int i,P cont)
9987: {
9988: LIST l;
9989: NODE node;
9990: Z iq;
9991:
9992: if ( !UNIQ(cont) ) {
9993: node = mknode(4,NULLP,NULLP,NULLP,cont);
9994: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
9995: nd_tracelist = node;
9996: }
1.6 noro 9997: STOZ(i,iq);
1.1 noro 9998: nd_tracelist = reverse_node(nd_tracelist);
9999: MKLIST(l,nd_tracelist);
10000: node = mknode(2,iq,l); MKLIST(l,node);
10001: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
10002: nd_alltracelist = node; nd_tracelist = 0;
10003: }
10004:
10005: void conv_ilist(int demand,int trace,NODE g,int **indp)
10006: {
10007: int n,i,j;
10008: int *ind;
10009: NODE t;
10010:
10011: n = length(g);
10012: ind = (int *)MALLOC(n*sizeof(int));
10013: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
10014: j = (long)BDY(t); ind[i] = j;
10015: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
10016: }
10017: if ( indp ) *indp = ind;
10018: }
10019:
1.30 noro 10020: NODE conv_ilist_s(int demand,int trace,int **indp)
10021: {
10022: int n,i,j;
10023: int *ind;
10024: NODE g0,g;
10025:
10026: n = nd_psn;
10027: ind = (int *)MALLOC(n*sizeof(int));
10028: g0 = 0;
10029: for ( i = 0; i < n; i++ ) {
10030: ind[i] = i;
10031: NEXTNODE(g0,g);
10032: BDY(g) = (pointer)(demand?ndv_load(i):(trace?nd_ps_trace[i]:nd_ps[i]));
10033: }
10034: if ( g0 ) NEXT(g) = 0;
10035: if ( indp ) *indp = ind;
10036: return g0;
10037: }
10038:
1.1 noro 10039: void parse_nd_option(NODE opt)
10040: {
1.38 noro 10041: NODE t,p,u;
1.1 noro 10042: int i,s,n;
1.38 noro 10043: char *key;
10044: Obj value;
1.1 noro 10045:
1.41 noro 10046: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_norb = 0; nd_gbblock = 0;
1.1 noro 10047: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
10048: nd_splist = 0; nd_check_splist = 0;
1.38 noro 10049: nd_sugarweight = 0; nd_f4red =0; nd_rank0 = 0;
10050: nd_f4_td = 0; nd_sba_f4step = 2; nd_sba_pot = 0; nd_sba_largelcm = 0;
1.41 noro 10051: nd_sba_dontsort = 0; nd_top = 0; nd_sba_redundant_check = 0;
1.44 ! noro 10052: nd_sba_syz = 0;
1.39 noro 10053:
1.38 noro 10054: for ( t = opt; t; t = NEXT(t) ) {
10055: p = BDY((LIST)BDY(t));
10056: key = BDY((STRING)BDY(p));
10057: value = (Obj)BDY(NEXT(p));
10058: if ( !strcmp(key,"gentrace") )
10059: nd_gentrace = value?1:0;
10060: else if ( !strcmp(key,"gensyz") )
10061: nd_gensyz = value?1:0;
10062: else if ( !strcmp(key,"nora") )
10063: nd_nora = value?1:0;
1.41 noro 10064: else if ( !strcmp(key,"norb") )
10065: nd_norb = value?1:0;
1.38 noro 10066: else if ( !strcmp(key,"gbblock") ) {
10067: if ( value && OID(value) == O_LIST ) {
1.1 noro 10068: u = BDY((LIST)value);
1.38 noro 10069: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
1.1 noro 10070: for ( i = 0; u; u = NEXT(u) ) {
10071: p = BDY((LIST)BDY(u));
1.6 noro 10072: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
10073: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 10074: }
10075: nd_gbblock[i] = -1;
1.38 noro 10076: } else
10077: nd_gbblock = 0;
1.1 noro 10078: } else if ( !strcmp(key,"newelim") )
10079: nd_newelim = value?1:0;
10080: else if ( !strcmp(key,"intersect") )
10081: nd_intersect = value?1:0;
1.17 noro 10082: else if ( !strcmp(key,"syzgen") )
10083: nd_intersect = ZTOS((Q)value);
1.1 noro 10084: else if ( !strcmp(key,"lf") )
10085: nd_lf = value?1:0;
10086: else if ( !strcmp(key,"trace") ) {
1.38 noro 10087: if ( value ) {
10088: u = BDY((LIST)value);
10089: nd_nzlist = BDY((LIST)ARG2(u));
10090: nd_bpe = ZTOS((Q)ARG3(u));
10091: }
1.1 noro 10092: } else if ( !strcmp(key,"f4red") ) {
1.38 noro 10093: nd_f4red = ZTOS((Q)value);
1.1 noro 10094: } else if ( !strcmp(key,"rank0") ) {
1.38 noro 10095: nd_rank0 = value?1:0;
1.1 noro 10096: } else if ( !strcmp(key,"splist") ) {
1.38 noro 10097: nd_splist = value?1:0;
1.1 noro 10098: } else if ( !strcmp(key,"check_splist") ) {
10099: nd_check_splist = BDY((LIST)value);
10100: } else if ( !strcmp(key,"sugarweight") ) {
10101: u = BDY((LIST)value);
1.38 noro 10102: n = length(u);
10103: nd_sugarweight = MALLOC(n*sizeof(int));
1.1 noro 10104: for ( i = 0; i < n; i++, u = NEXT(u) )
1.38 noro 10105: nd_sugarweight[i] = ZTOS((Q)BDY(u));
10106: } else if ( !strcmp(key,"f4_td") ) {
10107: nd_f4_td = value?1:0;
10108: } else if ( !strcmp(key,"sba_f4step") ) {
10109: nd_sba_f4step = value?ZTOS((Q)value):0;
10110: } else if ( !strcmp(key,"sba_pot") ) {
1.44 ! noro 10111: nd_sba_pot = ZTOS((Q)value);
1.38 noro 10112: } else if ( !strcmp(key,"sba_largelcm") ) {
10113: nd_sba_largelcm = value?1:0;
1.39 noro 10114: } else if ( !strcmp(key,"sba_dontsort") ) {
10115: nd_sba_dontsort = value?1:0;
1.44 ! noro 10116: } else if ( !strcmp(key,"sba_syz") ) {
! 10117: nd_sba_syz = value?1:0;
1.41 noro 10118: } else if ( !strcmp(key,"sba_redundant_check") ) {
10119: nd_sba_redundant_check = value?1:0;
1.39 noro 10120: } else if ( !strcmp(key,"top") ) {
10121: nd_top = value?1:0;
1.1 noro 10122: }
1.38 noro 10123: }
1.44 ! noro 10124: if ( nd_sba_syz ) nd_sba_dontsort = 1;
1.1 noro 10125: }
10126:
10127: ND mdptond(DP d);
10128: ND nd_mul_nm(int mod,NM m0,ND p);
10129: ND nd_mul_nm_lf(NM m0,ND p);
10130: ND *btog(NODE ti,ND **p,int nb,int mod);
10131: ND btog_one(NODE ti,ND *p,int nb,int mod);
10132: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
10133: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
10134:
10135: /* d:monomial */
10136: ND mdptond(DP d)
10137: {
10138: NM m;
10139: ND r;
10140:
10141: if ( OID(d) == 1 )
10142: r = ptond(CO,CO,(P)d);
10143: else {
10144: NEWNM(m);
10145: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 10146: CZ(m) = (Z)BDY(d)->c;
1.1 noro 10147: NEXT(m) = 0;
10148: MKND(NV(d),m,1,r);
10149: }
10150: return r;
10151: }
10152:
10153: ND nd_mul_nm(int mod,NM m0,ND p)
10154: {
10155: UINT *d0;
10156: int c0,c1,c;
10157: NM tm,mr,mr0;
10158: ND r;
10159:
10160: if ( !p ) return 0;
10161: d0 = DL(m0);
10162: c0 = CM(m0);
10163: mr0 = 0;
10164: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10165: NEXTNM(mr0,mr);
10166: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
10167: ndl_add(d0,DL(tm),DL(mr));
10168: }
10169: NEXT(mr) = 0;
10170: MKND(NV(p),mr0,LEN(p),r);
10171: return r;
10172: }
10173:
10174: ND nd_mul_nm_lf(NM m0,ND p)
10175: {
10176: UINT *d0;
10177: Z c0,c1,c;
10178: NM tm,mr,mr0;
10179: ND r;
10180:
10181: if ( !p ) return 0;
10182: d0 = DL(m0);
10183: c0 = CZ(m0);
10184: mr0 = 0;
10185: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
10186: NEXTNM(mr0,mr);
10187: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
10188: ndl_add(d0,DL(tm),DL(mr));
10189: }
10190: NEXT(mr) = 0;
10191: MKND(NV(p),mr0,LEN(p),r);
10192: return r;
10193: }
10194:
10195: ND *btog(NODE ti,ND **p,int nb,int mod)
10196: {
10197: PGeoBucket *r;
10198: int i,ci;
10199: NODE t,s;
10200: ND m,tp;
10201: ND *pi,*rd;
10202: P c;
10203:
10204: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10205: for ( i = 0; i < nb; i++ )
10206: r[i] = create_pbucket();
10207: for ( t = ti; t; t = NEXT(t) ) {
10208: s = BDY((LIST)BDY(t));
10209: if ( ARG0(s) ) {
10210: m = mdptond((DP)ARG2(s));
1.6 noro 10211: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10212: if ( (ci = ((MQ)c)->cont) != 0 ) {
10213: HCM(m) = ci;
1.6 noro 10214: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10215: for ( i = 0; i < nb; i++ ) {
10216: tp = nd_mul_nm(mod,BDY(m),pi[i]);
10217: add_pbucket(mod,r[i],tp);
10218: }
10219: }
10220: ci = 1;
10221: } else {
10222: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10223: ci = invm(ci,mod);
10224: }
10225: }
10226: rd = (ND *)MALLOC(nb*sizeof(ND));
10227: for ( i = 0; i < nb; i++ )
10228: rd[i] = normalize_pbucket(mod,r[i]);
10229: if ( ci != 1 )
10230: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
10231: return rd;
10232: }
10233:
10234: /* YYY */
10235: ND *btog_lf(NODE ti,ND **p,int nb)
10236: {
10237: PGeoBucket *r;
10238: int i;
10239: NODE t,s;
10240: ND m,tp;
10241: ND *pi,*rd;
10242: LM lm;
10243: Z lf,c;
10244:
10245: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
10246: for ( i = 0; i < nb; i++ )
10247: r[i] = create_pbucket();
10248: for ( t = ti; t; t = NEXT(t) ) {
10249: s = BDY((LIST)BDY(t));
10250: if ( ARG0(s) ) {
10251: m = mdptond((DP)ARG2(s));
1.6 noro 10252: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 10253: if ( lm ) {
10254: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 10255: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 10256: for ( i = 0; i < nb; i++ ) {
10257: tp = nd_mul_nm_lf(BDY(m),pi[i]);
10258: add_pbucket(-2,r[i],tp);
10259: }
10260: }
10261: c = ONE;
10262: } else {
10263: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
10264: }
10265: }
10266: rd = (ND *)MALLOC(nb*sizeof(ND));
10267: for ( i = 0; i < nb; i++ )
10268: rd[i] = normalize_pbucket(-2,r[i]);
10269: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
10270: return rd;
10271: }
10272:
10273: ND btog_one(NODE ti,ND *p,int nb,int mod)
10274: {
10275: PGeoBucket r;
10276: int i,ci,j;
10277: NODE t,s;
10278: ND m,tp;
10279: ND pi,rd;
10280: P c;
10281:
10282: r = create_pbucket();
10283: for ( t = ti; t; t = NEXT(t) ) {
10284: s = BDY((LIST)BDY(t));
10285: if ( ARG0(s) ) {
10286: m = mdptond((DP)ARG2(s));
1.6 noro 10287: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 10288: if ( (ci = ((MQ)c)->cont) != 0 ) {
10289: HCM(m) = ci;
1.6 noro 10290: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 10291: if ( !pi ) {
10292: pi = nd_load_mod(j);
10293: tp = nd_mul_nm(mod,BDY(m),pi);
10294: nd_free(pi);
10295: add_pbucket(mod,r,tp);
10296: } else {
10297: tp = nd_mul_nm(mod,BDY(m),pi);
10298: add_pbucket(mod,r,tp);
10299: }
10300: }
10301: ci = 1;
10302: } else {
10303: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
10304: ci = invm(ci,mod);
10305: }
10306: }
10307: rd = normalize_pbucket(mod,r);
10308: free_pbucket(r);
10309: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
10310: return rd;
10311: }
10312:
10313: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
10314:
10315: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
10316: {
10317: int i,j,n,m,nb,pi0,pi1,nvar;
10318: VL fv,tv,vv;
10319: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10320: ND **p;
10321: ND *c;
10322: ND u;
10323: P inv;
10324: MAT mat;
10325:
10326: if ( mod == -2 )
10327: return nd_btog_lf(f,v,ord,tlist,rp);
10328:
10329: parse_nd_option(current_option);
10330: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10331: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10332: switch ( ord->id ) {
10333: case 1:
10334: if ( ord->nv != nvar )
10335: error("nd_check : invalid order specification");
10336: break;
10337: default:
10338: break;
10339: }
10340: nd_init_ord(ord);
10341: #if 0
1.6 noro 10342: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10343: #else
10344: nd_bpe = 32;
10345: #endif
10346: nd_setup_parameters(nvar,0);
10347: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10348: intred = BDY((LIST)ARG3(BDY(tlist)));
10349: ind = BDY((LIST)ARG4(BDY(tlist)));
10350: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10351: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10352: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10353: if ( j > i ) i = j;
10354: }
10355: n = i+1;
10356: nb = length(BDY(f));
10357: p = (ND **)MALLOC(n*sizeof(ND *));
10358: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10359: pi = BDY((LIST)BDY(t));
1.6 noro 10360: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10361: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10362: ptomp(mod,(P)ARG2(pi),&inv);
10363: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10364: u = ptond(CO,vv,(P)ONE);
10365: HCM(u) = ((MQ)inv)->cont;
10366: c[pi1] = u;
10367: }
10368: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10369: printf("%d ",i); fflush(stdout);
10370: ti = BDY((LIST)BDY(t));
1.6 noro 10371: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10372: }
10373: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10374: printf("%d ",i); fflush(stdout);
10375: ti = BDY((LIST)BDY(t));
1.6 noro 10376: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10377: }
10378: m = length(ind);
10379: MKMAT(mat,nb,m);
10380: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10381: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10382: BDY(mat)[i][j] = ndtodp(mod,c[i]);
10383: return mat;
10384: }
10385:
10386: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
10387: {
10388: int i,j,n,m,nb,pi0,pi1,nvar;
10389: VL fv,tv,vv;
10390: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10391: ND **p;
10392: ND *c;
10393: ND u;
10394: MAT mat;
10395: LM lm;
10396: Z lf,inv;
10397:
10398: parse_nd_option(current_option);
10399: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10400: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10401: switch ( ord->id ) {
10402: case 1:
10403: if ( ord->nv != nvar )
10404: error("nd_check : invalid order specification");
10405: break;
10406: default:
10407: break;
10408: }
10409: nd_init_ord(ord);
10410: #if 0
1.6 noro 10411: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10412: #else
10413: nd_bpe = 32;
10414: #endif
10415: nd_setup_parameters(nvar,0);
10416: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10417: intred = BDY((LIST)ARG3(BDY(tlist)));
10418: ind = BDY((LIST)ARG4(BDY(tlist)));
10419: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10420: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10421: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10422: if ( j > i ) i = j;
10423: }
10424: n = i+1;
10425: nb = length(BDY(f));
10426: p = (ND **)MALLOC(n*sizeof(ND *));
10427: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10428: pi = BDY((LIST)BDY(t));
1.6 noro 10429: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10430: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
10431: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
10432: u = ptond(CO,vv,(P)ONE);
10433: HCZ(u) = inv;
10434: c[pi1] = u;
10435: }
10436: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10437: printf("%d ",i); fflush(stdout);
10438: ti = BDY((LIST)BDY(t));
1.6 noro 10439: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10440: }
10441: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10442: printf("%d ",i); fflush(stdout);
10443: ti = BDY((LIST)BDY(t));
1.6 noro 10444: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 10445: }
10446: m = length(ind);
10447: MKMAT(mat,nb,m);
10448: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 10449: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 10450: BDY(mat)[i][j] = ndtodp(-2,c[i]);
10451: return mat;
10452: }
10453:
10454: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
10455: LIST tlist,int pos,MAT *rp)
10456: {
10457: int i,j,n,m,nb,pi0,pi1,nvar;
10458: VL fv,tv,vv;
10459: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
10460: ND *p;
10461: ND *c;
10462: ND u;
10463: P inv;
10464: VECT vect;
10465:
10466: if ( mod == -2 )
10467: error("nd_btog_one : not implemented yet for a large finite field");
10468:
10469: parse_nd_option(current_option);
10470: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10471: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10472: switch ( ord->id ) {
10473: case 1:
10474: if ( ord->nv != nvar )
10475: error("nd_check : invalid order specification");
10476: break;
10477: default:
10478: break;
10479: }
10480: nd_init_ord(ord);
10481: #if 0
1.6 noro 10482: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 10483: #else
10484: nd_bpe = 32;
10485: #endif
10486: nd_setup_parameters(nvar,0);
10487: permtrace = BDY((LIST)ARG2(BDY(tlist)));
10488: intred = BDY((LIST)ARG3(BDY(tlist)));
10489: ind = BDY((LIST)ARG4(BDY(tlist)));
10490: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
10491: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 10492: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 10493: if ( j > i ) i = j;
10494: }
10495: n = i+1;
10496: nb = length(BDY(f));
10497: p = (ND *)MALLOC(n*sizeof(ND *));
10498: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
10499: pi = BDY((LIST)BDY(t));
1.6 noro 10500: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 10501: if ( pi1 == pos ) {
10502: ptomp(mod,(P)ARG2(pi),&inv);
10503: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
10504: u = ptond(CO,vv,(P)ONE);
10505: HCM(u) = ((MQ)inv)->cont;
10506: p[pi0] = u;
10507: }
10508: }
10509: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
10510: printf("%d ",i); fflush(stdout);
10511: ti = BDY((LIST)BDY(t));
1.6 noro 10512: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10513: if ( Demand ) {
10514: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10515: }
10516: }
10517: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
10518: printf("%d ",i); fflush(stdout);
10519: ti = BDY((LIST)BDY(t));
1.6 noro 10520: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 10521: if ( Demand ) {
10522: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
10523: }
10524: }
10525: m = length(ind);
10526: MKVECT(vect,m);
10527: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 10528: u = p[ZTOS((Q)BDY(t))];
1.1 noro 10529: if ( !u ) {
1.6 noro 10530: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 10531: BDY(vect)[j] = ndtodp(mod,u);
10532: nd_free(u);
10533: } else
10534: BDY(vect)[j] = ndtodp(mod,u);
10535: }
10536: return vect;
10537: }
10538:
10539: void ndv_print_lf(NDV p)
10540: {
10541: NMV m;
10542: int i,len;
10543:
10544: if ( !p ) printf("0\n");
10545: else {
10546: len = LEN(p);
10547: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
10548: printf("+");
10549: mpz_out_str(asir_out,10,BDY(CZ(m)));
10550: printf("*");
10551: ndl_print(DL(m));
10552: }
10553: printf("\n");
10554: }
10555: }
10556:
10557: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
10558: {
10559: VL tv,fv,vv,vc,av;
10560: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
10561: int m,nocheck,nvar,mindex,e,max;
10562: NDV c;
10563: NMV a;
10564: P p,zp;
10565: Q dmy;
10566: EPOS oepos;
10567: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
10568: Alg alpha,dp;
10569: P poly;
10570: LIST f1,f2,zpl;
10571: Obj obj;
10572: NumberField nf;
10573: struct order_spec *ord1;
10574: struct oEGT eg_check,eg0,eg1;
10575: NODE tr,tl1,tl2,tl3,tl4;
10576: LIST l1,l2,l3,l4,l5;
10577: int *perm;
10578: int j,ret;
10579: NODE retn;
10580: Q jq,bpe;
10581:
10582: nd_module = 0;
10583: parse_nd_option(current_option);
10584: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
10585: if ( nd_vc )
10586: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
10587: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
10588: switch ( ord->id ) {
10589: case 1:
10590: if ( ord->nv != nvar )
10591: error("nd_f4_lf_trace : invalid order specification");
10592: break;
10593: default:
10594: break;
10595: }
10596:
10597: nd_ntrans = nvar;
10598: nd_nalg = 0;
10599:
10600: nocheck = 0;
10601: mindex = 0;
10602:
10603: /* do not use on-demand load/save */
10604: nd_demand = 0;
10605: m = trace > 1 ? trace : get_lprime(mindex);
10606: nd_init_ord(ord);
10607: mrank = 0;
10608: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
10609: for ( tv = vv; tv; tv = NEXT(tv) ) {
10610: if ( nd_module ) {
10611: s = BDY((LIST)BDY(t));
10612: trank = length(s);
10613: mrank = MAX(mrank,trank);
10614: for ( ; s; s = NEXT(s) ) {
10615: e = getdeg(tv->v,(P)BDY(s));
10616: max = MAX(e,max);
10617: }
10618: } else {
10619: e = getdeg(tv->v,(P)BDY(t));
10620: max = MAX(e,max);
10621: }
10622: }
10623: nd_setup_parameters(nvar,max);
10624: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
10625: ishomo = 1;
10626: /* XXX */
10627: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
10628: if ( nd_module ) {
10629: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
10630: } else {
10631: c = (pointer)ptondv(CO,vv,(P)BDY(t));
10632: }
10633: if ( ishomo )
10634: ishomo = ishomo && ndv_ishomo(c);
10635: if ( c ) {
10636: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
10637: ndv_mod(-2,c);
10638: NEXTNODE(in0,in); BDY(in) = (pointer)c;
10639: }
10640: }
10641: if ( in0 ) NEXT(in) = 0;
10642: if ( fd0 ) NEXT(fd) = 0;
10643: if ( !ishomo && homo ) {
10644: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
10645: c = (NDV)BDY(t); len = LEN(c);
10646: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
10647: wmax = MAX(TD(DL(a)),wmax);
10648: }
10649: homogenize_order(ord,nvar,&ord1);
10650: nd_init_ord(ord1);
10651: nd_setup_parameters(nvar+1,wmax);
10652: for ( t = fd0; t; t = NEXT(t) )
10653: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
10654: }
10655: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 10656: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 10657: if ( ret )
10658: cand = nd_f4_lf_trace_main(m,&perm);
10659: if ( !ret || !cand ) {
10660: *rp = 0; return;
10661: }
10662: if ( !ishomo && homo ) {
10663: /* dehomogenization */
10664: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
10665: nd_init_ord(ord);
10666: nd_setup_parameters(nvar,0);
10667: }
10668: cand = ndv_reducebase(cand,perm);
10669: cand = ndv_reduceall(-2,cand);
10670: cbpe = nd_bpe;
10671: get_eg(&eg0);
10672: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
10673: /* gbcheck : cand is a GB of Id(cand) ? */
10674: retn = nd_f4(-2,0,0);
10675: }
10676: if ( !retn ) {
10677: /* failure */
10678: *rp = 0; return;
10679: }
10680: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
10681: if ( DP_Print )
1.5 noro 10682: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 10683: /* dp->p */
10684: nd_bpe = cbpe;
10685: nd_setup_parameters(nd_nvar,0);
10686: for ( r = cand; r; r = NEXT(r) ) {
10687: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
10688: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
10689: }
10690: MKLIST(*rp,cand);
10691: }
10692:
10693: NODE nd_f4_lf_trace_main(int m,int **indp)
10694: {
10695: int i,nh,stat,index;
10696: NODE r,rm,g;
10697: ND_pairs d,l,l0,t;
10698: ND spol,red;
10699: NDV nf,redv,nfqv,nfv;
10700: NM s0,s;
10701: NODE rp0,srp0,nflist,nflist_lf;
10702: int nsp,nred,col,rank,len,k,j,a;
10703: UINT c;
10704: UINT **spmat;
10705: UINT *s0vect,*svect,*p,*v;
10706: int *colstat;
10707: IndArray *imat;
10708: int *rhead;
10709: int spcol,sprow;
10710: int sugar;
10711: PGeoBucket bucket;
10712: struct oEGT eg0,eg1,eg_f4;
10713:
10714: g = 0; d = 0;
10715: for ( i = 0; i < nd_psn; i++ ) {
10716: d = update_pairs(d,g,i,0);
10717: g = update_base(g,i);
10718: }
10719: while ( d ) {
10720: get_eg(&eg0);
10721: l = nd_minsugarp(d,&d);
10722: sugar = SG(l);
10723: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
10724: bucket = create_pbucket();
10725: stat = nd_sp_f4(m,0,l,bucket);
10726: if ( !stat ) {
10727: for ( t = l; NEXT(t); t = NEXT(t) );
10728: NEXT(t) = d; d = l;
10729: d = nd_reconstruct(1,d);
10730: continue;
10731: }
10732: if ( bucket->m < 0 ) continue;
10733: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
10734: if ( !col ) {
10735: for ( t = l; NEXT(t); t = NEXT(t) );
10736: NEXT(t) = d; d = l;
10737: d = nd_reconstruct(1,d);
10738: continue;
10739: }
10740: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
10741: if ( DP_Print )
1.5 noro 10742: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 10743: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
10744: if ( !l0 ) continue;
10745: l = l0;
10746:
10747: /* over LF */
10748: bucket = create_pbucket();
10749: stat = nd_sp_f4(-2,1,l,bucket);
10750: if ( !stat ) {
10751: for ( t = l; NEXT(t); t = NEXT(t) );
10752: NEXT(t) = d; d = l;
10753: d = nd_reconstruct(1,d);
10754: continue;
10755: }
10756: if ( bucket->m < 0 ) continue;
10757: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
10758: if ( !col ) {
10759: for ( t = l; NEXT(t); t = NEXT(t) );
10760: NEXT(t) = d; d = l;
10761: d = nd_reconstruct(1,d);
10762: continue;
10763: }
10764: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
10765: /* adding new bases */
10766: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
10767: nfv = (NDV)BDY(rm);
10768: nfqv = (NDV)BDY(r);
10769: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
10770: ndv_removecont(m,nfv);
10771: ndv_removecont(-2,nfqv);
1.24 noro 10772: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 10773: d = update_pairs(d,g,nh,0);
10774: g = update_base(g,nh);
10775: }
10776: if ( r || rm ) return 0;
10777: }
10778: conv_ilist(nd_demand,1,g,indp);
10779: return g;
10780: }
10781:
1.7 noro 10782: #if SIZEOF_LONG==8
10783:
10784: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
10785: {
10786: int j,k,len;
10787: UINT *p;
10788: UINT c;
10789: NDV r;
10790: NMV mr0,mr;
10791:
10792: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
10793: if ( !len ) return 0;
10794: else {
10795: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
10796: #if 0
10797: ndv_alloc += nmv_adv*len;
10798: #endif
10799: mr = mr0;
10800: p = s0vect;
10801: for ( j = k = 0; j < col; j++, p += nd_wpd )
10802: if ( !rhead[j] ) {
10803: if ( (c = (UINT)vect[k++]) != 0 ) {
10804: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
10805: }
10806: }
10807: MKNDV(nd_nvar,mr0,len,r);
10808: return r;
10809: }
10810: }
10811:
1.28 noro 10812: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
10813: {
10814: int j,k,len;
10815: UINT *p;
10816: UINT c;
10817: NDV r;
10818: NMV mr0,mr;
10819:
10820: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
10821: if ( !len ) return 0;
10822: else {
10823: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
10824: mr = mr0;
10825: p = s0vect;
10826: for ( j = k = 0; j < col; j++, p += nd_wpd )
10827: if ( (c = (UINT)vect[k++]) != 0 ) {
10828: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
10829: }
10830: MKNDV(nd_nvar,mr0,len,r);
10831: return r;
10832: }
10833: }
10834:
1.7 noro 10835: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
10836: {
10837: NM m;
1.11 noro 10838: UINT *t,*s,*u;
10839: int i,st,ed,md,prev,c;
1.7 noro 10840:
10841: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 10842: prev = 0;
10843: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
10844: t = DL(m);
10845: st = prev;
10846: ed = n;
10847: while ( ed > st ) {
10848: md = (st+ed)/2;
10849: u = s0+md*nd_wpd;
10850: c = DL_COMPARE(u,t);
10851: if ( c == 0 ) break;
10852: else if ( c > 0 ) st = md;
10853: else ed = md;
10854: }
10855: r[md] = (mp_limb_t)CM(m);
10856: prev = md;
1.7 noro 10857: }
10858: for ( i = 0; !r[i]; i++ );
10859: return i;
10860: }
10861:
10862: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
10863:
1.28 noro 10864: 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 10865: {
10866: int i,j,k,len,pos,prev;
10867: mp_limb_t a,c,c1,c2;
10868: IndArray ivect;
10869: unsigned char *ivc;
10870: unsigned short *ivs;
10871: unsigned int *ivi;
10872: NDV redv;
10873: NMV mr;
10874: NODE rp;
10875: int maxrs;
10876:
10877: for ( i = 0; i < col; i++ ) cvect[i] = 0;
10878: maxrs = 0;
10879: for ( i = 0; i < nred; i++ ) {
10880: ivect = imat[i];
10881: k = ivect->head;
10882: a = svect[k]; c = cvect[k];
10883: MOD128(a,c,m);
10884: svect[k] = a; cvect[k] = 0;
1.28 noro 10885: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 10886: Nf4_red++;
1.7 noro 10887: maxrs = MAX(maxrs,rp0[i]->sugar);
10888: c = m-c; redv = nd_ps[rp0[i]->index];
10889: len = LEN(redv); mr = BDY(redv);
10890: svect[k] = 0; prev = k;
10891: switch ( ivect->width ) {
10892: case 1:
10893: ivc = ivect->index.c;
10894: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10895: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 10896: c2 = svect[pos]+c1*c;
10897: if ( c2 < svect[pos] ) cvect[pos]++;
10898: svect[pos] = c2;
1.7 noro 10899: }
10900: break;
10901: case 2:
10902: ivs = ivect->index.s;
10903: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10904: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 10905: c2 = svect[pos]+c1*c;
10906: if ( c2 < svect[pos] ) cvect[pos]++;
10907: svect[pos] = c2;
1.7 noro 10908: }
10909: break;
10910: case 4:
10911: ivi = ivect->index.i;
10912: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10913: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 10914: c2 = svect[pos]+c1*c;
10915: if ( c2 < svect[pos] ) cvect[pos]++;
10916: svect[pos] = c2;
1.7 noro 10917: }
10918: break;
10919: }
10920: }
10921: }
10922: for ( i = 0; i < col; i++ ) {
10923: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
10924: }
10925: return maxrs;
10926: }
10927:
10928: /* for Fp, 2^15=<p<2^29 */
10929:
10930: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
10931: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
10932: {
10933: int spcol,sprow,a;
10934: int i,j,k,l,rank;
10935: NODE r0,r;
10936: ND_pairs sp;
10937: ND spol;
10938: mp_limb_t **spmat;
10939: mp_limb_t *svect,*cvect;
10940: mp_limb_t *v;
10941: int *colstat;
10942: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
10943: int maxrs;
10944: int *spsugar;
10945: ND_pairs *spactive;
10946:
10947: spcol = col-nred;
10948: get_eg(&eg0);
10949: /* elimination (1st step) */
10950: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
10951: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10952: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10953: spsugar = (int *)MALLOC(nsp*sizeof(int));
10954: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
10955: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
10956: nd_sp(m,0,sp,&spol);
10957: if ( !spol ) continue;
10958: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 noro 10959: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 10960: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
10961: if ( i < col ) {
10962: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
10963: for ( j = k = 0; j < col; j++ )
10964: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
10965: spsugar[sprow] = MAX(maxrs,SG(spol));
10966: if ( nz )
10967: spactive[sprow] = sp;
10968: sprow++;
10969: }
10970: nd_free(spol);
10971: }
1.12 noro 10972: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 10973: if ( DP_Print ) {
10974: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
10975: fflush(asir_out);
10976: }
10977: /* free index arrays */
10978: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
10979:
10980: /* elimination (2nd step) */
10981: colstat = (int *)MALLOC(spcol*sizeof(int));
10982: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
10983: r0 = 0;
10984: for ( i = 0; i < rank; i++ ) {
10985: NEXTNODE(r0,r); BDY(r) =
10986: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
10987: SG((NDV)BDY(r)) = spsugar[i];
10988: GCFREE(spmat[i]);
10989: }
10990: if ( r0 ) NEXT(r) = 0;
10991:
10992: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 10993: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 10994: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
10995: if ( DP_Print ) {
10996: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
10997: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
10998: nsp,nred,sprow,spcol,rank);
10999: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11000: }
11001: if ( nz ) {
11002: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
11003: if ( rank > 0 ) {
11004: NEXT(spactive[rank-1]) = 0;
11005: *nz = spactive[0];
11006: } else
11007: *nz = 0;
11008: }
11009: return r0;
11010: }
11011:
11012: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
11013: {
11014: int i,j,k,l,rank,s;
11015: mp_limb_t inv;
11016: mp_limb_t a;
11017: UINT c;
11018: mp_limb_t *t,*pivot,*pk;
11019: UINT *ck;
11020: UINT **cmat;
11021: UINT *ct;
11022: ND_pairs pair;
11023:
11024: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11025: for ( i = 0; i < row; i++ ) {
11026: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11027: bzero(cmat[i],col*sizeof(UINT));
11028: }
11029:
11030: for ( rank = 0, j = 0; j < col; j++ ) {
11031: for ( i = rank; i < row; i++ ) {
11032: a = mat[i][j]; c = cmat[i][j];
11033: MOD128(a,c,md);
11034: mat[i][j] = a; cmat[i][j] = 0;
11035: }
11036: for ( i = rank; i < row; i++ )
11037: if ( mat[i][j] )
11038: break;
11039: if ( i == row ) {
11040: colstat[j] = 0;
11041: continue;
11042: } else
11043: colstat[j] = 1;
11044: if ( i != rank ) {
11045: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
11046: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
11047: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
11048: if ( spactive ) {
11049: pair = spactive[i]; spactive[i] = spactive[rank];
11050: spactive[rank] = pair;
11051: }
11052: }
11053: /* column j is normalized */
11054: s = sugar[rank];
11055: inv = invm((UINT)mat[rank][j],md);
11056: /* normalize pivot row */
11057: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
11058: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11059: }
11060: for ( i = rank+1; i < row; i++ ) {
11061: if ( (a = mat[i][j]) != 0 ) {
11062: sugar[i] = MAX(sugar[i],s);
11063: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 11064: Nf4_red++;
1.7 noro 11065: }
11066: }
11067: rank++;
11068: }
11069: for ( j = col-1, l = rank-1; j >= 0; j-- )
11070: if ( colstat[j] ) {
11071: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
11072: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
11073: }
11074: s = sugar[l];
11075: for ( i = 0; i < l; i++ ) {
11076: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
11077: if ( a ) {
11078: sugar[i] = MAX(sugar[i],s);
11079: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 11080: Nf4_red++;
1.7 noro 11081: }
11082: }
11083: l--;
11084: }
11085: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11086: GCFREE(cmat);
11087: return rank;
11088: }
11089:
1.28 noro 11090: 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)
11091: {
11092: int i,j,k,l,rank,s,imin;
11093: mp_limb_t inv;
11094: mp_limb_t a;
11095: UINT c;
11096: mp_limb_t *t,*pivot,*pk;
11097: UINT *ck;
11098: UINT **cmat;
11099: UINT *ct;
11100: ND_pairs pair;
11101: SIG sg;
1.31 noro 11102: int *used;
1.28 noro 11103:
1.31 noro 11104: used = (int *)MALLOC(row*sizeof(int));
1.28 noro 11105: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
11106: for ( i = 0; i < row; i++ ) {
11107: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
11108: bzero(cmat[i],col*sizeof(UINT));
11109: }
11110:
1.31 noro 11111: for ( j = 0; j < col; j++ ) {
11112: for ( i = 0; i < row; i++ ) {
1.28 noro 11113: a = mat[i][j]; c = cmat[i][j];
11114: MOD128(a,c,md);
11115: mat[i][j] = a; cmat[i][j] = 0;
11116: }
1.31 noro 11117: for ( i = 0; i < row; i++ )
11118: if ( !used[i] && mat[i][j] ) break;
11119: if ( i == row ) {
1.28 noro 11120: colstat[j] = 0;
11121: continue;
1.31 noro 11122: } else {
1.28 noro 11123: colstat[j] = 1;
1.31 noro 11124: used[i] = 1;
1.28 noro 11125: }
11126: /* column j is normalized */
1.31 noro 11127: s = sugar[i];
11128: inv = invm((UINT)mat[i][j],md);
1.28 noro 11129: /* normalize pivot row */
1.31 noro 11130: for ( k = j, pk = mat[i]+j, ck = cmat[i]+j; k < col; k++, pk++, ck++ ) {
1.28 noro 11131: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
11132: }
1.31 noro 11133: for ( k = i+1; k < row; k++ ) {
11134: if ( (a = mat[k][j]) != 0 ) {
11135: sugar[k] = MAX(sugar[k],s);
11136: red_by_vect64(md,mat[k]+j,cmat[k]+j,mat[i]+j,(int)(md-a),col-j);
1.28 noro 11137: Nf4_red++;
11138: }
11139: }
11140: }
1.31 noro 11141: rank = 0;
11142: for ( i = 0; i < row; i++ ) {
11143: for ( j = 0; j < col; j++ )
11144: if ( mat[i][j] ) break;
11145: if ( j == col ) sugar[i] = -1;
11146: else rank++;
11147: }
1.28 noro 11148: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
11149: GCFREE(cmat);
11150: return rank;
11151: }
11152:
11153: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
11154: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
11155: {
11156: int spcol,sprow,a;
11157: int i,j,k,l,rank;
11158: NODE r0,r;
11159: ND_pairs sp;
11160: ND spol;
11161: mp_limb_t **spmat;
11162: mp_limb_t *svect,*cvect;
11163: mp_limb_t *v;
11164: int *colstat;
11165: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
11166: int maxrs;
11167: int *spsugar;
11168: ND_pairs *spactive;
11169: SIG *spsig;
11170:
11171: get_eg(&eg0);
11172: /* elimination (1st step) */
11173: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
11174: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11175: spsugar = (int *)MALLOC(nsp*sizeof(int));
11176: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
11177: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
11178: nd_sp(m,0,sp,&spol);
11179: if ( !spol ) {
1.29 noro 11180: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11181: continue;
11182: }
11183: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
11184: nd_to_vect64(m,s0vect,col,spol,svect);
11185: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
11186: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
11187: if ( i < col ) {
11188: spmat[sprow] = svect;
11189: spsugar[sprow] = MAX(maxrs,SG(spol));
11190: spsig[sprow] = sp->sig;
11191: sprow++;
11192: } else {
1.29 noro 11193: syzlistp[sp->sig->pos] = insert_sig(syzlistp[sp->sig->pos],sp->sig);
1.28 noro 11194: }
11195: nd_free(spol);
11196: }
11197: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
11198: if ( DP_Print ) {
11199: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
11200: fflush(asir_out);
11201: }
11202: /* free index arrays */
11203: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
11204:
11205: /* elimination (2nd step) */
11206: colstat = (int *)MALLOC(col*sizeof(int));
11207: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
11208: r0 = 0;
1.31 noro 11209: for ( i = 0; i < sprow; i++ ) {
11210: if ( spsugar[i] >= 0 ) {
11211: NEXTNODE(r0,r);
11212: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
11213: SG((NDV)BDY(r)) = spsugar[i];
11214: ((NDV)BDY(r))->sig = spsig[i];
11215: } else
11216: syzlistp[spsig[i]->pos] = insert_sig(syzlistp[spsig[i]->pos],spsig[i]);
1.28 noro 11217: GCFREE(spmat[i]);
11218: }
11219: if ( r0 ) NEXT(r) = 0;
11220: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
11221: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
11222: if ( DP_Print ) {
11223: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
11224: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
11225: nsp,nred,sprow,col,rank);
11226: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
11227: }
11228: return r0;
11229: }
1.40 noro 11230: #endif
1.28 noro 11231:
11232: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
11233: {
11234: IndArray *imat;
11235: int nsp,nred,i,start;
11236: int *rhead;
11237: NODE r0,rp;
11238: ND_pairs sp;
11239: NM_ind_pair *rvect;
11240: UINT *s;
11241: int *s0hash;
11242: struct oEGT eg0,eg1,eg_conv;
11243:
11244: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
11245: nred = length(rp0);
11246: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
11247: rhead = (int *)MALLOC(col*sizeof(int));
11248: for ( i = 0; i < col; i++ ) rhead[i] = 0;
11249:
11250: /* construction of index arrays */
11251: get_eg(&eg0);
11252: if ( DP_Print ) {
11253: fprintf(asir_out,"%dx%d,",nsp+nred,col);
11254: fflush(asir_out);
11255: }
11256: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
11257: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
11258: rvect[i] = (NM_ind_pair)BDY(rp);
11259: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
11260: rhead[imat[i]->head] = 1;
11261: start = imat[i]->head;
11262: }
11263: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
11264: if ( DP_Print ) {
11265: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
11266: fflush(asir_out);
11267: }
11268: if ( m > 0 )
1.40 noro 11269: #if SIZEOF_LONG==8
1.28 noro 11270: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
1.40 noro 11271: #else
11272: r0 = nd_f4_red_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
11273: #endif
1.28 noro 11274: else
11275: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
11276: error("nd_f4_red_q_main_s : not implemented yet");
11277: return r0;
11278: }
11279:
11280: INLINE int ndl_find_reducer_minsig(UINT *dg)
11281: {
11282: RHist r;
11283: int i,singular,ret,d,k,imin;
11284: SIG t;
11285: static int wpd,nvar;
11286: static SIG quo,quomin;
11287: static UINT *tmp;
11288:
11289: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
11290: if ( wpd != nd_wpd ) {
11291: wpd = nd_wpd;
11292: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
11293: }
11294: #if 0
11295: d = ndl_hash_value(dg);
11296: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
11297: if ( ndl_equal(dg,DL(r)) ) {
11298: return r->index;
11299: }
11300: }
11301: #endif
11302: imin = -1;
11303: for ( i = 0; i < nd_psn; i++ ) {
11304: r = nd_psh[i];
11305: if ( ndl_reducible(dg,DL(r)) ) {
11306: ndl_sub(dg,DL(r),tmp);
11307: _ndltodl(tmp,DL(quo));
11308: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
11309: quo->pos = nd_psh[i]->sig->pos;
11310: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
11311: t = quo; quo = quomin; quomin = t;
11312: imin = i;
11313: }
11314: }
11315: }
11316: if ( imin == -1 ) return nd_psn;
11317: else {
11318: #if 0
11319: nd_append_red(dg,i);
11320: #endif
11321: return imin;
11322: }
11323: }
11324:
11325: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
11326: {
11327: NODE rp0,rp;
11328: NM mul,head,s0,s;
11329: int index,col,i,sugar;
11330: RHist h;
11331: UINT *s0v,*p;
11332: NM_ind_pair pair;
11333: ND red;
11334: NDV *ps;
11335: SIG sig;
11336:
11337: s0 = 0; rp0 = 0; col = 0;
11338: if ( nd_demand )
11339: ps = trace?nd_ps_trace_sym:nd_ps_sym;
11340: else
11341: ps = trace?nd_ps_trace:nd_ps;
11342: while ( 1 ) {
11343: head = remove_head_pbucket_symbolic(bucket);
11344: if ( !head ) break;
11345: if ( !s0 ) s0 = head;
11346: else NEXT(s) = head;
11347: s = head;
11348: index = ndl_find_reducer_minsig(DL(head));
11349: if ( index >= 0 && index < nd_psn ) {
11350: h = nd_psh[index];
11351: NEWNM(mul);
11352: ndl_sub(DL(head),DL(h),DL(mul));
11353: if ( ndl_check_bound2(index,DL(mul)) )
11354: return 0;
11355: sugar = TD(DL(mul))+SG(ps[index]);
11356: NEWSIG(sig);
11357: _ndltodl(DL(mul),DL(sig));
11358: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
11359: sig->pos = nd_psh[index]->sig->pos;
11360: MKNM_ind_pair(pair,mul,index,sugar,sig);
11361: red = ndv_mul_nm_symbolic(mul,ps[index]);
11362: add_pbucket_symbolic(bucket,nd_remove_head(red));
11363: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
11364: }
11365: col++;
11366: }
11367: if ( rp0 ) NEXT(rp) = 0;
11368: NEXT(s) = 0;
11369: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
11370: for ( i = 0, p = s0v, s = s0; i < col;
11371: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
11372: *s0vect = s0v;
11373: *r = rp0;
11374:
11375: return col;
11376: }
11377:
11378: NODE nd_sba_f4(int m,int **indp)
11379: {
1.34 noro 11380: int i,nh,stat,index,f4red,f4step;
1.33 noro 11381: int col,rank,len,k,j,a,sugar,nbase,psugar,ms;
11382: NODE r,g,rp0,nflist;
1.41 noro 11383: ND_pairs d,l,t,l1;
1.33 noro 11384: ND h,nf;
11385: NDV nfv;
11386: union oNDC hc;
11387: UINT *s0vect;
1.28 noro 11388: UINT c;
11389: PGeoBucket bucket;
1.33 noro 11390: NODE *syzlist;
11391: SIG sig;
1.28 noro 11392: struct oEGT eg0,eg1,eg_f4;
1.33 noro 11393: struct oEGT eg2,eg_update,eg_remove,eg_large,eg_nf,eg_nfzero;
1.28 noro 11394:
11395: Nf4_red=0;
1.30 noro 11396: d = 0;
1.29 noro 11397: syzlist = (NODE *)MALLOC(nd_psn*sizeof(NODE));
1.28 noro 11398: for ( i = 0; i < nd_psn; i++ ) {
1.30 noro 11399: d = update_pairs_s(d,i,syzlist);
1.28 noro 11400: }
1.30 noro 11401: nd_nbase = nd_psn;
1.28 noro 11402: f4red = 1;
1.33 noro 11403: psugar = 0;
1.34 noro 11404: f4step = 0;
1.28 noro 11405: while ( d ) {
1.33 noro 11406: for ( t = d, ms = SG(d); t; t = NEXT(t) )
11407: if ( SG(t) < ms ) ms = SG(t);
1.38 noro 11408: if ( ms == psugar && f4step >= nd_sba_f4step ) {
1.33 noro 11409: again:
11410: l = d; d = d->next;
1.41 noro 11411: #if 0
1.33 noro 11412: if ( small_lcm(l) ) {
11413: if ( DP_Print ) fprintf(asir_out,"M");
11414: continue;
11415: }
11416: sig = l->sig;
11417: stat = nd_sp(m,0,l,&h);
1.41 noro 11418: #else
11419: l1 = find_smallest_lcm(l);
11420: if ( l1 == 0 ) {
11421: if ( DP_Print ) fprintf(asir_out,"M");
11422: continue;
11423: }
11424: sig = l1->sig;
11425: stat = nd_sp(m,0,l1,&h);
11426: #endif
1.33 noro 11427: if ( !stat ) {
11428: NEXT(l) = d; d = l;
11429: d = nd_reconstruct(0,d);
11430: goto again;
11431: }
11432: get_eg(&eg1);
11433: #if USE_GEOBUCKET
1.39 noro 11434: 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 11435: #else
1.39 noro 11436: stat = nd_nf_s(m,0,h,nd_ps,!nd_top&&!Top,&nf);
1.33 noro 11437: #endif
11438: get_eg(&eg2);
11439: if ( !stat ) {
11440: NEXT(l) = d; d = l;
11441: d = nd_reconstruct(0,d);
11442: goto again;
11443: } else if ( stat == -1 ) {
11444: if ( DP_Print ) { printf("S"); fflush(stdout); }
11445: FREENDP(l);
11446: } else if ( nf ) {
11447: if ( DP_Print ) { printf("+"); fflush(stdout); }
11448: add_eg(&eg_nf,&eg1,&eg2);
11449: hc = HCU(nf);
11450: nd_removecont(m,nf);
11451: nfv = ndtondv(m,nf); nd_free(nf);
11452: nh = ndv_newps(m,nfv,0);
11453:
1.30 noro 11454: d = update_pairs_s(d,nh,syzlist);
11455: nd_sba_pos[sig->pos] = append_one(nd_sba_pos[sig->pos],nh);
1.33 noro 11456: FREENDP(l);
1.28 noro 11457: } else {
1.33 noro 11458: add_eg(&eg_nfzero,&eg1,&eg2);
11459: // syzygy
11460: get_eg(&eg1);
11461: d = remove_spair_s(d,sig);
11462: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.29 noro 11463: syzlist[sig->pos] = insert_sig(syzlist[sig->pos],sig);
1.33 noro 11464: if ( DP_Print ) { printf("."); fflush(stdout); }
11465: FREENDP(l);
11466: }
11467: } else {
1.34 noro 11468: if ( ms != psugar ) f4step = 1;
11469: else f4step++;
1.33 noro 11470: again2:
11471: psugar = ms;
11472: l = nd_minsugarp_s(d,&d);
11473: sugar = nd_sugarweight?d->sugar2:SG(d);
11474: bucket = create_pbucket();
11475: stat = nd_sp_f4(m,0,l,bucket);
11476: if ( !stat ) {
11477: for ( t = l; NEXT(t); t = NEXT(t) );
11478: NEXT(t) = d; d = l;
11479: d = nd_reconstruct(0,d);
11480: goto again2;
11481: }
11482: if ( bucket->m < 0 ) continue;
11483: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
11484: if ( !col ) {
1.37 noro 11485: for ( t = l; NEXT(t); t = NEXT(t) )
11486: ;
11487: NEXT(t) = d; d = l;
1.33 noro 11488: d = nd_reconstruct(0,d);
11489: goto again2;
11490: }
1.34 noro 11491: if ( DP_Print ) fprintf(asir_out,"\nsugar=%d,",psugar);
1.33 noro 11492: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,syzlist);
11493: /* adding new bases */
11494: for ( r = nflist; r; r = NEXT(r) ) {
11495: nfv = (NDV)BDY(r);
1.38 noro 11496: if ( nd_f4_td ) SG(nfv) = nd_tdeg(nfv);
1.33 noro 11497: ndv_removecont(m,nfv);
11498: nh = ndv_newps(m,nfv,0);
11499: d = update_pairs_s(d,nh,syzlist);
11500: nd_sba_pos[nfv->sig->pos] = append_one(nd_sba_pos[nfv->sig->pos],nh);
11501: }
11502: for ( i = 0; i < nd_nbase; i++ )
11503: for ( r = syzlist[i]; r; r = NEXT(r) )
11504: d = remove_spair_s(d,(SIG)BDY(r));
11505: d = remove_large_lcm(d);
11506: if ( DP_Print ) {
1.34 noro 11507: fprintf(asir_out,"f4red=%d,gblen=%d",f4red,nd_psn); fflush(asir_out);
1.33 noro 11508: }
11509: f4red++;
1.28 noro 11510: }
11511: }
11512: if ( DP_Print ) {
1.34 noro 11513: fprintf(asir_out,"\nnumber of red=%d,",Nf4_red);
1.28 noro 11514: }
1.30 noro 11515: g = conv_ilist_s(nd_demand,0,indp);
1.28 noro 11516: return g;
11517: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>