Annotation of OpenXM_contrib2/asir2018/engine/nd.c, Revision 1.28
1.28 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.27 2020/06/25 02:53:31 noro Exp $ */
1.1 noro 2:
3: #include "nd.h"
4:
1.11 noro 5: int Nnd_add,Nf4_red;
1.12 noro 6: struct oEGT eg_search,f4_symb,f4_conv,f4_elim1,f4_elim2;
1.1 noro 7:
8: int diag_period = 6;
9: int weight_check = 1;
10: int (*ndl_compare_function)(UINT *a1,UINT *a2);
1.21 noro 11: /* for general module order */
1.19 noro 12: int (*ndl_base_compare_function)(UINT *a1,UINT *a2);
1.21 noro 13: int (*dl_base_compare_function)(int nv,DL a,DL b);
14: int nd_base_ordtype;
1.1 noro 15: int nd_dcomp;
16: int nd_rref2;
17: NM _nm_free_list;
18: ND _nd_free_list;
19: ND_pairs _ndp_free_list;
20: NODE nd_hcf;
1.26 noro 21: int Nsyz;
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;
53: static int nd_psn,nd_pslen;
54: static RHist *nd_red;
55: static int *nd_work_vector;
56: static int **nd_matrix;
57: static int nd_matrix_len;
58: static struct weight_or_block *nd_worb;
59: static int nd_worb_len;
60: static int nd_found,nd_create,nd_notfirst;
61: static int nmv_adv;
62: static int nd_demand;
1.21 noro 63: static int nd_module,nd_module_ordtype,nd_mpos,nd_pot_nelim;
1.1 noro 64: static int nd_module_rank,nd_poly_weight_len;
65: static int *nd_poly_weight,*nd_module_weight;
66: static NODE nd_tracelist;
67: static NODE nd_alltracelist;
68: static int nd_gentrace,nd_gensyz,nd_nora,nd_newelim,nd_intersect,nd_lf;
69: static int *nd_gbblock;
70: static NODE nd_nzlist,nd_check_splist;
71: static int nd_splist;
72: static int *nd_sugarweight;
73: static int nd_f4red,nd_rank0,nd_last_nonzero;
1.27 noro 74: static DL *nd_sba_hm;
1.1 noro 75:
76: NumberField get_numberfield();
77: UINT *nd_det_compute_bound(NDV **dm,int n,int j);
78: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d);
79: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr);
80: int nd_monic(int m,ND *p);
81: NDV plain_vect_to_ndv_q(Z *mat,int col,UINT *s0vect);
82: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank);
83: NDV pltondv(VL vl,VL dvl,LIST p);
84: void pltozpl(LIST l,Q *cont,LIST *pp);
85: void ndl_max(UINT *d1,unsigned *d2,UINT *d);
86: void nmtodp(int mod,NM m,DP *r);
1.15 noro 87: void ndltodp(UINT *d,DP *r);
1.1 noro 88: NODE reverse_node(NODE n);
89: P ndc_div(int mod,union oNDC a,union oNDC b);
90: P ndctop(int mod,union oNDC c);
91: void finalize_tracelist(int i,P cont);
92: void conv_ilist(int demand,int trace,NODE g,int **indp);
93: void parse_nd_option(NODE opt);
94: void dltondl(int n,DL dl,UINT *r);
95: DP ndvtodp(int mod,NDV p);
96: DP ndtodp(int mod,ND p);
1.16 noro 97: DPM ndvtodpm(int mod,NDV p);
98: NDV dpmtondv(int mod,DPM p);
99: int dpm_getdeg(DPM p,int *rank);
100: void dpm_ptozp(DPM p,Z *cont,DPM *r);
101: int compdmm(int nv,DMM a,DMM b);
1.1 noro 102:
103: void Pdp_set_weight(NODE,VECT *);
104: void Pox_cmo_rpc(NODE,Obj *);
105:
106: ND nd_add_lf(ND p1,ND p2);
107: void nd_mul_c_lf(ND p,Z mul);
108: void ndv_mul_c_lf(NDV p,Z mul);
109: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
110: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
111: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
112: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz);
113: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
114: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred);
115: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat);
116: NODE nd_f4_lf_trace_main(int m,int **indp);
117: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp);
118:
119: extern int lf_lazy;
120: extern Z current_mod_lf;
121:
122: extern int Denominator,DP_Multiple,MaxDeg;
123:
124: #define BLEN (8*sizeof(unsigned long))
125:
126: typedef struct matrix {
127: int row,col;
128: unsigned long **a;
129: } *matrix;
130:
131:
132: void nd_free_private_storage()
133: {
134: _nm_free_list = 0;
135: _ndp_free_list = 0;
136: #if 0
137: GC_gcollect();
138: #endif
139: }
140:
141: void _NM_alloc()
142: {
143: NM p;
144: int i;
145:
146: for ( i = 0; i < 1024; i++ ) {
147: p = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
148: p->next = _nm_free_list; _nm_free_list = p;
149: }
150: }
151:
152: matrix alloc_matrix(int row,int col)
153: {
154: unsigned long **a;
155: int i,len,blen;
156: matrix mat;
157:
158: mat = (matrix)MALLOC(sizeof(struct matrix));
159: mat->row = row;
160: mat->col = col;
161: mat->a = a = (unsigned long **)MALLOC(row*sizeof(unsigned long *));
162: return mat;
163: }
164:
165:
166: void _ND_alloc()
167: {
168: ND p;
169: int i;
170:
171: for ( i = 0; i < 1024; i++ ) {
172: p = (ND)MALLOC(sizeof(struct oND));
173: p->body = (NM)_nd_free_list; _nd_free_list = p;
174: }
175: }
176:
177: void _NDP_alloc()
178: {
179: ND_pairs p;
180: int i;
181:
182: for ( i = 0; i < 1024; i++ ) {
183: p = (ND_pairs)MALLOC(sizeof(struct oND_pairs)
184: +(nd_wpd-1)*sizeof(UINT));
185: p->next = _ndp_free_list; _ndp_free_list = p;
186: }
187: }
188:
189: INLINE int nd_length(ND p)
190: {
191: NM m;
192: int i;
193:
194: if ( !p )
195: return 0;
196: else {
197: for ( i = 0, m = BDY(p); m; m = NEXT(m), i++ );
198: return i;
199: }
200: }
201:
202: extern int dp_negative_weight;
203:
204: INLINE int ndl_reducible(UINT *d1,UINT *d2)
205: {
206: UINT u1,u2;
207: int i,j;
208:
209: if ( nd_module && (MPOS(d1) != MPOS(d2)) ) return 0;
210:
211: if ( !dp_negative_weight && TD(d1) < TD(d2) ) return 0;
212: #if USE_UNROLL
213: switch ( nd_bpe ) {
214: case 3:
215: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
216: u1 = d1[i]; u2 = d2[i];
217: if ( (u1&0x38000000) < (u2&0x38000000) ) return 0;
218: if ( (u1& 0x7000000) < (u2& 0x7000000) ) return 0;
219: if ( (u1& 0xe00000) < (u2& 0xe00000) ) return 0;
220: if ( (u1& 0x1c0000) < (u2& 0x1c0000) ) return 0;
221: if ( (u1& 0x38000) < (u2& 0x38000) ) return 0;
222: if ( (u1& 0x7000) < (u2& 0x7000) ) return 0;
223: if ( (u1& 0xe00) < (u2& 0xe00) ) return 0;
224: if ( (u1& 0x1c0) < (u2& 0x1c0) ) return 0;
225: if ( (u1& 0x38) < (u2& 0x38) ) return 0;
226: if ( (u1& 0x7) < (u2& 0x7) ) return 0;
227: }
228: return 1;
229: break;
230: case 4:
231: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
232: u1 = d1[i]; u2 = d2[i];
233: if ( (u1&0xf0000000) < (u2&0xf0000000) ) return 0;
234: if ( (u1& 0xf000000) < (u2& 0xf000000) ) return 0;
235: if ( (u1& 0xf00000) < (u2& 0xf00000) ) return 0;
236: if ( (u1& 0xf0000) < (u2& 0xf0000) ) return 0;
237: if ( (u1& 0xf000) < (u2& 0xf000) ) return 0;
238: if ( (u1& 0xf00) < (u2& 0xf00) ) return 0;
239: if ( (u1& 0xf0) < (u2& 0xf0) ) return 0;
240: if ( (u1& 0xf) < (u2& 0xf) ) return 0;
241: }
242: return 1;
243: break;
244: case 6:
245: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
246: u1 = d1[i]; u2 = d2[i];
247: if ( (u1&0x3f000000) < (u2&0x3f000000) ) return 0;
248: if ( (u1& 0xfc0000) < (u2& 0xfc0000) ) return 0;
249: if ( (u1& 0x3f000) < (u2& 0x3f000) ) return 0;
250: if ( (u1& 0xfc0) < (u2& 0xfc0) ) return 0;
251: if ( (u1& 0x3f) < (u2& 0x3f) ) return 0;
252: }
253: return 1;
254: break;
255: case 8:
256: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
257: u1 = d1[i]; u2 = d2[i];
258: if ( (u1&0xff000000) < (u2&0xff000000) ) return 0;
259: if ( (u1& 0xff0000) < (u2& 0xff0000) ) return 0;
260: if ( (u1& 0xff00) < (u2& 0xff00) ) return 0;
261: if ( (u1& 0xff) < (u2& 0xff) ) return 0;
262: }
263: return 1;
264: break;
265: case 16:
266: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
267: u1 = d1[i]; u2 = d2[i];
268: if ( (u1&0xffff0000) < (u2&0xffff0000) ) return 0;
269: if ( (u1& 0xffff) < (u2& 0xffff) ) return 0;
270: }
271: return 1;
272: break;
273: case 32:
274: for ( i = nd_exporigin; i < nd_wpd; i++ )
275: if ( d1[i] < d2[i] ) return 0;
276: return 1;
277: break;
278: default:
279: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
280: u1 = d1[i]; u2 = d2[i];
281: for ( j = 0; j < nd_epw; j++ )
282: if ( (u1&nd_mask[j]) < (u2&nd_mask[j]) ) return 0;
283: }
284: return 1;
285: }
286: #else
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: #endif
294: }
295:
296: /*
297: * If the current order is a block order,
298: * then the last block is length 1 and contains
299: * the homo variable. Otherwise, the original
300: * order is either 0 or 2.
301: */
302:
303: void ndl_homogenize(UINT *d,UINT *r,int obpe,EPOS oepos,int ompos,int weight)
304: {
305: int w,i,e,n,omask0;
306:
307: omask0 = obpe==32?0xffffffff:((1<<obpe)-1);
308: n = nd_nvar-1;
309: ndl_zero(r);
310: for ( i = 0; i < n; i++ ) {
311: e = GET_EXP_OLD(d,i);
312: PUT_EXP(r,i,e);
313: }
314: w = TD(d);
315: PUT_EXP(r,nd_nvar-1,weight-w);
316: if ( nd_module ) MPOS(r) = d[ompos];
317: TD(r) = weight;
318: if ( nd_blockmask ) ndl_weight_mask(r);
319: }
320:
321: void ndl_dehomogenize(UINT *d)
322: {
323: UINT mask;
324: UINT h;
325: int i,bits;
326:
327: if ( nd_blockmask ) {
328: h = GET_EXP(d,nd_nvar-1);
329: XOR_EXP(d,nd_nvar-1,h);
330: TD(d) -= h;
331: ndl_weight_mask(d);
332: } else {
333: if ( nd_isrlex ) {
334: if ( nd_bpe == 32 ) {
335: h = d[nd_exporigin];
336: for ( i = nd_exporigin+1; i < nd_wpd; i++ )
337: d[i-1] = d[i];
338: d[i-1] = 0;
339: TD(d) -= h;
340: } else {
341: bits = nd_epw*nd_bpe;
342: mask = bits==32?0xffffffff:((1<<(nd_epw*nd_bpe))-1);
343: h = (d[nd_exporigin]>>((nd_epw-1)*nd_bpe))&nd_mask0;
344: for ( i = nd_exporigin; i < nd_wpd; i++ )
345: d[i] = ((d[i]<<nd_bpe)&mask)
346: |(i+1<nd_wpd?((d[i+1]>>((nd_epw-1)*nd_bpe))&nd_mask0):0);
347: TD(d) -= h;
348: }
349: } else {
350: h = GET_EXP(d,nd_nvar-1);
351: XOR_EXP(d,nd_nvar-1,h);
352: TD(d) -= h;
353: }
354: }
355: }
356:
357: void ndl_lcm(UINT *d1,unsigned *d2,UINT *d)
358: {
359: UINT t1,t2,u,u1,u2;
360: int i,j,l;
361:
362: if ( nd_module && (MPOS(d1) != MPOS(d2)) )
363: error("ndl_lcm : inconsistent monomials");
364: #if USE_UNROLL
365: switch ( nd_bpe ) {
366: case 3:
367: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
368: u1 = d1[i]; u2 = d2[i];
369: t1 = (u1&0x38000000); t2 = (u2&0x38000000); u = t1>t2?t1:t2;
370: t1 = (u1& 0x7000000); t2 = (u2& 0x7000000); u |= t1>t2?t1:t2;
371: t1 = (u1& 0xe00000); t2 = (u2& 0xe00000); u |= t1>t2?t1:t2;
372: t1 = (u1& 0x1c0000); t2 = (u2& 0x1c0000); u |= t1>t2?t1:t2;
373: t1 = (u1& 0x38000); t2 = (u2& 0x38000); u |= t1>t2?t1:t2;
374: t1 = (u1& 0x7000); t2 = (u2& 0x7000); u |= t1>t2?t1:t2;
375: t1 = (u1& 0xe00); t2 = (u2& 0xe00); u |= t1>t2?t1:t2;
376: t1 = (u1& 0x1c0); t2 = (u2& 0x1c0); u |= t1>t2?t1:t2;
377: t1 = (u1& 0x38); t2 = (u2& 0x38); u |= t1>t2?t1:t2;
378: t1 = (u1& 0x7); t2 = (u2& 0x7); u |= t1>t2?t1:t2;
379: d[i] = u;
380: }
381: break;
382: case 4:
383: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
384: u1 = d1[i]; u2 = d2[i];
385: t1 = (u1&0xf0000000); t2 = (u2&0xf0000000); u = t1>t2?t1:t2;
386: t1 = (u1& 0xf000000); t2 = (u2& 0xf000000); u |= t1>t2?t1:t2;
387: t1 = (u1& 0xf00000); t2 = (u2& 0xf00000); u |= t1>t2?t1:t2;
388: t1 = (u1& 0xf0000); t2 = (u2& 0xf0000); u |= t1>t2?t1:t2;
389: t1 = (u1& 0xf000); t2 = (u2& 0xf000); u |= t1>t2?t1:t2;
390: t1 = (u1& 0xf00); t2 = (u2& 0xf00); u |= t1>t2?t1:t2;
391: t1 = (u1& 0xf0); t2 = (u2& 0xf0); u |= t1>t2?t1:t2;
392: t1 = (u1& 0xf); t2 = (u2& 0xf); u |= t1>t2?t1:t2;
393: d[i] = u;
394: }
395: break;
396: case 6:
397: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
398: u1 = d1[i]; u2 = d2[i];
399: t1 = (u1&0x3f000000); t2 = (u2&0x3f000000); u = t1>t2?t1:t2;
400: t1 = (u1& 0xfc0000); t2 = (u2& 0xfc0000); u |= t1>t2?t1:t2;
401: t1 = (u1& 0x3f000); t2 = (u2& 0x3f000); u |= t1>t2?t1:t2;
402: t1 = (u1& 0xfc0); t2 = (u2& 0xfc0); u |= t1>t2?t1:t2;
403: t1 = (u1& 0x3f); t2 = (u2& 0x3f); u |= t1>t2?t1:t2;
404: d[i] = u;
405: }
406: break;
407: case 8:
408: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
409: u1 = d1[i]; u2 = d2[i];
410: t1 = (u1&0xff000000); t2 = (u2&0xff000000); u = t1>t2?t1:t2;
411: t1 = (u1& 0xff0000); t2 = (u2& 0xff0000); u |= t1>t2?t1:t2;
412: t1 = (u1& 0xff00); t2 = (u2& 0xff00); u |= t1>t2?t1:t2;
413: t1 = (u1& 0xff); t2 = (u2& 0xff); u |= t1>t2?t1:t2;
414: d[i] = u;
415: }
416: break;
417: case 16:
418: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
419: u1 = d1[i]; u2 = d2[i];
420: t1 = (u1&0xffff0000); t2 = (u2&0xffff0000); u = t1>t2?t1:t2;
421: t1 = (u1& 0xffff); t2 = (u2& 0xffff); u |= t1>t2?t1:t2;
422: d[i] = u;
423: }
424: break;
425: case 32:
426: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
427: u1 = d1[i]; u2 = d2[i];
428: d[i] = u1>u2?u1:u2;
429: }
430: break;
431: default:
432: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
433: u1 = d1[i]; u2 = d2[i];
434: for ( j = 0, u = 0; j < nd_epw; j++ ) {
435: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
436: }
437: d[i] = u;
438: }
439: break;
440: }
441: #else
442: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
443: u1 = d1[i]; u2 = d2[i];
444: for ( j = 0, u = 0; j < nd_epw; j++ ) {
445: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
446: }
447: d[i] = u;
448: }
449: #endif
450: if ( nd_module ) MPOS(d) = MPOS(d1);
451: TD(d) = ndl_weight(d);
452: if ( nd_blockmask ) ndl_weight_mask(d);
453: }
454:
455: void ndl_max(UINT *d1,unsigned *d2,UINT *d)
456: {
457: UINT t1,t2,u,u1,u2;
458: int i,j,l;
459:
460: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
461: u1 = d1[i]; u2 = d2[i];
462: for ( j = 0, u = 0; j < nd_epw; j++ ) {
463: t1 = (u1&nd_mask[j]); t2 = (u2&nd_mask[j]); u |= t1>t2?t1:t2;
464: }
465: d[i] = u;
466: }
467: }
468:
469: int ndl_weight(UINT *d)
470: {
471: UINT t,u;
472: int i,j;
473:
474: if ( current_dl_weight_vector )
475: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
476: u = GET_EXP(d,i);
477: t += MUL_WEIGHT(u,i);
478: }
479: else
480: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
481: u = d[i];
482: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
483: t += (u&nd_mask0);
484: }
1.20 noro 485: if ( nd_module && nd_module_rank && MPOS(d) )
486: t += nd_module_weight[MPOS(d)-1];
487: for ( i = nd_exporigin; i < nd_wpd; i++ )
488: if ( d[i] && !t )
489: printf("afo\n");
1.1 noro 490: return t;
491: }
492:
493: /* for sugarweight */
494:
495: int ndl_weight2(UINT *d)
496: {
497: int t,u;
498: int i,j;
499:
500: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
501: u = GET_EXP(d,i);
502: t += nd_sugarweight[i]*u;
503: }
1.20 noro 504: if ( nd_module && nd_module_rank && MPOS(d) )
505: t += nd_module_weight[MPOS(d)-1];
1.1 noro 506: return t;
507: }
508:
509: void ndl_weight_mask(UINT *d)
510: {
511: UINT t,u;
512: UINT *mask;
513: int i,j,k,l;
514:
515: l = nd_blockmask->n;
516: for ( k = 0; k < l; k++ ) {
517: mask = nd_blockmask->mask[k];
518: if ( current_dl_weight_vector )
519: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
520: u = GET_EXP_MASK(d,i,mask);
521: t += MUL_WEIGHT(u,i);
522: }
523: else
524: for ( t = 0, i = nd_exporigin; i < nd_wpd; i++ ) {
525: u = d[i]&mask[i];
526: for ( j = 0; j < nd_epw; j++, u>>=nd_bpe )
527: t += (u&nd_mask0);
528: }
529: d[k+1] = t;
530: }
531: }
532:
1.21 noro 533: int ndl_glex_compare(UINT *d1,UINT *d2)
534: {
535: if ( TD(d1) > TD(d2) ) return 1;
536: else if ( TD(d1) < TD(d2) ) return -1;
537: else return ndl_lex_compare(d1,d2);
538: }
539:
1.1 noro 540: int ndl_lex_compare(UINT *d1,UINT *d2)
541: {
542: int i;
543:
544: d1 += nd_exporigin;
545: d2 += nd_exporigin;
546: for ( i = nd_exporigin; i < nd_wpd; i++, d1++, d2++ )
547: if ( *d1 > *d2 )
548: return nd_isrlex ? -1 : 1;
549: else if ( *d1 < *d2 )
550: return nd_isrlex ? 1 : -1;
551: return 0;
552: }
553:
554: int ndl_block_compare(UINT *d1,UINT *d2)
555: {
556: int i,l,j,ord_o,ord_l;
557: struct order_pair *op;
558: UINT t1,t2,m;
559: UINT *mask;
560:
561: l = nd_blockmask->n;
562: op = nd_blockmask->order_pair;
563: for ( j = 0; j < l; j++ ) {
564: mask = nd_blockmask->mask[j];
565: ord_o = op[j].order;
566: if ( ord_o < 2 ) {
567: if ( (t1=d1[j+1]) > (t2=d2[j+1]) ) return 1;
568: else if ( t1 < t2 ) return -1;
569: }
570: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
571: m = mask[i];
572: t1 = d1[i]&m;
573: t2 = d2[i]&m;
574: if ( t1 > t2 )
575: return !ord_o ? -1 : 1;
576: else if ( t1 < t2 )
577: return !ord_o ? 1 : -1;
578: }
579: }
580: return 0;
581: }
582:
583: int ndl_matrix_compare(UINT *d1,UINT *d2)
584: {
585: int i,j,s,row;
586: int *v;
587: Z **mat;
588: Z *w;
589: Z t1;
590: Z t,t2;
591:
1.6 noro 592: for ( j = 0; j < nd_nvar; j++ )
593: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
1.1 noro 594: if ( nd_top_weight ) {
595: if ( OID(nd_top_weight) == O_VECT ) {
1.6 noro 596: mat = (Z **)&BDY((VECT)nd_top_weight);
597: row = 1;
1.1 noro 598: } else {
599: mat = (Z **)BDY((MAT)nd_top_weight);
1.6 noro 600: row = ((MAT)nd_top_weight)->row;
1.1 noro 601: }
602: for ( i = 0; i < row; i++ ) {
1.6 noro 603: w = mat[i];
1.1 noro 604: for ( j = 0, t = 0; j < nd_nvar; j++ ) {
1.6 noro 605: STOZ(nd_work_vector[j],t1);
1.1 noro 606: mulz(w[j],t1,&t2);
607: addz(t,t2,&t1);
608: t = t1;
609: }
1.6 noro 610: if ( t ) {
611: s = sgnz(t);
1.1 noro 612: if ( s > 0 ) return 1;
613: else if ( s < 0 ) return -1;
1.6 noro 614: }
1.1 noro 615: }
1.6 noro 616: }
617: for ( i = 0; i < nd_matrix_len; i++ ) {
618: v = nd_matrix[i];
619: for ( j = 0, s = 0; j < nd_nvar; j++ )
620: s += v[j]*nd_work_vector[j];
621: if ( s > 0 ) return 1;
622: else if ( s < 0 ) return -1;
623: }
1.1 noro 624: if ( !ndl_equal(d1,d2) )
1.6 noro 625: error("ndl_matrix_compare : invalid matrix");
626: return 0;
1.1 noro 627: }
628:
629: int ndl_composite_compare(UINT *d1,UINT *d2)
630: {
631: int i,j,s,start,end,len,o;
632: int *v;
633: struct sparse_weight *sw;
634:
635: for ( j = 0; j < nd_nvar; j++ )
636: nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j);
637: for ( i = 0; i < nd_worb_len; i++ ) {
638: len = nd_worb[i].length;
639: switch ( nd_worb[i].type ) {
640: case IS_DENSE_WEIGHT:
641: v = nd_worb[i].body.dense_weight;
642: for ( j = 0, s = 0; j < len; j++ )
643: s += v[j]*nd_work_vector[j];
644: if ( s > 0 ) return 1;
645: else if ( s < 0 ) return -1;
646: break;
647: case IS_SPARSE_WEIGHT:
648: sw = nd_worb[i].body.sparse_weight;
649: for ( j = 0, s = 0; j < len; j++ )
650: s += sw[j].value*nd_work_vector[sw[j].pos];
651: if ( s > 0 ) return 1;
652: else if ( s < 0 ) return -1;
653: break;
654: case IS_BLOCK:
655: o = nd_worb[i].body.block.order;
656: start = nd_worb[i].body.block.start;
657: switch ( o ) {
658: case 0:
659: end = start+len;
660: for ( j = start, s = 0; j < end; j++ )
661: s += MUL_WEIGHT(nd_work_vector[j],j);
662: if ( s > 0 ) return 1;
663: else if ( s < 0 ) return -1;
664: for ( j = end-1; j >= start; j-- )
665: if ( nd_work_vector[j] < 0 ) return 1;
666: else if ( nd_work_vector[j] > 0 ) return -1;
667: break;
668: case 1:
669: end = start+len;
670: for ( j = start, s = 0; j < end; j++ )
671: s += MUL_WEIGHT(nd_work_vector[j],j);
672: if ( s > 0 ) return 1;
673: else if ( s < 0 ) return -1;
674: for ( j = start; j < end; j++ )
675: if ( nd_work_vector[j] > 0 ) return 1;
676: else if ( nd_work_vector[j] < 0 ) return -1;
677: break;
678: case 2:
679: end = start+len;
680: for ( j = start; j < end; j++ )
681: if ( nd_work_vector[j] > 0 ) return 1;
682: else if ( nd_work_vector[j] < 0 ) return -1;
683: break;
684: }
685: break;
686: }
687: }
688: return 0;
689: }
690:
691: /* TDH -> WW -> TD-> RL */
692:
693: int ndl_ww_lex_compare(UINT *d1,UINT *d2)
694: {
695: int i,m,e1,e2;
696:
697: if ( TD(d1) > TD(d2) ) return 1;
698: else if ( TD(d1) < TD(d2) ) return -1;
699: m = nd_nvar>>1;
700: for ( i = 0, e1 = e2 = 0; i < m; i++ ) {
701: e1 += current_weyl_weight_vector[i]*(GET_EXP(d1,m+i)-GET_EXP(d1,i));
702: e2 += current_weyl_weight_vector[i]*(GET_EXP(d2,m+i)-GET_EXP(d2,i));
703: }
704: if ( e1 > e2 ) return 1;
705: else if ( e1 < e2 ) return -1;
706: return ndl_lex_compare(d1,d2);
707: }
708:
1.21 noro 709: // common function for module glex and grlex comparison
710: int ndl_module_glex_compare(UINT *d1,UINT *d2)
1.1 noro 711: {
1.21 noro 712: int c;
1.1 noro 713:
1.21 noro 714: switch ( nd_module_ordtype ) {
715: case 0:
716: if ( TD(d1) > TD(d2) ) return 1;
717: else if ( TD(d1) < TD(d2) ) return -1;
718: else if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
719: else if ( MPOS(d1) < MPOS(d2) ) return 1;
720: else if ( MPOS(d1) > MPOS(d2) ) return -1;
721: else return 0;
722: break;
1.1 noro 723:
1.21 noro 724: case 1:
1.19 noro 725: if ( nd_pot_nelim && MPOS(d1)>=nd_pot_nelim+1 && MPOS(d2) >= nd_pot_nelim+1 ) {
726: if ( TD(d1) > TD(d2) ) return 1;
727: else if ( TD(d1) < TD(d2) ) return -1;
728: if ( (c = ndl_lex_compare(d1,d2)) != 0 ) return c;
729: if ( MPOS(d1) < MPOS(d2) ) return 1;
730: else if ( MPOS(d1) > MPOS(d2) ) return -1;
731: }
732: if ( MPOS(d1) < MPOS(d2) ) return 1;
733: else if ( MPOS(d1) > MPOS(d2) ) return -1;
1.21 noro 734: else if ( TD(d1) > TD(d2) ) return 1;
735: else if ( TD(d1) < TD(d2) ) return -1;
736: else return ndl_lex_compare(d1,d2);
737: break;
1.1 noro 738:
1.21 noro 739: case 2: // weight -> POT
740: if ( TD(d1) > TD(d2) ) return 1;
741: else if ( TD(d1) < TD(d2) ) return -1;
742: else if ( MPOS(d1) < MPOS(d2) ) return 1;
743: else if ( MPOS(d1) > MPOS(d2) ) return -1;
744: else return ndl_lex_compare(d1,d2);
745: break;
1.1 noro 746:
1.21 noro 747: default:
748: error("ndl_module_glex_compare : invalid module_ordtype");
1.28 ! noro 749: return 0;
1.21 noro 750: }
1.1 noro 751: }
752:
1.21 noro 753: // common for module comparison
754: int ndl_module_compare(UINT *d1,UINT *d2)
1.1 noro 755: {
1.21 noro 756: int c;
1.1 noro 757:
1.21 noro 758: switch ( nd_module_ordtype ) {
759: case 0:
1.23 noro 760: if ( (c = (*ndl_base_compare_function)(d1,d2)) != 0 ) return c;
1.21 noro 761: else if ( MPOS(d1) > MPOS(d2) ) return -1;
762: else if ( MPOS(d1) < MPOS(d2) ) return 1;
763: else return 0;
764: break;
1.1 noro 765:
1.21 noro 766: case 1:
767: if ( MPOS(d1) < MPOS(d2) ) return 1;
768: else if ( MPOS(d1) > MPOS(d2) ) return -1;
769: else return (*ndl_base_compare_function)(d1,d2);
770: break;
1.1 noro 771:
1.21 noro 772: case 2: // weight -> POT
773: if ( TD(d1) > TD(d2) ) return 1;
774: else if ( TD(d1) < TD(d2) ) return -1;
775: else 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: default:
781: error("ndl_module_compare : invalid module_ordtype");
1.28 ! noro 782: return 0;
1.21 noro 783: }
1.1 noro 784: }
785:
1.21 noro 786: extern DMMstack dmm_stack;
787: void _addtodl(int n,DL d1,DL d2);
788: int _eqdl(int n,DL d1,DL d2);
789:
790: int ndl_module_schreyer_compare(UINT *m1,UINT *m2)
791: {
792: int pos1,pos2,t,j;
793: DMM *in;
794: DMMstack s;
795: static DL d1=0;
796: static DL d2=0;
797: static int dlen=0;
798:
799: pos1 = MPOS(m1); pos2 = MPOS(m2);
800: if ( pos1 == pos2 ) return (*ndl_base_compare_function)(m1,m2);
801: if ( nd_nvar > dlen ) {
802: NEWDL(d1,nd_nvar);
803: NEWDL(d2,nd_nvar);
804: dlen = nd_nvar;
805: }
806: d1->td = TD(m1);
807: for ( j = 0; j < nd_nvar; j++ ) d1->d[j] = GET_EXP(m1,j);
808: d2->td = TD(m2);
809: for ( j = 0; j < nd_nvar; j++ ) d2->d[j] = GET_EXP(m2,j);
810: for ( s = dmm_stack; s; s = NEXT(s) ) {
811: in = s->in;
812: _addtodl(nd_nvar,in[pos1]->dl,d1);
813: _addtodl(nd_nvar,in[pos2]->dl,d2);
814: if ( in[pos1]->pos == in[pos2]->pos && _eqdl(nd_nvar,d1,d2)) {
815: if ( pos1 < pos2 ) return 1;
816: else if ( pos1 > pos2 ) return -1;
817: else return 0;
818: }
819: pos1 = in[pos1]->pos;
820: pos2 = in[pos2]->pos;
821: if ( pos1 == pos2 ) return (*dl_base_compare_function)(nd_nvar,d1,d2);
822: }
823: // comparison by the bottom order
824: LAST:
825: switch ( nd_base_ordtype ) {
826: case 0:
827: t = (*dl_base_compare_function)(nd_nvar,d1,d2);
828: if ( t ) return t;
829: else if ( pos1 < pos2 ) return 1;
830: else if ( pos1 > pos2 ) return -1;
831: else return 0;
832: break;
833: case 1:
834: if ( pos1 < pos2 ) return 1;
835: else if ( pos1 > pos2 ) return -1;
836: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
837: break;
838: case 2:
839: if ( d1->td > d2->td ) return 1;
840: else if ( d1->td < d2->td ) return -1;
841: else if ( pos1 < pos2 ) return 1;
842: else if ( pos1 > pos2 ) return -1;
843: else return (*dl_base_compare_function)(nd_nvar,d1,d2);
844: break;
845: default:
846: error("ndl_schreyer_compare : invalid base ordtype");
1.28 ! noro 847: return 0;
1.21 noro 848: }
1.1 noro 849: }
850:
851: INLINE int ndl_equal(UINT *d1,UINT *d2)
852: {
853: int i;
854:
855: switch ( nd_wpd ) {
856: case 2:
857: if ( TD(d2) != TD(d1) ) return 0;
858: if ( d2[1] != d1[1] ) return 0;
859: return 1;
860: break;
861: case 3:
862: if ( TD(d2) != TD(d1) ) return 0;
863: if ( d2[1] != d1[1] ) return 0;
864: if ( d2[2] != d1[2] ) return 0;
865: return 1;
866: break;
867: default:
868: for ( i = 0; i < nd_wpd; i++ )
869: if ( *d1++ != *d2++ ) return 0;
870: return 1;
871: break;
872: }
873: }
874:
875: INLINE void ndl_copy(UINT *d1,UINT *d2)
876: {
877: int i;
878:
879: switch ( nd_wpd ) {
880: case 2:
881: TD(d2) = TD(d1);
882: d2[1] = d1[1];
883: break;
884: case 3:
885: TD(d2) = TD(d1);
886: d2[1] = d1[1];
887: d2[2] = d1[2];
888: break;
889: default:
890: for ( i = 0; i < nd_wpd; i++ )
891: d2[i] = d1[i];
892: break;
893: }
894: }
895:
896: INLINE void ndl_zero(UINT *d)
897: {
898: int i;
899: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
900: }
901:
902: INLINE void ndl_add(UINT *d1,UINT *d2,UINT *d)
903: {
904: int i;
905:
906: if ( nd_module ) {
907: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
908: error("ndl_add : invalid operation");
909: }
910: #if 1
911: switch ( nd_wpd ) {
912: case 2:
913: TD(d) = TD(d1)+TD(d2);
914: d[1] = d1[1]+d2[1];
915: break;
916: case 3:
917: TD(d) = TD(d1)+TD(d2);
918: d[1] = d1[1]+d2[1];
919: d[2] = d1[2]+d2[2];
920: break;
921: default:
922: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
923: break;
924: }
925: #else
926: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]+d2[i];
927: #endif
928: }
929:
930: /* d1 += d2 */
931: INLINE void ndl_addto(UINT *d1,UINT *d2)
932: {
933: int i;
934:
935: if ( nd_module ) {
936: if ( MPOS(d1) && MPOS(d2) && (MPOS(d1) != MPOS(d2)) )
937: error("ndl_addto : invalid operation");
938: }
939: #if 1
940: switch ( nd_wpd ) {
941: case 2:
942: TD(d1) += TD(d2);
943: d1[1] += d2[1];
944: break;
945: case 3:
946: TD(d1) += TD(d2);
947: d1[1] += d2[1];
948: d1[2] += d2[2];
949: break;
950: default:
951: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
952: break;
953: }
954: #else
955: for ( i = 0; i < nd_wpd; i++ ) d1[i] += d2[i];
956: #endif
957: }
958:
959: INLINE void ndl_sub(UINT *d1,UINT *d2,UINT *d)
960: {
961: int i;
962:
963: for ( i = 0; i < nd_wpd; i++ ) d[i] = d1[i]-d2[i];
964: }
965:
966: int ndl_disjoint(UINT *d1,UINT *d2)
967: {
968: UINT t1,t2,u,u1,u2;
969: int i,j;
970:
971: if ( nd_module && (MPOS(d1) == MPOS(d2)) ) return 0;
972: #if USE_UNROLL
973: switch ( nd_bpe ) {
974: case 3:
975: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
976: u1 = d1[i]; u2 = d2[i];
977: t1 = u1&0x38000000; t2 = u2&0x38000000; if ( t1&&t2 ) return 0;
978: t1 = u1& 0x7000000; t2 = u2& 0x7000000; if ( t1&&t2 ) return 0;
979: t1 = u1& 0xe00000; t2 = u2& 0xe00000; if ( t1&&t2 ) return 0;
980: t1 = u1& 0x1c0000; t2 = u2& 0x1c0000; if ( t1&&t2 ) return 0;
981: t1 = u1& 0x38000; t2 = u2& 0x38000; if ( t1&&t2 ) return 0;
982: t1 = u1& 0x7000; t2 = u2& 0x7000; if ( t1&&t2 ) return 0;
983: t1 = u1& 0xe00; t2 = u2& 0xe00; if ( t1&&t2 ) return 0;
984: t1 = u1& 0x1c0; t2 = u2& 0x1c0; if ( t1&&t2 ) return 0;
985: t1 = u1& 0x38; t2 = u2& 0x38; if ( t1&&t2 ) return 0;
986: t1 = u1& 0x7; t2 = u2& 0x7; if ( t1&&t2 ) return 0;
987: }
988: return 1;
989: break;
990: case 4:
991: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
992: u1 = d1[i]; u2 = d2[i];
993: t1 = u1&0xf0000000; t2 = u2&0xf0000000; if ( t1&&t2 ) return 0;
994: t1 = u1& 0xf000000; t2 = u2& 0xf000000; if ( t1&&t2 ) return 0;
995: t1 = u1& 0xf00000; t2 = u2& 0xf00000; if ( t1&&t2 ) return 0;
996: t1 = u1& 0xf0000; t2 = u2& 0xf0000; if ( t1&&t2 ) return 0;
997: t1 = u1& 0xf000; t2 = u2& 0xf000; if ( t1&&t2 ) return 0;
998: t1 = u1& 0xf00; t2 = u2& 0xf00; if ( t1&&t2 ) return 0;
999: t1 = u1& 0xf0; t2 = u2& 0xf0; if ( t1&&t2 ) return 0;
1000: t1 = u1& 0xf; t2 = u2& 0xf; if ( t1&&t2 ) return 0;
1001: }
1002: return 1;
1003: break;
1004: case 6:
1005: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1006: u1 = d1[i]; u2 = d2[i];
1007: t1 = u1&0x3f000000; t2 = u2&0x3f000000; if ( t1&&t2 ) return 0;
1008: t1 = u1& 0xfc0000; t2 = u2& 0xfc0000; if ( t1&&t2 ) return 0;
1009: t1 = u1& 0x3f000; t2 = u2& 0x3f000; if ( t1&&t2 ) return 0;
1010: t1 = u1& 0xfc0; t2 = u2& 0xfc0; if ( t1&&t2 ) return 0;
1011: t1 = u1& 0x3f; t2 = u2& 0x3f; if ( t1&&t2 ) return 0;
1012: }
1013: return 1;
1014: break;
1015: case 8:
1016: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1017: u1 = d1[i]; u2 = d2[i];
1018: t1 = u1&0xff000000; t2 = u2&0xff000000; if ( t1&&t2 ) return 0;
1019: t1 = u1& 0xff0000; t2 = u2& 0xff0000; if ( t1&&t2 ) return 0;
1020: t1 = u1& 0xff00; t2 = u2& 0xff00; if ( t1&&t2 ) return 0;
1021: t1 = u1& 0xff; t2 = u2& 0xff; if ( t1&&t2 ) return 0;
1022: }
1023: return 1;
1024: break;
1025: case 16:
1026: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1027: u1 = d1[i]; u2 = d2[i];
1028: t1 = u1&0xffff0000; t2 = u2&0xffff0000; if ( t1&&t2 ) return 0;
1029: t1 = u1& 0xffff; t2 = u2& 0xffff; if ( t1&&t2 ) return 0;
1030: }
1031: return 1;
1032: break;
1033: case 32:
1034: for ( i = nd_exporigin; i < nd_wpd; i++ )
1035: if ( d1[i] && d2[i] ) return 0;
1036: return 1;
1037: break;
1038: default:
1039: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1040: u1 = d1[i]; u2 = d2[i];
1041: for ( j = 0; j < nd_epw; j++ ) {
1042: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1043: u1 >>= nd_bpe; u2 >>= nd_bpe;
1044: }
1045: }
1046: return 1;
1047: break;
1048: }
1049: #else
1050: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1051: u1 = d1[i]; u2 = d2[i];
1052: for ( j = 0; j < nd_epw; j++ ) {
1053: if ( (u1&nd_mask0) && (u2&nd_mask0) ) return 0;
1054: u1 >>= nd_bpe; u2 >>= nd_bpe;
1055: }
1056: }
1057: return 1;
1058: #endif
1059: }
1060:
1061: int ndl_check_bound(UINT *d1,UINT *d2)
1062: {
1063: UINT u2;
1064: int i,j,ind,k;
1065:
1066: ind = 0;
1067: #if USE_UNROLL
1068: switch ( nd_bpe ) {
1069: case 3:
1070: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1071: u2 = d2[i];
1072: if ( d1[ind++]+((u2>>27)&0x7) >= 0x8 ) return 1;
1073: if ( d1[ind++]+((u2>>24)&0x7) >= 0x8 ) return 1;
1074: if ( d1[ind++]+((u2>>21)&0x7) >= 0x8 ) return 1;
1075: if ( d1[ind++]+((u2>>18)&0x7) >= 0x8 ) return 1;
1076: if ( d1[ind++]+((u2>>15)&0x7) >= 0x8 ) return 1;
1077: if ( d1[ind++]+((u2>>12)&0x7) >= 0x8 ) return 1;
1078: if ( d1[ind++]+((u2>>9)&0x7) >= 0x8 ) return 1;
1079: if ( d1[ind++]+((u2>>6)&0x7) >= 0x8 ) return 1;
1080: if ( d1[ind++]+((u2>>3)&0x7) >= 0x8 ) return 1;
1081: if ( d1[ind++]+(u2&0x7) >= 0x8 ) return 1;
1082: }
1083: return 0;
1084: break;
1085: case 4:
1086: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1087: u2 = d2[i];
1088: if ( d1[ind++]+((u2>>28)&0xf) >= 0x10 ) return 1;
1089: if ( d1[ind++]+((u2>>24)&0xf) >= 0x10 ) return 1;
1090: if ( d1[ind++]+((u2>>20)&0xf) >= 0x10 ) return 1;
1091: if ( d1[ind++]+((u2>>16)&0xf) >= 0x10 ) return 1;
1092: if ( d1[ind++]+((u2>>12)&0xf) >= 0x10 ) return 1;
1093: if ( d1[ind++]+((u2>>8)&0xf) >= 0x10 ) return 1;
1094: if ( d1[ind++]+((u2>>4)&0xf) >= 0x10 ) return 1;
1095: if ( d1[ind++]+(u2&0xf) >= 0x10 ) return 1;
1096: }
1097: return 0;
1098: break;
1099: case 6:
1100: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1101: u2 = d2[i];
1102: if ( d1[ind++]+((u2>>24)&0x3f) >= 0x40 ) return 1;
1103: if ( d1[ind++]+((u2>>18)&0x3f) >= 0x40 ) return 1;
1104: if ( d1[ind++]+((u2>>12)&0x3f) >= 0x40 ) return 1;
1105: if ( d1[ind++]+((u2>>6)&0x3f) >= 0x40 ) return 1;
1106: if ( d1[ind++]+(u2&0x3f) >= 0x40 ) return 1;
1107: }
1108: return 0;
1109: break;
1110: case 8:
1111: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1112: u2 = d2[i];
1113: if ( d1[ind++]+((u2>>24)&0xff) >= 0x100 ) return 1;
1114: if ( d1[ind++]+((u2>>16)&0xff) >= 0x100 ) return 1;
1115: if ( d1[ind++]+((u2>>8)&0xff) >= 0x100 ) return 1;
1116: if ( d1[ind++]+(u2&0xff) >= 0x100 ) return 1;
1117: }
1118: return 0;
1119: break;
1120: case 16:
1121: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1122: u2 = d2[i];
1123: if ( d1[ind++]+((u2>>16)&0xffff) > 0x10000 ) return 1;
1124: if ( d1[ind++]+(u2&0xffff) > 0x10000 ) return 1;
1125: }
1126: return 0;
1127: break;
1128: case 32:
1129: for ( i = nd_exporigin; i < nd_wpd; i++ )
1130: if ( d1[i]+d2[i]<d1[i] ) return 1;
1131: return 0;
1132: break;
1133: default:
1134: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1135: u2 = d2[i];
1136: k = (nd_epw-1)*nd_bpe;
1137: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1138: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1139: }
1140: return 0;
1141: break;
1142: }
1143: #else
1144: for ( i = nd_exporigin; i < nd_wpd; i++ ) {
1145: u2 = d2[i];
1146: k = (nd_epw-1)*nd_bpe;
1147: for ( j = 0; j < nd_epw; j++, k -= nd_bpe )
1148: if ( d1[ind++]+((u2>>k)&nd_mask0) > nd_mask0 ) return 1;
1149: }
1150: return 0;
1151: #endif
1152: }
1153:
1154: int ndl_check_bound2(int index,UINT *d2)
1155: {
1156: return ndl_check_bound(nd_bound[index],d2);
1157: }
1158:
1159: INLINE int ndl_hash_value(UINT *d)
1160: {
1161: int i;
1.11 noro 1162: UINT r;
1.1 noro 1163:
1164: r = 0;
1165: for ( i = 0; i < nd_wpd; i++ )
1.12 noro 1166: r = (r*1511+d[i]);
1.11 noro 1167: r %= REDTAB_LEN;
1.1 noro 1168: return r;
1169: }
1170:
1171: INLINE int ndl_find_reducer(UINT *dg)
1172: {
1173: RHist r;
1174: int d,k,i;
1175:
1176: d = ndl_hash_value(dg);
1177: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1178: if ( ndl_equal(dg,DL(r)) ) {
1179: if ( k > 0 ) nd_notfirst++;
1180: nd_found++;
1181: return r->index;
1182: }
1183: }
1184: if ( Reverse )
1185: for ( i = nd_psn-1; i >= 0; i-- ) {
1186: r = nd_psh[i];
1187: if ( ndl_reducible(dg,DL(r)) ) {
1188: nd_create++;
1189: nd_append_red(dg,i);
1190: return i;
1191: }
1192: }
1193: else
1194: for ( i = 0; i < nd_psn; i++ ) {
1195: r = nd_psh[i];
1196: if ( ndl_reducible(dg,DL(r)) ) {
1197: nd_create++;
1198: nd_append_red(dg,i);
1199: return i;
1200: }
1201: }
1202: return -1;
1203: }
1204:
1.24 noro 1205: // ret=0,...,nd_psn-1 => reducer found
1206: // ret=nd_psn => reducer not found
1207: // ret=-1 => singular top reducible
1208:
1209: int comp_sig(SIG s1,SIG s2);
1210: void _ndltodl(UINT *ndl,DL dl);
1211:
1212: void print_sig(SIG s)
1213: {
1214: int i;
1215:
1216: fprintf(asir_out,"<<");
1217: for ( i = 0; i < nd_nvar; i++ ) {
1218: fprintf(asir_out,"%d",s->dl->d[i]);
1219: if ( i != nd_nvar-1 ) fprintf(asir_out,",");
1220: }
1221: fprintf(asir_out,">>*e%d",s->pos);
1222: }
1223:
1224: INLINE int ndl_find_reducer_s(UINT *dg,SIG sig)
1225: {
1226: RHist r;
1.27 noro 1227: int i,singular,ret,d,k;
1.26 noro 1228: static int wpd,nvar;
1.24 noro 1229: static SIG quo;
1230: static UINT *tmp;
1231:
1.26 noro 1232: if ( !quo || nvar != nd_nvar ) NEWSIG(quo);
1233: if ( wpd != nd_wpd ) {
1.24 noro 1234: wpd = nd_wpd;
1235: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
1236: }
1.27 noro 1237: d = ndl_hash_value(dg);
1238: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
1239: if ( ndl_equal(dg,DL(r)) ) {
1240: return r->index;
1241: }
1242: }
1.24 noro 1243: singular = 0;
1244: for ( i = 0; i < nd_psn; i++ ) {
1245: r = nd_psh[i];
1246: if ( ndl_reducible(dg,DL(r)) ) {
1.27 noro 1247: ndl_sub(dg,DL(r),tmp);
1.24 noro 1248: _ndltodl(tmp,DL(quo));
1249: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
1250: quo->pos = nd_psh[i]->sig->pos;
1251: ret = comp_sig(sig,quo);
1252: if ( ret > 0 ) { singular = 0; break; }
1253: if ( ret == 0 ) { singular = 1; }
1254: }
1255: }
1256: if ( singular ) return -1;
1.27 noro 1257: else if ( i < nd_psn )
1258: nd_append_red(dg,i);
1259: return i;
1.24 noro 1260: }
1261:
1.1 noro 1262: ND nd_merge(ND p1,ND p2)
1263: {
1264: int n,c;
1265: int t,can,td1,td2;
1266: ND r;
1267: NM m1,m2,mr0,mr,s;
1268:
1269: if ( !p1 ) return p2;
1270: else if ( !p2 ) return p1;
1271: else {
1272: can = 0;
1273: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1274: c = DL_COMPARE(DL(m1),DL(m2));
1275: switch ( c ) {
1276: case 0:
1277: s = m1; m1 = NEXT(m1);
1278: can++; NEXTNM2(mr0,mr,s);
1279: s = m2; m2 = NEXT(m2); FREENM(s);
1280: break;
1281: case 1:
1282: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1283: break;
1284: case -1:
1285: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1286: break;
1287: }
1288: }
1289: if ( !mr0 )
1290: if ( m1 ) mr0 = m1;
1291: else if ( m2 ) mr0 = m2;
1292: else return 0;
1293: else if ( m1 ) NEXT(mr) = m1;
1294: else if ( m2 ) NEXT(mr) = m2;
1295: else NEXT(mr) = 0;
1296: BDY(p1) = mr0;
1297: SG(p1) = MAX(SG(p1),SG(p2));
1298: LEN(p1) = LEN(p1)+LEN(p2)-can;
1299: FREEND(p2);
1300: return p1;
1301: }
1302: }
1303:
1304: ND nd_add(int mod,ND p1,ND p2)
1305: {
1306: int n,c;
1307: int t,can,td1,td2;
1308: ND r;
1309: NM m1,m2,mr0,mr,s;
1310:
1.11 noro 1311: Nnd_add++;
1.1 noro 1312: if ( !p1 ) return p2;
1313: else if ( !p2 ) return p1;
1314: else if ( mod == -1 ) return nd_add_sf(p1,p2);
1315: else if ( mod == -2 ) return nd_add_lf(p1,p2);
1316: else if ( !mod ) return nd_add_q(p1,p2);
1317: else {
1318: can = 0;
1319: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1320: c = DL_COMPARE(DL(m1),DL(m2));
1321: switch ( c ) {
1322: case 0:
1323: t = ((CM(m1))+(CM(m2))) - mod;
1324: if ( t < 0 ) t += mod;
1325: s = m1; m1 = NEXT(m1);
1326: if ( t ) {
1327: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1328: } else {
1329: can += 2; FREENM(s);
1330: }
1331: s = m2; m2 = NEXT(m2); FREENM(s);
1332: break;
1333: case 1:
1334: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1335: break;
1336: case -1:
1337: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1338: break;
1339: }
1340: }
1341: if ( !mr0 )
1342: if ( m1 ) mr0 = m1;
1343: else if ( m2 ) mr0 = m2;
1344: else return 0;
1345: else if ( m1 ) NEXT(mr) = m1;
1346: else if ( m2 ) NEXT(mr) = m2;
1347: else NEXT(mr) = 0;
1348: BDY(p1) = mr0;
1349: SG(p1) = MAX(SG(p1),SG(p2));
1350: LEN(p1) = LEN(p1)+LEN(p2)-can;
1351: FREEND(p2);
1352: return p1;
1353: }
1354: }
1355:
1356: /* XXX on opteron, the inlined manipulation of destructive additon of
1357: * two NM seems to make gcc optimizer get confused, so the part is
1358: * done in a function.
1359: */
1360:
1361: int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr)
1362: {
1363: NM s;
1364: P t;
1365: int can;
1366:
1367: addp(nd_vc,CP(*m1),CP(*m2),&t);
1368: s = *m1; *m1 = NEXT(*m1);
1369: if ( t ) {
1370: can = 1; NEXTNM2(*mr0,*mr,s); CP(*mr) = (t);
1371: } else {
1372: can = 2; FREENM(s);
1373: }
1374: s = *m2; *m2 = NEXT(*m2); FREENM(s);
1375: return can;
1376: }
1377:
1378: ND nd_add_q(ND p1,ND p2)
1379: {
1380: int n,c,can;
1381: ND r;
1382: NM m1,m2,mr0,mr,s;
1383: P t;
1384:
1385: if ( !p1 ) return p2;
1386: else if ( !p2 ) return p1;
1387: else {
1388: can = 0;
1389: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1390: c = DL_COMPARE(DL(m1),DL(m2));
1391: switch ( c ) {
1392: case 0:
1393: #if defined(__x86_64__)
1394: can += nm_destructive_add_q(&m1,&m2,&mr0,&mr);
1395: #else
1396: addp(nd_vc,CP(m1),CP(m2),&t);
1397: s = m1; m1 = NEXT(m1);
1398: if ( t ) {
1399: can++; NEXTNM2(mr0,mr,s); CP(mr) = (t);
1400: } else {
1401: can += 2; FREENM(s);
1402: }
1403: s = m2; m2 = NEXT(m2); FREENM(s);
1404: #endif
1405: break;
1406: case 1:
1407: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1408: break;
1409: case -1:
1410: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1411: break;
1412: }
1413: }
1414: if ( !mr0 )
1415: if ( m1 ) mr0 = m1;
1416: else if ( m2 ) mr0 = m2;
1417: else return 0;
1418: else if ( m1 ) NEXT(mr) = m1;
1419: else if ( m2 ) NEXT(mr) = m2;
1420: else NEXT(mr) = 0;
1421: BDY(p1) = mr0;
1422: SG(p1) = MAX(SG(p1),SG(p2));
1423: LEN(p1) = LEN(p1)+LEN(p2)-can;
1424: FREEND(p2);
1425: return p1;
1426: }
1427: }
1428:
1429: ND nd_add_sf(ND p1,ND p2)
1430: {
1431: int n,c,can;
1432: ND r;
1433: NM m1,m2,mr0,mr,s;
1434: int t;
1435:
1436: if ( !p1 ) return p2;
1437: else if ( !p2 ) return p1;
1438: else {
1439: can = 0;
1440: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
1441: c = DL_COMPARE(DL(m1),DL(m2));
1442: switch ( c ) {
1443: case 0:
1444: t = _addsf(CM(m1),CM(m2));
1445: s = m1; m1 = NEXT(m1);
1446: if ( t ) {
1447: can++; NEXTNM2(mr0,mr,s); CM(mr) = (t);
1448: } else {
1449: can += 2; FREENM(s);
1450: }
1451: s = m2; m2 = NEXT(m2); FREENM(s);
1452: break;
1453: case 1:
1454: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
1455: break;
1456: case -1:
1457: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
1458: break;
1459: }
1460: }
1461: if ( !mr0 )
1462: if ( m1 ) mr0 = m1;
1463: else if ( m2 ) mr0 = m2;
1464: else return 0;
1465: else if ( m1 ) NEXT(mr) = m1;
1466: else if ( m2 ) NEXT(mr) = m2;
1467: else NEXT(mr) = 0;
1468: BDY(p1) = mr0;
1469: SG(p1) = MAX(SG(p1),SG(p2));
1470: LEN(p1) = LEN(p1)+LEN(p2)-can;
1471: FREEND(p2);
1472: return p1;
1473: }
1474: }
1475:
1476:
1477: ND nd_reduce2(int mod,ND d,ND g,NDV p,NM mul,NDC dn,Obj *divp)
1478: {
1479: int c,c1,c2;
1480: Z cg,cred,gcd,tq;
1481: P cgp,credp,gcdp;
1482: Obj tr,tr1;
1483:
1484: if ( mod == -1 ) {
1485: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1486: *divp = (Obj)ONE;
1487: } else if ( mod == -2 ) {
1488: Z inv,t;
1489: divlf(ONE,HCZ(p),&inv);
1490: chsgnlf(HCZ(g),&t);
1491: mullf(inv,t,&CZ(mul));
1492: *divp = (Obj)ONE;
1493: } else if ( mod ) {
1494: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1495: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1496: *divp = (Obj)ONE;
1497: } else if ( nd_vc ) {
1498: ezgcdpz(nd_vc,HCP(g),HCP(p),&gcdp);
1499: divsp(nd_vc,HCP(g),gcdp,&cgp); divsp(nd_vc,HCP(p),gcdp,&credp);
1500: chsgnp(cgp,&CP(mul));
1501: nd_mul_c_q(d,credp); nd_mul_c_q(g,credp);
1502: if ( dn ) {
1503: mulr(nd_vc,(Obj)dn->r,(Obj)credp,&tr);
1504: reductr(nd_vc,tr,&tr1); dn->r = (R)tr1;
1505: }
1506: *divp = (Obj)credp;
1507: } else {
1.6 noro 1508: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1509: chsgnz(cg,&CZ(mul));
1.1 noro 1510: nd_mul_c_q(d,(P)cred); nd_mul_c_q(g,(P)cred);
1511: if ( dn ) {
1512: mulz(dn->z,cred,&tq); dn->z = tq;
1513: }
1514: *divp = (Obj)cred;
1515: }
1516: return nd_add(mod,g,ndv_mul_nm(mod,mul,p));
1517: }
1518:
1519: /* ret=1 : success, ret=0 : overflow */
1.6 noro 1520: int nd_nf(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1.1 noro 1521: {
1522: NM m,mrd,tail;
1523: NM mul;
1524: int n,sugar,psugar,sugar0,stat,index;
1525: int c,c1,c2,dummy;
1526: RHist h;
1527: NDV p,red;
1528: Q cg,cred,gcd,tq,qq;
1529: Z iq;
1530: DP dmul;
1531: NODE node;
1532: LIST hist;
1533: double hmag;
1534: P tp,tp1;
1535: Obj tr,tr1,div;
1536: union oNDC hg;
1537: P cont;
1538:
1539: if ( !g ) {
1540: *rp = d;
1541: return 1;
1542: }
1543: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1544:
1545: sugar0 = sugar = SG(g);
1546: n = NV(g);
1547: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1548: if ( d )
1549: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1550: for ( ; g; ) {
1551: index = ndl_find_reducer(HDL(g));
1552: if ( index >= 0 ) {
1553: h = nd_psh[index];
1554: ndl_sub(HDL(g),DL(h),DL(mul));
1555: if ( ndl_check_bound2(index,DL(mul)) ) {
1556: nd_free(g); nd_free(d);
1557: return 0;
1558: }
1559: p = nd_demand ? ndv_load(index) : ps[index];
1560: /* d+g -> div*(d+g)+mul*p */
1.6 noro 1561: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1.1 noro 1562: if ( nd_gentrace ) {
1563: /* Trace=[div,index,mul,ONE] */
1.6 noro 1564: STOZ(index,iq);
1.1 noro 1565: nmtodp(mod,mul,&dmul);
1566: node = mknode(4,div,iq,dmul,ONE);
1567: }
1568: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1569: if ( !mod && g && !nd_vc && ((double)(p_mag(HCP(g))) > hmag) ) {
1570: hg = HCU(g);
1571: nd_removecont2(d,g);
1.6 noro 1572: if ( nd_gentrace ) {
1.1 noro 1573: /* overwrite cont : Trace=[div,index,mul,cont] */
1.6 noro 1574: /* exact division */
1.1 noro 1575: cont = ndc_div(mod,hg,HCU(g));
1576: if ( nd_gentrace && !UNIQ(cont) ) ARG3(node) = (pointer)cont;
1577: }
1578: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1579: }
1580: MKLIST(hist,node);
1581: MKNODE(node,hist,nd_tracelist); nd_tracelist = node;
1582: } else if ( !full ) {
1583: *rp = g;
1584: return 1;
1585: } else {
1586: m = BDY(g);
1587: if ( NEXT(m) ) {
1588: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1589: } else {
1590: FREEND(g); g = 0;
1591: }
1592: if ( d ) {
1593: NEXT(tail)=m; tail=m; LEN(d)++;
1594: } else {
1595: MKND(n,m,1,d); tail = BDY(d);
1596: }
1597: }
1598: }
1599: if ( d ) SG(d) = sugar;
1600: *rp = d;
1601: return 1;
1602: }
1603:
1.24 noro 1604: // ret=1 => success
1605: // ret=0 => overflow
1606: // ret=-1 => singular top reducible
1607:
1608: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *rp)
1609: {
1610: NM m,mrd,tail;
1611: NM mul;
1612: int n,sugar,psugar,sugar0,stat,index;
1613: int c,c1,c2,dummy;
1614: RHist h;
1615: NDV p,red;
1616: Q cg,cred,gcd,tq,qq;
1617: Z iq;
1618: DP dmul;
1619: NODE node;
1620: LIST hist;
1621: double hmag;
1622: P tp,tp1;
1623: Obj tr,tr1,div;
1624: union oNDC hg;
1625: P cont;
1626: SIG sig;
1627:
1628: if ( !g ) {
1629: *rp = d;
1630: return 1;
1631: }
1632: if ( !mod ) hmag = ((double)p_mag(HCP(g)))*nd_scale;
1633:
1634: sugar0 = sugar = SG(g);
1635: n = NV(g);
1636: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1637: if ( d )
1638: for ( tail = BDY(d); NEXT(tail); tail = NEXT(tail) );
1639: sig = g->sig;
1640: for ( ; g; ) {
1641: index = ndl_find_reducer_s(HDL(g),sig);
1642: if ( index >= 0 && index < nd_psn ) {
1643: // reducer found
1644: h = nd_psh[index];
1645: ndl_sub(HDL(g),DL(h),DL(mul));
1646: if ( ndl_check_bound2(index,DL(mul)) ) {
1647: nd_free(g); nd_free(d);
1648: return 0;
1649: }
1650: p = ps[index];
1651: /* d+g -> div*(d+g)+mul*p */
1652: g = nd_reduce2(mod,d,g,p,mul,0,&div);
1653: sugar = MAX(sugar,SG(p)+TD(DL(mul)));
1654: if ( !mod && g && ((double)(p_mag(HCP(g))) > hmag) ) {
1655: hg = HCU(g);
1656: nd_removecont2(d,g);
1657: hmag = ((double)p_mag(HCP(g)))*nd_scale;
1658: }
1659: } else if ( index == -1 ) {
1660: // singular top reducible
1661: return -1;
1662: } else if ( !full ) {
1663: *rp = g;
1664: g->sig = sig;
1665: return 1;
1666: } else {
1667: m = BDY(g);
1668: if ( NEXT(m) ) {
1669: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1670: } else {
1671: FREEND(g); g = 0;
1672: }
1673: if ( d ) {
1674: NEXT(tail)=m; tail=m; LEN(d)++;
1675: } else {
1676: MKND(n,m,1,d); tail = BDY(d);
1677: }
1678: }
1679: }
1680: if ( d ) {
1681: SG(d) = sugar;
1682: d->sig = sig;
1683: }
1684: *rp = d;
1685: return 1;
1686: }
1687:
1.1 noro 1688: int nd_nf_pbucket(int mod,ND g,NDV *ps,int full,ND *rp)
1689: {
1690: int hindex,index;
1691: NDV p;
1692: ND u,d,red;
1693: NODE l;
1694: NM mul,m,mrd,tail;
1695: int sugar,psugar,n,h_reducible;
1696: PGeoBucket bucket;
1697: int c,c1,c2;
1698: Z cg,cred,gcd,zzz;
1699: RHist h;
1700: double hmag,gmag;
1701: int count = 0;
1702: int hcount = 0;
1703:
1704: if ( !g ) {
1705: *rp = 0;
1706: return 1;
1707: }
1708: sugar = SG(g);
1709: n = NV(g);
1.6 noro 1710: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1711: bucket = create_pbucket();
1712: add_pbucket(mod,bucket,g);
1713: d = 0;
1714: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1715: while ( 1 ) {
1716: if ( mod > 0 || mod == -1 )
1717: hindex = head_pbucket(mod,bucket);
1718: else if ( mod == -2 )
1719: hindex = head_pbucket_lf(bucket);
1720: else
1721: hindex = head_pbucket_q(bucket);
1722: if ( hindex < 0 ) {
1723: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1724: if ( d ) SG(d) = sugar;
1725: *rp = d;
1726: return 1;
1727: }
1728: g = bucket->body[hindex];
1729: index = ndl_find_reducer(HDL(g));
1730: if ( index >= 0 ) {
1731: count++;
1732: if ( !d ) hcount++;
1733: h = nd_psh[index];
1734: ndl_sub(HDL(g),DL(h),DL(mul));
1735: if ( ndl_check_bound2(index,DL(mul)) ) {
1736: nd_free(d);
1737: free_pbucket(bucket);
1738: *rp = 0;
1739: return 0;
1740: }
1741: p = ps[index];
1742: if ( mod == -1 )
1743: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1744: else if ( mod == -2 ) {
1745: Z inv,t;
1746: divlf(ONE,HCZ(p),&inv);
1747: chsgnlf(HCZ(g),&t);
1748: mullf(inv,t,&CZ(mul));
1749: } else if ( mod ) {
1750: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1751: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1752: } else {
1.6 noro 1753: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1754: chsgnz(cg,&CZ(mul));
1.1 noro 1755: nd_mul_c_q(d,(P)cred);
1756: mulq_pbucket(bucket,cred);
1757: g = bucket->body[hindex];
1.6 noro 1758: gmag = (double)p_mag((P)HCZ(g));
1.1 noro 1759: }
1760: red = ndv_mul_nm(mod,mul,p);
1761: bucket->body[hindex] = nd_remove_head(g);
1762: red = nd_remove_head(red);
1763: add_pbucket(mod,bucket,red);
1764: psugar = SG(p)+TD(DL(mul));
1765: sugar = MAX(sugar,psugar);
1766: if ( !mod && hmag && (gmag > hmag) ) {
1767: g = normalize_pbucket(mod,bucket);
1768: if ( !g ) {
1769: if ( d ) SG(d) = sugar;
1770: *rp = d;
1771: return 1;
1772: }
1773: nd_removecont2(d,g);
1.6 noro 1774: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1.1 noro 1775: add_pbucket(mod,bucket,g);
1776: }
1777: } else if ( !full ) {
1778: g = normalize_pbucket(mod,bucket);
1779: if ( g ) SG(g) = sugar;
1780: *rp = g;
1781: return 1;
1782: } else {
1783: m = BDY(g);
1784: if ( NEXT(m) ) {
1785: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1786: } else {
1787: FREEND(g); g = 0;
1788: }
1789: bucket->body[hindex] = g;
1790: NEXT(m) = 0;
1791: if ( d ) {
1792: NEXT(tail)=m; tail=m; LEN(d)++;
1793: } else {
1794: MKND(n,m,1,d); tail = BDY(d);
1795: }
1796: }
1797: }
1798: }
1799:
1.25 noro 1800: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *rp)
1801: {
1802: int hindex,index;
1803: NDV p;
1804: ND u,d,red;
1805: NODE l;
1806: NM mul,m,mrd,tail;
1807: int sugar,psugar,n,h_reducible;
1808: PGeoBucket bucket;
1809: int c,c1,c2;
1810: Z cg,cred,gcd,zzz;
1811: RHist h;
1812: double hmag,gmag;
1813: int count = 0;
1814: int hcount = 0;
1815: SIG sig;
1816:
1817: if ( !g ) {
1818: *rp = 0;
1819: return 1;
1820: }
1821: sugar = SG(g);
1822: n = NV(g);
1823: if ( !mod ) hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1824: bucket = create_pbucket();
1825: add_pbucket(mod,bucket,g);
1826: d = 0;
1827: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
1828: sig = g->sig;
1829: while ( 1 ) {
1830: if ( mod > 0 || mod == -1 )
1831: hindex = head_pbucket(mod,bucket);
1832: else if ( mod == -2 )
1833: hindex = head_pbucket_lf(bucket);
1834: else
1835: hindex = head_pbucket_q(bucket);
1836: if ( hindex < 0 ) {
1837: if ( DP_Print > 3 ) printf("(%d %d)",count,hcount);
1838: if ( d ) {
1839: SG(d) = sugar;
1840: d->sig = sig;
1841: }
1842: *rp = d;
1843: return 1;
1844: }
1845: g = bucket->body[hindex];
1846: index = ndl_find_reducer_s(HDL(g),sig);
1847: if ( index >= 0 && index < nd_psn ) {
1848: count++;
1849: if ( !d ) hcount++;
1850: h = nd_psh[index];
1851: ndl_sub(HDL(g),DL(h),DL(mul));
1852: if ( ndl_check_bound2(index,DL(mul)) ) {
1853: nd_free(d);
1854: free_pbucket(bucket);
1855: *rp = 0;
1856: return 0;
1857: }
1858: p = ps[index];
1859: if ( mod == -1 )
1860: CM(mul) = _mulsf(_invsf(HCM(p)),_chsgnsf(HCM(g)));
1861: else if ( mod == -2 ) {
1862: Z inv,t;
1863: divlf(ONE,HCZ(p),&inv);
1864: chsgnlf(HCZ(g),&t);
1865: mullf(inv,t,&CZ(mul));
1866: } else if ( mod ) {
1867: c1 = invm(HCM(p),mod); c2 = mod-HCM(g);
1868: DMAR(c1,c2,0,mod,c); CM(mul) = c;
1869: } else {
1870: igcd_cofactor(HCZ(g),HCZ(p),&gcd,&cg,&cred);
1871: chsgnz(cg,&CZ(mul));
1872: nd_mul_c_q(d,(P)cred);
1873: mulq_pbucket(bucket,cred);
1874: g = bucket->body[hindex];
1875: gmag = (double)p_mag((P)HCZ(g));
1876: }
1877: red = ndv_mul_nm(mod,mul,p);
1878: bucket->body[hindex] = nd_remove_head(g);
1879: red = nd_remove_head(red);
1880: add_pbucket(mod,bucket,red);
1881: psugar = SG(p)+TD(DL(mul));
1882: sugar = MAX(sugar,psugar);
1883: if ( !mod && hmag && (gmag > hmag) ) {
1884: g = normalize_pbucket(mod,bucket);
1885: if ( !g ) {
1886: if ( d ) {
1887: SG(d) = sugar;
1888: d->sig = sig;
1889: }
1890: *rp = d;
1891: return 1;
1892: }
1893: nd_removecont2(d,g);
1894: hmag = ((double)p_mag((P)HCZ(g)))*nd_scale;
1895: add_pbucket(mod,bucket,g);
1896: }
1897: } else if ( index == -1 ) {
1898: // singular top reducible
1899: return -1;
1900: } else if ( !full ) {
1901: g = normalize_pbucket(mod,bucket);
1902: if ( g ) {
1903: SG(g) = sugar;
1904: g->sig = sig;
1905: }
1906: *rp = g;
1907: return 1;
1908: } else {
1909: m = BDY(g);
1910: if ( NEXT(m) ) {
1911: BDY(g) = NEXT(m); NEXT(m) = 0; LEN(g)--;
1912: } else {
1913: FREEND(g); g = 0;
1914: }
1915: bucket->body[hindex] = g;
1916: NEXT(m) = 0;
1917: if ( d ) {
1918: NEXT(tail)=m; tail=m; LEN(d)++;
1919: } else {
1920: MKND(n,m,1,d); tail = BDY(d);
1921: }
1922: }
1923: }
1924: }
1925:
1.1 noro 1926: /* input : list of NDV, cand : list of NDV */
1927:
1928: int ndv_check_membership(int m,NODE input,int obpe,int oadv,EPOS oepos,NODE cand)
1929: {
1930: int n,i,stat;
1931: ND nf,d;
1932: NDV r;
1933: NODE t,s;
1934: union oNDC dn;
1935: Z q;
1936: LIST list;
1937:
1.24 noro 1938: ndv_setup(m,0,cand,nd_gentrace?1:0,1,0);
1.1 noro 1939: n = length(cand);
1940:
1941: if ( nd_gentrace ) { nd_alltracelist = 0; nd_tracelist = 0; }
1942: /* membercheck : list is a subset of Id(cand) ? */
1943: for ( t = input, i = 0; t; t = NEXT(t), i++ ) {
1944: again:
1945: nd_tracelist = 0;
1946: if ( nd_bpe > obpe )
1947: r = ndv_dup_realloc((NDV)BDY(t),obpe,oadv,oepos);
1948: else
1949: r = (NDV)BDY(t);
1950: #if 0
1951: // moved to nd_f4_lf_trace()
1952: if ( m == -2 ) ndv_mod(m,r);
1953: #endif
1954: d = ndvtond(m,r);
1.6 noro 1955: stat = nd_nf(m,0,d,nd_ps,0,&nf);
1.1 noro 1956: if ( !stat ) {
1957: nd_reconstruct(0,0);
1958: goto again;
1959: } else if ( nf ) return 0;
1960: if ( nd_gentrace ) {
1961: nd_tracelist = reverse_node(nd_tracelist);
1962: MKLIST(list,nd_tracelist);
1.6 noro 1963: STOZ(i,q); s = mknode(2,q,list); MKLIST(list,s);
1.1 noro 1964: MKNODE(s,list,nd_alltracelist);
1965: nd_alltracelist = s; nd_tracelist = 0;
1966: }
1967: if ( DP_Print ) { printf("."); fflush(stdout); }
1968: }
1969: if ( DP_Print ) { printf("\n"); }
1970: return 1;
1971: }
1972:
1973: ND nd_remove_head(ND p)
1974: {
1975: NM m;
1976:
1977: m = BDY(p);
1978: if ( !NEXT(m) ) {
1979: FREEND(p); p = 0;
1980: } else {
1981: BDY(p) = NEXT(m); LEN(p)--;
1982: }
1983: FREENM(m);
1984: return p;
1985: }
1986:
1987: ND nd_separate_head(ND p,ND *head)
1988: {
1989: NM m,m0;
1990: ND r;
1991:
1992: m = BDY(p);
1993: if ( !NEXT(m) ) {
1994: *head = p; p = 0;
1995: } else {
1996: m0 = m;
1997: BDY(p) = NEXT(m); LEN(p)--;
1998: NEXT(m0) = 0;
1999: MKND(NV(p),m0,1,r);
2000: *head = r;
2001: }
2002: return p;
2003: }
2004:
2005: PGeoBucket create_pbucket()
2006: {
2007: PGeoBucket g;
2008:
2009: g = CALLOC(1,sizeof(struct oPGeoBucket));
2010: g->m = -1;
2011: return g;
2012: }
2013:
2014: void free_pbucket(PGeoBucket b) {
2015: int i;
2016:
2017: for ( i = 0; i <= b->m; i++ )
2018: if ( b->body[i] ) {
2019: nd_free(b->body[i]);
2020: b->body[i] = 0;
2021: }
2022: GCFREE(b);
2023: }
2024:
2025: void add_pbucket_symbolic(PGeoBucket g,ND d)
2026: {
2027: int l,i,k,m;
2028:
2029: if ( !d )
2030: return;
2031: l = LEN(d);
2032: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2033: /* 2^(k-1) < l <= 2^k (=m) */
2034: d = nd_merge(g->body[k],d);
2035: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2036: g->body[k] = 0;
2037: d = nd_merge(g->body[k+1],d);
2038: }
2039: g->body[k] = d;
2040: g->m = MAX(g->m,k);
2041: }
2042:
2043: void add_pbucket(int mod,PGeoBucket g,ND d)
2044: {
2045: int l,i,k,m;
2046:
2047: if ( !d )
2048: return;
2049: l = LEN(d);
2050: for ( k = 0, m = 1; l > m; k++, m <<= 1 );
2051: /* 2^(k-1) < l <= 2^k (=m) */
2052: d = nd_add(mod,g->body[k],d);
2053: for ( ; d && LEN(d) > m; k++, m <<= 1 ) {
2054: g->body[k] = 0;
2055: d = nd_add(mod,g->body[k+1],d);
2056: }
2057: g->body[k] = d;
2058: g->m = MAX(g->m,k);
2059: }
2060:
2061: void mulq_pbucket(PGeoBucket g,Z c)
2062: {
2063: int k;
2064:
2065: for ( k = 0; k <= g->m; k++ )
2066: nd_mul_c_q(g->body[k],(P)c);
2067: }
2068:
2069: NM remove_head_pbucket_symbolic(PGeoBucket g)
2070: {
2071: int j,i,k,c;
2072: NM head;
2073:
2074: k = g->m;
2075: j = -1;
2076: for ( i = 0; i <= k; i++ ) {
2077: if ( !g->body[i] ) continue;
2078: if ( j < 0 ) j = i;
2079: else {
2080: c = DL_COMPARE(HDL(g->body[i]),HDL(g->body[j]));
2081: if ( c > 0 )
2082: j = i;
2083: else if ( c == 0 )
2084: g->body[i] = nd_remove_head(g->body[i]);
2085: }
2086: }
2087: if ( j < 0 ) return 0;
2088: else {
2089: head = BDY(g->body[j]);
2090: if ( !NEXT(head) ) {
2091: FREEND(g->body[j]);
2092: g->body[j] = 0;
2093: } else {
2094: BDY(g->body[j]) = NEXT(head);
2095: LEN(g->body[j])--;
2096: }
2097: return head;
2098: }
2099: }
2100:
2101: int head_pbucket(int mod,PGeoBucket g)
2102: {
2103: int j,i,c,k,nv,sum;
2104: UINT *di,*dj;
2105: ND gi,gj;
2106:
2107: k = g->m;
2108: while ( 1 ) {
2109: j = -1;
2110: for ( i = 0; i <= k; i++ ) {
2111: if ( !(gi = g->body[i]) )
2112: continue;
2113: if ( j < 0 ) {
2114: j = i;
2115: gj = g->body[j];
2116: dj = HDL(gj);
2117: sum = HCM(gj);
2118: } else {
2119: c = DL_COMPARE(HDL(gi),dj);
2120: if ( c > 0 ) {
2121: if ( sum ) HCM(gj) = sum;
2122: else g->body[j] = nd_remove_head(gj);
2123: j = i;
2124: gj = g->body[j];
2125: dj = HDL(gj);
2126: sum = HCM(gj);
2127: } else if ( c == 0 ) {
2128: if ( mod == -1 )
2129: sum = _addsf(sum,HCM(gi));
2130: else {
2131: sum = sum+HCM(gi)-mod;
2132: if ( sum < 0 ) sum += mod;
2133: }
2134: g->body[i] = nd_remove_head(gi);
2135: }
2136: }
2137: }
2138: if ( j < 0 ) return -1;
2139: else if ( sum ) {
2140: HCM(gj) = sum;
2141: return j;
2142: } else
2143: g->body[j] = nd_remove_head(gj);
2144: }
2145: }
2146:
2147: int head_pbucket_q(PGeoBucket g)
2148: {
2149: int j,i,c,k,nv;
2150: Z sum,t;
2151: ND gi,gj;
2152:
2153: k = g->m;
2154: while ( 1 ) {
2155: j = -1;
2156: for ( i = 0; i <= k; i++ ) {
2157: if ( !(gi = g->body[i]) ) continue;
2158: if ( j < 0 ) {
2159: j = i;
2160: gj = g->body[j];
1.6 noro 2161: sum = HCZ(gj);
1.1 noro 2162: } else {
2163: nv = NV(gi);
2164: c = DL_COMPARE(HDL(gi),HDL(gj));
2165: if ( c > 0 ) {
1.6 noro 2166: if ( sum ) HCZ(gj) = sum;
1.1 noro 2167: else g->body[j] = nd_remove_head(gj);
2168: j = i;
2169: gj = g->body[j];
1.6 noro 2170: sum = HCZ(gj);
1.1 noro 2171: } else if ( c == 0 ) {
1.6 noro 2172: addz(sum,HCZ(gi),&t);
1.1 noro 2173: sum = t;
2174: g->body[i] = nd_remove_head(gi);
2175: }
2176: }
2177: }
2178: if ( j < 0 ) return -1;
2179: else if ( sum ) {
1.6 noro 2180: HCZ(gj) = sum;
1.1 noro 2181: return j;
2182: } else
2183: g->body[j] = nd_remove_head(gj);
2184: }
2185: }
2186:
2187: int head_pbucket_lf(PGeoBucket g)
2188: {
2189: int j,i,c,k,nv;
2190: Z sum,t;
2191: ND gi,gj;
2192:
2193: k = g->m;
2194: while ( 1 ) {
2195: j = -1;
2196: for ( i = 0; i <= k; i++ ) {
2197: if ( !(gi = g->body[i]) ) continue;
2198: if ( j < 0 ) {
2199: j = i;
2200: gj = g->body[j];
2201: sum = HCZ(gj);
2202: } else {
2203: nv = NV(gi);
2204: c = DL_COMPARE(HDL(gi),HDL(gj));
2205: if ( c > 0 ) {
2206: if ( sum ) HCZ(gj) = sum;
2207: else g->body[j] = nd_remove_head(gj);
2208: j = i;
2209: gj = g->body[j];
2210: sum = HCZ(gj);
2211: } else if ( c == 0 ) {
2212: addlf(sum,HCZ(gi),&t);
2213: sum = t;
2214: g->body[i] = nd_remove_head(gi);
2215: }
2216: }
2217: }
2218: if ( j < 0 ) return -1;
2219: else if ( sum ) {
2220: HCZ(gj) = sum;
2221: return j;
2222: } else
2223: g->body[j] = nd_remove_head(gj);
2224: }
2225: }
2226:
2227: ND normalize_pbucket(int mod,PGeoBucket g)
2228: {
2229: int i;
2230: ND r,t;
2231:
2232: r = 0;
2233: for ( i = 0; i <= g->m; i++ ) {
2234: r = nd_add(mod,r,g->body[i]);
2235: g->body[i] = 0;
2236: }
2237: g->m = -1;
2238: return r;
2239: }
2240:
2241: #if 0
2242: void register_hcf(NDV p)
2243: {
2244: DCP dc,t;
2245: P hc,h;
2246: int c;
2247: NODE l,l1,prev;
2248:
2249: hc = p->body->c.p;
2250: if ( !nd_vc || NUM(hc) ) return;
2251: fctrp(nd_vc,hc,&dc);
2252: for ( t = dc; t; t = NEXT(t) ) {
2253: h = t->c;
2254: if ( NUM(h) ) continue;
2255: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2256: c = compp(nd_vc,h,(P)BDY(l));
2257: if ( c >= 0 ) break;
2258: }
2259: if ( !l || c > 0 ) {
2260: MKNODE(l1,h,l);
2261: if ( !prev )
2262: nd_hcf = l1;
2263: else
2264: NEXT(prev) = l1;
2265: }
2266: }
2267: }
2268: #else
2269: void register_hcf(NDV p)
2270: {
2271: DCP dc,t;
2272: P hc,h,q;
2273: Q dmy;
2274: int c;
2275: NODE l,l1,prev;
2276:
2277: hc = p->body->c.p;
2278: if ( NUM(hc) ) return;
2279: ptozp(hc,1,&dmy,&h);
2280: #if 1
2281: for ( l = nd_hcf; l; l = NEXT(l) ) {
2282: while ( 1 ) {
2283: if ( divtpz(nd_vc,h,(P)BDY(l),&q) ) h = q;
2284: else break;
2285: }
2286: }
2287: if ( NUM(h) ) return;
2288: #endif
2289: for ( prev = 0, l = nd_hcf; l; prev = l, l = NEXT(l) ) {
2290: c = compp(nd_vc,h,(P)BDY(l));
2291: if ( c >= 0 ) break;
2292: }
2293: if ( !l || c > 0 ) {
2294: MKNODE(l1,h,l);
2295: if ( !prev )
2296: nd_hcf = l1;
2297: else
2298: NEXT(prev) = l1;
2299: }
2300: }
2301: #endif
2302:
2303: int do_diagonalize(int sugar,int m)
2304: {
1.6 noro 2305: int i,nh,stat;
2306: NODE r,g,t;
2307: ND h,nf,s,head;
2308: NDV nfv;
2309: Q q;
2310: P nm,nmp,dn,mnp,dnp,cont,cont1;
2311: union oNDC hc;
2312: NODE node;
2313: LIST l;
2314: Z iq;
1.1 noro 2315:
1.6 noro 2316: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2317: if ( nd_gentrace ) {
2318: /* Trace = [1,index,1,1] */
2319: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2320: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2321: }
2322: if ( nd_demand )
2323: nfv = ndv_load(i);
2324: else
2325: nfv = nd_ps[i];
2326: s = ndvtond(m,nfv);
2327: s = nd_separate_head(s,&head);
2328: stat = nd_nf(m,head,s,nd_ps,1,&nf);
2329: if ( !stat ) return 0;
2330: ndv_free(nfv);
2331: hc = HCU(nf); nd_removecont(m,nf);
2332: /* exact division */
2333: cont = ndc_div(m,hc,HCU(nf));
1.1 noro 2334: if ( nd_gentrace ) finalize_tracelist(i,cont);
1.6 noro 2335: nfv = ndtondv(m,nf);
2336: nd_free(nf);
2337: nd_bound[i] = ndv_compute_bound(nfv);
2338: if ( !m ) register_hcf(nfv);
2339: if ( nd_demand ) {
2340: ndv_save(nfv,i);
2341: ndv_free(nfv);
2342: } else
2343: nd_ps[i] = nfv;
2344: }
2345: return 1;
1.1 noro 2346: }
2347:
2348: LIST compute_splist()
2349: {
2350: NODE g,tn0,tn,node;
2351: LIST l0;
2352: ND_pairs d,t;
2353: int i;
2354: Z i1,i2;
2355:
2356: g = 0; d = 0;
2357: for ( i = 0; i < nd_psn; i++ ) {
2358: d = update_pairs(d,g,i,0);
2359: g = update_base(g,i);
2360: }
2361: for ( t = d, tn0 = 0; t; t = NEXT(t) ) {
2362: NEXTNODE(tn0,tn);
1.6 noro 2363: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 2364: node = mknode(2,i1,i2); MKLIST(l0,node);
2365: BDY(tn) = l0;
2366: }
2367: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
2368: return l0;
2369: }
2370:
2371: /* return value = 0 => input is not a GB */
2372:
2373: NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,int **indp)
2374: {
1.6 noro 2375: int i,nh,sugar,stat;
2376: NODE r,g,t;
2377: ND_pairs d;
2378: ND_pairs l;
2379: ND h,nf,s,head,nf1;
2380: NDV nfv;
2381: Z q;
2382: union oNDC dn,hc;
2383: int diag_count = 0;
2384: P cont;
2385: LIST list;
1.27 noro 2386: struct oEGT eg1,eg2,eg_update;
1.6 noro 2387:
1.27 noro 2388: init_eg(&eg_update);
1.11 noro 2389: Nnd_add = 0;
1.6 noro 2390: g = 0; d = 0;
2391: for ( i = 0; i < nd_psn; i++ ) {
2392: d = update_pairs(d,g,i,gensyz);
2393: g = update_base(g,i);
2394: }
2395: sugar = 0;
2396: while ( d ) {
1.1 noro 2397: again:
1.6 noro 2398: l = nd_minp(d,&d);
2399: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2400: if ( SG(l) != sugar ) {
2401: if ( ishomo ) {
2402: diag_count = 0;
2403: stat = do_diagonalize(sugar,m);
1.1 noro 2404: if ( !stat ) {
1.6 noro 2405: NEXT(l) = d; d = l;
2406: d = nd_reconstruct(0,d);
2407: goto again;
1.1 noro 2408: }
1.6 noro 2409: }
2410: sugar = SG(l);
2411: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2412: }
2413: stat = nd_sp(m,0,l,&h);
2414: if ( !stat ) {
2415: NEXT(l) = d; d = l;
2416: d = nd_reconstruct(0,d);
2417: goto again;
2418: }
1.1 noro 2419: #if USE_GEOBUCKET
1.6 noro 2420: stat = (m&&!nd_gentrace)?nd_nf_pbucket(m,h,nd_ps,!Top,&nf)
2421: :nd_nf(m,0,h,nd_ps,!Top,&nf);
1.1 noro 2422: #else
1.6 noro 2423: stat = nd_nf(m,0,h,nd_ps,!Top,&nf);
1.1 noro 2424: #endif
1.6 noro 2425: if ( !stat ) {
2426: NEXT(l) = d; d = l;
2427: d = nd_reconstruct(0,d);
2428: goto again;
2429: } else if ( nf ) {
2430: if ( checkonly || gensyz ) return 0;
1.1 noro 2431: if ( nd_newelim ) {
2432: if ( nd_module ) {
2433: if ( MPOS(HDL(nf)) > 1 ) return 0;
2434: } else if ( !(HDL(nf)[nd_exporigin] & nd_mask[0]) ) return 0;
2435: }
1.6 noro 2436: if ( DP_Print ) { printf("+"); fflush(stdout); }
2437: hc = HCU(nf);
2438: nd_removecont(m,nf);
2439: if ( !m && nd_nalg ) {
2440: nd_monic(0,&nf);
2441: nd_removecont(m,nf);
2442: }
2443: if ( nd_gentrace ) {
2444: /* exact division */
1.1 noro 2445: cont = ndc_div(m,hc,HCU(nf));
2446: if ( m || !UNIQ(cont) ) {
1.6 noro 2447: t = mknode(4,NULLP,NULLP,NULLP,cont);
2448: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
1.1 noro 2449: nd_tracelist = t;
2450: }
2451: }
1.6 noro 2452: nfv = ndtondv(m,nf); nd_free(nf);
1.24 noro 2453: nh = ndv_newps(m,nfv,0);
1.6 noro 2454: if ( !m && (ishomo && ++diag_count == diag_period) ) {
2455: diag_count = 0;
2456: stat = do_diagonalize(sugar,m);
2457: if ( !stat ) {
2458: NEXT(l) = d; d = l;
2459: d = nd_reconstruct(1,d);
2460: goto again;
1.1 noro 2461: }
1.6 noro 2462: }
1.27 noro 2463: get_eg(&eg1);
1.6 noro 2464: d = update_pairs(d,g,nh,0);
1.27 noro 2465: get_eg(&eg2); add_eg(&eg_update,&eg1,&eg2);
1.6 noro 2466: g = update_base(g,nh);
2467: FREENDP(l);
2468: } else {
2469: if ( nd_gentrace && gensyz ) {
2470: nd_tracelist = reverse_node(nd_tracelist);
2471: MKLIST(list,nd_tracelist);
2472: STOZ(-1,q); t = mknode(2,q,list); MKLIST(list,t);
2473: MKNODE(t,list,nd_alltracelist);
2474: nd_alltracelist = t; nd_tracelist = 0;
2475: }
2476: if ( DP_Print ) { printf("."); fflush(stdout); }
2477: FREENDP(l);
2478: }
2479: }
2480: conv_ilist(nd_demand,0,g,indp);
1.11 noro 2481: if ( !checkonly && DP_Print ) { printf("nd_gb done. Number of nd_add=%d\n",Nnd_add); fflush(stdout); }
1.27 noro 2482: print_eg("update",&eg_update);
1.1 noro 2483: return g;
2484: }
2485:
1.24 noro 2486: ND_pairs update_pairs_s(ND_pairs d,NODE g,int t,NODE syz);
2487: ND_pairs nd_newpairs_s( NODE g, int t ,NODE syz);
2488:
2489: int nd_nf_pbucket_s(int mod,ND g,NDV *ps,int full,ND *nf);
2490: int nd_nf_s(int mod,ND d,ND g,NDV *ps,int full,ND *nf);
2491:
2492: void _copydl(int n,DL d1,DL d2);
2493: void _subfromdl(int n,DL d1,DL d2);
2494: extern int (*cmpdl)(int n,DL d1,DL d2);
2495:
2496: NODE insert_sig(NODE l,SIG s)
2497: {
2498: int pos;
2499: DL sig;
2500: struct oNODE root;
2501: NODE p,prev,r;
2502: SIG t;
2503:
2504: pos = s->pos; sig = DL(s);
2505: root.next = l; prev = &root;
2506: for ( p = l; p; p = p->next ) {
2507: t = (SIG)p->body;
2508: if ( t->pos == pos ) {
2509: if ( _dl_redble(DL(t),sig,nd_nvar) )
2510: return root.next;
2511: else if ( _dl_redble(sig,DL(t),nd_nvar) )
2512: // remove p
2513: prev->next = p->next;
2514: } else
2515: prev = p;
2516: }
1.27 noro 2517: NEWNODE(r); r->body = (pointer)s; r->next = 0;
2518: for ( p = &root; p->next; p = p->next );
2519: p->next = r;
2520: // r->next = root.next;
2521: // return r;
2522: return root.next;
1.24 noro 2523: }
2524:
2525: ND_pairs remove_spair_s(ND_pairs d,SIG sig)
2526: {
2527: struct oND_pairs root;
2528: ND_pairs prev,p;
2529: SIG spsig;
2530:
2531: root.next = d;
2532: prev = &root; p = d;
2533: while ( p ) {
2534: spsig = p->sig;
1.26 noro 2535: if ( sig->pos == spsig->pos && _dl_redble(DL(sig),DL(spsig),nd_nvar) ) {
1.24 noro 2536: // remove p
2537: prev->next = p->next;
1.26 noro 2538: Nsyz++;
2539: } else
1.24 noro 2540: prev = p;
2541: p = p->next;
2542: }
2543: return (ND_pairs)root.next;
2544: }
2545:
1.28 ! noro 2546: int small_lcm(ND_pairs l)
! 2547: {
! 2548: SIG sig;
! 2549: int i;
! 2550: static DL lcm,mul,quo;
! 2551: static int nvar;
! 2552:
! 2553: if ( nvar < nd_nvar ) {
! 2554: nvar = nd_nvar; NEWDL(lcm,nvar); NEWDL(quo,nvar); NEWDL(mul,nvar);
! 2555: }
! 2556: sig = l->sig;
! 2557: _ndltodl(l->lcm,lcm);
! 2558: for ( i = 0; i < nd_psn; i++ ) {
! 2559: if ( sig->pos == nd_psh[i]->sig->pos &&
! 2560: _dl_redble(DL(nd_psh[i]->sig),DL(sig),nd_nvar) ) {
! 2561: _copydl(nd_nvar,DL(sig),quo);
! 2562: _subfromdl(nd_nvar,DL(nd_psh[i]->sig),quo);
! 2563: _ndltodl(DL(nd_psh[i]),mul);
! 2564: _addtodl(nd_nvar,quo,mul);
! 2565: if ( (*cmpdl)(nd_nvar,lcm,mul) > 0 )
! 2566: break;
! 2567: }
! 2568: }
! 2569: if ( i < nd_psn ) return 1;
! 2570: else return 0;
! 2571: }
! 2572:
! 2573: ND_pairs remove_large_lcm(ND_pairs d)
! 2574: {
! 2575: struct oND_pairs root;
! 2576: ND_pairs prev,p;
! 2577:
! 2578: root.next = d;
! 2579: prev = &root; p = d;
! 2580: while ( p ) {
! 2581: if ( small_lcm(p) ) {
! 2582: // remove p
! 2583: prev->next = p->next;
! 2584: } else
! 2585: prev = p;
! 2586: p = p->next;
! 2587: }
! 2588: return (ND_pairs)root.next;
! 2589: }
! 2590:
1.26 noro 2591: struct oEGT eg_create,eg_newpairs,eg_merge;
2592:
1.24 noro 2593: NODE nd_sba_buch(int m,int ishomo,int **indp)
2594: {
2595: int i,nh,sugar,stat;
2596: NODE r,g,t;
2597: ND_pairs d;
2598: ND_pairs l;
2599: ND h,nf,s,head,nf1;
2600: NDV nfv;
2601: Z q;
2602: union oNDC dn,hc;
2603: P cont;
2604: LIST list;
2605: SIG sig;
2606: NODE syzlist;
1.26 noro 2607: int Nredundant;
1.28 ! noro 2608: DL lcm,quo,mul;
1.27 noro 2609: struct oEGT eg1,eg2,eg_update,eg_remove;
1.24 noro 2610:
1.27 noro 2611: init_eg(&eg_remove);
1.24 noro 2612: syzlist = 0;
1.26 noro 2613: Nsyz = 0;
1.24 noro 2614: Nnd_add = 0;
1.26 noro 2615: Nredundant = 0;
1.24 noro 2616: g = 0; d = 0;
2617: for ( i = 0; i < nd_psn; i++ ) {
2618: d = update_pairs_s(d,g,i,0);
2619: g = append_one(g,i);
2620: }
2621: sugar = 0;
1.26 noro 2622: NEWDL(lcm,nd_nvar); NEWDL(quo,nd_nvar); NEWDL(mul,nd_nvar);
2623: init_eg(&eg_create);
2624: init_eg(&eg_merge);
1.24 noro 2625: while ( d ) {
2626: again:
1.26 noro 2627: if ( DP_Print ) {
2628: int len;
2629: ND_pairs td;
1.28 ! noro 2630: for ( td = d, len=0; td; td = td->next, len++)
! 2631: ;
1.26 noro 2632: if ( !(len%100) ) fprintf(asir_out,"(%d)",len);
2633: }
1.24 noro 2634: l = d; d = d->next;
1.28 ! noro 2635: if ( small_lcm(l) ) {
1.24 noro 2636: if ( DP_Print ) fprintf(asir_out,"M");
1.26 noro 2637: Nredundant++;
1.24 noro 2638: continue;
2639: }
2640: if ( SG(l) != sugar ) {
2641: sugar = SG(l);
2642: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2643: }
1.28 ! noro 2644: sig = l->sig;
1.24 noro 2645: stat = nd_sp(m,0,l,&h);
2646: if ( !stat ) {
2647: NEXT(l) = d; d = l;
2648: d = nd_reconstruct(0,d);
2649: goto again;
2650: }
1.25 noro 2651: #if USE_GEOBUCKET
1.24 noro 2652: stat = m?nd_nf_pbucket_s(m,h,nd_ps,!Top,&nf):nd_nf_s(m,0,h,nd_ps,!Top,&nf);
2653: #else
2654: stat = nd_nf_s(m,0,h,nd_ps,!Top,&nf);
2655: #endif
2656: if ( !stat ) {
2657: NEXT(l) = d; d = l;
2658: d = nd_reconstruct(0,d);
2659: goto again;
2660: } else if ( stat == -1 ) {
2661: if ( DP_Print ) { printf("S"); fflush(stdout); }
1.27 noro 2662: FREENDP(l);
1.24 noro 2663: } else if ( nf ) {
2664: if ( DP_Print ) { printf("+"); fflush(stdout); }
2665: hc = HCU(nf);
2666: nd_removecont(m,nf);
2667: nfv = ndtondv(m,nf); nd_free(nf);
2668: nh = ndv_newps(m,nfv,0);
1.26 noro 2669:
1.24 noro 2670: d = update_pairs_s(d,g,nh,syzlist);
2671: g = append_one(g,nh);
2672: FREENDP(l);
2673: } else {
2674: // syzygy
1.27 noro 2675: get_eg(&eg1);
1.24 noro 2676: d = remove_spair_s(d,sig);
1.27 noro 2677: get_eg(&eg2); add_eg(&eg_remove,&eg1,&eg2);
1.24 noro 2678: syzlist = insert_sig(syzlist,sig);
2679: if ( DP_Print ) { printf("."); fflush(stdout); }
2680: FREENDP(l);
2681: }
2682: }
2683: conv_ilist(nd_demand,0,g,indp);
1.26 noro 2684: if ( DP_Print ) {
2685: printf("\nnd_sba done. nd_add=%d,Nsyz=%d,Nredundant=%d\n",Nnd_add,Nsyz,Nredundant);
2686: fflush(stdout);
2687: print_eg("create",&eg_create);
2688: print_eg("merge",&eg_merge);
1.27 noro 2689: print_eg("remove",&eg_remove);
2690: printf("\n");
1.26 noro 2691: }
1.24 noro 2692: return g;
2693: }
2694:
1.1 noro 2695: /* splist = [[i1,i2],...] */
2696:
2697: int check_splist(int m,NODE splist)
2698: {
2699: NODE t,p;
2700: ND_pairs d,r,l;
2701: int stat;
2702: ND h,nf;
2703:
2704: for ( d = 0, t = splist; t; t = NEXT(t) ) {
2705: p = BDY((LIST)BDY(t));
1.6 noro 2706: NEXTND_pairs(d,r);
2707: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
2708: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 2709: SG(r) = TD(LCM(r)); /* XXX */
2710: }
2711: if ( d ) NEXT(r) = 0;
2712:
1.6 noro 2713: while ( d ) {
1.1 noro 2714: again:
1.6 noro 2715: l = nd_minp(d,&d);
2716: stat = nd_sp(m,0,l,&h);
2717: if ( !stat ) {
2718: NEXT(l) = d; d = l;
2719: d = nd_reconstruct(0,d);
2720: goto again;
2721: }
2722: stat = nd_nf(m,0,h,nd_ps,!Top,&nf);
2723: if ( !stat ) {
2724: NEXT(l) = d; d = l;
2725: d = nd_reconstruct(0,d);
2726: goto again;
2727: } else if ( nf ) return 0;
1.1 noro 2728: if ( DP_Print) { printf("."); fflush(stdout); }
1.6 noro 2729: }
1.1 noro 2730: if ( DP_Print) { printf("done.\n"); fflush(stdout); }
2731: return 1;
2732: }
2733:
2734: int check_splist_f4(int m,NODE splist)
2735: {
2736: UINT *s0vect;
1.6 noro 2737: PGeoBucket bucket;
1.1 noro 2738: NODE p,rp0,t;
2739: ND_pairs d,r,l,ll;
2740: int col,stat;
2741:
2742: for ( d = 0, t = splist; t; t = NEXT(t) ) {
2743: p = BDY((LIST)BDY(t));
1.6 noro 2744: NEXTND_pairs(d,r);
2745: r->i1 = ZTOS((Q)ARG0(p)); r->i2 = ZTOS((Q)ARG1(p));
2746: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
1.1 noro 2747: SG(r) = TD(LCM(r)); /* XXX */
2748: }
2749: if ( d ) NEXT(r) = 0;
2750:
1.6 noro 2751: while ( d ) {
2752: l = nd_minsugarp(d,&d);
2753: bucket = create_pbucket();
2754: stat = nd_sp_f4(m,0,l,bucket);
2755: if ( !stat ) {
2756: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
2757: NEXT(ll) = d; d = l;
2758: d = nd_reconstruct(0,d);
2759: continue;
2760: }
2761: if ( bucket->m < 0 ) continue;
2762: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
2763: if ( !col ) {
2764: for ( ll = l; NEXT(ll); ll = NEXT(ll) );
2765: NEXT(ll) = d; d = l;
2766: d = nd_reconstruct(0,d);
2767: continue;
1.1 noro 2768: }
1.6 noro 2769: if ( nd_f4_red(m,l,0,s0vect,col,rp0,0) ) return 0;
2770: }
2771: return 1;
1.1 noro 2772: }
2773:
2774: int do_diagonalize_trace(int sugar,int m)
2775: {
1.6 noro 2776: int i,nh,stat;
2777: NODE r,g,t;
2778: ND h,nf,nfq,s,head;
2779: NDV nfv,nfqv;
2780: Q q,den,num;
2781: union oNDC hc;
2782: NODE node;
2783: LIST l;
2784: Z iq;
2785: P cont,cont1;
1.1 noro 2786:
1.6 noro 2787: for ( i = nd_psn-1; i >= 0 && SG(nd_psh[i]) == sugar; i-- ) {
2788: if ( nd_gentrace ) {
2789: /* Trace = [1,index,1,1] */
2790: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
2791: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
2792: }
2793: /* for nd_ps */
2794: s = ndvtond(m,nd_ps[i]);
2795: s = nd_separate_head(s,&head);
2796: stat = nd_nf_pbucket(m,s,nd_ps,1,&nf);
2797: if ( !stat ) return 0;
2798: nf = nd_add(m,head,nf);
2799: ndv_free(nd_ps[i]);
2800: nd_ps[i] = ndtondv(m,nf);
2801: nd_free(nf);
2802:
2803: /* for nd_ps_trace */
2804: if ( nd_demand )
2805: nfv = ndv_load(i);
2806: else
2807: nfv = nd_ps_trace[i];
2808: s = ndvtond(0,nfv);
2809: s = nd_separate_head(s,&head);
2810: stat = nd_nf(0,head,s,nd_ps_trace,1,&nf);
2811: if ( !stat ) return 0;
2812: ndv_free(nfv);
2813: hc = HCU(nf); nd_removecont(0,nf);
2814: /* exact division */
1.1 noro 2815: cont = ndc_div(0,hc,HCU(nf));
1.6 noro 2816: if ( nd_gentrace ) finalize_tracelist(i,cont);
2817: nfv = ndtondv(0,nf);
2818: nd_free(nf);
2819: nd_bound[i] = ndv_compute_bound(nfv);
2820: register_hcf(nfv);
2821: if ( nd_demand ) {
2822: ndv_save(nfv,i);
2823: ndv_free(nfv);
2824: } else
2825: nd_ps_trace[i] = nfv;
2826: }
2827: return 1;
1.1 noro 2828: }
2829:
2830: static struct oEGT eg_invdalg;
2831: struct oEGT eg_le;
2832:
2833: void nd_subst_vector(VL vl,P p,NODE subst,P *r)
2834: {
2835: NODE tn;
2836: P p1;
2837:
2838: for ( tn = subst; tn; tn = NEXT(NEXT(tn)) ) {
2839: substp(vl,p,BDY(tn),BDY(NEXT(tn)),&p1); p = p1;
2840: }
2841: *r = p;
2842: }
2843:
2844: NODE nd_gb_trace(int m,int ishomo,int **indp)
2845: {
1.6 noro 2846: int i,nh,sugar,stat;
2847: NODE r,g,t;
2848: ND_pairs d;
2849: ND_pairs l;
2850: ND h,nf,nfq,s,head;
2851: NDV nfv,nfqv;
2852: Z q,den,num;
2853: P hc;
2854: union oNDC dn,hnfq;
2855: struct oEGT eg_monic,egm0,egm1;
2856: int diag_count = 0;
2857: P cont;
2858: LIST list;
2859:
2860: init_eg(&eg_monic);
2861: init_eg(&eg_invdalg);
2862: init_eg(&eg_le);
2863: g = 0; d = 0;
2864: for ( i = 0; i < nd_psn; i++ ) {
2865: d = update_pairs(d,g,i,0);
2866: g = update_base(g,i);
2867: }
2868: sugar = 0;
2869: while ( d ) {
1.1 noro 2870: again:
1.6 noro 2871: l = nd_minp(d,&d);
2872: if ( MaxDeg > 0 && SG(l) > MaxDeg ) break;
2873: if ( SG(l) != sugar ) {
1.1 noro 2874: #if 1
1.6 noro 2875: if ( ishomo ) {
2876: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2877: stat = do_diagonalize_trace(sugar,m);
2878: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2879: diag_count = 0;
1.1 noro 2880: if ( !stat ) {
1.6 noro 2881: NEXT(l) = d; d = l;
2882: d = nd_reconstruct(1,d);
2883: goto again;
1.1 noro 2884: }
1.6 noro 2885: }
2886: #endif
2887: sugar = SG(l);
2888: if ( DP_Print ) fprintf(asir_out,"%d",sugar);
2889: }
2890: stat = nd_sp(m,0,l,&h);
2891: if ( !stat ) {
2892: NEXT(l) = d; d = l;
2893: d = nd_reconstruct(1,d);
2894: goto again;
2895: }
1.1 noro 2896: #if USE_GEOBUCKET
1.6 noro 2897: stat = nd_nf_pbucket(m,h,nd_ps,!Top,&nf);
1.1 noro 2898: #else
1.6 noro 2899: stat = nd_nf(m,0,h,nd_ps,!Top,&nf);
1.1 noro 2900: #endif
1.6 noro 2901: if ( !stat ) {
2902: NEXT(l) = d; d = l;
2903: d = nd_reconstruct(1,d);
2904: goto again;
2905: } else if ( nf ) {
2906: if ( nd_demand ) {
2907: nfqv = ndv_load(nd_psn);
2908: nfq = ndvtond(0,nfqv);
2909: } else
2910: nfq = 0;
2911: if ( !nfq ) {
2912: if ( !nd_sp(0,1,l,&h) || !nd_nf(0,0,h,nd_ps_trace,!Top,&nfq) ) {
2913: NEXT(l) = d; d = l;
2914: d = nd_reconstruct(1,d);
2915: goto again;
2916: }
2917: }
2918: if ( nfq ) {
2919: /* m|HC(nfq) => failure */
2920: if ( nd_vc ) {
2921: nd_subst_vector(nd_vc,HCP(nfq),nd_subst,&hc); q = (Z)hc;
2922: } else
2923: q = HCZ(nfq);
2924: if ( !remqi((Q)q,m) ) return 0;
2925:
2926: if ( DP_Print ) { printf("+"); fflush(stdout); }
2927: hnfq = HCU(nfq);
2928: if ( nd_nalg ) {
2929: /* m|DN(HC(nf)^(-1)) => failure */
2930: get_eg(&egm0);
2931: if ( !nd_monic(m,&nfq) ) return 0;
2932: get_eg(&egm1); add_eg(&eg_monic,&egm0,&egm1);
2933: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
2934: nfv = ndv_dup(0,nfqv); ndv_mod(m,nfv); nd_free(nf);
2935: } else {
2936: nd_removecont(0,nfq); nfqv = ndtondv(0,nfq); nd_free(nfq);
2937: nd_removecont(m,nf); nfv = ndtondv(m,nf); nd_free(nf);
2938: }
2939: if ( nd_gentrace ) {
2940: /* exact division */
2941: cont = ndc_div(0,hnfq,HCU(nfqv));
2942: if ( !UNIQ(cont) ) {
2943: t = mknode(4,NULLP,NULLP,NULLP,cont);
2944: MKLIST(list,t); MKNODE(t,list,nd_tracelist);
2945: nd_tracelist = t;
2946: }
2947: }
1.24 noro 2948: nh = ndv_newps(0,nfv,nfqv);
1.6 noro 2949: if ( ishomo && ++diag_count == diag_period ) {
2950: diag_count = 0;
2951: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2952: stat = do_diagonalize_trace(sugar,m);
2953: if ( DP_Print > 2 ) fprintf(asir_out,"|");
2954: if ( !stat ) {
1.1 noro 2955: NEXT(l) = d; d = l;
2956: d = nd_reconstruct(1,d);
2957: goto again;
1.6 noro 2958: }
1.1 noro 2959: }
1.6 noro 2960: d = update_pairs(d,g,nh,0);
2961: g = update_base(g,nh);
2962: } else {
2963: if ( DP_Print ) { printf("*"); fflush(stdout); }
2964: }
2965: } else {
2966: if ( DP_Print ) { printf("."); fflush(stdout); }
1.1 noro 2967: }
1.6 noro 2968: FREENDP(l);
2969: }
2970: if ( nd_nalg ) {
2971: if ( DP_Print ) {
2972: print_eg("monic",&eg_monic);
2973: print_eg("invdalg",&eg_invdalg);
2974: print_eg("le",&eg_le);
1.1 noro 2975: }
1.6 noro 2976: }
1.1 noro 2977: conv_ilist(nd_demand,1,g,indp);
1.6 noro 2978: if ( DP_Print ) { printf("nd_gb_trace done.\n"); fflush(stdout); }
2979: return g;
1.1 noro 2980: }
2981:
2982: int ndv_compare(NDV *p1,NDV *p2)
2983: {
2984: return DL_COMPARE(HDL(*p1),HDL(*p2));
2985: }
2986:
2987: int ndv_compare_rev(NDV *p1,NDV *p2)
2988: {
2989: return -DL_COMPARE(HDL(*p1),HDL(*p2));
2990: }
2991:
2992: int ndvi_compare(NDVI p1,NDVI p2)
2993: {
2994: return DL_COMPARE(HDL(p1->p),HDL(p2->p));
2995: }
2996:
2997: int ndvi_compare_rev(NDVI p1,NDVI p2)
2998: {
2999: return -DL_COMPARE(HDL(p1->p),HDL(p2->p));
3000: }
3001:
3002: NODE ndv_reduceall(int m,NODE f)
3003: {
3004: int i,j,n,stat;
3005: ND nf,g,head;
3006: NODE t,a0,a;
3007: union oNDC dn;
3008: Q q,num,den;
3009: NODE node;
3010: LIST l;
3011: Z iq,jq;
3012: int *perm;
3013: union oNDC hc;
3014: P cont,cont1;
3015:
3016: if ( nd_nora ) return f;
3017: n = length(f);
1.24 noro 3018: ndv_setup(m,0,f,0,1,0);
1.1 noro 3019: perm = (int *)MALLOC(n*sizeof(int));
3020: if ( nd_gentrace ) {
3021: for ( t = nd_tracelist, i = 0; i < n; i++, t = NEXT(t) )
1.6 noro 3022: perm[i] = ZTOS((Q)ARG1(BDY((LIST)BDY(t))));
1.1 noro 3023: }
3024: for ( i = 0; i < n; ) {
3025: if ( nd_gentrace ) {
3026: /* Trace = [1,index,1,1] */
1.6 noro 3027: STOZ(i,iq); node = mknode(4,ONE,iq,ONE,ONE);
1.1 noro 3028: MKLIST(l,node); MKNODE(nd_tracelist,l,0);
3029: }
3030: g = ndvtond(m,nd_ps[i]);
3031: g = nd_separate_head(g,&head);
1.6 noro 3032: stat = nd_nf(m,head,g,nd_ps,1,&nf);
1.1 noro 3033: if ( !stat )
3034: nd_reconstruct(0,0);
3035: else {
3036: if ( DP_Print ) { printf("."); fflush(stdout); }
3037: ndv_free(nd_ps[i]);
3038: hc = HCU(nf); nd_removecont(m,nf);
3039: if ( nd_gentrace ) {
3040: for ( t = nd_tracelist; t; t = NEXT(t) ) {
1.6 noro 3041: jq = ARG1(BDY((LIST)BDY(t))); j = ZTOS(jq);
3042: STOZ(perm[j],jq); ARG1(BDY((LIST)BDY(t))) = jq;
1.1 noro 3043: }
1.6 noro 3044: /* exact division */
1.1 noro 3045: cont = ndc_div(m,hc,HCU(nf));
3046: finalize_tracelist(perm[i],cont);
3047: }
3048: nd_ps[i] = ndtondv(m,nf); nd_free(nf);
3049: nd_bound[i] = ndv_compute_bound(nd_ps[i]);
3050: i++;
3051: }
3052: }
3053: if ( DP_Print ) { printf("\n"); }
3054: for ( a0 = 0, i = 0; i < n; i++ ) {
3055: NEXTNODE(a0,a);
3056: if ( !nd_gentrace ) BDY(a) = (pointer)nd_ps[i];
3057: else {
3058: for ( j = 0; j < n; j++ ) if ( perm[j] == i ) break;
3059: BDY(a) = (pointer)nd_ps[j];
3060: }
3061: }
3062: NEXT(a) = 0;
3063: return a0;
3064: }
3065:
3066: ND_pairs update_pairs( ND_pairs d, NODE /* of index */ g, int t, int gensyz)
3067: {
3068: ND_pairs d1,nd,cur,head,prev,remove;
3069:
3070: if ( !g ) return d;
3071: /* for testing */
3072: if ( gensyz && nd_gensyz == 2 ) {
3073: d1 = nd_newpairs(g,t);
3074: if ( !d )
3075: return d1;
3076: else {
3077: nd = d;
3078: while ( NEXT(nd) ) nd = NEXT(nd);
3079: NEXT(nd) = d1;
3080: return d;
3081: }
3082: }
3083: d = crit_B(d,t);
3084: d1 = nd_newpairs(g,t);
3085: d1 = crit_M(d1);
3086: d1 = crit_F(d1);
3087: if ( gensyz || do_weyl )
3088: head = d1;
3089: else {
3090: prev = 0; cur = head = d1;
3091: while ( cur ) {
3092: if ( crit_2( cur->i1,cur->i2 ) ) {
3093: remove = cur;
3094: if ( !prev ) head = cur = NEXT(cur);
3095: else cur = NEXT(prev) = NEXT(cur);
3096: FREENDP(remove);
3097: } else {
3098: prev = cur; cur = NEXT(cur);
3099: }
3100: }
3101: }
3102: if ( !d )
3103: return head;
3104: else {
3105: nd = d;
3106: while ( NEXT(nd) ) nd = NEXT(nd);
3107: NEXT(nd) = head;
3108: return d;
3109: }
3110: }
3111:
1.24 noro 3112: ND_pairs merge_pairs_s(ND_pairs d,ND_pairs d1);
3113:
3114: ND_pairs update_pairs_s( ND_pairs d, NODE /* of index */ g, int t,NODE syz)
3115: {
3116: ND_pairs d1;
1.26 noro 3117: struct oEGT eg1,eg2,eg3;
1.24 noro 3118:
3119: if ( !g ) return d;
1.26 noro 3120: get_eg(&eg1);
1.24 noro 3121: d1 = nd_newpairs_s(g,t,syz);
1.26 noro 3122: get_eg(&eg2); add_eg(&eg_create,&eg1,&eg2);
1.24 noro 3123: d = merge_pairs_s(d,d1);
1.26 noro 3124: get_eg(&eg3); add_eg(&eg_merge,&eg2,&eg3);
1.24 noro 3125: return d;
3126: }
1.1 noro 3127:
3128: ND_pairs nd_newpairs( NODE g, int t )
3129: {
3130: NODE h;
3131: UINT *dl;
3132: int ts,s,i,t0,min,max;
3133: ND_pairs r,r0;
3134:
3135: dl = DL(nd_psh[t]);
3136: ts = SG(nd_psh[t]) - TD(dl);
1.17 noro 3137: if ( nd_module && nd_intersect && (MPOS(dl) > nd_intersect) ) return 0;
1.1 noro 3138: for ( r0 = 0, h = g; h; h = NEXT(h) ) {
3139: if ( nd_module && (MPOS(DL(nd_psh[(long)BDY(h)])) != MPOS(dl)) )
3140: continue;
3141: if ( nd_gbblock ) {
3142: t0 = (long)BDY(h);
3143: for ( i = 0; nd_gbblock[i] >= 0; i += 2 ) {
3144: min = nd_gbblock[i]; max = nd_gbblock[i+1];
3145: if ( t0 >= min && t0 <= max && t >= min && t <= max )
3146: break;
3147: }
3148: if ( nd_gbblock[i] >= 0 )
3149: continue;
3150: }
3151: NEXTND_pairs(r0,r);
3152: r->i1 = (long)BDY(h);
3153: r->i2 = t;
3154: ndl_lcm(DL(nd_psh[r->i1]),dl,r->lcm);
3155: s = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3156: SG(r) = MAX(s,ts) + TD(LCM(r));
3157: /* experimental */
3158: if ( nd_sugarweight )
3159: r->sugar2 = ndl_weight2(r->lcm);
3160: }
3161: if ( r0 ) NEXT(r) = 0;
3162: return r0;
3163: }
3164:
1.24 noro 3165:
3166: int comp_sig(SIG s1,SIG s2)
3167: {
3168: #if 0
3169: if ( s1->pos > s2->pos ) return 1;
3170: else if ( s1->pos < s2->pos ) return -1;
3171: else return (*cmpdl)(nd_nvar,s1->dl,s2->dl);
3172: #else
3173: static DL m1,m2;
3174: static int nvar;
3175: int ret;
3176:
1.26 noro 3177: if ( nvar != nd_nvar ) {
3178: nvar = nd_nvar; NEWDL(m1,nvar); NEWDL(m2,nvar);
1.24 noro 3179: }
1.27 noro 3180: // _ndltodl(DL(nd_psh[s1->pos]),m1);
3181: // _ndltodl(DL(nd_psh[s2->pos]),m2);
3182: _copydl(nd_nvar,nd_sba_hm[s1->pos],m1);
3183: _copydl(nd_nvar,nd_sba_hm[s2->pos],m2);
1.24 noro 3184: _addtodl(nd_nvar,s1->dl,m1);
3185: _addtodl(nd_nvar,s2->dl,m2);
3186: ret = (*cmpdl)(nd_nvar,m1,m2);
3187: if ( ret != 0 ) return ret;
3188: else if ( s1->pos > s2->pos ) return 1;
3189: else if ( s1->pos < s2->pos ) return -1;
3190: else return 0;
3191: #endif
3192: }
3193:
3194: int _create_spair_s(int i1,int i2,ND_pairs sp,SIG sig1,SIG sig2)
3195: {
3196: int ret,s1,s2;
3197: RHist p1,p2;
3198: static int wpd;
3199: static UINT *lcm;
3200:
3201: sp->i1 = i1;
3202: sp->i2 = i2;
3203: p1 = nd_psh[i1];
3204: p2 = nd_psh[i2];
3205: ndl_lcm(DL(p1),DL(p2),sp->lcm);
3206: s1 = SG(p1)-TD(DL(p1));
3207: s2 = SG(p2)-TD(DL(p2));
3208: SG(sp) = MAX(s1,s2) + TD(sp->lcm);
3209:
1.26 noro 3210: if ( wpd != nd_wpd ) {
1.24 noro 3211: wpd = nd_wpd;
3212: lcm = (UINT *)MALLOC(wpd*sizeof(UINT));
3213: }
3214: // DL(sig1) <- sp->lcm
3215: // DL(sig1) -= DL(p1)
3216: // DL(sig1) += DL(p1->sig)
1.27 noro 3217: ndl_sub(sp->lcm,DL(p1),lcm);
1.24 noro 3218: _ndltodl(lcm,DL(sig1));
3219: _addtodl(nd_nvar,DL(p1->sig),DL(sig1));
3220: sig1->pos = p1->sig->pos;
3221:
3222: // DL(sig2) <- sp->lcm
3223: // DL(sig2) -= DL(p2)
3224: // DL(sig2) += DL(p2->sig)
1.27 noro 3225: ndl_sub(sp->lcm,DL(p2),lcm);
1.24 noro 3226: _ndltodl(lcm,DL(sig2));
3227: _addtodl(nd_nvar,DL(p2->sig),DL(sig2));
3228: sig2->pos = p2->sig->pos;
3229:
3230: ret = comp_sig(sig1,sig2);
3231: if ( ret == 0 ) return 0;
3232: else if ( ret > 0 ) sp->sig = sig1;
3233: else sp->sig = sig2;
3234: return 1;
3235: }
3236:
3237: SIG dup_sig(SIG sig)
3238: {
3239: SIG r;
3240:
3241: if ( !sig ) return 0;
3242: else {
3243: NEWSIG(r);
3244: _copydl(nd_nvar,DL(sig),DL(r));
3245: r->pos = sig->pos;
3246: return r;
3247: }
3248: }
3249:
3250: void dup_ND_pairs(ND_pairs to,ND_pairs from)
3251: {
3252: to->i1 = from->i1;
3253: to->i2 = from->i2;
3254: to->sugar = from->sugar;
3255: to->sugar2 = from->sugar2;
3256: ndl_copy(from->lcm,to->lcm);
3257: to->sig = dup_sig(from->sig);
3258: }
3259:
3260: ND_pairs merge_pairs_s(ND_pairs p1,ND_pairs p2)
3261: {
3262: struct oND_pairs root;
3263: ND_pairs q1,q2,r0,r;
3264: int ret;
3265:
3266: r = &root;
3267: for ( q1 = p1, q2 = p2; q1 != 0 && q2 != 0; ) {
3268: ret = comp_sig(q1->sig,q2->sig);
3269: if ( ret < 0 ) {
3270: r->next = q1; r = q1; q1 = q1->next;
3271: } else if ( ret > 0 ) {
3272: r->next = q2; r = q2; q2 = q2->next;
3273: } else {
3274: ret = DL_COMPARE(q1->lcm,q2->lcm);
3275: if ( ret < 0 ) {
3276: r->next = q1; r = q1; q1 = q1->next;
3277: q2 = q2->next;
3278: } else {
3279: r->next = q2; r = q2; q2 = q2->next;
3280: q1 = q1->next;
3281: }
3282: }
3283: }
3284: if ( q1 ) {
3285: r->next = q1;
3286: } else {
3287: r->next = q2;
3288: }
3289: return root.next;
3290: }
3291:
3292: ND_pairs insert_pair_s(ND_pairs l,ND_pairs s)
3293: {
3294: ND_pairs p,prev;
3295: int ret;
3296:
3297: for ( p = l, prev = 0; p != 0; prev = p, p = p->next ) {
3298: if ( (ret = comp_sig(s->sig,p->sig)) <= 0 )
3299: break;
3300: }
3301: if ( ret == 0 ) {
3302: ret = DL_COMPARE(s->lcm,p->lcm);
3303: if ( ret < 0 ) {
3304: // replace p with s
3305: s->next = p->next;
3306: if ( prev == 0 ) {
3307: return s;
3308: } else {
3309: prev->next = s;
3310: return l;
3311: }
3312: } else
3313: return l;
3314: } else {
3315: // insert s between prev and p
3316: s->next = p;
3317: if ( prev == 0 ) {
3318: return s;
3319: } else {
3320: prev->next = s;
3321: return l;
3322: }
3323: }
3324: }
3325:
3326: ND_pairs nd_newpairs_s( NODE g, int t, NODE syz)
3327: {
3328: NODE h,s;
3329: UINT *dl;
1.27 noro 3330: int ts,ret,i;
1.24 noro 3331: ND_pairs r,r0,_sp,sp;
3332: SIG _sig1,_sig2,spsig,tsig;
1.26 noro 3333: struct oEGT eg1,eg2,eg3,eg4;
1.24 noro 3334:
3335: NEWND_pairs(_sp);
3336: NEWSIG(_sig1); NEWSIG(_sig2);
3337: r0 = 0;
1.27 noro 3338: for ( i = 0; i < t; i++ ) {
3339: ret = _create_spair_s(i,t,_sp,_sig1,_sig2);
3340: // for ( h = g; h; h = NEXT(h) ) {
3341: // ret = _create_spair_s((long)BDY(h),t,_sp,_sig1,_sig2);
1.24 noro 3342: if ( ret ) {
3343: spsig = _sp->sig;
3344: for ( s = syz; s; s = s->next ) {
3345: tsig = (SIG)s->body;
3346: if ( tsig->pos == spsig->pos && _dl_redble(DL(tsig),DL(spsig),nd_nvar) )
3347: break;
3348: }
3349: if ( s == 0 ) {
3350: NEWND_pairs(sp);
3351: dup_ND_pairs(sp,_sp);
3352: r0 = insert_pair_s(r0,sp);
1.26 noro 3353: } else
3354: Nsyz++;
1.24 noro 3355: }
3356: }
3357: return r0;
3358: }
3359:
1.1 noro 3360: /* ipair = [i1,i2],[i1,i2],... */
3361: ND_pairs nd_ipairtospair(NODE ipair)
3362: {
3363: int s1,s2;
3364: NODE tn,t;
3365: ND_pairs r,r0;
3366:
3367: for ( r0 = 0, t = ipair; t; t = NEXT(t) ) {
3368: NEXTND_pairs(r0,r);
3369: tn = BDY((LIST)BDY(t));
1.6 noro 3370: r->i1 = ZTOS((Q)ARG0(tn));
3371: r->i2 = ZTOS((Q)ARG1(tn));
1.1 noro 3372: ndl_lcm(DL(nd_psh[r->i1]),DL(nd_psh[r->i2]),r->lcm);
3373: s1 = SG(nd_psh[r->i1])-TD(DL(nd_psh[r->i1]));
3374: s2 = SG(nd_psh[r->i2])-TD(DL(nd_psh[r->i2]));
3375: SG(r) = MAX(s1,s2) + TD(LCM(r));
3376: /* experimental */
3377: if ( nd_sugarweight )
3378: r->sugar2 = ndl_weight2(r->lcm);
3379: }
3380: if ( r0 ) NEXT(r) = 0;
3381: return r0;
3382: }
3383:
3384: /* kokokara */
3385:
3386: ND_pairs crit_B( ND_pairs d, int s )
3387: {
3388: ND_pairs cur,head,prev,remove;
3389: UINT *t,*tl,*lcm;
3390: int td,tdl;
3391:
3392: if ( !d ) return 0;
3393: t = DL(nd_psh[s]);
3394: prev = 0;
3395: head = cur = d;
3396: lcm = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
3397: while ( cur ) {
3398: tl = cur->lcm;
3399: if ( ndl_reducible(tl,t) ) {
3400: ndl_lcm(DL(nd_psh[cur->i1]),t,lcm);
3401: if ( !ndl_equal(lcm,tl) ) {
3402: ndl_lcm(DL(nd_psh[cur->i2]),t,lcm);
3403: if (!ndl_equal(lcm,tl)) {
3404: remove = cur;
3405: if ( !prev ) {
3406: head = cur = NEXT(cur);
3407: } else {
3408: cur = NEXT(prev) = NEXT(cur);
3409: }
3410: FREENDP(remove);
3411: } else {
3412: prev = cur; cur = NEXT(cur);
3413: }
3414: } else {
3415: prev = cur; cur = NEXT(cur);
3416: }
3417: } else {
3418: prev = cur; cur = NEXT(cur);
3419: }
3420: }
3421: return head;
3422: }
3423:
3424: ND_pairs crit_M( ND_pairs d1 )
3425: {
3426: ND_pairs e,d2,d3,dd,p;
3427: UINT *id,*jd;
3428:
3429: if ( !d1 ) return d1;
3430: for ( dd = 0, e = d1; e; e = d3 ) {
3431: if ( !(d2 = NEXT(e)) ) {
3432: NEXT(e) = dd;
3433: return e;
3434: }
3435: id = LCM(e);
3436: for ( d3 = 0; d2; d2 = p ) {
3437: p = NEXT(d2);
3438: jd = LCM(d2);
3439: if ( ndl_equal(jd,id) )
3440: ;
3441: else if ( TD(jd) > TD(id) )
3442: if ( ndl_reducible(jd,id) ) continue;
3443: else ;
3444: else if ( ndl_reducible(id,jd) ) goto delit;
3445: NEXT(d2) = d3;
3446: d3 = d2;
3447: }
3448: NEXT(e) = dd;
3449: dd = e;
3450: continue;
3451: /**/
3452: delit: NEXT(d2) = d3;
3453: d3 = d2;
3454: for ( ; p; p = d2 ) {
3455: d2 = NEXT(p);
3456: NEXT(p) = d3;
3457: d3 = p;
3458: }
3459: FREENDP(e);
3460: }
3461: return dd;
3462: }
3463:
3464: ND_pairs crit_F( ND_pairs d1 )
3465: {
3466: ND_pairs rest, head,remove;
3467: ND_pairs last, p, r, w;
3468: int s;
3469:
3470: if ( !d1 ) return d1;
3471: for ( head = last = 0, p = d1; NEXT(p); ) {
3472: r = w = equivalent_pairs(p,&rest);
3473: s = SG(r);
3474: w = NEXT(w);
3475: while ( w ) {
3476: if ( crit_2(w->i1,w->i2) ) {
3477: r = w;
3478: w = NEXT(w);
3479: while ( w ) {
3480: remove = w;
3481: w = NEXT(w);
3482: FREENDP(remove);
3483: }
3484: break;
3485: } else if ( SG(w) < s ) {
3486: FREENDP(r);
3487: r = w;
3488: s = SG(r);
3489: w = NEXT(w);
3490: } else {
3491: remove = w;
3492: w = NEXT(w);
3493: FREENDP(remove);
3494: }
3495: }
3496: if ( last ) NEXT(last) = r;
3497: else head = r;
3498: NEXT(last = r) = 0;
3499: p = rest;
3500: if ( !p ) return head;
3501: }
3502: if ( !last ) return p;
3503: NEXT(last) = p;
3504: return head;
3505: }
3506:
3507: int crit_2( int dp1, int dp2 )
3508: {
3509: return ndl_disjoint(DL(nd_psh[dp1]),DL(nd_psh[dp2]));
3510: }
3511:
3512: ND_pairs equivalent_pairs( ND_pairs d1, ND_pairs *prest )
3513: {
3514: ND_pairs w,p,r,s;
3515: UINT *d;
3516:
3517: w = d1;
3518: d = LCM(w);
3519: s = NEXT(w);
3520: NEXT(w) = 0;
3521: for ( r = 0; s; s = p ) {
3522: p = NEXT(s);
3523: if ( ndl_equal(d,LCM(s)) ) {
3524: NEXT(s) = w; w = s;
3525: } else {
3526: NEXT(s) = r; r = s;
3527: }
3528: }
3529: *prest = r;
3530: return w;
3531: }
3532:
3533: NODE update_base(NODE nd,int ndp)
3534: {
3535: UINT *dl, *dln;
3536: NODE last, p, head;
3537:
3538: dl = DL(nd_psh[ndp]);
3539: for ( head = last = 0, p = nd; p; ) {
3540: dln = DL(nd_psh[(long)BDY(p)]);
3541: if ( ndl_reducible( dln, dl ) ) {
3542: p = NEXT(p);
3543: if ( last ) NEXT(last) = p;
3544: } else {
3545: if ( !last ) head = p;
3546: p = NEXT(last = p);
3547: }
3548: }
3549: head = append_one(head,ndp);
3550: return head;
3551: }
3552:
3553: ND_pairs nd_minp( ND_pairs d, ND_pairs *prest )
3554: {
3555: ND_pairs m,ml,p,l;
3556: UINT *lcm;
3557: int s,td,len,tlen,c,c1;
3558:
3559: if ( !(p = NEXT(m = d)) ) {
3560: *prest = p;
3561: NEXT(m) = 0;
3562: return m;
3563: }
3564: if ( !NoSugar ) {
3565: if ( nd_sugarweight ) {
3566: s = m->sugar2;
3567: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3568: if ( (p->sugar2 < s)
3569: || ((p->sugar2 == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3570: ml = l; m = p; s = m->sugar2;
3571: }
3572: } else {
3573: s = SG(m);
3574: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3575: if ( (SG(p) < s)
3576: || ((SG(p) == s) && (DL_COMPARE(LCM(p),LCM(m)) < 0)) ) {
3577: ml = l; m = p; s = SG(m);
3578: }
3579: }
3580: } else {
3581: for ( ml = 0, l = m; p; p = NEXT(l = p) )
3582: if ( DL_COMPARE(LCM(p),LCM(m)) < 0 ) {
3583: ml = l; m = p; s = SG(m);
3584: }
3585: }
3586: if ( !ml ) *prest = NEXT(m);
3587: else {
3588: NEXT(ml) = NEXT(m);
3589: *prest = d;
3590: }
3591: NEXT(m) = 0;
3592: return m;
3593: }
3594:
3595: ND_pairs nd_minsugarp( ND_pairs d, ND_pairs *prest )
3596: {
3597: int msugar,i;
3598: ND_pairs t,dm0,dm,dr0,dr;
3599:
3600: if ( nd_sugarweight ) {
3601: for ( msugar = d->sugar2, t = NEXT(d); t; t = NEXT(t) )
3602: if ( t->sugar2 < msugar ) msugar = t->sugar2;
3603: dm0 = 0; dr0 = 0;
3604: for ( i = 0, t = d; t; t = NEXT(t) )
3605: if ( i < nd_f4_nsp && t->sugar2 == msugar ) {
3606: if ( dm0 ) NEXT(dm) = t;
3607: else dm0 = t;
3608: dm = t;
3609: i++;
3610: } else {
3611: if ( dr0 ) NEXT(dr) = t;
3612: else dr0 = t;
3613: dr = t;
3614: }
3615: } else {
3616: for ( msugar = SG(d), t = NEXT(d); t; t = NEXT(t) )
3617: if ( SG(t) < msugar ) msugar = SG(t);
3618: dm0 = 0; dr0 = 0;
3619: for ( i = 0, t = d; t; t = NEXT(t) )
3620: if ( i < nd_f4_nsp && SG(t) == msugar ) {
3621: if ( dm0 ) NEXT(dm) = t;
3622: else dm0 = t;
3623: dm = t;
3624: i++;
3625: } else {
3626: if ( dr0 ) NEXT(dr) = t;
3627: else dr0 = t;
3628: dr = t;
3629: }
3630: }
3631: NEXT(dm) = 0;
3632: if ( dr0 ) NEXT(dr) = 0;
3633: *prest = dr0;
3634: return dm0;
3635: }
3636:
1.28 ! noro 3637: ND_pairs nd_minsugarp_s( ND_pairs d, ND_pairs *prest )
! 3638: {
! 3639: int msugar;
! 3640: ND_pairs t,last;
! 3641:
! 3642: #if 0
! 3643: for ( msugar = SG(d), t = d; t; t = NEXT(t) )
! 3644: if ( SG(t) == msugar ) last = t;
! 3645: #else
! 3646: msugar = (d->sig->dl->td)+nd_sba_hm[d->sig->pos]->td;
! 3647: for ( t = d; t; t = NEXT(t) )
! 3648: if ( ((t->sig->dl->td)+nd_sba_hm[t->sig->pos]->td) == msugar ) last = t;
! 3649: #endif
! 3650: *prest = last->next;
! 3651: last->next = 0;
! 3652: return d;
! 3653: }
! 3654:
1.1 noro 3655: int nd_tdeg(NDV c)
3656: {
3657: int wmax = 0;
3658: int i,len;
3659: NMV a;
3660:
3661: len = LEN(c);
3662: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
3663: wmax = MAX(TD(DL(a)),wmax);
3664: return wmax;
3665: }
3666:
1.24 noro 3667: int ndv_newps(int m,NDV a,NDV aq)
1.1 noro 3668: {
3669: int len;
3670: RHist r;
3671: NDV b;
3672: NODE tn;
3673: LIST l;
3674: Z iq;
3675:
3676: if ( nd_psn == nd_pslen ) {
3677: nd_pslen *= 2;
3678: nd_ps = (NDV *)REALLOC((char *)nd_ps,nd_pslen*sizeof(NDV));
3679: nd_ps_trace = (NDV *)REALLOC((char *)nd_ps_trace,nd_pslen*sizeof(NDV));
3680: nd_psh = (RHist *)REALLOC((char *)nd_psh,nd_pslen*sizeof(RHist));
3681: nd_bound = (UINT **)
3682: REALLOC((char *)nd_bound,nd_pslen*sizeof(UINT *));
3683: nd_ps_sym = (NDV *)REALLOC((char *)nd_ps_sym,nd_pslen*sizeof(NDV));
3684: nd_ps_trace_sym = (NDV *)REALLOC((char *)nd_ps_trace_sym,nd_pslen*sizeof(NDV));
3685: }
3686: NEWRHist(r); nd_psh[nd_psn] = r;
3687: nd_ps[nd_psn] = a;
3688: if ( aq ) {
3689: nd_ps_trace[nd_psn] = aq;
3690: if ( !m ) {
3691: register_hcf(aq);
3692: } else if ( m == -2 ) {
3693: /* do nothing */
3694: } else
3695: error("ndv_newps : invalud modulus");
3696: nd_bound[nd_psn] = ndv_compute_bound(aq);
3697: #if 1
3698: SG(r) = SG(aq);
3699: #else
3700: SG(r) = nd_tdeg(aq);
3701: #endif
3702: ndl_copy(HDL(aq),DL(r));
1.24 noro 3703: r->sig = dup_sig(aq->sig);
1.1 noro 3704: } else {
3705: if ( !m ) register_hcf(a);
3706: nd_bound[nd_psn] = ndv_compute_bound(a);
3707: #if 1
3708: SG(r) = SG(a);
3709: #else
3710: SG(r) = nd_tdeg(a);
3711: #endif
3712: ndl_copy(HDL(a),DL(r));
1.24 noro 3713: r->sig = dup_sig(a->sig);
1.1 noro 3714: }
3715: if ( nd_demand ) {
3716: if ( aq ) {
3717: ndv_save(nd_ps_trace[nd_psn],nd_psn);
3718: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3719: nd_ps_trace_sym[nd_psn] = ndv_symbolic(m,nd_ps_trace[nd_psn]);
3720: nd_ps_trace[nd_psn] = 0;
3721: } else {
3722: ndv_save(nd_ps[nd_psn],nd_psn);
3723: nd_ps_sym[nd_psn] = ndv_symbolic(m,nd_ps[nd_psn]);
3724: nd_ps[nd_psn] = 0;
3725: }
3726: }
3727: if ( nd_gentrace ) {
3728: /* reverse the tracelist and append it to alltracelist */
3729: nd_tracelist = reverse_node(nd_tracelist); MKLIST(l,nd_tracelist);
1.6 noro 3730: STOZ(nd_psn,iq); tn = mknode(2,iq,l); MKLIST(l,tn);
1.1 noro 3731: MKNODE(tn,l,nd_alltracelist); nd_alltracelist = tn; nd_tracelist = 0;
3732: }
3733: return nd_psn++;
3734: }
3735:
3736: /* nd_tracelist = [[0,index,div],...,[nd_psn-1,index,div]] */
3737: /* return 1 if success, 0 if failure (HC(a mod p)) */
3738:
1.24 noro 3739: int ndv_setup(int mod,int trace,NODE f,int dont_sort,int dont_removecont,int sba)
1.1 noro 3740: {
1.6 noro 3741: int i,j,td,len,max;
3742: NODE s,s0,f0,tn;
3743: UINT *d;
3744: RHist r;
3745: NDVI w;
3746: NDV a,am;
3747: union oNDC hc;
3748: NODE node;
3749: P hcp;
3750: Z iq,jq;
3751: LIST l;
3752:
3753: nd_found = 0; nd_notfirst = 0; nd_create = 0;
3754: /* initialize the tracelist */
3755: nd_tracelist = 0;
3756:
3757: for ( nd_psn = 0, s = f; s; s = NEXT(s) ) if ( BDY(s) ) nd_psn++;
3758: w = (NDVI)MALLOC(nd_psn*sizeof(struct oNDVI));
3759: for ( i = j = 0, s = f; s; s = NEXT(s), j++ )
3760: if ( BDY(s) ) { w[i].p = BDY(s); w[i].i = j; i++; }
3761: if ( !dont_sort ) {
3762: /* XXX heuristic */
1.26 noro 3763: if ( !sba && !nd_ord->id && (nd_ord->ord.simple<2) )
1.6 noro 3764: qsort(w,nd_psn,sizeof(struct oNDVI),
3765: (int (*)(const void *,const void *))ndvi_compare_rev);
3766: else
3767: qsort(w,nd_psn,sizeof(struct oNDVI),
3768: (int (*)(const void *,const void *))ndvi_compare);
3769: }
3770: nd_pslen = 2*nd_psn;
3771: nd_ps = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3772: nd_ps_trace = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3773: nd_ps_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3774: nd_ps_trace_sym = (NDV *)MALLOC(nd_pslen*sizeof(NDV));
3775: nd_psh = (RHist *)MALLOC(nd_pslen*sizeof(RHist));
3776: nd_bound = (UINT **)MALLOC(nd_pslen*sizeof(UINT *));
3777: nd_hcf = 0;
1.1 noro 3778:
1.6 noro 3779: if ( trace && nd_vc )
3780: makesubst(nd_vc,&nd_subst);
3781: else
3782: nd_subst = 0;
1.1 noro 3783:
1.6 noro 3784: if ( !nd_red )
3785: nd_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
3786: for ( i = 0; i < REDTAB_LEN; i++ ) nd_red[i] = 0;
3787: for ( i = 0; i < nd_psn; i++ ) {
3788: hc = HCU(w[i].p);
3789: if ( trace ) {
3790: if ( mod == -2 ) {
3791: /* over a large finite field */
3792: /* trace = small modulus */
3793: a = nd_ps_trace[i] = ndv_dup(-2,w[i].p);
3794: ndv_mod(-2,a);
3795: if ( !dont_removecont) ndv_removecont(-2,a);
3796: am = nd_ps[i] = ndv_dup(trace,w[i].p);
3797: ndv_mod(trace,am);
3798: if ( DL_COMPARE(HDL(am),HDL(a)) )
3799: return 0;
3800: ndv_removecont(trace,am);
3801: } else {
3802: a = nd_ps_trace[i] = ndv_dup(0,w[i].p);
3803: if ( !dont_removecont) ndv_removecont(0,a);
3804: register_hcf(a);
3805: am = nd_ps[i] = ndv_dup(mod,a);
3806: ndv_mod(mod,am);
3807: if ( DL_COMPARE(HDL(am),HDL(a)) )
3808: return 0;
3809: ndv_removecont(mod,am);
3810: }
3811: } else {
3812: a = nd_ps[i] = ndv_dup(mod,w[i].p);
3813: if ( mod || !dont_removecont ) ndv_removecont(mod,a);
3814: if ( !mod ) register_hcf(a);
1.1 noro 3815: }
1.6 noro 3816: if ( nd_gentrace ) {
3817: STOZ(i,iq); STOZ(w[i].i,jq); node = mknode(3,iq,jq,ONE);
3818: /* exact division */
1.1 noro 3819: if ( !dont_removecont )
1.6 noro 3820: ARG2(node) = (pointer)ndc_div(trace?0:mod,hc,HCU(a));
3821: MKLIST(l,node); NEXTNODE(nd_tracelist,tn); BDY(tn) = l;
3822: }
3823: NEWRHist(r); SG(r) = HTD(a); ndl_copy(HDL(a),DL(r));
3824: nd_bound[i] = ndv_compute_bound(a);
3825: nd_psh[i] = r;
3826: if ( nd_demand ) {
3827: if ( trace ) {
3828: ndv_save(nd_ps_trace[i],i);
3829: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
3830: nd_ps_trace_sym[i] = ndv_symbolic(mod,nd_ps_trace[i]);
3831: nd_ps_trace[i] = 0;
3832: } else {
3833: ndv_save(nd_ps[i],i);
3834: nd_ps_sym[i] = ndv_symbolic(mod,nd_ps[i]);
3835: nd_ps[i] = 0;
3836: }
1.1 noro 3837: }
1.6 noro 3838: }
1.24 noro 3839: if ( sba ) {
1.27 noro 3840: nd_sba_hm = (DL *)MALLOC(nd_psn*sizeof(DL));
1.24 noro 3841: // setup signatures
1.27 noro 3842: for ( i = 0; i < nd_psn; i++ ) {
3843: SIG sig;
1.24 noro 3844:
1.27 noro 3845: NEWSIG(sig); sig->pos = i;
3846: nd_ps[i]->sig = sig;
3847: if ( nd_demand ) nd_ps_sym[i]->sig = sig;
3848: nd_psh[i]->sig = sig;
3849: if ( trace ) {
3850: nd_ps_trace[i]->sig = sig;
3851: if ( nd_demand ) nd_ps_trace_sym[i]->sig = sig;
3852: }
3853: NEWDL(nd_sba_hm[i],nd_nvar);
3854: _ndltodl(DL(nd_psh[i]),nd_sba_hm[i]);
3855: }
1.24 noro 3856: }
1.6 noro 3857: if ( nd_gentrace && nd_tracelist ) NEXT(tn) = 0;
3858: return 1;
1.1 noro 3859: }
3860:
3861: struct order_spec *append_block(struct order_spec *spec,
3862: int nv,int nalg,int ord);
3863:
3864: extern VECT current_dl_weight_vector_obj;
3865: static VECT prev_weight_vector_obj;
3866:
3867: void preprocess_algcoef(VL vv,VL av,struct order_spec *ord,LIST f,
3868: struct order_spec **ord1p,LIST *f1p,NODE *alistp)
3869: {
3870: NODE alist,t,s,r0,r,arg;
3871: VL tv;
3872: P poly;
3873: DP d;
3874: Alg alpha,dp;
3875: DAlg inv,da,hc;
3876: MP m;
3877: int i,nvar,nalg,n;
3878: NumberField nf;
3879: LIST f1,f2;
3880: struct order_spec *current_spec;
3881: VECT obj,obj0;
3882: VECT tmp;
3883:
3884: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++);
3885: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++);
3886:
3887: for ( alist = 0, tv = av; tv; tv = NEXT(tv) ) {
3888: NEXTNODE(alist,t); MKV(tv->v,poly);
3889: MKAlg(poly,alpha); BDY(t) = (pointer)alpha;
3890: tv->v = tv->v->priv;
3891: }
3892: NEXT(t) = 0;
3893:
3894: /* simplification, making polynomials monic */
3895: setfield_dalg(alist);
3896: obj_algtodalg((Obj)f,(Obj *)&f1);
3897: for ( t = BDY(f); t; t = NEXT(t) ) {
3898: initd(ord); ptod(vv,vv,(P)BDY(t),&d);
3899: hc = (DAlg)BDY(d)->c;
3900: if ( NID(hc) == N_DA ) {
3901: invdalg(hc,&inv);
3902: for ( m = BDY(d); m; m = NEXT(m) ) {
3903: muldalg(inv,(DAlg)m->c,&da); m->c = (Obj)da;
3904: }
3905: }
3906: initd(ord); dtop(vv,vv,d,(Obj *)&poly); BDY(f) = (pointer)poly;
3907: }
3908: obj_dalgtoalg((Obj)f1,(Obj *)&f);
3909:
3910: /* append alg vars to the var list */
3911: for ( tv = vv; NEXT(tv); tv = NEXT(tv) );
3912: NEXT(tv) = av;
3913:
3914: /* append a block to ord */
3915: *ord1p = append_block(ord,nvar,nalg,2);
3916:
3917: /* create generator list */
3918: nf = get_numberfield();
3919: for ( i = nalg-1, t = BDY(f); i >= 0; i-- ) {
3920: MKAlg(nf->defpoly[i],dp);
3921: MKNODE(s,dp,t); t = s;
3922: }
3923: MKLIST(f1,t);
3924: *alistp = alist;
3925: algobjtorat((Obj)f1,(Obj *)f1p);
3926:
3927: /* creating a new weight vector */
3928: prev_weight_vector_obj = obj0 = current_dl_weight_vector_obj;
3929: n = nvar+nalg+1;
3930: MKVECT(obj,n);
3931: if ( obj0 && obj0->len == nvar )
3932: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = BDY(obj0)[i];
3933: else
3934: for ( i = 0; i < nvar; i++ ) BDY(obj)[i] = (pointer)ONE;
3935: for ( i = 0; i < nalg; i++ ) BDY(obj)[i+nvar] = 0;
3936: BDY(obj)[n-1] = (pointer)ONE;
3937: arg = mknode(1,obj);
3938: Pdp_set_weight(arg,&tmp);
3939: }
3940:
3941: NODE postprocess_algcoef(VL av,NODE alist,NODE r)
3942: {
3943: NODE s,t,u0,u;
3944: P p;
3945: VL tv;
3946: Obj obj;
3947: VECT tmp;
3948: NODE arg;
3949:
3950: u0 = 0;
3951: for ( t = r; t; t = NEXT(t) ) {
3952: p = (P)BDY(t);
3953: for ( tv = av, s = alist; tv; tv = NEXT(tv), s = NEXT(s) ) {
3954: substr(CO,0,(Obj)p,tv->v,(Obj)BDY(s),&obj); p = (P)obj;
3955: }
3956: if ( OID(p) == O_P || (OID(p) == O_N && NID((Num)p) != N_A) ) {
3957: NEXTNODE(u0,u);
3958: BDY(u) = (pointer)p;
3959: }
3960: }
3961: arg = mknode(1,prev_weight_vector_obj);
3962: Pdp_set_weight(arg,&tmp);
3963:
3964: return u0;
3965: }
3966:
3967: void nd_gr(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
3968: {
3969: VL tv,fv,vv,vc,av;
3970: NODE fd,fd0,r,r0,t,x,s,xx,alist;
3971: int e,max,nvar,i;
3972: NDV b;
3973: int ishomo,nalg,mrank,trank,wmax,len;
3974: NMV a;
3975: Alg alpha,dp;
3976: P p,zp;
3977: Q dmy;
3978: LIST f1,f2,zpl;
3979: Obj obj;
3980: NumberField nf;
3981: struct order_spec *ord1;
3982: NODE tr,tl1,tl2,tl3,tl4,nzlist;
3983: LIST l1,l2,l3,l4,l5;
3984: int j;
3985: Z jq,bpe,last_nonzero;
3986: int *perm;
3987: EPOS oepos;
3988: int obpe,oadv,ompos,cbpe;
1.15 noro 3989: VECT hvect;
1.1 noro 3990:
3991: nd_module = 0;
3992: if ( !m && Demand ) nd_demand = 1;
3993: else nd_demand = 0;
3994: parse_nd_option(current_option);
3995:
3996: if ( DP_Multiple )
3997: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
3998: #if 0
3999: ndv_alloc = 0;
4000: #endif
4001: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4002: if ( m && nd_vc )
4003: error("nd_{gr,f4} : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4004: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4005: switch ( ord->id ) {
4006: case 1:
4007: if ( ord->nv != nvar )
4008: error("nd_{gr,f4} : invalid order specification");
4009: break;
4010: default:
4011: break;
4012: }
4013: nd_nalg = 0;
4014: av = 0;
4015: if ( !m ) {
4016: get_algtree((Obj)f,&av);
4017: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4018: nd_ntrans = nvar;
4019: nd_nalg = nalg;
4020: /* #i -> t#i */
4021: if ( nalg ) {
4022: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4023: ord = ord1;
4024: f = f1;
4025: }
4026: nvar += nalg;
4027: }
4028: nd_init_ord(ord);
4029: mrank = 0;
4030: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4031: for ( tv = vv; tv; tv = NEXT(tv) ) {
4032: if ( nd_module ) {
1.16 noro 4033: if ( OID(BDY(t)) == O_DPM ) {
4034: e = dpm_getdeg((DPM)BDY(t),&trank);
4035: max = MAX(e,max);
4036: mrank = MAX(mrank,trank);
4037: } else {
4038: s = BDY((LIST)BDY(t));
4039: trank = length(s);
4040: mrank = MAX(mrank,trank);
4041: for ( ; s; s = NEXT(s) ) {
4042: e = getdeg(tv->v,(P)BDY(s));
4043: max = MAX(e,max);
4044: }
1.1 noro 4045: }
4046: } else {
4047: e = getdeg(tv->v,(P)BDY(t));
4048: max = MAX(e,max);
4049: }
4050: }
4051: nd_setup_parameters(nvar,nd_nzlist?0:max);
4052: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4053: ishomo = 1;
4054: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4055: if ( nd_module ) {
1.16 noro 4056: if ( OID(BDY(t)) == O_DPM ) {
4057: Z cont;
4058: DPM zdpm;
4059:
4060: if ( !m && !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
4061: else zdpm = (DPM)BDY(t);
4062: b = (pointer)dpmtondv(m,zdpm);
4063: } else {
4064: if ( !m && !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4065: else zpl = (LIST)BDY(t);
1.1 noro 4066: b = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4067: }
1.1 noro 4068: } else {
4069: if ( !m && !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4070: else zp = (P)BDY(t);
4071: b = (pointer)ptondv(CO,vv,zp);
4072: }
4073: if ( ishomo )
4074: ishomo = ishomo && ndv_ishomo(b);
4075: if ( m ) ndv_mod(m,b);
4076: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4077: }
4078: if ( fd0 ) NEXT(fd) = 0;
4079:
4080: if ( !ishomo && homo ) {
4081: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4082: b = (NDV)BDY(t); len = LEN(b);
4083: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4084: wmax = MAX(TD(DL(a)),wmax);
4085: }
4086: homogenize_order(ord,nvar,&ord1);
4087: nd_init_ord(ord1);
4088: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4089: for ( t = fd0; t; t = NEXT(t) )
4090: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4091: }
4092:
1.24 noro 4093: ndv_setup(m,0,fd0,(nd_gbblock||nd_splist||nd_check_splist)?1:0,0,0);
1.1 noro 4094: if ( nd_gentrace ) {
4095: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4096: }
4097: if ( nd_splist ) {
4098: *rp = compute_splist();
4099: return;
4100: }
4101: if ( nd_check_splist ) {
4102: if ( f4 ) {
4103: if ( check_splist_f4(m,nd_check_splist) ) *rp = (LIST)ONE;
4104: else *rp = 0;
4105: } else {
4106: if ( check_splist(m,nd_check_splist) ) *rp = (LIST)ONE;
4107: else *rp = 0;
4108: }
4109: return;
4110: }
4111: x = f4?nd_f4(m,0,&perm):nd_gb(m,ishomo || homo,0,0,&perm);
4112: if ( !x ) {
4113: *rp = 0; return;
4114: }
1.15 noro 4115: if ( nd_gentrace ) {
4116: MKVECT(hvect,nd_psn);
4117: for ( i = 0; i < nd_psn; i++ )
4118: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4119: }
1.1 noro 4120: if ( !ishomo && homo ) {
4121: /* dehomogenization */
4122: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4123: nd_init_ord(ord);
4124: nd_setup_parameters(nvar,0);
4125: }
4126: nd_demand = 0;
4127: if ( nd_module && nd_intersect ) {
4128: for ( j = nd_psn-1, x = 0; j >= 0; j-- )
1.17 noro 4129: if ( MPOS(DL(nd_psh[j])) > nd_intersect ) {
1.1 noro 4130: MKNODE(xx,(pointer)((unsigned long)j),x); x = xx;
4131: }
4132: conv_ilist(nd_demand,0,x,0);
4133: goto FINAL;
4134: }
4135: if ( nd_gentrace && f4 ) { nzlist = nd_alltracelist; }
4136: x = ndv_reducebase(x,perm);
4137: if ( nd_gentrace && !f4 ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4138: x = ndv_reduceall(m,x);
4139: cbpe = nd_bpe;
4140: if ( nd_gentrace && !f4 ) {
4141: tl2 = nd_alltracelist; nd_alltracelist = 0;
4142: ndv_check_membership(m,fd0,obpe,oadv,oepos,x);
4143: tl3 = nd_alltracelist; nd_alltracelist = 0;
4144: if ( nd_gensyz ) {
4145: nd_gb(m,0,1,1,0);
4146: tl4 = nd_alltracelist; nd_alltracelist = 0;
4147: } else tl4 = 0;
4148: }
4149: nd_bpe = cbpe;
4150: nd_setup_parameters(nd_nvar,0);
4151: FINAL:
4152: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
1.16 noro 4153: NEXTNODE(r0,r);
4154: if ( nd_module ) {
4155: if ( retdp ) BDY(r) = ndvtodpm(m,BDY(t));
4156: else BDY(r) = ndvtopl(m,CO,vv,BDY(t),mrank);
4157: } else if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
4158: else BDY(r) = ndvtop(m,CO,vv,BDY(t));
1.1 noro 4159: }
4160: if ( r0 ) NEXT(r) = 0;
4161: if ( !m && nd_nalg )
4162: r0 = postprocess_algcoef(av,alist,r0);
4163: MKLIST(*rp,r0);
4164: if ( nd_gentrace ) {
4165: if ( f4 ) {
1.6 noro 4166: STOZ(16,bpe);
4167: STOZ(nd_last_nonzero,last_nonzero);
1.15 noro 4168: tr = mknode(6,*rp,(!ishomo&&homo)?ONE:0,BDY(nzlist),bpe,last_nonzero,hvect); MKLIST(*rp,tr);
1.1 noro 4169: } else {
4170: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4171: tl3 = reverse_node(tl3);
4172: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4173: for ( t = tl2; t; t = NEXT(t) ) {
4174: /* s = [i,[*,j,*,*],...] */
4175: s = BDY((LIST)BDY(t));
1.6 noro 4176: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4177: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4178: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4179: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4180: }
4181: }
4182: for ( j = length(x)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4183: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4184: }
4185: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4186: MKLIST(l5,tl4);
1.6 noro 4187: STOZ(nd_bpe,bpe);
1.15 noro 4188: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4189: }
4190: }
4191: #if 0
4192: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
4193: #endif
4194: }
4195:
1.28 ! noro 4196: NODE nd_sba_f4(int m,int **indp);
! 4197:
! 4198: void nd_sba(LIST f,LIST v,int m,int homo,int retdp,int f4,struct order_spec *ord,LIST *rp)
1.24 noro 4199: {
4200: VL tv,fv,vv,vc,av;
4201: NODE fd,fd0,r,r0,t,x,s,xx;
4202: int e,max,nvar,i;
4203: NDV b;
4204: int ishomo,nalg,wmax,len;
4205: NMV a;
4206: P p,zp;
4207: Q dmy;
4208: struct order_spec *ord1;
4209: int j;
4210: int *perm;
4211: EPOS oepos;
4212: int obpe,oadv,ompos,cbpe;
4213:
4214: nd_module = 0;
4215: nd_demand = 0;
4216: parse_nd_option(current_option);
4217:
4218: if ( DP_Multiple )
4219: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4220: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4221: if ( m && nd_vc )
4222: error("nd_sba : computation over Fp(X) is unsupported. Use dp_gr_mod_main().");
4223: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4224: switch ( ord->id ) {
4225: case 1:
4226: if ( ord->nv != nvar )
4227: error("nd_sba : invalid order specification");
4228: break;
4229: default:
4230: break;
4231: }
4232: nd_nalg = 0;
4233: nd_init_ord(ord);
4234: // for SIG comparison
4235: initd(ord);
4236: for ( t = BDY(f), max = 1; t; t = NEXT(t) ) {
4237: for ( tv = vv; tv; tv = NEXT(tv) ) {
4238: e = getdeg(tv->v,(P)BDY(t));
4239: max = MAX(e,max);
4240: }
4241: }
1.25 noro 4242: nd_setup_parameters(nvar,max);
1.24 noro 4243: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4244: ishomo = 1;
4245: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4246: if ( !m ) ptozp((P)BDY(t),1,&dmy,&zp);
4247: else zp = (P)BDY(t);
4248: b = (pointer)ptondv(CO,vv,zp);
4249: if ( ishomo )
4250: ishomo = ishomo && ndv_ishomo(b);
4251: if ( m ) ndv_mod(m,b);
4252: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4253: }
4254: if ( fd0 ) NEXT(fd) = 0;
4255:
4256: if ( !ishomo && homo ) {
4257: for ( t = fd0, wmax = max; t; t = NEXT(t) ) {
4258: b = (NDV)BDY(t); len = LEN(b);
4259: for ( a = BDY(b), i = 0; i < len; i++, NMV_ADV(a) )
4260: wmax = MAX(TD(DL(a)),wmax);
4261: }
4262: homogenize_order(ord,nvar,&ord1);
4263: nd_init_ord(ord1);
4264: nd_setup_parameters(nvar+1,nd_nzlist?0:wmax);
4265: for ( t = fd0; t; t = NEXT(t) )
4266: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4267: }
4268:
4269: ndv_setup(m,0,fd0,0,0,1);
1.28 ! noro 4270: x = f4 ? nd_sba_f4(m,&perm) : nd_sba_buch(m,ishomo || homo,&perm);
1.24 noro 4271: if ( !x ) {
4272: *rp = 0; return;
4273: }
4274: if ( !ishomo && homo ) {
4275: /* dehomogenization */
4276: for ( t = x; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4277: nd_init_ord(ord);
4278: nd_setup_parameters(nvar,0);
4279: }
4280: nd_demand = 0;
4281: x = ndv_reducebase(x,perm);
4282: x = ndv_reduceall(m,x);
4283: nd_setup_parameters(nd_nvar,0);
4284: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4285: NEXTNODE(r0,r);
4286: if ( retdp ) BDY(r) = ndvtodp(m,BDY(t));
4287: BDY(r) = ndvtop(m,CO,vv,BDY(t));
4288: }
4289: if ( r0 ) NEXT(r) = 0;
4290: MKLIST(*rp,r0);
4291: }
4292:
1.1 noro 4293: void nd_gr_postproc(LIST f,LIST v,int m,struct order_spec *ord,int do_check,LIST *rp)
4294: {
4295: VL tv,fv,vv,vc,av;
4296: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4297: int e,max,nvar,i;
4298: NDV b;
4299: int ishomo,nalg;
4300: Alg alpha,dp;
4301: P p,zp;
4302: Q dmy;
4303: LIST f1,f2;
4304: Obj obj;
4305: NumberField nf;
4306: struct order_spec *ord1;
4307: int *perm;
4308:
4309: parse_nd_option(current_option);
4310: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4311: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4312: switch ( ord->id ) {
4313: case 1:
4314: if ( ord->nv != nvar )
4315: error("nd_check : invalid order specification");
4316: break;
4317: default:
4318: break;
4319: }
4320: nd_nalg = 0;
4321: av = 0;
4322: if ( !m ) {
4323: get_algtree((Obj)f,&av);
4324: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4325: nd_ntrans = nvar;
4326: nd_nalg = nalg;
4327: /* #i -> t#i */
4328: if ( nalg ) {
4329: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4330: ord = ord1;
4331: f = f1;
4332: }
4333: nvar += nalg;
4334: }
4335: nd_init_ord(ord);
4336: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4337: for ( tv = vv; tv; tv = NEXT(tv) ) {
4338: e = getdeg(tv->v,(P)BDY(t));
4339: max = MAX(e,max);
4340: }
4341: nd_setup_parameters(nvar,max);
4342: ishomo = 1;
4343: for ( fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4344: ptozp((P)BDY(t),1,&dmy,&zp);
4345: b = (pointer)ptondv(CO,vv,zp);
4346: if ( ishomo )
4347: ishomo = ishomo && ndv_ishomo(b);
4348: if ( m ) ndv_mod(m,b);
4349: if ( b ) { NEXTNODE(fd0,fd); BDY(fd) = (pointer)b; }
4350: }
4351: if ( fd0 ) NEXT(fd) = 0;
1.24 noro 4352: ndv_setup(m,0,fd0,0,1,0);
1.1 noro 4353: for ( x = 0, i = 0; i < nd_psn; i++ )
4354: x = update_base(x,i);
4355: if ( do_check ) {
4356: x = nd_gb(m,ishomo,1,0,&perm);
4357: if ( !x ) {
4358: *rp = 0;
4359: return;
4360: }
4361: } else {
4362: #if 0
4363: /* bug ? */
4364: for ( t = x; t; t = NEXT(t) )
4365: BDY(t) = (pointer)nd_ps[(long)BDY(t)];
4366: #else
4367: conv_ilist(0,0,x,&perm);
4368: #endif
4369: }
4370: x = ndv_reducebase(x,perm);
4371: x = ndv_reduceall(m,x);
4372: for ( r0 = 0, t = x; t; t = NEXT(t) ) {
4373: NEXTNODE(r0,r);
4374: BDY(r) = ndvtop(m,CO,vv,BDY(t));
4375: }
4376: if ( r0 ) NEXT(r) = 0;
4377: if ( !m && nd_nalg )
4378: r0 = postprocess_algcoef(av,alist,r0);
4379: MKLIST(*rp,r0);
4380: }
4381:
4382: NDV recompute_trace(NODE trace,NDV *p,int m);
4383: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp);
4384:
4385: NDV recompute_trace(NODE ti,NDV *p,int mod)
4386: {
4387: int c,c1,c2,i;
4388: NM mul,m,tail;
4389: ND d,r,rm;
4390: NODE sj;
4391: NDV red;
4392: Obj mj;
4393:
4394: mul = (NM)MALLOC(sizeof(struct oNM)+(nd_wpd-1)*sizeof(UINT));
4395: CM(mul) = 1;
4396: tail = 0;
4397: for ( i = 0, d = r = 0; ti; ti = NEXT(ti), i++ ) {
4398: sj = BDY((LIST)BDY(ti));
4399: if ( ARG0(sj) ) {
1.6 noro 4400: red = p[ZTOS((Q)ARG1(sj))];
1.1 noro 4401: mj = (Obj)ARG2(sj);
4402: if ( OID(mj) != O_DP ) ndl_zero(DL(mul));
4403: else dltondl(nd_nvar,BDY((DP)mj)->dl,DL(mul));
4404: rm = ndv_mul_nm(mod,mul,red);
4405: if ( !r ) r = rm;
4406: else {
4407: for ( m = BDY(r); m && !ndl_equal(m->dl,BDY(rm)->dl); m = NEXT(m), LEN(r)-- ) {
4408: if ( d ) {
4409: NEXT(tail) = m; tail = m; LEN(d)++;
4410: } else {
4411: MKND(nd_nvar,m,1,d); tail = BDY(d);
4412: }
4413: }
4414: if ( !m ) return 0; /* failure */
4415: else {
4416: BDY(r) = m;
4417: if ( mod > 0 || mod == -1 ) {
4418: c1 = invm(HCM(rm),mod); c2 = mod-HCM(r);
4419: DMAR(c1,c2,0,mod,c);
4420: nd_mul_c(mod,rm,c);
4421: } else {
4422: Z t,u;
4423:
4424: chsgnlf(HCZ(r),&t);
4425: divlf(t,HCZ(rm),&u);
4426: nd_mul_c_lf(rm,u);
4427: }
4428: r = nd_add(mod,r,rm);
4429: }
4430: }
4431: }
4432: }
4433: if ( tail ) NEXT(tail) = 0;
4434: d = nd_add(mod,d,r);
4435: nd_mul_c(mod,d,invm(HCM(d),mod));
4436: return ndtondv(mod,d);
4437: }
4438:
4439: void nd_gr_recompute_trace(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,LIST *rp)
4440: {
4441: VL tv,fv,vv,vc,av;
4442: NODE fd,fd0,r,r0,t,x,s,xx,alist;
4443: int e,max,nvar,i;
4444: NDV b;
4445: int ishomo,nalg;
4446: Alg alpha,dp;
4447: P p,zp;
4448: Q dmy;
4449: LIST f1,f2;
4450: Obj obj;
4451: NumberField nf;
4452: struct order_spec *ord1;
4453: NODE permtrace,intred,ind,perm,trace,ti;
4454: int len,n,j;
4455: NDV *db,*pb;
4456:
4457: parse_nd_option(current_option);
4458: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4459: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4460: switch ( ord->id ) {
4461: case 1:
4462: if ( ord->nv != nvar )
4463: error("nd_check : invalid order specification");
4464: break;
4465: default:
4466: break;
4467: }
4468: nd_init_ord(ord);
1.6 noro 4469: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 4470: nd_setup_parameters(nvar,0);
4471:
4472: len = length(BDY(f));
4473: db = (NDV *)MALLOC(len*sizeof(NDV *));
4474: for ( i = 0, t = BDY(f); t; i++, t = NEXT(t) ) {
4475: ptozp((P)BDY(t),1,&dmy,&zp);
4476: b = ptondv(CO,vv,zp);
4477: ndv_mod(m,b);
4478: ndv_mul_c(m,b,invm(HCM(b),m));
4479: db[i] = b;
4480: }
4481:
4482: permtrace = BDY((LIST)ARG2(BDY(tlist)));
4483: intred = BDY((LIST)ARG3(BDY(tlist)));
4484: ind = BDY((LIST)ARG4(BDY(tlist)));
4485: perm = BDY((LIST)ARG0(permtrace));
4486: trace = NEXT(permtrace);
4487:
4488: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 4489: j = ZTOS((Q)ARG0(BDY((LIST)BDY(t))));
1.1 noro 4490: if ( j > i ) i = j;
4491: }
4492: n = i+1;
4493: pb = (NDV *)MALLOC(n*sizeof(NDV *));
4494: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
4495: ti = BDY((LIST)BDY(t));
1.6 noro 4496: pb[ZTOS((Q)ARG0(ti))] = db[ZTOS((Q)ARG1(ti))];
1.1 noro 4497: }
4498: for ( t = trace; t; t = NEXT(t) ) {
4499: ti = BDY((LIST)BDY(t));
1.6 noro 4500: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4501: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4502: if ( DP_Print ) {
4503: fprintf(asir_out,"."); fflush(asir_out);
4504: }
4505: }
4506: for ( t = intred; t; t = NEXT(t) ) {
4507: ti = BDY((LIST)BDY(t));
1.6 noro 4508: pb[ZTOS((Q)ARG0(ti))] = recompute_trace(BDY((LIST)ARG1(ti)),pb,m);
4509: if ( !pb[ZTOS((Q)ARG0(ti))] ) { *rp = 0; return; }
1.1 noro 4510: if ( DP_Print ) {
4511: fprintf(asir_out,"*"); fflush(asir_out);
4512: }
4513: }
4514: for ( r0 = 0, t = ind; t; t = NEXT(t) ) {
4515: NEXTNODE(r0,r);
1.6 noro 4516: b = pb[ZTOS((Q)BDY(t))];
1.1 noro 4517: ndv_mul_c(m,b,invm(HCM(b),m));
4518: #if 0
1.6 noro 4519: BDY(r) = ndvtop(m,CO,vv,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4520: #else
1.6 noro 4521: BDY(r) = ndvtodp(m,pb[ZTOS((Q)BDY(t))]);
1.1 noro 4522: #endif
4523: }
4524: if ( r0 ) NEXT(r) = 0;
4525: MKLIST(*rp,r0);
4526: if ( DP_Print ) fprintf(asir_out,"\n");
4527: }
4528:
1.16 noro 4529: 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 4530: {
4531: VL tv,fv,vv,vc,av;
4532: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
4533: int m,nocheck,nvar,mindex,e,max;
4534: NDV c;
4535: NMV a;
4536: P p,zp;
4537: Q dmy;
4538: EPOS oepos;
4539: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
4540: Alg alpha,dp;
4541: P poly;
4542: LIST f1,f2,zpl;
4543: Obj obj;
4544: NumberField nf;
4545: struct order_spec *ord1;
4546: struct oEGT eg_check,eg0,eg1;
4547: NODE tr,tl1,tl2,tl3,tl4;
4548: LIST l1,l2,l3,l4,l5;
4549: int *perm;
4550: int j,ret;
4551: Z jq,bpe;
1.15 noro 4552: VECT hvect;
1.1 noro 4553:
4554: nd_module = 0;
4555: nd_lf = 0;
4556: parse_nd_option(current_option);
4557: if ( nd_lf ) {
4558: if ( f4 )
4559: nd_f4_lf_trace(f,v,trace,homo,ord,rp);
4560: else
4561: error("nd_gr_trace is not implemented yet over a large finite field");
4562: return;
4563: }
4564: if ( DP_Multiple )
4565: nd_scale = ((double)DP_Multiple)/(double)(Denominator?Denominator:1);
4566:
4567: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
4568: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
4569: switch ( ord->id ) {
4570: case 1:
4571: if ( ord->nv != nvar )
4572: error("nd_gr_trace : invalid order specification");
4573: break;
4574: default:
4575: break;
4576: }
4577:
4578: get_algtree((Obj)f,&av);
4579: for ( nalg = 0, tv = av; tv; tv = NEXT(tv), nalg++ );
4580: nd_ntrans = nvar;
4581: nd_nalg = nalg;
4582: /* #i -> t#i */
4583: if ( nalg ) {
4584: preprocess_algcoef(vv,av,ord,f,&ord1,&f1,&alist);
4585: ord = ord1;
4586: f = f1;
4587: }
4588: nvar += nalg;
4589:
4590: nocheck = 0;
4591: mindex = 0;
4592:
4593: if ( Demand ) nd_demand = 1;
4594: else nd_demand = 0;
4595:
4596: /* setup modulus */
4597: if ( trace < 0 ) {
4598: trace = -trace;
4599: nocheck = 1;
4600: }
4601: m = trace > 1 ? trace : get_lprime(mindex);
4602: nd_init_ord(ord);
4603: mrank = 0;
4604: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
4605: for ( tv = vv; tv; tv = NEXT(tv) ) {
4606: if ( nd_module ) {
1.16 noro 4607: if ( OID(BDY(t)) == O_DPM ) {
4608: e = dpm_getdeg((DPM)BDY(t),&trank);
4609: max = MAX(e,max);
4610: mrank = MAX(mrank,trank);
4611: } else {
1.1 noro 4612: s = BDY((LIST)BDY(t));
4613: trank = length(s);
4614: mrank = MAX(mrank,trank);
4615: for ( ; s; s = NEXT(s) ) {
4616: e = getdeg(tv->v,(P)BDY(s));
4617: max = MAX(e,max);
4618: }
1.16 noro 4619: }
1.1 noro 4620: } else {
4621: e = getdeg(tv->v,(P)BDY(t));
4622: max = MAX(e,max);
4623: }
4624: }
4625: nd_setup_parameters(nvar,max);
4626: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
4627: ishomo = 1;
4628: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
4629: if ( nd_module ) {
1.16 noro 4630: if ( OID(BDY(t)) == O_DPM ) {
4631: Z cont;
4632: DPM zdpm;
4633:
1.17 noro 4634: if ( !nd_gentrace ) dpm_ptozp((DPM)BDY(t),&cont,&zdpm);
1.16 noro 4635: else zdpm = (DPM)BDY(t);
4636: c = (pointer)dpmtondv(m,zdpm);
4637: } else {
4638: if ( !nd_gentrace ) pltozpl((LIST)BDY(t),&dmy,&zpl);
4639: else zpl = (LIST)BDY(t);
1.1 noro 4640: c = (pointer)pltondv(CO,vv,zpl);
1.16 noro 4641: }
1.1 noro 4642: } else {
1.16 noro 4643: if ( !nd_gentrace ) ptozp((P)BDY(t),1,&dmy,&zp);
4644: else zp = (P)BDY(t);
4645: c = (pointer)ptondv(CO,vv,zp);
1.1 noro 4646: }
4647: if ( ishomo )
4648: ishomo = ishomo && ndv_ishomo(c);
4649: if ( c ) {
4650: NEXTNODE(in0,in); BDY(in) = (pointer)c;
4651: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
4652: }
4653: }
4654: if ( in0 ) NEXT(in) = 0;
4655: if ( fd0 ) NEXT(fd) = 0;
4656: if ( !ishomo && homo ) {
4657: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
4658: c = (NDV)BDY(t); len = LEN(c);
4659: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
4660: wmax = MAX(TD(DL(a)),wmax);
4661: }
4662: homogenize_order(ord,nvar,&ord1);
4663: nd_init_ord(ord1);
4664: nd_setup_parameters(nvar+1,wmax);
4665: for ( t = fd0; t; t = NEXT(t) )
4666: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
4667: }
4668: if ( MaxDeg > 0 ) nocheck = 1;
4669: while ( 1 ) {
4670: tl1 = tl2 = tl3 = tl4 = 0;
4671: if ( Demand )
4672: nd_demand = 1;
1.24 noro 4673: ret = ndv_setup(m,1,fd0,nd_gbblock?1:0,0,0);
1.1 noro 4674: if ( nd_gentrace ) {
4675: MKLIST(l1,nd_tracelist); MKNODE(nd_alltracelist,l1,0);
4676: }
4677: if ( ret )
4678: cand = f4?nd_f4_trace(m,&perm):nd_gb_trace(m,ishomo || homo,&perm);
4679: if ( !ret || !cand ) {
4680: /* failure */
4681: if ( trace > 1 ) { *rp = 0; return; }
4682: else m = get_lprime(++mindex);
4683: continue;
4684: }
1.15 noro 4685: if ( nd_gentrace ) {
4686: MKVECT(hvect,nd_psn);
4687: for ( i = 0; i < nd_psn; i++ )
4688: ndltodp(nd_psh[i]->dl,(DP *)&BDY(hvect)[i]);
4689: }
1.1 noro 4690: if ( !ishomo && homo ) {
4691: /* dehomogenization */
4692: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
4693: nd_init_ord(ord);
4694: nd_setup_parameters(nvar,0);
4695: }
4696: nd_demand = 0;
4697: cand = ndv_reducebase(cand,perm);
4698: if ( nd_gentrace ) { tl1 = nd_alltracelist; nd_alltracelist = 0; }
4699: cand = ndv_reduceall(0,cand);
4700: cbpe = nd_bpe;
4701: if ( nd_gentrace ) { tl2 = nd_alltracelist; nd_alltracelist = 0; }
4702: get_eg(&eg0);
4703: if ( nocheck )
4704: break;
4705: if ( (ret = ndv_check_membership(0,in0,obpe,oadv,oepos,cand)) != 0 ) {
4706: if ( nd_gentrace ) {
4707: tl3 = nd_alltracelist; nd_alltracelist = 0;
4708: } else tl3 = 0;
4709: /* gbcheck : cand is a GB of Id(cand) ? */
4710: if ( nd_vc || nd_gentrace || nd_gensyz )
4711: ret = nd_gb(0,0,1,nd_gensyz?1:0,0)!=0;
4712: else
4713: ret = nd_f4(0,1,0)!=0;
4714: if ( nd_gentrace && nd_gensyz ) {
4715: tl4 = nd_alltracelist; nd_alltracelist = 0;
4716: } else tl4 = 0;
4717: }
4718: if ( ret ) break;
4719: else if ( trace > 1 ) {
4720: /* failure */
4721: *rp = 0; return;
4722: } else {
4723: /* try the next modulus */
4724: m = get_lprime(++mindex);
4725: /* reset the parameters */
4726: if ( !ishomo && homo ) {
4727: nd_init_ord(ord1);
4728: nd_setup_parameters(nvar+1,wmax);
4729: } else {
4730: nd_init_ord(ord);
4731: nd_setup_parameters(nvar,max);
4732: }
4733: }
4734: }
4735: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
4736: if ( DP_Print )
1.6 noro 4737: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 4738: /* dp->p */
4739: nd_bpe = cbpe;
4740: nd_setup_parameters(nd_nvar,0);
4741: for ( r = cand; r; r = NEXT(r) ) {
1.16 noro 4742: if ( nd_module ) {
1.17 noro 4743: if ( retdp ) BDY(r) = ndvtodpm(0,BDY(r));
1.16 noro 4744: else BDY(r) = ndvtopl(0,CO,vv,BDY(r),mrank);
1.17 noro 4745: } else if ( retdp ) BDY(r) = ndvtodp(0,BDY(r));
4746: else BDY(r) = (pointer)ndvtop(0,CO,vv,BDY(r));
1.1 noro 4747: }
4748: if ( nd_nalg )
4749: cand = postprocess_algcoef(av,alist,cand);
4750: MKLIST(*rp,cand);
4751: if ( nd_gentrace ) {
4752: tl1 = reverse_node(tl1); tl2 = reverse_node(tl2);
4753: tl3 = reverse_node(tl3);
4754: /* tl2 = [[i,[[*,j,*,*],...]],...] */
4755: for ( t = tl2; t; t = NEXT(t) ) {
4756: /* s = [i,[*,j,*,*],...] */
4757: s = BDY((LIST)BDY(t));
1.6 noro 4758: j = perm[ZTOS((Q)ARG0(s))]; STOZ(j,jq); ARG0(s) = (pointer)jq;
1.1 noro 4759: for ( s = BDY((LIST)ARG1(s)); s; s = NEXT(s) ) {
1.6 noro 4760: j = perm[ZTOS((Q)ARG1(BDY((LIST)BDY(s))))]; STOZ(j,jq);
1.1 noro 4761: ARG1(BDY((LIST)BDY(s))) = (pointer)jq;
4762: }
4763: }
4764: for ( j = length(cand)-1, t = 0; j >= 0; j-- ) {
1.6 noro 4765: STOZ(perm[j],jq); MKNODE(s,jq,t); t = s;
1.1 noro 4766: }
4767: MKLIST(l1,tl1); MKLIST(l2,tl2); MKLIST(l3,t); MKLIST(l4,tl3);
4768: MKLIST(l5,tl4);
1.6 noro 4769: STOZ(nd_bpe,bpe);
1.15 noro 4770: tr = mknode(9,*rp,(!ishomo&&homo)?ONE:0,l1,l2,l3,l4,l5,bpe,hvect); MKLIST(*rp,tr);
1.1 noro 4771: }
4772: }
4773:
4774: /* XXX : module element is not considered */
4775:
4776: void dltondl(int n,DL dl,UINT *r)
4777: {
4778: UINT *d;
4779: int i,j,l,s,ord_l;
4780: struct order_pair *op;
4781:
4782: d = (unsigned int *)dl->d;
4783: for ( i = 0; i < nd_wpd; i++ ) r[i] = 0;
4784: if ( nd_blockmask ) {
4785: l = nd_blockmask->n;
4786: op = nd_blockmask->order_pair;
4787: for ( j = 0, s = 0; j < l; j++ ) {
4788: ord_l = op[j].length;
4789: for ( i = 0; i < ord_l; i++, s++ ) PUT_EXP(r,s,d[s]);
4790: }
4791: TD(r) = ndl_weight(r);
4792: ndl_weight_mask(r);
4793: } else {
4794: for ( i = 0; i < n; i++ ) PUT_EXP(r,i,d[i]);
4795: TD(r) = ndl_weight(r);
4796: }
4797: }
4798:
4799: DL ndltodl(int n,UINT *ndl)
4800: {
4801: DL dl;
4802: int *d;
4803: int i,j,l,s,ord_l;
4804: struct order_pair *op;
4805:
4806: NEWDL(dl,n);
4807: dl->td = TD(ndl);
4808: d = dl->d;
4809: if ( nd_blockmask ) {
4810: l = nd_blockmask->n;
4811: op = nd_blockmask->order_pair;
4812: for ( j = 0, s = 0; j < l; j++ ) {
4813: ord_l = op[j].length;
4814: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
4815: }
4816: } else {
4817: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
4818: }
4819: return dl;
4820: }
4821:
1.24 noro 4822: void _ndltodl(UINT *ndl,DL dl)
4823: {
4824: int *d;
4825: int i,j,l,s,ord_l,n;
4826: struct order_pair *op;
4827:
4828: n = nd_nvar;
4829: dl->td = TD(ndl);
4830: d = dl->d;
4831: if ( nd_blockmask ) {
4832: l = nd_blockmask->n;
4833: op = nd_blockmask->order_pair;
4834: for ( j = 0, s = 0; j < l; j++ ) {
4835: ord_l = op[j].length;
4836: for ( i = 0; i < ord_l; i++, s++ ) d[s] = GET_EXP(ndl,s);
4837: }
4838: } else {
4839: for ( i = 0; i < n; i++ ) d[i] = GET_EXP(ndl,i);
4840: }
4841: }
4842:
1.1 noro 4843: void nmtodp(int mod,NM m,DP *r)
4844: {
4845: DP dp;
4846: MP mr;
4847:
4848: NEWMP(mr);
4849: mr->dl = ndltodl(nd_nvar,DL(m));
4850: mr->c = (Obj)ndctop(mod,m->c);
4851: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
4852: *r = dp;
4853: }
4854:
1.15 noro 4855: void ndltodp(UINT *d,DP *r)
4856: {
4857: DP dp;
4858: MP mr;
4859:
4860: NEWMP(mr);
4861: mr->dl = ndltodl(nd_nvar,d);
4862: mr->c = (Obj)ONE;
4863: NEXT(mr) = 0; MKDP(nd_nvar,mr,dp); dp->sugar = mr->dl->td;
4864: *r = dp;
4865: }
4866:
1.1 noro 4867: void ndl_print(UINT *dl)
4868: {
4869: int n;
4870: int i,j,l,ord_l,s,s0;
4871: struct order_pair *op;
4872:
4873: n = nd_nvar;
4874: printf("<<");
4875: if ( nd_blockmask ) {
4876: l = nd_blockmask->n;
4877: op = nd_blockmask->order_pair;
4878: for ( j = 0, s = s0 = 0; j < l; j++ ) {
4879: ord_l = op[j].length;
4880: for ( i = 0; i < ord_l; i++, s++ )
4881: printf(s==n-1?"%d":"%d,",GET_EXP(dl,s));
4882: }
4883: } else {
4884: for ( i = 0; i < n; i++ ) printf(i==n-1?"%d":"%d,",GET_EXP(dl,i));
4885: }
4886: printf(">>");
4887: if ( nd_module && MPOS(dl) )
4888: printf("*e%d",MPOS(dl));
4889: }
4890:
4891: void nd_print(ND p)
4892: {
4893: NM m;
4894:
4895: if ( !p )
4896: printf("0\n");
4897: else {
4898: for ( m = BDY(p); m; m = NEXT(m) ) {
4899: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 ! noro 4900: else printf("+%ld*",CM(m));
1.1 noro 4901: ndl_print(DL(m));
4902: }
4903: printf("\n");
4904: }
4905: }
4906:
4907: void nd_print_q(ND p)
4908: {
4909: NM m;
4910:
4911: if ( !p )
4912: printf("0\n");
4913: else {
4914: for ( m = BDY(p); m; m = NEXT(m) ) {
4915: printf("+");
1.6 noro 4916: printexpr(CO,(Obj)CZ(m));
1.1 noro 4917: printf("*");
4918: ndl_print(DL(m));
4919: }
4920: printf("\n");
4921: }
4922: }
4923:
4924: void ndp_print(ND_pairs d)
4925: {
4926: ND_pairs t;
4927:
4928: for ( t = d; t; t = NEXT(t) ) printf("%d,%d ",t->i1,t->i2);
4929: printf("\n");
4930: }
4931:
4932: void nd_removecont(int mod,ND p)
4933: {
4934: int i,n;
4935: Z *w;
4936: NM m;
4937: struct oVECT v;
4938:
4939: if ( mod == -1 ) nd_mul_c(mod,p,_invsf(HCM(p)));
4940: else if ( mod == -2 ) {
4941: Z inv;
4942: divlf(ONE,HCZ(p),&inv);
4943: nd_mul_c_lf(p,inv);
4944: } else if ( mod ) nd_mul_c(mod,p,invm(HCM(p),mod));
4945: else {
4946: for ( m = BDY(p), n = 0; m; m = NEXT(m), n++ );
4947: w = (Z *)MALLOC(n*sizeof(Q));
4948: v.len = n;
4949: v.body = (pointer *)w;
1.6 noro 4950: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 4951: removecont_array((P *)w,n,1);
1.6 noro 4952: for ( m = BDY(p), i = 0; i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 4953: }
4954: }
4955:
4956: void nd_removecont2(ND p1,ND p2)
4957: {
4958: int i,n1,n2,n;
4959: Z *w;
4960: NM m;
4961: struct oVECT v;
4962:
4963: n1 = nd_length(p1);
4964: n2 = nd_length(p2);
4965: n = n1+n2;
4966: w = (Z *)MALLOC(n*sizeof(Q));
4967: v.len = n;
4968: v.body = (pointer *)w;
4969: i = 0;
4970: if ( p1 )
1.6 noro 4971: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 4972: if ( p2 )
1.6 noro 4973: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) w[i] = CZ(m);
1.1 noro 4974: removecont_array((P *)w,n,1);
4975: i = 0;
4976: if ( p1 )
1.6 noro 4977: for ( m = BDY(p1); i < n1; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 4978: if ( p2 )
1.6 noro 4979: for ( m = BDY(p2); i < n; m = NEXT(m), i++ ) CZ(m) = w[i];
1.1 noro 4980: }
4981:
4982: void ndv_removecont(int mod,NDV p)
4983: {
4984: int i,len,all_p;
4985: Z *c;
4986: P *w;
4987: Z dvr,t;
4988: P g,cont,tp;
4989: NMV m;
4990:
4991: if ( mod == -1 )
4992: ndv_mul_c(mod,p,_invsf(HCM(p)));
4993: else if ( mod == -2 ) {
4994: Z inv;
4995: divlf(ONE,HCZ(p),&inv);
4996: ndv_mul_c_lf(p,inv);
4997: } else if ( mod )
4998: ndv_mul_c(mod,p,invm(HCM(p),mod));
4999: else {
5000: len = p->len;
5001: w = (P *)MALLOC(len*sizeof(P));
5002: c = (Z *)MALLOC(len*sizeof(Q));
5003: for ( m = BDY(p), all_p = 1, i = 0; i < len; NMV_ADV(m), i++ ) {
5004: ptozp(CP(m),1,(Q *)&c[i],&w[i]);
5005: all_p = all_p && !NUM(w[i]);
5006: }
5007: if ( all_p ) {
5008: qltozl((Q *)c,len,&dvr); nd_heu_nezgcdnpz(nd_vc,w,len,1,&g);
5009: mulp(nd_vc,(P)dvr,g,&cont);
5010: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5011: divsp(nd_vc,CP(m),cont,&tp); CP(m) = tp;
5012: }
5013: } else {
5014: sortbynm((Q *)c,len);
5015: qltozl((Q *)c,len,&dvr);
5016: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ ) {
5017: divsp(nd_vc,CP(m),(P)dvr,&tp); CP(m) = tp;
5018: }
5019: }
5020: }
5021: }
5022:
5023: /* koko */
5024:
5025: void ndv_homogenize(NDV p,int obpe,int oadv,EPOS oepos,int ompos)
5026: {
5027: int len,i,max;
5028: NMV m,mr0,mr,t;
5029:
5030: len = p->len;
1.14 noro 5031: for ( m = BDY(p), i = 0, max = 0; i < len; NMV_OADV(m), i++ )
1.1 noro 5032: max = MAX(max,TD(DL(m)));
5033: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5034: m = (NMV)((char *)mr0+(len-1)*oadv);
5035: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5036: t = (NMV)MALLOC(nmv_adv);
5037: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
5038: ndl_homogenize(DL(m),DL(t),obpe,oepos,ompos,max);
1.6 noro 5039: CZ(mr) = CZ(m);
1.1 noro 5040: ndl_copy(DL(t),DL(mr));
5041: }
5042: NV(p)++;
5043: BDY(p) = mr0;
5044: }
5045:
5046: void ndv_dehomogenize(NDV p,struct order_spec *ord)
5047: {
5048: int i,j,adj,len,newnvar,newwpd,newadv,newexporigin,newmpos;
5049: int pos;
5050: Q *w;
5051: Q dvr,t;
5052: NMV m,r;
5053:
5054: len = p->len;
5055: newnvar = nd_nvar-1;
5056: newexporigin = nd_get_exporigin(ord);
5057: if ( nd_module ) newmpos = newexporigin-1;
5058: newwpd = newnvar/nd_epw+(newnvar%nd_epw?1:0)+newexporigin;
5059: for ( m = BDY(p), i = 0; i < len; NMV_ADV(m), i++ )
5060: ndl_dehomogenize(DL(m));
5061: if ( newwpd != nd_wpd ) {
5062: newadv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(newwpd-1)*sizeof(UINT));
5063: for ( m = r = BDY(p), i = 0; i < len; NMV_ADV(m), NDV_NADV(r), i++ ) {
1.6 noro 5064: CZ(r) = CZ(m);
1.1 noro 5065: if ( nd_module ) pos = MPOS(DL(m));
5066: for ( j = 0; j < newexporigin; j++ ) DL(r)[j] = DL(m)[j];
5067: adj = nd_exporigin-newexporigin;
5068: for ( ; j < newwpd; j++ ) DL(r)[j] = DL(m)[j+adj];
5069: if ( nd_module ) {
5070: DL(r)[newmpos] = pos;
5071: }
5072: }
5073: }
5074: NV(p)--;
5075: }
5076:
5077: void nd_heu_nezgcdnpz(VL vl,P *pl,int m,int full,P *pr)
5078: {
5079: int i;
5080: P *tpl,*tpl1;
5081: NODE l;
5082: P h,gcd,t;
5083:
5084: tpl = (P *)MALLOC(m*sizeof(P));
5085: tpl1 = (P *)MALLOC(m*sizeof(P));
5086: bcopy(pl,tpl,m*sizeof(P));
5087: gcd = (P)ONE;
5088: for ( l = nd_hcf; l; l = NEXT(l) ) {
5089: h = (P)BDY(l);
5090: while ( 1 ) {
5091: for ( i = 0; i < m; i++ )
5092: if ( !divtpz(vl,tpl[i],h,&tpl1[i]) )
5093: break;
5094: if ( i == m ) {
5095: bcopy(tpl1,tpl,m*sizeof(P));
5096: mulp(vl,gcd,h,&t); gcd = t;
5097: } else
5098: break;
5099: }
5100: }
5101: if ( DP_Print > 2 ){fprintf(asir_out,"[%d]",nmonop(gcd)); fflush(asir_out);}
5102: if ( full ) {
5103: heu_nezgcdnpz(vl,tpl,m,&t);
5104: mulp(vl,gcd,t,pr);
5105: } else
5106: *pr = gcd;
5107: }
5108:
5109: void removecont_array(P *p,int n,int full)
5110: {
5111: int all_p,all_q,i;
5112: Z *c;
5113: P *w;
5114: P t,s;
5115:
5116: for ( all_q = 1, i = 0; i < n; i++ )
5117: all_q = all_q && NUM(p[i]);
5118: if ( all_q ) {
5119: removecont_array_q((Z *)p,n);
5120: } else {
5121: c = (Z *)MALLOC(n*sizeof(Z));
5122: w = (P *)MALLOC(n*sizeof(P));
5123: for ( i = 0; i < n; i++ ) {
5124: ptozp(p[i],1,(Q *)&c[i],&w[i]);
5125: }
5126: removecont_array_q(c,n);
5127: nd_heu_nezgcdnpz(nd_vc,w,n,full,&t);
5128: for ( i = 0; i < n; i++ ) {
5129: divsp(nd_vc,w[i],t,&s); mulp(nd_vc,s,(P)c[i],&p[i]);
5130: }
5131: }
5132: }
5133:
5134: /* c is an int array */
5135:
5136: void removecont_array_q(Z *c,int n)
5137: {
5138: struct oVECT v;
5139: Z d0,d1,a,u,u1,gcd;
5140: int i,j;
5141: Z *q,*r;
5142:
5143: q = (Z *)MALLOC(n*sizeof(Z));
5144: r = (Z *)MALLOC(n*sizeof(Z));
5145: v.id = O_VECT; v.len = n; v.body = (pointer *)c;
5146: gcdvz_estimate(&v,&d0);
5147: for ( i = 0; i < n; i++ ) {
5148: divqrz(c[i],d0,&q[i],&r[i]);
5149: }
5150: for ( i = 0; i < n; i++ ) if ( r[i] ) break;
5151: if ( i < n ) {
5152: v.id = O_VECT; v.len = n; v.body = (pointer *)r;
5153: gcdvz(&v,&d1);
5154: gcdz(d0,d1,&gcd);
1.6 noro 5155: /* exact division */
5156: divsz(d0,gcd,&a);
1.1 noro 5157: for ( i = 0; i < n; i++ ) {
5158: mulz(a,q[i],&u);
5159: if ( r[i] ) {
1.6 noro 5160: /* exact division */
5161: divsz(r[i],gcd,&u1);
1.1 noro 5162: addz(u,u1,&q[i]);
5163: } else
5164: q[i] = u;
5165: }
5166: }
5167: for ( i = 0; i < n; i++ ) c[i] = q[i];
5168: }
5169:
1.4 noro 5170: void gcdv_mpz_estimate(mpz_t d0,mpz_t *c,int n);
5171:
5172: void mpz_removecont_array(mpz_t *c,int n)
5173: {
5174: mpz_t d0,a,u,u1,gcd;
5175: int i,j;
1.13 noro 5176: static mpz_t *q,*r;
5177: static int c_len = 0;
1.4 noro 5178:
5179: for ( i = 0; i < n; i++ )
5180: if ( mpz_sgn(c[i]) ) break;
5181: if ( i == n ) return;
5182: gcdv_mpz_estimate(d0,c,n);
1.13 noro 5183: if ( n > c_len ) {
5184: q = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5185: r = (mpz_t *)MALLOC(n*sizeof(mpz_t));
5186: c_len = n;
5187: }
1.4 noro 5188: for ( i = 0; i < n; i++ ) {
5189: mpz_init(q[i]); mpz_init(r[i]);
5190: mpz_fdiv_qr(q[i],r[i],c[i],d0);
5191: }
5192: for ( i = 0; i < n; i++ )
5193: if ( mpz_sgn(r[i]) ) break;
5194: mpz_init(gcd); mpz_init(a); mpz_init(u); mpz_init(u1);
5195: if ( i < n ) {
5196: mpz_gcd(gcd,d0,r[i]);
5197: for ( j = i+1; j < n; j++ ) mpz_gcd(gcd,gcd,r[j]);
5198: mpz_div(a,d0,gcd);
5199: for ( i = 0; i < n; i++ ) {
5200: mpz_mul(u,a,q[i]);
5201: if ( mpz_sgn(r[i]) ) {
5202: mpz_div(u1,r[i],gcd);
5203: mpz_add(q[i],u,u1);
5204: } else
5205: mpz_set(q[i],u);
5206: }
5207: }
5208: for ( i = 0; i < n; i++ )
5209: mpz_set(c[i],q[i]);
5210: }
5211:
1.1 noro 5212: void nd_mul_c(int mod,ND p,int mul)
5213: {
5214: NM m;
5215: int c,c1;
5216:
5217: if ( !p ) return;
5218: if ( mul == 1 ) return;
5219: if ( mod == -1 )
5220: for ( m = BDY(p); m; m = NEXT(m) )
5221: CM(m) = _mulsf(CM(m),mul);
5222: else
5223: for ( m = BDY(p); m; m = NEXT(m) ) {
5224: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5225: }
5226: }
5227:
5228: void nd_mul_c_lf(ND p,Z mul)
5229: {
5230: NM m;
5231: Z c;
5232:
5233: if ( !p ) return;
5234: if ( UNIZ(mul) ) return;
5235: for ( m = BDY(p); m; m = NEXT(m) ) {
5236: mullf(CZ(m),mul,&c); CZ(m) = c;
5237: }
5238: }
5239:
5240: void nd_mul_c_q(ND p,P mul)
5241: {
5242: NM m;
5243: P c;
5244:
5245: if ( !p ) return;
5246: if ( UNIQ(mul) ) return;
5247: for ( m = BDY(p); m; m = NEXT(m) ) {
5248: mulp(nd_vc,CP(m),mul,&c); CP(m) = c;
5249: }
5250: }
5251:
5252: void nd_mul_c_p(VL vl,ND p,P mul)
5253: {
5254: NM m;
5255: P c;
5256:
5257: if ( !p ) return;
5258: for ( m = BDY(p); m; m = NEXT(m) ) {
5259: mulp(vl,CP(m),mul,&c); CP(m) = c;
5260: }
5261: }
5262:
5263: void nd_free(ND p)
5264: {
5265: NM t,s;
5266:
5267: if ( !p ) return;
5268: t = BDY(p);
5269: while ( t ) {
5270: s = NEXT(t);
5271: FREENM(t);
5272: t = s;
5273: }
5274: FREEND(p);
5275: }
5276:
5277: void ndv_free(NDV p)
5278: {
5279: GCFREE(BDY(p));
5280: }
5281:
5282: void nd_append_red(UINT *d,int i)
5283: {
5284: RHist m,m0;
5285: int h;
5286:
5287: NEWRHist(m);
5288: h = ndl_hash_value(d);
5289: m->index = i;
5290: ndl_copy(d,DL(m));
5291: NEXT(m) = nd_red[h];
5292: nd_red[h] = m;
5293: }
5294:
5295: UINT *ndv_compute_bound(NDV p)
5296: {
5297: UINT *d1,*d2,*t;
5298: UINT u;
5299: int i,j,k,l,len,ind;
5300: NMV m;
5301:
5302: if ( !p )
5303: return 0;
5304: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5305: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5306: len = LEN(p);
5307: m = BDY(p); ndl_copy(DL(m),d1); NMV_ADV(m);
5308: for ( i = 1; i < len; i++, NMV_ADV(m) ) {
5309: ndl_max(DL(m),d1,d2);
5310: t = d1; d1 = d2; d2 = t;
5311: }
5312: l = nd_nvar+31;
5313: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5314: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5315: u = d1[i];
5316: k = (nd_epw-1)*nd_bpe;
5317: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5318: t[ind] = (u>>k)&nd_mask0;
5319: }
5320: for ( ; ind < l; ind++ ) t[ind] = 0;
5321: return t;
5322: }
5323:
5324: UINT *nd_compute_bound(ND p)
5325: {
5326: UINT *d1,*d2,*t;
5327: UINT u;
5328: int i,j,k,l,len,ind;
5329: NM m;
5330:
5331: if ( !p )
5332: return 0;
5333: d1 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5334: d2 = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
5335: len = LEN(p);
5336: m = BDY(p); ndl_copy(DL(m),d1); m = NEXT(m);
5337: for ( m = NEXT(m); m; m = NEXT(m) ) {
5338: ndl_lcm(DL(m),d1,d2);
5339: t = d1; d1 = d2; d2 = t;
5340: }
5341: l = nd_nvar+31;
5342: t = (UINT *)MALLOC_ATOMIC(l*sizeof(UINT));
5343: for ( i = nd_exporigin, ind = 0; i < nd_wpd; i++ ) {
5344: u = d1[i];
5345: k = (nd_epw-1)*nd_bpe;
5346: for ( j = 0; j < nd_epw; j++, k -= nd_bpe, ind++ )
5347: t[ind] = (u>>k)&nd_mask0;
5348: }
5349: for ( ; ind < l; ind++ ) t[ind] = 0;
5350: return t;
5351: }
5352:
5353: /* if nd_module == 1 then d[nd_exporigin-1] indicates the position */
5354: /* of a term. In this case we need additional 1 word. */
5355:
5356: int nd_get_exporigin(struct order_spec *ord)
5357: {
5358: switch ( ord->id ) {
1.21 noro 5359: case 0: case 2: case 256: case 258: case 300:
1.1 noro 5360: return 1+nd_module;
5361: case 1: case 257:
5362: /* block order */
5363: /* poly ring d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */
5364: /* module d[0]:weight d[1]:w0,...,d[nd_exporigin-2]:w(n-1) */
5365: return ord->ord.block.length+1+nd_module;
5366: case 3: case 259:
5367: #if 0
5368: error("nd_get_exporigin : composite order is not supported yet.");
5369: #else
5370: return 1+nd_module;
5371: #endif
5372: default:
5373: error("nd_get_exporigin : ivalid argument.");
5374: return 0;
5375: }
5376: }
5377:
5378: void nd_setup_parameters(int nvar,int max) {
5379: int i,j,n,elen,ord_o,ord_l,l,s,wpd;
5380: struct order_pair *op;
5381:
5382: nd_nvar = nvar;
5383: if ( max ) {
5384: /* XXX */
5385: if ( do_weyl ) nd_bpe = 32;
5386: else if ( max < 2 ) nd_bpe = 1;
5387: else if ( max < 4 ) nd_bpe = 2;
5388: else if ( max < 8 ) nd_bpe = 3;
5389: else if ( max < 16 ) nd_bpe = 4;
5390: else if ( max < 32 ) nd_bpe = 5;
5391: else if ( max < 64 ) nd_bpe = 6;
5392: else if ( max < 256 ) nd_bpe = 8;
5393: else if ( max < 1024 ) nd_bpe = 10;
5394: else if ( max < 65536 ) nd_bpe = 16;
5395: else nd_bpe = 32;
5396: }
5397: if ( !do_weyl && weight_check && (current_dl_weight_vector || nd_matrix) ) {
5398: UINT t;
5399: int st;
5400: int *v;
5401: /* t = max(weights) */
5402: t = 0;
5403: if ( current_dl_weight_vector )
5404: for ( i = 0, t = 0; i < nd_nvar; i++ ) {
5405: if ( (st=current_dl_weight_vector[i]) < 0 ) st = -st;
5406: if ( t < st ) t = st;
5407: }
5408: if ( nd_matrix )
5409: for ( i = 0; i < nd_matrix_len; i++ )
5410: for ( j = 0, v = nd_matrix[i]; j < nd_nvar; j++ ) {
5411: if ( (st=v[j]) < 0 ) st = -st;
5412: if ( t < st ) t = st;
5413: }
5414: /* i = bitsize of t */
5415: for ( i = 0; t; t >>=1, i++ );
5416: /* i += bitsize of nd_nvar */
5417: for ( t = nd_nvar; t; t >>=1, i++);
5418: /* nd_bpe+i = bitsize of max(weights)*max(exp)*nd_nvar */
5419: if ( (nd_bpe+i) >= 31 )
5420: error("nd_setup_parameters : too large weight");
5421: }
5422: nd_epw = (sizeof(UINT)*8)/nd_bpe;
5423: elen = nd_nvar/nd_epw+(nd_nvar%nd_epw?1:0);
5424: nd_exporigin = nd_get_exporigin(nd_ord);
5425: wpd = nd_exporigin+elen;
5426: if ( nd_module )
5427: nd_mpos = nd_exporigin-1;
5428: else
5429: nd_mpos = -1;
5430: if ( wpd != nd_wpd ) {
5431: nd_free_private_storage();
5432: nd_wpd = wpd;
5433: }
5434: if ( nd_bpe < 32 ) {
5435: nd_mask0 = (1<<nd_bpe)-1;
5436: } else {
5437: nd_mask0 = 0xffffffff;
5438: }
5439: bzero(nd_mask,sizeof(nd_mask));
5440: nd_mask1 = 0;
5441: for ( i = 0; i < nd_epw; i++ ) {
5442: nd_mask[nd_epw-i-1] = (nd_mask0<<(i*nd_bpe));
5443: nd_mask1 |= (1<<(nd_bpe-1))<<(i*nd_bpe);
5444: }
5445: nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT));
5446: nd_epos = nd_create_epos(nd_ord);
5447: nd_blockmask = nd_create_blockmask(nd_ord);
5448: nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int));
5449: }
5450:
5451: ND_pairs nd_reconstruct(int trace,ND_pairs d)
5452: {
5453: int i,obpe,oadv,h;
5454: static NM prev_nm_free_list;
5455: static ND_pairs prev_ndp_free_list;
5456: RHist mr0,mr;
5457: RHist r;
5458: RHist *old_red;
5459: ND_pairs s0,s,t;
5460: EPOS oepos;
5461:
5462: obpe = nd_bpe;
5463: oadv = nmv_adv;
5464: oepos = nd_epos;
5465: if ( obpe < 2 ) nd_bpe = 2;
5466: else if ( obpe < 3 ) nd_bpe = 3;
5467: else if ( obpe < 4 ) nd_bpe = 4;
5468: else if ( obpe < 5 ) nd_bpe = 5;
5469: else if ( obpe < 6 ) nd_bpe = 6;
5470: else if ( obpe < 8 ) nd_bpe = 8;
5471: else if ( obpe < 10 ) nd_bpe = 10;
5472: else if ( obpe < 16 ) nd_bpe = 16;
5473: else if ( obpe < 32 ) nd_bpe = 32;
5474: else error("nd_reconstruct : exponent too large");
5475:
5476: nd_setup_parameters(nd_nvar,0);
5477: prev_nm_free_list = _nm_free_list;
5478: prev_ndp_free_list = _ndp_free_list;
5479: _nm_free_list = 0;
5480: _ndp_free_list = 0;
5481: for ( i = nd_psn-1; i >= 0; i-- ) {
5482: ndv_realloc(nd_ps[i],obpe,oadv,oepos);
5483: ndv_realloc(nd_ps_sym[i],obpe,oadv,oepos);
5484: }
5485: if ( trace )
5486: for ( i = nd_psn-1; i >= 0; i-- ) {
5487: ndv_realloc(nd_ps_trace[i],obpe,oadv,oepos);
5488: ndv_realloc(nd_ps_trace_sym[i],obpe,oadv,oepos);
5489: }
5490: s0 = 0;
5491: for ( t = d; t; t = NEXT(t) ) {
5492: NEXTND_pairs(s0,s);
5493: s->i1 = t->i1;
5494: s->i2 = t->i2;
1.24 noro 5495: s->sig = t->sig;
1.1 noro 5496: SG(s) = SG(t);
5497: ndl_reconstruct(LCM(t),LCM(s),obpe,oepos);
5498: }
5499:
5500: old_red = (RHist *)MALLOC(REDTAB_LEN*sizeof(RHist));
5501: for ( i = 0; i < REDTAB_LEN; i++ ) {
5502: old_red[i] = nd_red[i];
5503: nd_red[i] = 0;
5504: }
5505: for ( i = 0; i < REDTAB_LEN; i++ )
5506: for ( r = old_red[i]; r; r = NEXT(r) ) {
5507: NEWRHist(mr);
5508: mr->index = r->index;
5509: SG(mr) = SG(r);
5510: ndl_reconstruct(DL(r),DL(mr),obpe,oepos);
5511: h = ndl_hash_value(DL(mr));
5512: NEXT(mr) = nd_red[h];
5513: nd_red[h] = mr;
1.24 noro 5514: mr->sig = r->sig;
1.1 noro 5515: }
5516: for ( i = 0; i < REDTAB_LEN; i++ ) old_red[i] = 0;
5517: old_red = 0;
5518: for ( i = 0; i < nd_psn; i++ ) {
5519: NEWRHist(r); SG(r) = SG(nd_psh[i]);
5520: ndl_reconstruct(DL(nd_psh[i]),DL(r),obpe,oepos);
1.24 noro 5521: r->sig = nd_psh[i]->sig;
1.1 noro 5522: nd_psh[i] = r;
5523: }
5524: if ( s0 ) NEXT(s) = 0;
5525: prev_nm_free_list = 0;
5526: prev_ndp_free_list = 0;
5527: #if 0
5528: GC_gcollect();
5529: #endif
5530: return s0;
5531: }
5532:
5533: void ndl_reconstruct(UINT *d,UINT *r,int obpe,EPOS oepos)
5534: {
5535: int n,i,ei,oepw,omask0,j,s,ord_l,l;
5536: struct order_pair *op;
5537:
5538: n = nd_nvar;
5539: oepw = (sizeof(UINT)*8)/obpe;
5540: omask0 = (1<<obpe)-1;
5541: TD(r) = TD(d);
5542: for ( i = nd_exporigin; i < nd_wpd; i++ ) r[i] = 0;
5543: if ( nd_blockmask ) {
5544: l = nd_blockmask->n;
5545: op = nd_blockmask->order_pair;
5546: for ( i = 1; i < nd_exporigin; i++ )
5547: r[i] = d[i];
5548: for ( j = 0, s = 0; j < l; j++ ) {
5549: ord_l = op[j].length;
5550: for ( i = 0; i < ord_l; i++, s++ ) {
5551: ei = GET_EXP_OLD(d,s);
5552: PUT_EXP(r,s,ei);
5553: }
5554: }
5555: } else {
5556: for ( i = 0; i < n; i++ ) {
5557: ei = GET_EXP_OLD(d,i);
5558: PUT_EXP(r,i,ei);
5559: }
5560: }
5561: if ( nd_module ) MPOS(r) = MPOS(d);
5562: }
5563:
5564: ND nd_copy(ND p)
5565: {
5566: NM m,mr,mr0;
5567: int c,n;
5568: ND r;
5569:
5570: if ( !p )
5571: return 0;
5572: else {
5573: for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
5574: NEXTNM(mr0,mr);
5575: CM(mr) = CM(m);
5576: ndl_copy(DL(m),DL(mr));
5577: }
5578: NEXT(mr) = 0;
5579: MKND(NV(p),mr0,LEN(p),r);
5580: SG(r) = SG(p);
5581: return r;
5582: }
5583: }
5584:
5585: int nd_sp(int mod,int trace,ND_pairs p,ND *rp)
5586: {
5587: NM m1,m2;
5588: NDV p1,p2;
5589: ND t1,t2;
5590: UINT *lcm;
5591: P gp,tp;
5592: Z g,t;
5593: Z iq;
5594: int td;
5595: LIST hist;
5596: NODE node;
5597: DP d;
5598:
5599: if ( !mod && nd_demand ) {
5600: p1 = ndv_load(p->i1); p2 = ndv_load(p->i2);
5601: } else {
5602: if ( trace ) {
5603: p1 = nd_ps_trace[p->i1]; p2 = nd_ps_trace[p->i2];
5604: } else {
5605: p1 = nd_ps[p->i1]; p2 = nd_ps[p->i2];
5606: }
5607: }
5608: lcm = LCM(p);
5609: NEWNM(m1); ndl_sub(lcm,HDL(p1),DL(m1));
5610: if ( ndl_check_bound2(p->i1,DL(m1)) ) {
5611: FREENM(m1); return 0;
5612: }
5613: NEWNM(m2); ndl_sub(lcm,HDL(p2),DL(m2));
5614: if ( ndl_check_bound2(p->i2,DL(m2)) ) {
5615: FREENM(m1); FREENM(m2); return 0;
5616: }
5617:
5618: if ( mod == -1 ) {
5619: CM(m1) = HCM(p2); CM(m2) = _chsgnsf(HCM(p1));
5620: } else if ( mod > 0 ) {
5621: CM(m1) = HCM(p2); CM(m2) = mod-HCM(p1);
5622: } else if ( mod == -2 ) {
5623: CZ(m1) = HCZ(p2); chsgnlf(HCZ(p1),&CZ(m2));
5624: } else if ( nd_vc ) {
5625: ezgcdpz(nd_vc,HCP(p1),HCP(p2),&gp);
5626: divsp(nd_vc,HCP(p2),gp,&CP(m1));
5627: divsp(nd_vc,HCP(p1),gp,&tp); chsgnp(tp,&CP(m2));
5628: } else {
1.6 noro 5629: igcd_cofactor(HCZ(p1),HCZ(p2),&g,&t,&CZ(m1)); chsgnz(t,&CZ(m2));
1.1 noro 5630: }
5631: t1 = ndv_mul_nm(mod,m1,p1); t2 = ndv_mul_nm(mod,m2,p2);
5632: *rp = nd_add(mod,t1,t2);
5633: if ( nd_gentrace ) {
5634: /* nd_tracelist is initialized */
1.6 noro 5635: STOZ(p->i1,iq); nmtodp(mod,m1,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 5636: MKLIST(hist,node); MKNODE(nd_tracelist,hist,0);
1.6 noro 5637: STOZ(p->i2,iq); nmtodp(mod,m2,&d); node = mknode(4,ONE,iq,d,ONE);
1.1 noro 5638: MKLIST(hist,node); MKNODE(node,hist,nd_tracelist);
5639: nd_tracelist = node;
5640: }
1.24 noro 5641: if ( *rp )
5642: (*rp)->sig = p->sig;
1.1 noro 5643: FREENM(m1); FREENM(m2);
5644: return 1;
5645: }
5646:
5647: void ndv_mul_c(int mod,NDV p,int mul)
5648: {
5649: NMV m;
5650: int c,c1,len,i;
5651:
5652: if ( !p ) return;
5653: len = LEN(p);
5654: if ( mod == -1 )
5655: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) )
5656: CM(m) = _mulsf(CM(m),mul);
5657: else
5658: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
5659: c1 = CM(m); DMAR(c1,mul,0,mod,c); CM(m) = c;
5660: }
5661: }
5662:
5663: void ndv_mul_c_lf(NDV p,Z mul)
5664: {
5665: NMV m;
5666: Z c;
5667: int len,i;
5668:
5669: if ( !p ) return;
5670: len = LEN(p);
5671: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
5672: mullf(CZ(m),mul,&c); CZ(m) = c;
5673: }
5674: }
5675:
5676: /* for nd_det */
5677: void ndv_mul_c_q(NDV p,Z mul)
5678: {
5679: NMV m;
5680: Z c;
5681: int len,i;
5682:
5683: if ( !p ) return;
5684: len = LEN(p);
5685: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 5686: mulz(CZ(m),mul,&c); CZ(m) = c;
1.1 noro 5687: }
5688: }
5689:
5690: ND weyl_ndv_mul_nm(int mod,NM m0,NDV p) {
5691: int n2,i,j,l,n,tlen;
5692: UINT *d0;
5693: NM *tab,*psum;
5694: ND s,r;
5695: NM t;
5696: NMV m1;
5697:
5698: if ( !p ) return 0;
5699: n = NV(p); n2 = n>>1;
5700: d0 = DL(m0);
5701: l = LEN(p);
5702: for ( i = 0, tlen = 1; i < n2; i++ ) tlen *= (GET_EXP(d0,n2+i)+1);
5703: tab = (NM *)MALLOC(tlen*sizeof(NM));
5704: psum = (NM *)MALLOC(tlen*sizeof(NM));
5705: for ( i = 0; i < tlen; i++ ) psum[i] = 0;
5706: m1 = (NMV)(((char *)BDY(p))+nmv_adv*(l-1));
5707: for ( i = l-1; i >= 0; i--, NMV_PREV(m1) ) {
5708: /* m0(NM) * m1(NMV) => tab(NM) */
5709: weyl_mul_nm_nmv(n,mod,m0,m1,tab,tlen);
5710: for ( j = 0; j < tlen; j++ ) {
5711: if ( tab[j] ) {
5712: NEXT(tab[j]) = psum[j]; psum[j] = tab[j];
5713: }
5714: }
5715: }
5716: for ( i = tlen-1, r = 0; i >= 0; i-- )
5717: if ( psum[i] ) {
5718: for ( j = 0, t = psum[i]; t; t = NEXT(t), j++ );
5719: MKND(n,psum[i],j,s);
5720: r = nd_add(mod,r,s);
5721: }
5722: if ( r ) SG(r) = SG(p)+TD(d0);
5723: return r;
5724: }
5725:
5726: /* product of monomials */
5727: /* XXX block order is not handled correctly */
5728:
5729: void weyl_mul_nm_nmv(int n,int mod,NM m0,NMV m1,NM *tab,int tlen)
5730: {
5731: int i,n2,j,s,curlen,homo,h,a,b,k,l,u,min;
5732: UINT *d0,*d1,*d,*dt,*ctab;
5733: Z *ctab_q;
5734: Z q,q1;
5735: UINT c0,c1,c;
5736: NM *p;
5737: NM m,t;
5738: int mpos;
5739:
5740: for ( i = 0; i < tlen; i++ ) tab[i] = 0;
5741: if ( !m0 || !m1 ) return;
5742: d0 = DL(m0); d1 = DL(m1); n2 = n>>1;
5743: if ( nd_module )
5744: if ( MPOS(d0) ) error("weyl_mul_nm_nmv : invalid operation");
5745:
5746: NEWNM(m); d = DL(m);
5747: if ( mod ) {
5748: c0 = CM(m0); c1 = CM(m1); DMAR(c0,c1,0,mod,c); CM(m) = c;
5749: } else if ( nd_vc )
5750: mulp(nd_vc,CP(m0),CP(m1),&CP(m));
5751: else
1.6 noro 5752: mulz(CZ(m0),CZ(m1),&CZ(m));
1.1 noro 5753: for ( i = 0; i < nd_wpd; i++ ) d[i] = 0;
5754: homo = n&1 ? 1 : 0;
5755: if ( homo ) {
5756: /* offset of h-degree */
5757: h = GET_EXP(d0,n-1)+GET_EXP(d1,n-1);
5758: PUT_EXP(DL(m),n-1,h);
5759: TD(DL(m)) = h;
5760: if ( nd_blockmask ) ndl_weight_mask(DL(m));
5761: }
5762: tab[0] = m;
5763: NEWNM(m); d = DL(m);
5764: for ( i = 0, curlen = 1; i < n2; i++ ) {
5765: a = GET_EXP(d0,i); b = GET_EXP(d1,n2+i);
5766: k = GET_EXP(d0,n2+i); l = GET_EXP(d1,i);
5767: /* xi^a*(Di^k*xi^l)*Di^b */
5768: a += l; b += k;
5769: s = MUL_WEIGHT(a,i)+MUL_WEIGHT(b,n2+i);
5770: if ( !k || !l ) {
5771: for ( j = 0; j < curlen; j++ )
5772: if ( (t = tab[j]) != 0 ) {
5773: dt = DL(t);
5774: PUT_EXP(dt,i,a); PUT_EXP(dt,n2+i,b); TD(dt) += s;
5775: if ( nd_blockmask ) ndl_weight_mask(dt);
5776: }
5777: curlen *= k+1;
5778: continue;
5779: }
5780: min = MIN(k,l);
5781: if ( mod ) {
5782: ctab = (UINT *)MALLOC((min+1)*sizeof(UINT));
5783: mkwcm(k,l,mod,(int *)ctab);
5784: } else {
5785: ctab_q = (Z *)MALLOC((min+1)*sizeof(Z));
5786: mkwc(k,l,ctab_q);
5787: }
5788: for ( j = min; j >= 0; j-- ) {
5789: for ( u = 0; u < nd_wpd; u++ ) d[u] = 0;
5790: PUT_EXP(d,i,a-j); PUT_EXP(d,n2+i,b-j);
5791: h = MUL_WEIGHT(a-j,i)+MUL_WEIGHT(b-j,n2+i);
5792: if ( homo ) {
5793: TD(d) = s;
5794: PUT_EXP(d,n-1,s-h);
5795: } else TD(d) = h;
5796: if ( nd_blockmask ) ndl_weight_mask(d);
5797: if ( mod ) c = ctab[j];
5798: else q = ctab_q[j];
5799: p = tab+curlen*j;
5800: if ( j == 0 ) {
5801: for ( u = 0; u < curlen; u++, p++ ) {
5802: if ( tab[u] ) {
5803: ndl_addto(DL(tab[u]),d);
5804: if ( mod ) {
5805: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(tab[u]) = c1;
5806: } else if ( nd_vc )
5807: mulp(nd_vc,CP(tab[u]),(P)q,&CP(tab[u]));
5808: else {
1.6 noro 5809: mulz(CZ(tab[u]),q,&q1); CZ(tab[u]) = q1;
1.1 noro 5810: }
5811: }
5812: }
5813: } else {
5814: for ( u = 0; u < curlen; u++, p++ ) {
5815: if ( tab[u] ) {
5816: NEWNM(t);
5817: ndl_add(DL(tab[u]),d,DL(t));
5818: if ( mod ) {
5819: c0 = CM(tab[u]); DMAR(c0,c,0,mod,c1); CM(t) = c1;
5820: } else if ( nd_vc )
5821: mulp(nd_vc,CP(tab[u]),(P)q,&CP(t));
5822: else
1.6 noro 5823: mulz(CZ(tab[u]),q,&CZ(t));
1.1 noro 5824: *p = t;
5825: }
5826: }
5827: }
5828: }
5829: curlen *= k+1;
5830: }
5831: FREENM(m);
5832: if ( nd_module ) {
5833: mpos = MPOS(d1);
5834: for ( i = 0; i < tlen; i++ )
5835: if ( tab[i] ) {
5836: d = DL(tab[i]);
5837: MPOS(d) = mpos;
5838: TD(d) = ndl_weight(d);
5839: }
5840: }
5841: }
5842:
5843: ND ndv_mul_nm_symbolic(NM m0,NDV p)
5844: {
5845: NM mr,mr0;
5846: NMV m;
5847: UINT *d,*dt,*dm;
5848: int c,n,td,i,c1,c2,len;
5849: Q q;
5850: ND r;
5851:
5852: if ( !p ) return 0;
5853: else {
5854: n = NV(p); m = BDY(p);
5855: d = DL(m0);
5856: len = LEN(p);
5857: mr0 = 0;
5858: td = TD(d);
5859: c = CM(m0);
5860: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
5861: NEXTNM(mr0,mr);
5862: CM(mr) = 1;
5863: ndl_add(DL(m),d,DL(mr));
5864: }
5865: NEXT(mr) = 0;
5866: MKND(NV(p),mr0,len,r);
5867: SG(r) = SG(p) + TD(d);
5868: return r;
5869: }
5870: }
5871:
5872: ND ndv_mul_nm(int mod,NM m0,NDV p)
5873: {
5874: NM mr,mr0;
5875: NMV m;
5876: UINT *d,*dt,*dm;
5877: int c,n,td,i,c1,c2,len;
5878: P q;
5879: ND r;
5880:
5881: if ( !p ) return 0;
5882: else if ( do_weyl ) {
5883: if ( mod < 0 ) {
5884: error("ndv_mul_nm : not implemented (weyl)");
5885: return 0;
5886: } else
5887: return weyl_ndv_mul_nm(mod,m0,p);
5888: } else {
5889: n = NV(p); m = BDY(p);
5890: d = DL(m0);
5891: len = LEN(p);
5892: mr0 = 0;
5893: td = TD(d);
5894: if ( mod == -1 ) {
5895: c = CM(m0);
5896: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
5897: NEXTNM(mr0,mr);
5898: CM(mr) = _mulsf(CM(m),c);
5899: ndl_add(DL(m),d,DL(mr));
5900: }
5901: } else if ( mod == -2 ) {
5902: Z cl;
5903: cl = CZ(m0);
5904: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
5905: NEXTNM(mr0,mr);
5906: mullf(CZ(m),cl,&CZ(mr));
5907: ndl_add(DL(m),d,DL(mr));
5908: }
5909: } else if ( mod ) {
5910: c = CM(m0);
5911: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
5912: NEXTNM(mr0,mr);
5913: c1 = CM(m);
5914: DMAR(c1,c,0,mod,c2);
5915: CM(mr) = c2;
5916: ndl_add(DL(m),d,DL(mr));
5917: }
5918: } else {
5919: q = CP(m0);
5920: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
5921: NEXTNM(mr0,mr);
5922: mulp(nd_vc,CP(m),q,&CP(mr));
5923: ndl_add(DL(m),d,DL(mr));
5924: }
5925: }
5926: NEXT(mr) = 0;
5927: MKND(NV(p),mr0,len,r);
5928: SG(r) = SG(p) + TD(d);
5929: return r;
5930: }
5931: }
5932:
5933: ND nd_quo(int mod,PGeoBucket bucket,NDV d)
5934: {
5935: NM mq0,mq;
5936: NMV tm;
5937: Q q;
5938: int i,nv,sg,c,c1,c2,hindex;
5939: ND p,t,r;
5940:
5941: if ( bucket->m < 0 ) return 0;
5942: else {
5943: nv = NV(d);
5944: mq0 = 0;
5945: tm = (NMV)MALLOC(nmv_adv);
5946: while ( 1 ) {
5947: if ( mod > 0 || mod == -1 )
5948: hindex = head_pbucket(mod,bucket);
5949: else if ( mod == -2 )
5950: hindex = head_pbucket_lf(bucket);
5951: else
5952: hindex = head_pbucket_q(bucket);
5953: if ( hindex < 0 ) break;
5954: p = bucket->body[hindex];
5955: NEXTNM(mq0,mq);
5956: ndl_sub(HDL(p),HDL(d),DL(mq));
5957: ndl_copy(DL(mq),DL(tm));
5958: if ( mod ) {
5959: c1 = invm(HCM(d),mod); c2 = HCM(p);
5960: DMAR(c1,c2,0,mod,c); CM(mq) = c;
5961: CM(tm) = mod-c;
5962: } else {
1.6 noro 5963: divsz(HCZ(p),HCZ(d),&CZ(mq));
5964: chsgnz(CZ(mq),&CZ(tm));
1.1 noro 5965: }
5966: t = ndv_mul_nmv_trunc(mod,tm,d,HDL(d));
5967: bucket->body[hindex] = nd_remove_head(p);
5968: t = nd_remove_head(t);
5969: add_pbucket(mod,bucket,t);
5970: }
5971: if ( !mq0 )
5972: r = 0;
5973: else {
5974: NEXT(mq) = 0;
5975: for ( i = 0, mq = mq0; mq; mq = NEXT(mq), i++ );
5976: MKND(nv,mq0,i,r);
5977: /* XXX */
5978: SG(r) = HTD(r);
5979: }
5980: return r;
5981: }
5982: }
5983:
5984: void ndv_realloc(NDV p,int obpe,int oadv,EPOS oepos)
5985: {
5986: NMV m,mr,mr0,t;
5987: int len,i,k;
5988:
5989: if ( !p ) return;
5990: m = BDY(p); len = LEN(p);
5991: mr0 = nmv_adv>oadv?(NMV)REALLOC(BDY(p),len*nmv_adv):BDY(p);
5992: m = (NMV)((char *)mr0+(len-1)*oadv);
5993: mr = (NMV)((char *)mr0+(len-1)*nmv_adv);
5994: t = (NMV)MALLOC(nmv_adv);
5995: for ( i = 0; i < len; i++, NMV_OPREV(m), NMV_PREV(mr) ) {
1.6 noro 5996: CZ(t) = CZ(m);
1.1 noro 5997: for ( k = 0; k < nd_wpd; k++ ) DL(t)[k] = 0;
5998: ndl_reconstruct(DL(m),DL(t),obpe,oepos);
1.6 noro 5999: CZ(mr) = CZ(t);
1.1 noro 6000: ndl_copy(DL(t),DL(mr));
6001: }
6002: BDY(p) = mr0;
6003: }
6004:
6005: NDV ndv_dup_realloc(NDV p,int obpe,int oadv,EPOS oepos)
6006: {
6007: NMV m,mr,mr0;
6008: int len,i;
6009: NDV r;
6010:
6011: if ( !p ) return 0;
6012: m = BDY(p); len = LEN(p);
6013: mr0 = mr = (NMV)MALLOC(len*nmv_adv);
6014: for ( i = 0; i < len; i++, NMV_OADV(m), NMV_ADV(mr) ) {
6015: ndl_zero(DL(mr));
6016: ndl_reconstruct(DL(m),DL(mr),obpe,oepos);
1.6 noro 6017: CZ(mr) = CZ(m);
1.1 noro 6018: }
6019: MKNDV(NV(p),mr0,len,r);
6020: SG(r) = SG(p);
1.24 noro 6021: r->sig = p->sig;
1.1 noro 6022: return r;
6023: }
6024:
6025: /* duplicate p */
6026:
6027: NDV ndv_dup(int mod,NDV p)
6028: {
6029: NDV d;
6030: NMV t,m,m0;
6031: int i,len;
6032:
6033: if ( !p ) return 0;
6034: len = LEN(p);
6035: m0 = m = (NMV)((mod>0 || mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6036: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6037: ndl_copy(DL(t),DL(m));
1.6 noro 6038: CZ(m) = CZ(t);
1.1 noro 6039: }
6040: MKNDV(NV(p),m0,len,d);
6041: SG(d) = SG(p);
6042: return d;
6043: }
6044:
6045: NDV ndv_symbolic(int mod,NDV p)
6046: {
6047: NDV d;
6048: NMV t,m,m0;
6049: int i,len;
6050:
6051: if ( !p ) return 0;
6052: len = LEN(p);
6053: m0 = m = (NMV)((mod>0||mod==-1)?MALLOC_ATOMIC(len*nmv_adv):MALLOC(len*nmv_adv));
6054: for ( t = BDY(p), i = 0; i < len; i++, NMV_ADV(t), NMV_ADV(m) ) {
6055: ndl_copy(DL(t),DL(m));
1.6 noro 6056: CZ(m) = ONE;
1.1 noro 6057: }
6058: MKNDV(NV(p),m0,len,d);
6059: SG(d) = SG(p);
6060: return d;
6061: }
6062:
6063: ND nd_dup(ND p)
6064: {
6065: ND d;
6066: NM t,m,m0;
6067:
6068: if ( !p ) return 0;
6069: for ( m0 = 0, t = BDY(p); t; t = NEXT(t) ) {
6070: NEXTNM(m0,m);
6071: ndl_copy(DL(t),DL(m));
1.6 noro 6072: CZ(m) = CZ(t);
1.1 noro 6073: }
6074: if ( m0 ) NEXT(m) = 0;
6075: MKND(NV(p),m0,LEN(p),d);
6076: SG(d) = SG(p);
6077: return d;
6078: }
6079:
6080: /* XXX if p->len == 0 then it represents 0 */
6081:
6082: void ndv_mod(int mod,NDV p)
6083: {
6084: NMV t,d;
6085: int r,s,u;
6086: int i,len,dlen;
6087: P cp;
6088: Z c;
6089: Obj gfs;
6090:
6091: if ( !p ) return;
6092: len = LEN(p);
6093: dlen = 0;
6094: if ( mod == -1 )
6095: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6096: simp_ff((Obj)CP(t),&gfs);
6097: if ( gfs ) {
6098: r = FTOIF(CONT((GFS)gfs));
6099: CM(d) = r;
6100: ndl_copy(DL(t),DL(d));
6101: NMV_ADV(d);
6102: dlen++;
6103: }
6104: }
6105: else if ( mod == -2 )
6106: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6107: simp_ff((Obj)CP(t),&gfs);
6108: if ( gfs ) {
6109: lmtolf((LM)gfs,&CZ(d));
6110: ndl_copy(DL(t),DL(d));
6111: NMV_ADV(d);
6112: dlen++;
6113: }
6114: }
6115: else
6116: for ( t = d = BDY(p), i = 0; i < len; i++, NMV_ADV(t) ) {
6117: if ( nd_vc ) {
6118: nd_subst_vector(nd_vc,CP(t),nd_subst,&cp);
6119: c = (Z)cp;
6120: } else
1.6 noro 6121: c = CZ(t);
1.1 noro 6122: r = remqi((Q)c,mod);
6123: if ( r ) {
6124: CM(d) = r;
6125: ndl_copy(DL(t),DL(d));
6126: NMV_ADV(d);
6127: dlen++;
6128: }
6129: }
6130: LEN(p) = dlen;
6131: }
6132:
6133: NDV ptondv(VL vl,VL dvl,P p)
6134: {
6135: ND nd;
6136:
6137: nd = ptond(vl,dvl,p);
6138: return ndtondv(0,nd);
6139: }
6140:
6141: void pltozpl(LIST l,Q *cont,LIST *pp)
6142: {
1.16 noro 6143: NODE nd,nd1;
6144: int n;
6145: P *pl;
6146: Q *cl;
6147: int i;
6148: P dmy;
6149: Z dvr,inv;
6150: LIST r;
6151:
6152: nd = BDY(l); n = length(nd);
6153: pl = (P *)MALLOC(n*sizeof(P));
6154: cl = (Q *)MALLOC(n*sizeof(Q));
6155: for ( i = 0; i < n; i++, nd = NEXT(nd) ) {
6156: ptozp((P)BDY(nd),1,&cl[i],&dmy);
6157: }
6158: qltozl(cl,n,&dvr);
6159: divz(ONE,dvr,&inv);
6160: nd = BDY(l);
6161: for ( i = 0; i < n; i++, nd = NEXT(nd) )
6162: divsp(CO,(P)BDY(nd),(P)dvr,&pl[i]);
6163: nd = 0;
6164: for ( i = n-1; i >= 0; i-- ) {
6165: MKNODE(nd1,pl[i],nd); nd = nd1;
6166: }
6167: MKLIST(r,nd);
6168: *pp = r;
1.1 noro 6169: }
6170:
6171: /* (a1,a2,...,an) -> a1*e(1)+...+an*e(n) */
6172:
6173: NDV pltondv(VL vl,VL dvl,LIST p)
6174: {
6175: int i;
6176: NODE t;
6177: ND r,ri;
6178: NM m;
6179:
6180: if ( !nd_module ) error("pltond : module order must be set");
6181: r = 0;
6182: for ( i = 1, t = BDY(p); t; t = NEXT(t), i++ ) {
6183: ri = ptond(vl,dvl,(P)BDY(t));
6184: if ( ri )
6185: for ( m = BDY(ri); m; m = NEXT(m) ) {
6186: MPOS(DL(m)) = i;
6187: TD(DL(m)) = ndl_weight(DL(m));
6188: if ( nd_blockmask ) ndl_weight_mask(DL(m));
6189: }
6190: r = nd_add(0,r,ri);
6191: }
6192: return ndtondv(0,r);
6193: }
6194:
6195: ND ptond(VL vl,VL dvl,P p)
6196: {
6197: int n,i,j,k,e;
6198: VL tvl;
6199: V v;
6200: DCP dc;
6201: DCP *w;
6202: ND r,s,t,u;
6203: P x;
6204: int c;
6205: UINT *d;
6206: NM m,m0;
6207:
6208: if ( !p )
6209: return 0;
6210: else if ( NUM(p) ) {
6211: NEWNM(m);
6212: ndl_zero(DL(m));
6213: if ( !INT((Q)p) )
6214: error("ptond : input must be integer-coefficient");
1.6 noro 6215: CZ(m) = (Z)p;
1.1 noro 6216: NEXT(m) = 0;
6217: MKND(nd_nvar,m,1,r);
6218: SG(r) = 0;
6219: return r;
6220: } else {
6221: for ( dc = DC(p), k = 0; dc; dc = NEXT(dc), k++ );
6222: w = (DCP *)MALLOC(k*sizeof(DCP));
6223: for ( dc = DC(p), j = 0; j < k; dc = NEXT(dc), j++ ) w[j] = dc;
6224: for ( i = 0, tvl = dvl, v = VR(p);
6225: tvl && tvl->v != v; tvl = NEXT(tvl), i++ );
6226: if ( !tvl ) {
6227: for ( j = k-1, s = 0, MKV(v,x); j >= 0; j-- ) {
6228: t = ptond(vl,dvl,COEF(w[j]));
6229: pwrp(vl,x,DEG(w[j]),&p);
6230: nd_mul_c_p(CO,t,p); s = nd_add(0,s,t);
6231: }
6232: return s;
6233: } else {
6234: NEWNM(m0); d = DL(m0);
6235: for ( j = k-1, s = 0; j >= 0; j-- ) {
1.6 noro 6236: ndl_zero(d); e = ZTOS(DEG(w[j])); PUT_EXP(d,i,e);
1.1 noro 6237: TD(d) = MUL_WEIGHT(e,i);
6238: if ( nd_blockmask) ndl_weight_mask(d);
6239: if ( nd_module ) MPOS(d) = 0;
6240: t = ptond(vl,dvl,COEF(w[j]));
6241: for ( m = BDY(t); m; m = NEXT(m) )
6242: ndl_addto(DL(m),d);
6243: SG(t) += TD(d);
6244: s = nd_add(0,s,t);
6245: }
6246: FREENM(m0);
6247: return s;
6248: }
6249: }
6250: }
6251:
6252: P ndvtop(int mod,VL vl,VL dvl,NDV p)
6253: {
6254: VL tvl;
6255: int len,n,j,i,e;
6256: NMV m;
6257: Z q;
6258: P c;
6259: UINT *d;
6260: P s,r,u,t,w;
6261: GFS gfs;
6262:
6263: if ( !p ) return 0;
6264: else {
6265: len = LEN(p);
6266: n = NV(p);
6267: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6268: for ( j = len-1, s = 0; j >= 0; j--, NMV_PREV(m) ) {
6269: if ( mod == -1 ) {
6270: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6271: } else if ( mod == -2 ) {
6272: c = (P)CZ(m);
6273: } else if ( mod > 0 ) {
1.6 noro 6274: STOZ(CM(m),q); c = (P)q;
1.1 noro 6275: } else
6276: c = CP(m);
6277: d = DL(m);
6278: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6279: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6280: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6281: }
6282: addp(vl,s,t,&u); s = u;
6283: }
6284: return s;
6285: }
6286: }
6287:
6288: LIST ndvtopl(int mod,VL vl,VL dvl,NDV p,int rank)
6289: {
6290: VL tvl;
6291: int len,n,j,i,e;
6292: NMV m;
6293: Z q;
6294: P c;
6295: UINT *d;
6296: P s,r,u,t,w;
6297: GFS gfs;
6298: P *a;
6299: LIST l;
6300: NODE nd,nd1;
6301:
6302: if ( !p ) return 0;
6303: else {
6304: a = (P *)MALLOC((rank+1)*sizeof(P));
6305: for ( i = 0; i <= rank; i++ ) a[i] = 0;
6306: len = LEN(p);
6307: n = NV(p);
6308: m = (NMV)(((char *)BDY(p))+nmv_adv*(len-1));
6309: for ( j = len-1; j >= 0; j--, NMV_PREV(m) ) {
6310: if ( mod == -1 ) {
6311: e = IFTOF(CM(m)); MKGFS(e,gfs); c = (P)gfs;
6312: } else if ( mod ) {
1.6 noro 6313: STOZ(CM(m),q); c = (P)q;
1.1 noro 6314: } else
6315: c = CP(m);
6316: d = DL(m);
6317: for ( i = 0, t = c, tvl = dvl; i < n; tvl = NEXT(tvl), i++ ) {
1.6 noro 6318: MKV(tvl->v,r); e = GET_EXP(d,i); STOZ(e,q);
1.1 noro 6319: pwrp(vl,r,q,&u); mulp(vl,t,u,&w); t = w;
6320: }
6321: addp(vl,a[MPOS(d)],t,&u); a[MPOS(d)] = u;
6322: }
6323: nd = 0;
6324: for ( i = rank; i > 0; i-- ) {
6325: MKNODE(nd1,a[i],nd); nd = nd1;
6326: }
6327: MKLIST(l,nd);
6328: return l;
6329: }
6330: }
6331:
6332: NDV ndtondv(int mod,ND p)
6333: {
6334: NDV d;
6335: NMV m,m0;
6336: NM t;
6337: int i,len;
6338:
6339: if ( !p ) return 0;
6340: len = LEN(p);
6341: if ( mod > 0 || mod == -1 )
6342: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6343: else
6344: m0 = m = MALLOC(len*nmv_adv);
6345: #if 0
6346: ndv_alloc += nmv_adv*len;
6347: #endif
6348: for ( t = BDY(p), i = 0; t; t = NEXT(t), i++, NMV_ADV(m) ) {
6349: ndl_copy(DL(t),DL(m));
1.6 noro 6350: CZ(m) = CZ(t);
1.1 noro 6351: }
6352: MKNDV(NV(p),m0,len,d);
6353: SG(d) = SG(p);
1.24 noro 6354: d->sig = p->sig;
1.1 noro 6355: return d;
6356: }
6357:
1.16 noro 6358: static int dmm_comp_nv;
6359:
6360: int dmm_comp(DMM *a,DMM *b)
6361: {
6362: return -compdmm(dmm_comp_nv,*a,*b);
6363: }
6364:
6365: void dmm_sort_by_ord(DMM *a,int len,int nv)
6366: {
6367: dmm_comp_nv = nv;
6368: qsort(a,len,sizeof(DMM),(int (*)(const void *,const void *))dmm_comp);
6369: }
6370:
6371: void dpm_sort(DPM p,DPM *rp)
6372: {
6373: DMM t,t1;
6374: int len,i,n;
6375: DMM *a;
6376: DPM d;
6377:
6378: if ( !p ) *rp = 0;
6379: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6380: a = (DMM *)MALLOC(len*sizeof(DMM));
6381: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6382: n = p->nv;
6383: dmm_sort_by_ord(a,len,n);
6384: t = 0;
6385: for ( i = len-1; i >= 0; i-- ) {
6386: NEWDMM(t1);
6387: t1->c = a[i]->c;
6388: t1->dl = a[i]->dl;
6389: t1->pos = a[i]->pos;
6390: t1->next = t;
6391: t = t1;
6392: }
6393: MKDPM(n,t,d);
6394: SG(d) = SG(p);
6395: *rp = d;
6396: }
6397:
1.18 noro 6398: int dpm_comp(DPM *a,DPM *b)
6399: {
1.22 noro 6400: return -compdpm(CO,*a,*b);
1.18 noro 6401: }
6402:
6403: NODE dpm_sort_list(NODE l)
6404: {
6405: int i,len;
6406: NODE t,t1;
6407: DPM *a;
6408:
6409: len = length(l);
6410: a = (DPM *)MALLOC(len*sizeof(DPM));
6411: for ( t = l, i = 0; i < len; i++, t = NEXT(t) ) a[i] = (DPM)BDY(t);
6412: qsort(a,len,sizeof(DPM),(int (*)(const void *,const void *))dpm_comp);
6413: t = 0;
6414: for ( i = len-1; i >= 0; i-- ) {
6415: MKNODE(t1,(pointer)a[i],t); t = t1;
6416: }
6417: return t;
6418: }
6419:
1.20 noro 6420: int nmv_comp(NMV a,NMV b)
6421: {
1.21 noro 6422: int t;
6423: t = DL_COMPARE(a->dl,b->dl);
6424: return -t;
1.20 noro 6425: }
6426:
1.16 noro 6427: NDV dpmtondv(int mod,DPM p)
6428: {
6429: NDV d;
6430: NMV m,m0;
6431: DMM t;
6432: DMM *a;
6433: int i,len,n;
6434:
6435: if ( !p ) return 0;
6436: for ( t = BDY(p), len = 0; t; t = NEXT(t), len++ );
6437: a = (DMM *)MALLOC(len*sizeof(DMM));
6438: for ( i = 0, t = BDY(p); i < len; i++, t = NEXT(t) ) a[i] = t;
6439: n = p->nv;
6440: dmm_sort_by_ord(a,len,n);
6441: if ( mod > 0 || mod == -1 )
6442: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(len*nmv_adv);
6443: else
6444: m0 = m = MALLOC(len*nmv_adv);
6445: #if 0
6446: ndv_alloc += nmv_adv*len;
6447: #endif
6448: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
6449: dltondl(n,a[i]->dl,DL(m));
6450: MPOS(DL(m)) = a[i]->pos;
1.20 noro 6451: TD(DL(m)) = ndl_weight(DL(m));
1.16 noro 6452: CZ(m) = (Z)a[i]->c;
6453: }
1.20 noro 6454: qsort(m0,len,nmv_adv,(int (*)(const void *,const void *))nmv_comp);
1.16 noro 6455: MKNDV(NV(p),m0,len,d);
6456: SG(d) = SG(p);
6457: return d;
6458: }
6459:
1.1 noro 6460: ND ndvtond(int mod,NDV p)
6461: {
6462: ND d;
6463: NM m,m0;
6464: NMV t;
6465: int i,len;
6466:
6467: if ( !p ) return 0;
6468: m0 = 0;
6469: len = p->len;
6470: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6471: NEXTNM(m0,m);
6472: ndl_copy(DL(t),DL(m));
1.6 noro 6473: CZ(m) = CZ(t);
1.1 noro 6474: }
6475: NEXT(m) = 0;
6476: MKND(NV(p),m0,len,d);
6477: SG(d) = SG(p);
1.28 ! noro 6478: d->sig = p->sig;
1.1 noro 6479: return d;
6480: }
6481:
6482: DP ndvtodp(int mod,NDV p)
6483: {
6484: MP m,m0;
6485: DP d;
6486: NMV t;
6487: int i,len;
6488:
6489: if ( !p ) return 0;
6490: m0 = 0;
6491: len = p->len;
6492: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6493: NEXTMP(m0,m);
6494: m->dl = ndltodl(nd_nvar,DL(t));
6495: m->c = (Obj)ndctop(mod,t->c);
6496: }
6497: NEXT(m) = 0;
6498: MKDP(nd_nvar,m0,d);
6499: SG(d) = SG(p);
6500: return d;
6501: }
6502:
1.16 noro 6503: DPM ndvtodpm(int mod,NDV p)
6504: {
6505: DMM m,m0;
6506: DPM d;
6507: NMV t;
6508: int i,len;
6509:
6510: if ( !p ) return 0;
6511: m0 = 0;
6512: len = p->len;
6513: for ( t = BDY(p), i = 0; i < len; NMV_ADV(t), i++ ) {
6514: NEXTDMM(m0,m);
6515: m->dl = ndltodl(nd_nvar,DL(t));
6516: m->c = (Obj)ndctop(mod,t->c);
6517: m->pos = MPOS(DL(t));
6518: }
6519: NEXT(m) = 0;
6520: MKDPM(nd_nvar,m0,d);
6521: SG(d) = SG(p);
6522: return d;
6523: }
6524:
6525:
1.1 noro 6526: DP ndtodp(int mod,ND p)
6527: {
6528: MP m,m0;
6529: DP d;
6530: NM t;
6531: int i,len;
6532:
6533: if ( !p ) return 0;
6534: m0 = 0;
6535: len = p->len;
6536: for ( t = BDY(p); t; t = NEXT(t) ) {
6537: NEXTMP(m0,m);
6538: m->dl = ndltodl(nd_nvar,DL(t));
6539: m->c = (Obj)ndctop(mod,t->c);
6540: }
6541: NEXT(m) = 0;
6542: MKDP(nd_nvar,m0,d);
6543: SG(d) = SG(p);
6544: return d;
6545: }
6546:
6547: void ndv_print(NDV p)
6548: {
6549: NMV m;
6550: int i,len;
6551:
6552: if ( !p ) printf("0\n");
6553: else {
6554: len = LEN(p);
6555: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6556: if ( CM(m) & 0x80000000 ) printf("+@_%d*",IFTOF(CM(m)));
1.28 ! noro 6557: else printf("+%ld*",CM(m));
1.1 noro 6558: ndl_print(DL(m));
6559: }
6560: printf("\n");
6561: }
6562: }
6563:
6564: void ndv_print_q(NDV p)
6565: {
6566: NMV m;
6567: int i,len;
6568:
6569: if ( !p ) printf("0\n");
6570: else {
6571: len = LEN(p);
6572: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
6573: printf("+");
1.6 noro 6574: printexpr(CO,(Obj)CZ(m));
1.1 noro 6575: printf("*");
6576: ndl_print(DL(m));
6577: }
6578: printf("\n");
6579: }
6580: }
6581:
6582: NODE ndv_reducebase(NODE x,int *perm)
6583: {
6584: int len,i,j;
6585: NDVI w;
6586: NODE t,t0;
6587:
6588: len = length(x);
6589: w = (NDVI)MALLOC(len*sizeof(struct oNDVI));
6590: for ( i = 0, t = x; i < len; i++, t = NEXT(t) ) {
6591: w[i].p = BDY(t); w[i].i = perm[i];
6592: }
6593: for ( i = 0; i < len; i++ ) {
6594: for ( j = 0; j < i; j++ ) {
6595: if ( w[i].p && w[j].p ) {
6596: if ( ndl_reducible(HDL(w[i].p),HDL(w[j].p)) ) w[i].p = 0;
6597: else if ( ndl_reducible(HDL(w[j].p),HDL(w[i].p)) ) w[j].p = 0;
6598: }
6599: }
6600: }
6601: for ( i = j = 0, t0 = 0; i < len; i++ ) {
6602: if ( w[i].p ) {
6603: NEXTNODE(t0,t); BDY(t) = (pointer)w[i].p;
6604: perm[j++] = w[i].i;
6605: }
6606: }
6607: NEXT(t) = 0; x = t0;
6608: return x;
6609: }
6610:
6611: /* XXX incomplete */
6612:
1.21 noro 6613: extern DMMstack dmm_stack;
6614: int ndl_module_schreyer_compare(UINT *a,UINT *b);
1.16 noro 6615:
1.1 noro 6616: void nd_init_ord(struct order_spec *ord)
6617: {
6618: nd_module = (ord->id >= 256);
6619: if ( nd_module ) {
6620: nd_dcomp = -1;
1.21 noro 6621: nd_module_ordtype = ord->module_ordtype;
1.1 noro 6622: nd_pot_nelim = ord->pot_nelim;
6623: nd_poly_weight_len = ord->nv;
6624: nd_poly_weight = ord->top_weight;
6625: nd_module_rank = ord->module_rank;
6626: nd_module_weight = ord->module_top_weight;
6627: }
6628: nd_matrix = 0;
6629: nd_matrix_len = 0;
6630: switch ( ord->id ) {
6631: case 0:
6632: switch ( ord->ord.simple ) {
6633: case 0:
6634: nd_dcomp = 1;
6635: nd_isrlex = 1;
6636: break;
6637: case 1:
6638: nd_dcomp = 1;
6639: nd_isrlex = 0;
6640: break;
6641: case 2:
6642: nd_dcomp = 0;
6643: nd_isrlex = 0;
6644: ndl_compare_function = ndl_lex_compare;
6645: break;
6646: case 11:
6647: /* XXX */
6648: nd_dcomp = 0;
6649: nd_isrlex = 1;
6650: ndl_compare_function = ndl_ww_lex_compare;
6651: break;
6652: default:
6653: error("nd_gr : unsupported order");
6654: }
6655: break;
6656: case 1:
6657: /* block order */
6658: /* XXX */
6659: nd_dcomp = -1;
6660: nd_isrlex = 0;
6661: ndl_compare_function = ndl_block_compare;
6662: break;
6663: case 2:
6664: /* matrix order */
6665: /* XXX */
6666: nd_dcomp = -1;
6667: nd_isrlex = 0;
6668: nd_matrix_len = ord->ord.matrix.row;
6669: nd_matrix = ord->ord.matrix.matrix;
6670: ndl_compare_function = ndl_matrix_compare;
6671: break;
6672: case 3:
6673: /* composite order */
6674: nd_dcomp = -1;
6675: nd_isrlex = 0;
6676: nd_worb_len = ord->ord.composite.length;
6677: nd_worb = ord->ord.composite.w_or_b;
6678: ndl_compare_function = ndl_composite_compare;
6679: break;
6680:
6681: /* module order */
6682: case 256:
6683: switch ( ord->ord.simple ) {
6684: case 0:
1.21 noro 6685: nd_dcomp = 0;
1.1 noro 6686: nd_isrlex = 1;
1.21 noro 6687: ndl_compare_function = ndl_module_glex_compare;
1.1 noro 6688: break;
6689: case 1:
1.21 noro 6690: nd_dcomp = 0;
1.1 noro 6691: nd_isrlex = 0;
6692: ndl_compare_function = ndl_module_glex_compare;
6693: break;
6694: case 2:
1.21 noro 6695: nd_dcomp = 0;
1.1 noro 6696: nd_isrlex = 0;
1.21 noro 6697: ndl_compare_function = ndl_module_compare;
6698: ndl_base_compare_function = ndl_lex_compare;
1.1 noro 6699: break;
6700: default:
1.21 noro 6701: error("nd_init_ord : unsupported order");
1.1 noro 6702: }
6703: break;
6704: case 257:
6705: /* block order */
6706: nd_isrlex = 0;
1.21 noro 6707: ndl_compare_function = ndl_module_compare;
6708: ndl_base_compare_function = ndl_block_compare;
1.1 noro 6709: break;
6710: case 258:
6711: /* matrix order */
6712: nd_isrlex = 0;
6713: nd_matrix_len = ord->ord.matrix.row;
6714: nd_matrix = ord->ord.matrix.matrix;
1.21 noro 6715: ndl_compare_function = ndl_module_compare;
6716: ndl_base_compare_function = ndl_matrix_compare;
1.1 noro 6717: break;
6718: case 259:
6719: /* composite order */
6720: nd_isrlex = 0;
6721: nd_worb_len = ord->ord.composite.length;
6722: nd_worb = ord->ord.composite.w_or_b;
1.21 noro 6723: ndl_compare_function = ndl_module_compare;
6724: ndl_base_compare_function = ndl_composite_compare;
6725: break;
6726: case 300:
6727: /* schreyer order */
6728: if ( ord->base->id != 256 )
6729: error("nd_init_ord : unsupported base order");
6730: ndl_compare_function = ndl_module_schreyer_compare;
6731: dmm_stack = ord->dmmstack;
6732: switch ( ord->base->ord.simple ) {
6733: case 0:
6734: nd_isrlex = 1;
6735: ndl_base_compare_function = ndl_glex_compare;
6736: dl_base_compare_function = cmpdl_revgradlex;
6737: break;
6738: case 1:
6739: nd_isrlex = 0;
6740: ndl_base_compare_function = ndl_glex_compare;
6741: dl_base_compare_function = cmpdl_gradlex;
6742: break;
6743: case 2:
6744: nd_isrlex = 0;
6745: ndl_base_compare_function = ndl_lex_compare;
6746: dl_base_compare_function = cmpdl_lex;
6747: break;
6748: default:
6749: error("nd_init_ord : unsupported order");
6750: }
1.1 noro 6751: break;
6752: }
6753: nd_ord = ord;
6754: }
6755:
6756: BlockMask nd_create_blockmask(struct order_spec *ord)
6757: {
6758: int n,i,j,s,l;
6759: UINT *t;
6760: BlockMask bm;
6761:
6762: /* we only create mask table for block order */
6763: if ( ord->id != 1 && ord->id != 257 )
6764: return 0;
6765: n = ord->ord.block.length;
6766: bm = (BlockMask)MALLOC(sizeof(struct oBlockMask));
6767: bm->n = n;
6768: bm->order_pair = ord->ord.block.order_pair;
6769: bm->mask = (UINT **)MALLOC(n*sizeof(UINT *));
6770: for ( i = 0, s = 0; i < n; i++ ) {
6771: bm->mask[i] = t = (UINT *)MALLOC_ATOMIC(nd_wpd*sizeof(UINT));
6772: for ( j = 0; j < nd_wpd; j++ ) t[j] = 0;
6773: l = bm->order_pair[i].length;
6774: for ( j = 0; j < l; j++, s++ ) PUT_EXP(t,s,nd_mask0);
6775: }
6776: return bm;
6777: }
6778:
6779: EPOS nd_create_epos(struct order_spec *ord)
6780: {
6781: int i,j,l,s,ord_l,ord_o;
6782: EPOS epos;
6783: struct order_pair *op;
6784:
6785: epos = (EPOS)MALLOC_ATOMIC(nd_nvar*sizeof(struct oEPOS));
6786: switch ( ord->id ) {
1.21 noro 6787: case 0: case 256: case 300:
1.1 noro 6788: if ( nd_isrlex ) {
6789: for ( i = 0; i < nd_nvar; i++ ) {
6790: epos[i].i = nd_exporigin + (nd_nvar-1-i)/nd_epw;
6791: epos[i].s = (nd_epw-((nd_nvar-1-i)%nd_epw)-1)*nd_bpe;
6792: }
6793: } else {
6794: for ( i = 0; i < nd_nvar; i++ ) {
6795: epos[i].i = nd_exporigin + i/nd_epw;
6796: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
6797: }
6798: }
6799: break;
6800: case 1: case 257:
6801: /* block order */
6802: l = ord->ord.block.length;
6803: op = ord->ord.block.order_pair;
6804: for ( j = 0, s = 0; j < l; j++ ) {
6805: ord_o = op[j].order;
6806: ord_l = op[j].length;
6807: if ( !ord_o )
6808: for ( i = 0; i < ord_l; i++ ) {
6809: epos[s+i].i = nd_exporigin + (s+ord_l-i-1)/nd_epw;
6810: epos[s+i].s = (nd_epw-((s+ord_l-i-1)%nd_epw)-1)*nd_bpe;
6811: }
6812: else
6813: for ( i = 0; i < ord_l; i++ ) {
6814: epos[s+i].i = nd_exporigin + (s+i)/nd_epw;
6815: epos[s+i].s = (nd_epw-((s+i)%nd_epw)-1)*nd_bpe;
6816: }
6817: s += ord_l;
6818: }
6819: break;
6820: case 2:
6821: /* matrix order */
6822: case 3:
6823: /* composite order */
6824: default:
6825: for ( i = 0; i < nd_nvar; i++ ) {
6826: epos[i].i = nd_exporigin + i/nd_epw;
6827: epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe;
6828: }
6829: break;
6830: }
6831: return epos;
6832: }
6833:
6834: /* external interface */
6835:
6836: void nd_nf_p(Obj f,LIST g,LIST v,int m,struct order_spec *ord,Obj *rp)
6837: {
6838: NODE t,in0,in;
6839: ND ndf,nf;
6840: NDV ndvf;
6841: VL vv,tv;
6842: int stat,nvar,max,mrank;
6843: union oNDC dn;
6844: Q cont;
6845: P pp;
6846: LIST ppl;
6847:
6848: if ( !f ) {
6849: *rp = 0;
6850: return;
6851: }
6852: pltovl(v,&vv);
6853: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
6854:
6855: /* max=65536 implies nd_bpe=32 */
6856: max = 65536;
6857:
6858: nd_module = 0;
6859: /* nd_module will be set if ord is a module ordering */
6860: nd_init_ord(ord);
6861: nd_setup_parameters(nvar,max);
6862: if ( nd_module && OID(f) != O_LIST )
6863: error("nd_nf_p : the first argument must be a list");
6864: if ( nd_module ) mrank = length(BDY((LIST)f));
6865: /* conversion to ndv */
6866: for ( in0 = 0, t = BDY(g); t; t = NEXT(t) ) {
6867: NEXTNODE(in0,in);
6868: if ( nd_module ) {
6869: if ( !BDY(t) || OID(BDY(t)) != O_LIST
6870: || length(BDY((LIST)BDY(t))) != mrank )
6871: error("nd_nf_p : inconsistent basis element");
6872: if ( !m ) pltozpl((LIST)BDY(t),&cont,&ppl);
6873: else ppl = (LIST)BDY(t);
6874: BDY(in) = (pointer)pltondv(CO,vv,ppl);
6875: } else {
6876: if ( !m ) ptozp((P)BDY(t),1,&cont,&pp);
6877: else pp = (P)BDY(t);
6878: BDY(in) = (pointer)ptondv(CO,vv,pp);
6879: }
6880: if ( m ) ndv_mod(m,(NDV)BDY(in));
6881: }
6882: if ( in0 ) NEXT(in) = 0;
6883:
6884: if ( nd_module ) ndvf = pltondv(CO,vv,(LIST)f);
6885: else ndvf = ptondv(CO,vv,(P)f);
6886: if ( m ) ndv_mod(m,ndvf);
6887: ndf = (pointer)ndvtond(m,ndvf);
6888:
6889: /* dont sort, dont removecont */
1.24 noro 6890: ndv_setup(m,0,in0,1,1,0);
1.1 noro 6891: nd_scale=2;
1.6 noro 6892: stat = nd_nf(m,0,ndf,nd_ps,1,&nf);
1.1 noro 6893: if ( !stat )
6894: error("nd_nf_p : exponent too large");
6895: if ( nd_module ) *rp = (Obj)ndvtopl(m,CO,vv,ndtondv(m,nf),mrank);
6896: else *rp = (Obj)ndvtop(m,CO,vv,ndtondv(m,nf));
6897: }
6898:
6899: int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r)
6900: {
6901: NM m;
6902: UINT *t,*s;
6903: int i;
6904:
6905: for ( i = 0; i < n; i++ ) r[i] = 0;
6906: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
6907: t = DL(m);
6908: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
6909: r[i] = CM(m);
6910: }
6911: for ( i = 0; !r[i]; i++ );
6912: return i;
6913: }
6914:
6915: int nd_to_vect_q(UINT *s0,int n,ND d,Z *r)
6916: {
6917: NM m;
6918: UINT *t,*s;
6919: int i;
6920:
6921: for ( i = 0; i < n; i++ ) r[i] = 0;
6922: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
6923: t = DL(m);
6924: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 6925: r[i] = CZ(m);
1.1 noro 6926: }
6927: for ( i = 0; !r[i]; i++ );
6928: return i;
6929: }
6930:
6931: int nd_to_vect_lf(UINT *s0,int n,ND d,mpz_t *r)
6932: {
6933: NM m;
6934: UINT *t,*s;
6935: int i;
6936:
6937: for ( i = 0; i < n; i++ ) { mpz_init(r[i]); mpz_set_ui(r[i],0); }
6938: for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) {
6939: t = DL(m);
6940: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
6941: mpz_set(r[i],BDY(CZ(m)));
6942: }
6943: for ( i = 0; !mpz_sgn(r[i]); i++ );
6944: return i;
6945: }
6946:
6947: unsigned long *nd_to_vect_2(UINT *s0,int n,int *s0hash,ND p)
6948: {
6949: NM m;
6950: unsigned long *v;
6951: int i,j,h,size;
6952: UINT *s,*t;
6953:
6954: size = sizeof(unsigned long)*(n+BLEN-1)/BLEN;
6955: v = (unsigned long *)MALLOC_ATOMIC_IGNORE_OFF_PAGE(size);
6956: bzero(v,size);
6957: for ( i = j = 0, s = s0, m = BDY(p); m; j++, m = NEXT(m) ) {
6958: t = DL(m);
6959: h = ndl_hash_value(t);
6960: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
6961: v[i/BLEN] |= 1L <<(i%BLEN);
6962: }
6963: return v;
6964: }
6965:
6966: int nd_nm_to_vect_2(UINT *s0,int n,int *s0hash,NDV p,NM m,unsigned long *v)
6967: {
6968: NMV mr;
6969: UINT *d,*t,*s;
6970: int i,j,len,h,head;
6971:
6972: d = DL(m);
6973: len = LEN(p);
6974: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
6975: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
6976: ndl_add(d,DL(mr),t);
6977: h = ndl_hash_value(t);
6978: for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ );
6979: if ( j == 0 ) head = i;
6980: v[i/BLEN] |= 1L <<(i%BLEN);
6981: }
6982: return head;
6983: }
6984:
6985: Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_pair pair)
6986: {
6987: NM m;
6988: NMV mr;
6989: UINT *d,*t,*s;
6990: NDV p;
6991: int i,j,len;
6992: Z *r;
6993:
6994: m = pair->mul;
6995: d = DL(m);
6996: p = nd_ps[pair->index];
6997: len = LEN(p);
6998: r = (Z *)CALLOC(n,sizeof(Q));
6999: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7000: for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) {
7001: ndl_add(d,DL(mr),t);
7002: for ( ; !ndl_equal(t,s); s += nd_wpd, i++ );
1.6 noro 7003: r[i] = CZ(mr);
1.1 noro 7004: }
7005: return r;
7006: }
7007:
1.11 noro 7008: IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start)
1.1 noro 7009: {
7010: NM m;
7011: NMV mr;
1.11 noro 7012: UINT *d,*t,*s,*u;
1.1 noro 7013: NDV p;
7014: unsigned char *ivc;
7015: unsigned short *ivs;
7016: UINT *v,*ivi,*s0v;
1.11 noro 7017: int i,j,len,prev,diff,cdiff,h,st,ed,md,c;
1.1 noro 7018: IndArray r;
7019:
7020: m = pair->mul;
7021: d = DL(m);
7022: if ( trace )
7023: p = nd_demand?nd_ps_trace_sym[pair->index]:nd_ps_trace[pair->index];
7024: else
7025: p = nd_demand?nd_ps_sym[pair->index]:nd_ps[pair->index];
7026:
7027: len = LEN(p);
7028: t = (UINT *)MALLOC(nd_wpd*sizeof(UINT));
7029: v = (unsigned int *)MALLOC(len*sizeof(unsigned int));
1.11 noro 7030: for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) {
7031: ndl_add(d,DL(mr),t);
7032: st = prev;
7033: ed = n;
7034: while ( ed > st ) {
7035: md = (st+ed)/2;
7036: u = s0+md*nd_wpd;
7037: c = DL_COMPARE(u,t);
7038: if ( c == 0 ) break;
7039: else if ( c > 0 ) st = md;
7040: else ed = md;
7041: }
7042: prev = v[j] = md;
1.1 noro 7043: }
7044: r = (IndArray)MALLOC(sizeof(struct oIndArray));
7045: r->head = v[0];
7046: diff = 0;
7047: for ( i = 1; i < len; i++ ) {
7048: cdiff = v[i]-v[i-1]; diff = MAX(cdiff,diff);
7049: }
7050: if ( diff < 256 ) {
7051: r->width = 1;
7052: ivc = (unsigned char *)MALLOC_ATOMIC(len*sizeof(unsigned char));
7053: r->index.c = ivc;
7054: for ( i = 1, ivc[0] = 0; i < len; i++ ) ivc[i] = v[i]-v[i-1];
7055: } else if ( diff < 65536 ) {
7056: r->width = 2;
7057: ivs = (unsigned short *)MALLOC_ATOMIC(len*sizeof(unsigned short));
7058: r->index.s = ivs;
7059: for ( i = 1, ivs[0] = 0; i < len; i++ ) ivs[i] = v[i]-v[i-1];
7060: } else {
7061: r->width = 4;
7062: ivi = (unsigned int *)MALLOC_ATOMIC(len*sizeof(unsigned int));
7063: r->index.i = ivi;
7064: for ( i = 1, ivi[0] = 0; i < len; i++ ) ivi[i] = v[i]-v[i-1];
7065: }
7066: return r;
7067: }
7068:
7069: int compress_array(Z *svect,Z *cvect,int n)
7070: {
7071: int i,j;
7072:
7073: for ( i = j = 0; i < n; i++ )
7074: if ( svect[i] ) cvect[j++] = svect[i];
7075: return j;
7076: }
7077:
7078: void expand_array(Z *svect,Z *cvect,int n)
7079: {
7080: int i,j;
7081:
7082: for ( i = j = 0; j < n; i++ )
7083: if ( svect[i] ) svect[i] = cvect[j++];
7084: }
7085:
1.8 noro 7086: #if 0
1.1 noro 7087: int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7088: {
7089: int i,j,k,len,pos,prev,nz;
7090: Z cs,mcs,c1,c2,cr,gcd,t;
7091: IndArray ivect;
7092: unsigned char *ivc;
7093: unsigned short *ivs;
7094: unsigned int *ivi;
7095: NDV redv;
7096: NMV mr;
7097: NODE rp;
7098: int maxrs;
7099: double hmag;
7100: Z *cvect;
1.3 noro 7101: int l;
1.1 noro 7102:
7103: maxrs = 0;
7104: for ( i = 0; i < col && !svect[i]; i++ );
7105: if ( i == col ) return maxrs;
7106: hmag = p_mag((P)svect[i])*nd_scale;
7107: cvect = (Z *)MALLOC(col*sizeof(Q));
7108: for ( i = 0; i < nred; i++ ) {
7109: ivect = imat[i];
7110: k = ivect->head;
7111: if ( svect[k] ) {
7112: maxrs = MAX(maxrs,rp0[i]->sugar);
7113: redv = nd_demand?ndv_load(rp0[i]->index)
7114: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7115: len = LEN(redv); mr = BDY(redv);
1.6 noro 7116: igcd_cofactor(svect[k],CZ(mr),&gcd,&cs,&cr);
1.1 noro 7117: chsgnz(cs,&mcs);
7118: if ( !UNIQ(cr) ) {
7119: for ( j = 0; j < col; j++ ) {
7120: mulz(svect[j],cr,&c1); svect[j] = c1;
7121: }
7122: }
7123: svect[k] = 0; prev = k;
7124: switch ( ivect->width ) {
7125: case 1:
7126: ivc = ivect->index.c;
7127: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7128: pos = prev+ivc[j]; prev = pos;
1.6 noro 7129: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7130: }
7131: break;
7132: case 2:
7133: ivs = ivect->index.s;
7134: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7135: pos = prev+ivs[j]; prev = pos;
1.6 noro 7136: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7137: }
7138: break;
7139: case 4:
7140: ivi = ivect->index.i;
7141: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7142: pos = prev+ivi[j]; prev = pos;
1.6 noro 7143: muladdtoz(CZ(mr),mcs,&svect[pos]);
1.1 noro 7144: }
7145: break;
7146: }
7147: for ( j = k+1; j < col && !svect[j]; j++ );
7148: if ( j == col ) break;
7149: if ( hmag && ((double)p_mag((P)svect[j]) > hmag) ) {
7150: nz = compress_array(svect,cvect,col);
7151: removecont_array((P *)cvect,nz,1);
7152: expand_array(svect,cvect,nz);
7153: hmag = ((double)p_mag((P)svect[j]))*nd_scale;
7154: }
7155: }
7156: }
7157: nz = compress_array(svect,cvect,col);
7158: removecont_array((P *)cvect,nz,1);
7159: expand_array(svect,cvect,nz);
7160: if ( DP_Print ) {
7161: fprintf(asir_out,"-"); fflush(asir_out);
7162: }
7163: return maxrs;
7164: }
1.4 noro 7165: #else
1.9 noro 7166:
1.4 noro 7167: /* direct mpz version */
7168: int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7169: {
7170: int i,j,k,len,pos,prev;
7171: mpz_t cs,cr,gcd;
7172: IndArray ivect;
7173: unsigned char *ivc;
7174: unsigned short *ivs;
7175: unsigned int *ivi;
7176: NDV redv;
7177: NMV mr;
7178: NODE rp;
7179: int maxrs;
7180: double hmag;
7181: int l;
1.13 noro 7182: static mpz_t *svect;
7183: static int svect_len=0;
1.4 noro 7184:
7185: maxrs = 0;
7186: for ( i = 0; i < col && !svect0[i]; i++ );
7187: if ( i == col ) return maxrs;
7188: hmag = p_mag((P)svect0[i])*nd_scale;
1.13 noro 7189: if ( col > svect_len ) {
7190: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
7191: svect_len = col;
7192: }
1.4 noro 7193: for ( i = 0; i < col; i++ ) {
7194: mpz_init(svect[i]);
7195: if ( svect0[i] )
7196: mpz_set(svect[i],BDY(svect0[i]));
7197: else
7198: mpz_set_ui(svect[i],0);
7199: }
7200: mpz_init(gcd); mpz_init(cs); mpz_init(cr);
7201: for ( i = 0; i < nred; i++ ) {
7202: ivect = imat[i];
7203: k = ivect->head;
7204: if ( mpz_sgn(svect[k]) ) {
7205: maxrs = MAX(maxrs,rp0[i]->sugar);
7206: redv = nd_demand?ndv_load(rp0[i]->index)
7207: :(trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index]);
7208: len = LEN(redv); mr = BDY(redv);
1.6 noro 7209: mpz_gcd(gcd,svect[k],BDY(CZ(mr)));
1.4 noro 7210: mpz_div(cs,svect[k],gcd);
1.6 noro 7211: mpz_div(cr,BDY(CZ(mr)),gcd);
1.4 noro 7212: mpz_neg(cs,cs);
1.9 noro 7213: if ( MUNIMPZ(cr) )
7214: for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]);
7215: else if ( !UNIMPZ(cr) )
7216: for ( j = 0; j < col; j++ ) {
7217: if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr);
7218: }
1.4 noro 7219: mpz_set_ui(svect[k],0);
7220: prev = k;
7221: switch ( ivect->width ) {
7222: case 1:
7223: ivc = ivect->index.c;
7224: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7225: pos = prev+ivc[j]; prev = pos;
1.6 noro 7226: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7227: }
7228: break;
7229: case 2:
7230: ivs = ivect->index.s;
7231: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7232: pos = prev+ivs[j]; prev = pos;
1.6 noro 7233: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7234: }
7235: break;
7236: case 4:
7237: ivi = ivect->index.i;
7238: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7239: pos = prev+ivi[j]; prev = pos;
1.6 noro 7240: mpz_addmul(svect[pos],BDY(CZ(mr)),cs);
1.4 noro 7241: }
7242: break;
7243: }
7244: for ( j = k+1; j < col && !svect[j]; j++ );
7245: if ( j == col ) break;
7246: if ( hmag && ((double)mpz_sizeinbase(svect[j],2) > hmag) ) {
7247: mpz_removecont_array(svect,col);
7248: hmag = ((double)mpz_sizeinbase(svect[j],2))*nd_scale;
7249: }
7250: }
7251: }
7252: mpz_removecont_array(svect,col);
7253: if ( DP_Print ) {
7254: fprintf(asir_out,"-"); fflush(asir_out);
7255: }
7256: for ( i = 0; i < col; i++ )
7257: if ( mpz_sgn(svect[i]) ) MPZTOZ(svect[i],svect0[i]);
7258: else svect0[i] = 0;
7259: return maxrs;
7260: }
7261: #endif
1.1 noro 7262:
7263: int ndv_reduce_vect(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7264: {
7265: int i,j,k,len,pos,prev;
7266: UINT c,c1,c2,c3,up,lo,dmy;
7267: IndArray ivect;
7268: unsigned char *ivc;
7269: unsigned short *ivs;
7270: unsigned int *ivi;
7271: NDV redv;
7272: NMV mr;
7273: NODE rp;
7274: int maxrs;
7275:
7276: maxrs = 0;
7277: for ( i = 0; i < nred; i++ ) {
7278: ivect = imat[i];
7279: k = ivect->head; svect[k] %= m;
7280: if ( (c = svect[k]) != 0 ) {
7281: maxrs = MAX(maxrs,rp0[i]->sugar);
7282: c = m-c; redv = nd_ps[rp0[i]->index];
7283: len = LEN(redv); mr = BDY(redv);
7284: svect[k] = 0; prev = k;
7285: switch ( ivect->width ) {
7286: case 1:
7287: ivc = ivect->index.c;
7288: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7289: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
7290: if ( c1 ) {
7291: c2 = svect[pos];
7292: DMA(c1,c,c2,up,lo);
7293: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7294: } else svect[pos] = lo;
7295: }
7296: }
7297: break;
7298: case 2:
7299: ivs = ivect->index.s;
7300: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7301: pos = prev+ivs[j]; c1 = CM(mr);
7302: prev = pos;
7303: if ( c1 ) {
7304: c2 = svect[pos];
7305: DMA(c1,c,c2,up,lo);
7306: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7307: } else svect[pos] = lo;
7308: }
7309: }
7310: break;
7311: case 4:
7312: ivi = ivect->index.i;
7313: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7314: pos = prev+ivi[j]; c1 = CM(mr);
7315: prev = pos;
7316: if ( c1 ) {
7317: c2 = svect[pos];
7318: DMA(c1,c,c2,up,lo);
7319: if ( up ) { DSAB(m,up,lo,dmy,c3); svect[pos] = c3;
7320: } else svect[pos] = lo;
7321: }
7322: }
7323: break;
7324: }
7325: }
7326: }
7327: for ( i = 0; i < col; i++ )
7328: if ( svect[i] >= (UINT)m ) svect[i] %= m;
7329: return maxrs;
7330: }
7331:
7332: int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7333: {
7334: int i,j,k,len,pos,prev;
7335: UINT c,c1,c2,c3,up,lo,dmy;
7336: IndArray ivect;
7337: unsigned char *ivc;
7338: unsigned short *ivs;
7339: unsigned int *ivi;
7340: NDV redv;
7341: NMV mr;
7342: NODE rp;
7343: int maxrs;
7344:
7345: maxrs = 0;
7346: for ( i = 0; i < nred; i++ ) {
7347: ivect = imat[i];
7348: k = ivect->head;
7349: if ( (c = svect[k]) != 0 ) {
7350: maxrs = MAX(maxrs,rp0[i]->sugar);
7351: c = _chsgnsf(c); redv = nd_ps[rp0[i]->index];
7352: len = LEN(redv); mr = BDY(redv);
7353: svect[k] = 0; prev = k;
7354: switch ( ivect->width ) {
7355: case 1:
7356: ivc = ivect->index.c;
7357: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7358: pos = prev+ivc[j]; prev = pos;
7359: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7360: }
7361: break;
7362: case 2:
7363: ivs = ivect->index.s;
7364: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7365: pos = prev+ivs[j]; prev = pos;
7366: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7367: }
7368: break;
7369: case 4:
7370: ivi = ivect->index.i;
7371: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7372: pos = prev+ivi[j]; prev = pos;
7373: svect[pos] = _addsf(_mulsf(CM(mr),c),svect[pos]);
7374: }
7375: break;
7376: }
7377: }
7378: }
7379: return maxrs;
7380: }
7381:
7382: ND nd_add_lf(ND p1,ND p2)
7383: {
7384: int n,c,can;
7385: ND r;
7386: NM m1,m2,mr0,mr,s;
7387: Z t;
7388:
7389: if ( !p1 ) return p2;
7390: else if ( !p2 ) return p1;
7391: else {
7392: can = 0;
7393: for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) {
7394: c = DL_COMPARE(DL(m1),DL(m2));
7395: switch ( c ) {
7396: case 0:
7397: addlf(CZ(m1),CZ(m2),&t);
7398: s = m1; m1 = NEXT(m1);
7399: if ( t ) {
7400: can++; NEXTNM2(mr0,mr,s); CZ(mr) = (t);
7401: } else {
7402: can += 2; FREENM(s);
7403: }
7404: s = m2; m2 = NEXT(m2); FREENM(s);
7405: break;
7406: case 1:
7407: s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s);
7408: break;
7409: case -1:
7410: s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s);
7411: break;
7412: }
7413: }
7414: if ( !mr0 )
7415: if ( m1 ) mr0 = m1;
7416: else if ( m2 ) mr0 = m2;
7417: else return 0;
7418: else if ( m1 ) NEXT(mr) = m1;
7419: else if ( m2 ) NEXT(mr) = m2;
7420: else NEXT(mr) = 0;
7421: BDY(p1) = mr0;
7422: SG(p1) = MAX(SG(p1),SG(p2));
7423: LEN(p1) = LEN(p1)+LEN(p2)-can;
7424: FREEND(p2);
7425: return p1;
7426: }
7427: }
7428:
7429: int ndv_reduce_vect_lf(mpz_t *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred)
7430: {
7431: int i,j,k,len,pos,prev;
7432: mpz_t c,mc,c1;
7433: IndArray ivect;
7434: unsigned char *ivc;
7435: unsigned short *ivs;
7436: unsigned int *ivi;
7437: NDV redv;
7438: NMV mr;
7439: NODE rp;
7440: int maxrs;
7441:
7442: maxrs = 0;
7443: lf_lazy = 1;
7444: for ( i = 0; i < nred; i++ ) {
7445: ivect = imat[i];
7446: k = ivect->head;
7447: mpz_mod(svect[k],svect[k],BDY(current_mod_lf));
7448: if ( mpz_sgn(svect[k]) ) {
7449: maxrs = MAX(maxrs,rp0[i]->sugar);
7450: mpz_neg(svect[k],svect[k]);
7451: redv = trace?nd_ps_trace[rp0[i]->index]:nd_ps[rp0[i]->index];
7452: len = LEN(redv); mr = BDY(redv);
7453: prev = k;
7454: switch ( ivect->width ) {
7455: case 1:
7456: ivc = ivect->index.c;
7457: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7458: pos = prev+ivc[j]; prev = pos;
7459: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7460: }
7461: break;
7462: case 2:
7463: ivs = ivect->index.s;
7464: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7465: pos = prev+ivs[j]; prev = pos;
7466: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7467: }
7468: break;
7469: case 4:
7470: ivi = ivect->index.i;
7471: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
7472: pos = prev+ivi[j]; prev = pos;
7473: mpz_addmul(svect[pos],svect[k],BDY(CZ(mr)));
7474: }
7475: break;
7476: }
7477: mpz_set_ui(svect[k],0);
7478: }
7479: }
7480: lf_lazy=0;
7481: for ( i = 0; i < col; i++ ) {
7482: mpz_mod(svect[i],svect[i],BDY(current_mod_lf));
7483: }
7484: return maxrs;
7485: }
7486:
7487: int nd_gauss_elim_lf(mpz_t **mat0,int *sugar,int row,int col,int *colstat)
7488: {
7489: int i,j,k,l,rank,s;
7490: mpz_t a,a1,inv;
7491: mpz_t *t,*pivot,*pk;
7492: mpz_t **mat;
7493: struct oEGT eg0,eg1,eg_forward,eg_mod,eg_back;
7494: int size,size1;
7495:
7496: mpz_init(inv);
7497: mpz_init(a);
7498: mat = (mpz_t **)mat0;
7499: size = 0;
7500: for ( rank = 0, j = 0; j < col; j++ ) {
7501: for ( i = rank; i < row; i++ ) {
7502: mpz_mod(mat[i][j],mat[i][j],BDY(current_mod_lf));
7503: }
7504: for ( i = rank; i < row; i++ )
7505: if ( mpz_sgn(mat[i][j]) )
7506: break;
7507: if ( i == row ) {
7508: colstat[j] = 0;
7509: continue;
7510: } else
7511: colstat[j] = 1;
7512: if ( i != rank ) {
7513: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
7514: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
7515: }
7516: pivot = mat[rank];
7517: s = sugar[rank];
7518: mpz_invert(inv,pivot[j],BDY(current_mod_lf));
7519: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
7520: if ( mpz_sgn(*pk) ) {
7521: mpz_mul(a,*pk,inv); mpz_mod(*pk,a,BDY(current_mod_lf));
7522: }
7523: for ( i = rank+1; i < row; i++ ) {
7524: t = mat[i];
7525: if ( mpz_sgn(t[j]) ) {
7526: sugar[i] = MAX(sugar[i],s);
7527: mpz_neg(a,t[j]);
7528: red_by_vect_lf(t+j,pivot+j,a,col-j);
7529: }
7530: }
7531: rank++;
7532: }
7533: for ( j = col-1, l = rank-1; j >= 0; j-- )
7534: if ( colstat[j] ) {
7535: pivot = mat[l];
7536: s = sugar[l];
7537: for ( k = j; k < col; k++ )
7538: mpz_mod(pivot[k],pivot[k],BDY(current_mod_lf));
7539: for ( i = 0; i < l; i++ ) {
7540: t = mat[i];
7541: if ( mpz_sgn(t[j]) ) {
7542: sugar[i] = MAX(sugar[i],s);
7543: mpz_neg(a,t[j]);
7544: red_by_vect_lf(t+j,pivot+j,a,col-j);
7545: }
7546: }
7547: l--;
7548: }
7549: for ( j = 0, l = 0; l < rank; j++ )
7550: if ( colstat[j] ) {
7551: t = mat[l];
7552: for ( k = j; k < col; k++ ) {
7553: mpz_mod(t[k],t[k],BDY(current_mod_lf));
7554: }
7555: l++;
7556: }
7557: return rank;
7558: }
7559:
7560:
7561: NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhead,UINT *s0vect)
7562: {
7563: int j,k,len;
7564: UINT *p;
7565: UINT c;
7566: NDV r;
7567: NMV mr0,mr;
7568:
7569: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
7570: if ( !len ) return 0;
7571: else {
7572: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
7573: #if 0
7574: ndv_alloc += nmv_adv*len;
7575: #endif
7576: mr = mr0;
7577: p = s0vect;
7578: for ( j = k = 0; j < col; j++, p += nd_wpd )
7579: if ( !rhead[j] ) {
7580: if ( (c = vect[k++]) != 0 ) {
7581: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
7582: }
7583: }
7584: MKNDV(nd_nvar,mr0,len,r);
7585: return r;
7586: }
7587: }
7588:
7589: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect)
7590: {
7591: int j,k,len;
7592: UINT *p;
7593: NDV r;
7594: NMV mr0,mr;
7595:
7596: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) len++;
7597: if ( !len ) return 0;
7598: else {
7599: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
7600: mr = mr0;
7601: p = s0vect;
7602: for ( j = 0; j < col; j++, p += nd_wpd )
7603: if ( vect[j/BLEN] & (1L<<(j%BLEN)) ) {
7604: ndl_copy(p,DL(mr)); CM(mr) = 1; NMV_ADV(mr);
7605: }
7606: MKNDV(nd_nvar,mr0,len,r);
7607: return r;
7608: }
7609: }
7610:
7611: /* for preprocessed vector */
7612:
7613: NDV vect_to_ndv_q(Z *vect,int spcol,int col,int *rhead,UINT *s0vect)
7614: {
1.6 noro 7615: int j,k,len;
7616: UINT *p;
7617: Z c;
7618: NDV r;
7619: NMV mr0,mr;
1.1 noro 7620:
1.6 noro 7621: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
7622: if ( !len ) return 0;
7623: else {
7624: mr0 = (NMV)MALLOC(nmv_adv*len);
1.1 noro 7625: #if 0
1.6 noro 7626: ndv_alloc += nmv_adv*len;
1.1 noro 7627: #endif
1.6 noro 7628: mr = mr0;
7629: p = s0vect;
7630: for ( j = k = 0; j < col; j++, p += nd_wpd ) {
7631: if ( !rhead[j] ) {
7632: if ( (c = vect[k++]) != 0 ) {
7633: if ( !INT(c) )
7634: error("vect_to_ndv_q : components must be integers");
7635: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
7636: }
7637: }
1.1 noro 7638: }
1.6 noro 7639: MKNDV(nd_nvar,mr0,len,r);
7640: return r;
7641: }
1.1 noro 7642: }
7643:
7644: NDV vect_to_ndv_lf(mpz_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
7645: {
7646: int j,k,len;
7647: UINT *p;
7648: mpz_t c;
7649: NDV r;
7650: NMV mr0,mr;
7651:
7652: for ( j = 0, len = 0; j < spcol; j++ ) if ( mpz_sgn(vect[j]) ) len++;
7653: if ( !len ) return 0;
7654: else {
7655: mr0 = (NMV)MALLOC(nmv_adv*len);
7656: #if 0
7657: ndv_alloc += nmv_adv*len;
7658: #endif
7659: mr = mr0;
7660: p = s0vect;
7661: for ( j = k = 0; j < col; j++, p += nd_wpd )
7662: if ( !rhead[j] ) {
7663: c[0] = vect[k++][0];
7664: if ( mpz_sgn(c) ) {
7665: ndl_copy(p,DL(mr)); MPZTOZ(c,CZ(mr)); NMV_ADV(mr);
7666: }
7667: }
7668: MKNDV(nd_nvar,mr0,len,r);
7669: return r;
7670: }
7671: }
7672:
7673: /* for plain vector */
7674:
7675: NDV plain_vect_to_ndv_q(Z *vect,int col,UINT *s0vect)
7676: {
7677: int j,k,len;
7678: UINT *p;
7679: Z c;
7680: NDV r;
7681: NMV mr0,mr;
7682:
7683: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
7684: if ( !len ) return 0;
7685: else {
7686: mr0 = (NMV)MALLOC(nmv_adv*len);
7687: #if 0
7688: ndv_alloc += nmv_adv*len;
7689: #endif
7690: mr = mr0;
7691: p = s0vect;
7692: for ( j = k = 0; j < col; j++, p += nd_wpd, k++ )
7693: if ( (c = vect[k]) != 0 ) {
7694: if ( !INT(c) )
1.6 noro 7695: error("plain_vect_to_ndv_q : components must be integers");
7696: ndl_copy(p,DL(mr)); CZ(mr) = c; NMV_ADV(mr);
1.1 noro 7697: }
7698: MKNDV(nd_nvar,mr0,len,r);
7699: return r;
7700: }
7701: }
7702:
7703: int nd_sp_f4(int m,int trace,ND_pairs l,PGeoBucket bucket)
7704: {
7705: ND_pairs t;
7706: NODE sp0,sp;
7707: int stat;
7708: ND spol;
7709:
7710: for ( t = l; t; t = NEXT(t) ) {
7711: stat = nd_sp(m,trace,t,&spol);
7712: if ( !stat ) return 0;
7713: if ( spol ) {
7714: add_pbucket_symbolic(bucket,spol);
7715: }
7716: }
7717: return 1;
7718: }
7719:
7720: int nd_symbolic_preproc(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
7721: {
7722: NODE rp0,rp;
7723: NM mul,head,s0,s;
7724: int index,col,i,sugar;
7725: RHist h;
7726: UINT *s0v,*p;
7727: NM_ind_pair pair;
7728: ND red;
7729: NDV *ps;
7730:
7731: s0 = 0; rp0 = 0; col = 0;
7732: if ( nd_demand )
7733: ps = trace?nd_ps_trace_sym:nd_ps_sym;
7734: else
7735: ps = trace?nd_ps_trace:nd_ps;
7736: while ( 1 ) {
7737: head = remove_head_pbucket_symbolic(bucket);
7738: if ( !head ) break;
7739: if ( !s0 ) s0 = head;
7740: else NEXT(s) = head;
7741: s = head;
7742: index = ndl_find_reducer(DL(head));
7743: if ( index >= 0 ) {
7744: h = nd_psh[index];
7745: NEWNM(mul);
7746: ndl_sub(DL(head),DL(h),DL(mul));
7747: if ( ndl_check_bound2(index,DL(mul)) )
7748: return 0;
7749: sugar = TD(DL(mul))+SG(ps[index]);
1.28 ! noro 7750: MKNM_ind_pair(pair,mul,index,sugar,0);
1.1 noro 7751: red = ndv_mul_nm_symbolic(mul,ps[index]);
7752: add_pbucket_symbolic(bucket,nd_remove_head(red));
7753: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
7754: }
7755: col++;
7756: }
7757: if ( rp0 ) NEXT(rp) = 0;
7758: NEXT(s) = 0;
7759: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
7760: for ( i = 0, p = s0v, s = s0; i < col;
7761: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
7762: *s0vect = s0v;
7763: *r = rp0;
7764: return col;
7765: }
7766:
7767: void print_ndp(ND_pairs l)
7768: {
7769: ND_pairs t;
7770:
7771: for ( t = l; t; t = NEXT(t) )
7772: printf("[%d,%d] ",t->i1,t->i2);
7773: printf("\n");
7774: }
7775:
7776: NODE nd_f4(int m,int checkonly,int **indp)
7777: {
7778: int i,nh,stat,index,f4red;
7779: NODE r,g,tn0,tn,node;
7780: ND_pairs d,l,t,ll0,ll,lh;
7781: LIST l0,l1;
7782: ND spol,red;
7783: NDV nf,redv;
7784: NM s0,s;
7785: NODE rp0,srp0,nflist,nzlist,nzlist_t;
7786: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
7787: UINT c;
7788: UINT **spmat;
7789: UINT *s0vect,*svect,*p,*v;
7790: int *colstat;
7791: IndArray *imat;
7792: int *rhead;
7793: int spcol,sprow;
7794: int sugar,sugarh;
7795: PGeoBucket bucket;
7796: struct oEGT eg0,eg1,eg_f4;
7797: Z i1,i2,sugarq;
1.12 noro 7798:
7799: init_eg(&f4_symb); init_eg(&f4_conv); init_eg(&f4_conv); init_eg(&f4_elim1); init_eg(&f4_elim2);
1.1 noro 7800: #if 0
7801: ndv_alloc = 0;
7802: #endif
1.11 noro 7803: Nf4_red=0;
1.1 noro 7804: g = 0; d = 0;
7805: for ( i = 0; i < nd_psn; i++ ) {
7806: d = update_pairs(d,g,i,0);
7807: g = update_base(g,i);
7808: }
7809: nzlist = 0;
7810: nzlist_t = nd_nzlist;
7811: f4red = 1;
7812: nd_last_nonzero = 0;
7813: while ( d ) {
7814: get_eg(&eg0);
7815: l = nd_minsugarp(d,&d);
7816: sugar = nd_sugarweight?l->sugar2:SG(l);
7817: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
7818: if ( nzlist_t ) {
7819: node = BDY((LIST)BDY(nzlist_t));
1.6 noro 7820: sugarh = ZTOS((Q)ARG0(node));
1.1 noro 7821: tn = BDY((LIST)ARG1(node));
7822: if ( !tn ) {
7823: nzlist_t = NEXT(nzlist_t);
7824: continue;
7825: }
7826: /* tn = [[i1,i2],...] */
7827: lh = nd_ipairtospair(tn);
7828: }
7829: bucket = create_pbucket();
7830: stat = nd_sp_f4(m,0,l,bucket);
7831: if ( !stat ) {
7832: for ( t = l; NEXT(t); t = NEXT(t) );
7833: NEXT(t) = d; d = l;
7834: d = nd_reconstruct(0,d);
7835: continue;
7836: }
7837: if ( bucket->m < 0 ) continue;
7838: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
7839: if ( !col ) {
7840: for ( t = l; NEXT(t); t = NEXT(t) );
7841: NEXT(t) = d; d = l;
7842: d = nd_reconstruct(0,d);
7843: continue;
7844: }
1.12 noro 7845: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1); add_eg(&f4_symb,&eg0,&eg1);
1.1 noro 7846: if ( DP_Print )
1.6 noro 7847: fprintf(asir_out,"sugar=%d,symb=%.3fsec,",
1.5 noro 7848: sugar,eg_f4.exectime);
1.1 noro 7849: nflist = nd_f4_red(m,nd_nzlist?lh:l,0,s0vect,col,rp0,nd_gentrace?&ll:0);
7850: if ( checkonly && nflist ) return 0;
7851: /* adding new bases */
7852: if ( nflist ) nd_last_nonzero = f4red;
7853: for ( r = nflist; r; r = NEXT(r) ) {
7854: nf = (NDV)BDY(r);
7855: ndv_removecont(m,nf);
7856: if ( !m && nd_nalg ) {
7857: ND nf1;
7858:
7859: nf1 = ndvtond(m,nf);
7860: nd_monic(0,&nf1);
7861: nd_removecont(m,nf1);
7862: nf = ndtondv(m,nf1);
7863: }
1.24 noro 7864: nh = ndv_newps(m,nf,0);
1.1 noro 7865: d = update_pairs(d,g,nh,0);
7866: g = update_base(g,nh);
7867: }
7868: if ( DP_Print ) {
7869: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
7870: }
7871: if ( nd_gentrace ) {
7872: for ( t = ll, tn0 = 0; t; t = NEXT(t) ) {
7873: NEXTNODE(tn0,tn);
1.6 noro 7874: STOZ(t->i1,i1); STOZ(t->i2,i2);
1.1 noro 7875: node = mknode(2,i1,i2); MKLIST(l0,node);
7876: BDY(tn) = l0;
7877: }
7878: if ( tn0 ) NEXT(tn) = 0; MKLIST(l0,tn0);
1.6 noro 7879: STOZ(sugar,sugarq); node = mknode(2,sugarq,l0); MKLIST(l1,node);
1.1 noro 7880: MKNODE(node,l1,nzlist); nzlist = node;
7881: }
7882: if ( nd_nzlist ) nzlist_t = NEXT(nzlist_t);
7883: f4red++;
7884: if ( nd_f4red && f4red > nd_f4red ) break;
7885: if ( nd_rank0 && !nflist ) break;
7886: }
7887: if ( nd_gentrace ) {
7888: MKLIST(l0,reverse_node(nzlist));
7889: MKNODE(nd_alltracelist,l0,0);
7890: }
7891: #if 0
7892: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
7893: #endif
1.12 noro 7894: if ( DP_Print ) {
7895: fprintf(asir_out,"number of red=%d,",Nf4_red);
7896: fprintf(asir_out,"symb=%.3fsec,conv=%.3fsec,elim1=%.3fsec,elim2=%.3fsec\n",
7897: f4_symb.exectime,f4_conv.exectime,f4_elim1.exectime,f4_elim2.exectime);
7898: }
1.1 noro 7899: conv_ilist(nd_demand,0,g,indp);
7900: return g;
7901: }
7902:
7903: NODE nd_f4_trace(int m,int **indp)
7904: {
7905: int i,nh,stat,index;
7906: NODE r,g;
7907: ND_pairs d,l,l0,t;
7908: ND spol,red;
7909: NDV nf,redv,nfqv,nfv;
7910: NM s0,s;
7911: NODE rp0,srp0,nflist;
7912: int nsp,nred,col,rank,len,k,j,a;
7913: UINT c;
7914: UINT **spmat;
7915: UINT *s0vect,*svect,*p,*v;
7916: int *colstat;
7917: IndArray *imat;
7918: int *rhead;
7919: int spcol,sprow;
7920: int sugar;
7921: PGeoBucket bucket;
7922: struct oEGT eg0,eg1,eg_f4;
7923:
7924: g = 0; d = 0;
7925: for ( i = 0; i < nd_psn; i++ ) {
7926: d = update_pairs(d,g,i,0);
7927: g = update_base(g,i);
7928: }
7929: while ( d ) {
7930: get_eg(&eg0);
7931: l = nd_minsugarp(d,&d);
7932: sugar = SG(l);
7933: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
7934: bucket = create_pbucket();
7935: stat = nd_sp_f4(m,0,l,bucket);
7936: if ( !stat ) {
7937: for ( t = l; NEXT(t); t = NEXT(t) );
7938: NEXT(t) = d; d = l;
7939: d = nd_reconstruct(1,d);
7940: continue;
7941: }
7942: if ( bucket->m < 0 ) continue;
7943: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
7944: if ( !col ) {
7945: for ( t = l; NEXT(t); t = NEXT(t) );
7946: NEXT(t) = d; d = l;
7947: d = nd_reconstruct(1,d);
7948: continue;
7949: }
7950: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
7951: if ( DP_Print )
1.3 noro 7952: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",
1.5 noro 7953: sugar,eg_f4.exectime);
1.1 noro 7954: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
7955: if ( !l0 ) continue;
7956: l = l0;
7957:
7958: /* over Q */
7959: bucket = create_pbucket();
7960: stat = nd_sp_f4(0,1,l,bucket);
7961: if ( !stat ) {
7962: for ( t = l; NEXT(t); t = NEXT(t) );
7963: NEXT(t) = d; d = l;
7964: d = nd_reconstruct(1,d);
7965: continue;
7966: }
7967: if ( bucket->m < 0 ) continue;
7968: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
7969: if ( !col ) {
7970: for ( t = l; NEXT(t); t = NEXT(t) );
7971: NEXT(t) = d; d = l;
7972: d = nd_reconstruct(1,d);
7973: continue;
7974: }
7975: nflist = nd_f4_red(0,l,1,s0vect,col,rp0,0);
7976: /* adding new bases */
7977: for ( r = nflist; r; r = NEXT(r) ) {
7978: nfqv = (NDV)BDY(r);
7979: ndv_removecont(0,nfqv);
1.6 noro 7980: if ( !remqi((Q)HCZ(nfqv),m) ) return 0;
1.1 noro 7981: if ( nd_nalg ) {
7982: ND nf1;
7983:
7984: nf1 = ndvtond(m,nfqv);
7985: nd_monic(0,&nf1);
7986: nd_removecont(0,nf1);
7987: nfqv = ndtondv(0,nf1); nd_free(nf1);
7988: }
7989: nfv = ndv_dup(0,nfqv);
7990: ndv_mod(m,nfv);
7991: ndv_removecont(m,nfv);
1.24 noro 7992: nh = ndv_newps(0,nfv,nfqv);
1.1 noro 7993: d = update_pairs(d,g,nh,0);
7994: g = update_base(g,nh);
7995: }
7996: }
7997: #if 0
7998: fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc);
7999: #endif
8000: conv_ilist(nd_demand,1,g,indp);
8001: return g;
8002: }
8003:
8004: int rref(matrix mat,int *sugar)
8005: {
8006: int row,col,i,j,k,l,s,wcol,wj;
8007: unsigned long bj;
8008: unsigned long **a;
8009: unsigned long *ai,*ak,*as,*t;
8010: int *pivot;
8011:
8012: row = mat->row;
8013: col = mat->col;
8014: a = mat->a;
8015: wcol = (col+BLEN-1)/BLEN;
8016: pivot = (int *)MALLOC_ATOMIC(row*sizeof(int));
8017: i = 0;
8018: for ( j = 0; j < col; j++ ) {
8019: wj = j/BLEN; bj = 1L<<(j%BLEN);
8020: for ( k = i; k < row; k++ )
8021: if ( a[k][wj] & bj ) break;
8022: if ( k == row ) continue;
8023: pivot[i] = j;
8024: if ( k != i ) {
8025: t = a[i]; a[i] = a[k]; a[k] = t;
8026: s = sugar[i]; sugar[i] = sugar[k]; sugar[k] = s;
8027: }
8028: ai = a[i];
8029: for ( k = i+1; k < row; k++ ) {
8030: ak = a[k];
8031: if ( ak[wj] & bj ) {
8032: for ( l = wj; l < wcol; l++ )
8033: ak[l] ^= ai[l];
8034: sugar[k] = MAX(sugar[k],sugar[i]);
8035: }
8036: }
8037: i++;
8038: }
8039: for ( k = i-1; k >= 0; k-- ) {
8040: j = pivot[k]; wj = j/BLEN; bj = 1L<<(j%BLEN);
8041: ak = a[k];
8042: for ( s = 0; s < k; s++ ) {
8043: as = a[s];
8044: if ( as[wj] & bj ) {
8045: for ( l = wj; l < wcol; l++ )
8046: as[l] ^= ak[l];
8047: sugar[s] = MAX(sugar[s],sugar[k]);
8048: }
8049: }
8050: }
8051: return i;
8052: }
8053:
8054: void print_matrix(matrix mat)
8055: {
8056: int row,col,i,j;
8057: unsigned long *ai;
8058:
8059: row = mat->row;
8060: col = mat->col;
8061: printf("%d x %d\n",row,col);
8062: for ( i = 0; i < row; i++ ) {
8063: ai = mat->a[i];
8064: for ( j = 0; j < col; j++ ) {
8065: if ( ai[j/BLEN] & (1L<<(j%BLEN)) ) putchar('1');
8066: else putchar('0');
8067: }
8068: putchar('\n');
8069: }
8070: }
8071:
8072: NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect);
8073:
8074: void red_by_vect_2(matrix mat,int *sugar,unsigned long *v,int rhead,int rsugar)
8075: {
8076: int row,col,wcol,wj,i,j;
8077: unsigned long bj;
8078: unsigned long *ai;
8079: unsigned long **a;
8080: int len;
8081: int *pos;
8082:
8083: row = mat->row;
8084: col = mat->col;
8085: wcol = (col+BLEN-1)/BLEN;
8086: pos = (int *)MALLOC(wcol*sizeof(int));
8087: bzero(pos,wcol*sizeof(int));
8088: for ( i = j = 0; i < wcol; i++ )
8089: if ( v[i] ) pos[j++] = i;;
8090: len = j;
8091: wj = rhead/BLEN;
8092: bj = 1L<<rhead%BLEN;
8093: a = mat->a;
8094: for ( i = 0; i < row; i++ ) {
8095: ai = a[i];
8096: if ( ai[wj]&bj ) {
8097: for ( j = 0; j < len; j++ )
8098: ai[pos[j]] ^= v[pos[j]];
8099: sugar[i] = MAX(sugar[i],rsugar);
8100: }
8101: }
8102: }
8103:
8104: NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8105: {
8106: int nsp,nred,i,i0,k,rank,row;
8107: NODE r0,rp;
8108: ND_pairs sp;
8109: ND spol;
8110: NM_ind_pair rt;
8111: int *s0hash;
8112: UINT *s;
8113: int *pivot,*sugar,*head;
8114: matrix mat;
8115: NM m;
8116: NODE r;
8117: struct oEGT eg0,eg1,eg2,eg_elim1,eg_elim2;
8118: int rhead,rsugar,size;
8119: unsigned long *v;
8120:
8121: get_eg(&eg0);
8122: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8123: nred = length(rp0);
8124: mat = alloc_matrix(nsp,col);
8125: s0hash = (int *)MALLOC(col*sizeof(int));
8126: for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd )
8127: s0hash[i] = ndl_hash_value(s);
8128:
8129: sugar = (int *)MALLOC(nsp*sizeof(int));
8130: for ( i = 0, sp = sp0; sp; sp = NEXT(sp) ) {
8131: nd_sp(2,0,sp,&spol);
8132: if ( spol ) {
8133: mat->a[i] = nd_to_vect_2(s0vect,col,s0hash,spol);
8134: sugar[i] = SG(spol);
8135: i++;
8136: }
8137: }
8138: mat->row = i;
8139: if ( DP_Print ) {
8140: fprintf(asir_out,"%dx%d,",mat->row,mat->col); fflush(asir_out);
8141: }
8142: size = ((col+BLEN-1)/BLEN)*sizeof(unsigned long);
8143: v = CALLOC((col+BLEN-1)/BLEN,sizeof(unsigned long));
8144: for ( rp = rp0, i = 0; rp; rp = NEXT(rp), i++ ) {
8145: rt = (NM_ind_pair)BDY(rp);
8146: bzero(v,size);
8147: rhead = nd_nm_to_vect_2(s0vect,col,s0hash,nd_ps[rt->index],rt->mul,v);
8148: rsugar = SG(nd_ps[rt->index])+TD(DL(rt->mul));
8149: red_by_vect_2(mat,sugar,v,rhead,rsugar);
8150: }
8151:
8152: get_eg(&eg1);
8153: init_eg(&eg_elim1); add_eg(&eg_elim1,&eg0,&eg1);
8154: rank = rref(mat,sugar);
8155:
8156: for ( i = 0, r0 = 0; i < rank; i++ ) {
8157: NEXTNODE(r0,r);
8158: BDY(r) = (pointer)vect_to_ndv_2(mat->a[i],col,s0vect);
8159: SG((NDV)BDY(r)) = sugar[i];
8160: }
8161: if ( r0 ) NEXT(r) = 0;
8162: get_eg(&eg2);
8163: init_eg(&eg_elim2); add_eg(&eg_elim2,&eg1,&eg2);
8164: if ( DP_Print ) {
8165: fprintf(asir_out,"elim1=%.3fsec,elim2=%.3fsec,",
1.5 noro 8166: eg_elim1.exectime,eg_elim2.exectime);
1.1 noro 8167: fflush(asir_out);
8168: }
8169: return r0;
8170: }
8171:
8172:
8173: NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz)
8174: {
8175: IndArray *imat;
1.11 noro 8176: int nsp,nred,i,start;
1.1 noro 8177: int *rhead;
8178: NODE r0,rp;
8179: ND_pairs sp;
8180: NM_ind_pair *rvect;
8181: UINT *s;
8182: int *s0hash;
1.11 noro 8183: struct oEGT eg0,eg1,eg_conv;
1.1 noro 8184:
8185: if ( m == 2 && nd_rref2 )
8186: return nd_f4_red_2(sp0,s0vect,col,rp0,nz);
8187:
8188: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
8189: nred = length(rp0);
8190: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
8191: rhead = (int *)MALLOC(col*sizeof(int));
8192: for ( i = 0; i < col; i++ ) rhead[i] = 0;
8193:
8194: /* construction of index arrays */
1.11 noro 8195: get_eg(&eg0);
1.1 noro 8196: if ( DP_Print ) {
1.11 noro 8197: fprintf(asir_out,"%dx%d,",nsp+nred,col);
8198: fflush(asir_out);
1.1 noro 8199: }
8200: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
1.11 noro 8201: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
1.1 noro 8202: rvect[i] = (NM_ind_pair)BDY(rp);
1.11 noro 8203: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
1.1 noro 8204: rhead[imat[i]->head] = 1;
1.11 noro 8205: start = imat[i]->head;
8206: }
1.12 noro 8207: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
1.11 noro 8208: if ( DP_Print ) {
8209: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
8210: fflush(asir_out);
1.1 noro 8211: }
8212: if ( m > 0 )
1.7 noro 8213: #if SIZEOF_LONG==8
1.1 noro 8214: r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8215: #else
8216: r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8217: #endif
8218: else if ( m == -1 )
8219: r0 = nd_f4_red_sf_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz);
8220: else if ( m == -2 )
8221: r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8222: else
8223: r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
8224: return r0;
8225: }
8226:
8227: /* for Fp, 2<=p<2^16 */
8228:
8229: NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8230: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8231: {
8232: int spcol,sprow,a;
8233: int i,j,k,l,rank;
8234: NODE r0,r;
8235: ND_pairs sp;
8236: ND spol;
8237: UINT **spmat;
8238: UINT *svect,*v;
8239: int *colstat;
8240: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8241: int maxrs;
8242: int *spsugar;
8243: ND_pairs *spactive;
8244:
8245: spcol = col-nred;
8246: get_eg(&eg0);
8247: /* elimination (1st step) */
8248: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8249: svect = (UINT *)MALLOC(col*sizeof(UINT));
8250: spsugar = (int *)MALLOC(nsp*sizeof(int));
8251: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8252: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8253: nd_sp(m,0,sp,&spol);
8254: if ( !spol ) continue;
8255: nd_to_vect(m,s0vect,col,spol,svect);
8256: if ( m == -1 )
8257: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8258: else
8259: maxrs = ndv_reduce_vect(m,svect,col,imat,rvect,nred);
8260: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8261: if ( i < col ) {
8262: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8263: for ( j = k = 0; j < col; j++ )
8264: if ( !rhead[j] ) v[k++] = svect[j];
8265: spsugar[sprow] = MAX(maxrs,SG(spol));
8266: if ( nz )
8267: spactive[sprow] = sp;
8268: sprow++;
8269: }
8270: nd_free(spol);
8271: }
8272: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8273: if ( DP_Print ) {
1.5 noro 8274: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8275: fflush(asir_out);
8276: }
8277: /* free index arrays */
8278: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8279:
8280: /* elimination (2nd step) */
8281: colstat = (int *)MALLOC(spcol*sizeof(int));
8282: if ( m == -1 )
8283: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8284: else
8285: rank = nd_gauss_elim_mod(spmat,spsugar,spactive,sprow,spcol,m,colstat);
8286: r0 = 0;
8287: for ( i = 0; i < rank; i++ ) {
8288: NEXTNODE(r0,r); BDY(r) =
8289: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8290: SG((NDV)BDY(r)) = spsugar[i];
8291: GCFREE(spmat[i]);
8292: }
8293: if ( r0 ) NEXT(r) = 0;
8294:
8295: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8296: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8297: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8298: if ( DP_Print ) {
1.5 noro 8299: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8300: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8301: nsp,nred,sprow,spcol,rank);
1.5 noro 8302: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8303: }
8304: if ( nz ) {
8305: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8306: if ( rank > 0 ) {
8307: NEXT(spactive[rank-1]) = 0;
8308: *nz = spactive[0];
8309: } else
8310: *nz = 0;
8311: }
8312: return r0;
8313: }
8314:
8315:
8316: /* for small finite fields */
8317:
8318: NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
8319: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
8320: {
8321: int spcol,sprow,a;
8322: int i,j,k,l,rank;
8323: NODE r0,r;
8324: ND_pairs sp;
8325: ND spol;
8326: UINT **spmat;
8327: UINT *svect,*v;
8328: int *colstat;
8329: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8330: int maxrs;
8331: int *spsugar;
8332: ND_pairs *spactive;
8333:
8334: spcol = col-nred;
8335: get_eg(&eg0);
8336: /* elimination (1st step) */
8337: spmat = (UINT **)MALLOC(nsp*sizeof(UINT *));
8338: svect = (UINT *)MALLOC(col*sizeof(UINT));
8339: spsugar = (int *)MALLOC(nsp*sizeof(int));
8340: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
8341: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8342: nd_sp(m,0,sp,&spol);
8343: if ( !spol ) continue;
8344: nd_to_vect(m,s0vect,col,spol,svect);
8345: maxrs = ndv_reduce_vect_sf(m,svect,col,imat,rvect,nred);
8346: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8347: if ( i < col ) {
8348: spmat[sprow] = v = (UINT *)MALLOC_ATOMIC(spcol*sizeof(UINT));
8349: for ( j = k = 0; j < col; j++ )
8350: if ( !rhead[j] ) v[k++] = svect[j];
8351: spsugar[sprow] = MAX(maxrs,SG(spol));
8352: if ( nz )
8353: spactive[sprow] = sp;
8354: sprow++;
8355: }
8356: nd_free(spol);
8357: }
8358: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8359: if ( DP_Print ) {
1.5 noro 8360: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8361: fflush(asir_out);
8362: }
8363: /* free index arrays */
8364: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
8365:
8366: /* elimination (2nd step) */
8367: colstat = (int *)MALLOC(spcol*sizeof(int));
8368: rank = nd_gauss_elim_sf(spmat,spsugar,sprow,spcol,m,colstat);
8369: r0 = 0;
8370: for ( i = 0; i < rank; i++ ) {
8371: NEXTNODE(r0,r); BDY(r) =
8372: (pointer)vect_to_ndv(spmat[i],spcol,col,rhead,s0vect);
8373: SG((NDV)BDY(r)) = spsugar[i];
8374: GCFREE(spmat[i]);
8375: }
8376: if ( r0 ) NEXT(r) = 0;
8377:
8378: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
8379: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8380: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8381: if ( DP_Print ) {
1.5 noro 8382: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8383: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8384: nsp,nred,sprow,spcol,rank);
1.5 noro 8385: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8386: }
8387: if ( nz ) {
8388: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
8389: if ( rank > 0 ) {
8390: NEXT(spactive[rank-1]) = 0;
8391: *nz = spactive[0];
8392: } else
8393: *nz = 0;
8394: }
8395: return r0;
8396: }
8397:
8398: NODE nd_f4_red_lf_main(int m,ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
8399: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
8400: {
8401: int spcol,sprow,a;
8402: int i,j,k,l,rank;
8403: NODE r0,r;
8404: ND_pairs sp;
8405: ND spol;
8406: mpz_t **spmat;
8407: mpz_t *svect,*v;
8408: int *colstat;
8409: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8410: int maxrs;
8411: int *spsugar;
8412: pointer *w;
8413:
8414: spcol = col-nred;
8415: get_eg(&eg0);
8416: /* elimination (1st step) */
8417: spmat = (mpz_t **)MALLOC(nsp*sizeof(mpz_t *));
8418: svect = (mpz_t *)MALLOC(col*sizeof(mpz_t));
8419: spsugar = (int *)MALLOC(nsp*sizeof(int));
8420: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8421: nd_sp(m,trace,sp,&spol);
8422: if ( !spol ) continue;
8423: nd_to_vect_lf(s0vect,col,spol,svect);
8424: maxrs = ndv_reduce_vect_lf(svect,trace,col,imat,rvect,nred);
8425: for ( i = 0; i < col; i++ ) if ( mpz_sgn(svect[i]) ) break;
8426: if ( i < col ) {
8427: spmat[sprow] = v = (mpz_t *)MALLOC(spcol*sizeof(mpz_t));
8428: for ( j = k = 0; j < col; j++ )
8429: if ( !rhead[j] ) v[k++][0] = svect[j][0];
8430: spsugar[sprow] = MAX(maxrs,SG(spol));
8431: sprow++;
8432: }
8433: /* nd_free(spol); */
8434: }
8435: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8436: if ( DP_Print ) {
1.5 noro 8437: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8438: fflush(asir_out);
8439: }
8440: /* free index arrays */
8441: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
8442:
8443: /* elimination (2nd step) */
8444: colstat = (int *)MALLOC(spcol*sizeof(int));
8445: rank = nd_gauss_elim_lf(spmat,spsugar,sprow,spcol,colstat);
8446: w = (pointer *)MALLOC(rank*sizeof(pointer));
8447: for ( i = 0; i < rank; i++ ) {
8448: #if 0
8449: w[rank-i-1] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
8450: SG((NDV)w[rank-i-1]) = spsugar[i];
8451: #else
8452: w[i] = (pointer)vect_to_ndv_lf(spmat[i],spcol,col,rhead,s0vect);
8453: SG((NDV)w[i]) = spsugar[i];
8454: #endif
8455: /* GCFREE(spmat[i]); */
8456:
8457: }
8458: #if 0
8459: qsort(w,rank,sizeof(NDV),
8460: (int (*)(const void *,const void *))ndv_compare);
8461: #endif
8462: r0 = 0;
8463: for ( i = 0; i < rank; i++ ) {
8464: NEXTNODE(r0,r); BDY(r) = w[i];
8465: }
8466: if ( r0 ) NEXT(r) = 0;
8467:
8468: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
8469: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8470: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8471: if ( DP_Print ) {
1.5 noro 8472: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8473: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8474: nsp,nred,sprow,spcol,rank);
1.5 noro 8475: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8476: }
8477: return r0;
8478: }
8479:
8480: NODE nd_f4_red_q_main(ND_pairs sp0,int nsp,int trace,UINT *s0vect,int col,
8481: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred)
8482: {
8483: int spcol,sprow,a;
8484: int i,j,k,l,rank;
8485: NODE r0,r;
8486: ND_pairs sp;
8487: ND spol;
8488: Z **spmat;
8489: Z *svect,*v;
8490: int *colstat;
8491: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
8492: int maxrs;
8493: int *spsugar;
8494: pointer *w;
8495:
8496: spcol = col-nred;
8497: get_eg(&eg0);
8498: /* elimination (1st step) */
8499: spmat = (Z **)MALLOC(nsp*sizeof(Q *));
8500: svect = (Z *)MALLOC(col*sizeof(Q));
8501: spsugar = (int *)MALLOC(nsp*sizeof(int));
8502: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
8503: nd_sp(0,trace,sp,&spol);
8504: if ( !spol ) continue;
8505: nd_to_vect_q(s0vect,col,spol,svect);
8506: maxrs = ndv_reduce_vect_q(svect,trace,col,imat,rvect,nred);
8507: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
8508: if ( i < col ) {
8509: spmat[sprow] = v = (Z *)MALLOC(spcol*sizeof(Q));
8510: for ( j = k = 0; j < col; j++ )
8511: if ( !rhead[j] ) v[k++] = svect[j];
8512: spsugar[sprow] = MAX(maxrs,SG(spol));
8513: sprow++;
8514: }
8515: /* nd_free(spol); */
8516: }
8517: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1);
8518: if ( DP_Print ) {
1.5 noro 8519: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
1.1 noro 8520: fflush(asir_out);
8521: }
8522: /* free index arrays */
8523: /* for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); */
8524:
8525: /* elimination (2nd step) */
8526: colstat = (int *)MALLOC(spcol*sizeof(int));
8527: rank = nd_gauss_elim_q(spmat,spsugar,sprow,spcol,colstat);
8528: w = (pointer *)MALLOC(rank*sizeof(pointer));
8529: for ( i = 0; i < rank; i++ ) {
8530: #if 0
8531: w[rank-i-1] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
8532: SG((NDV)w[rank-i-1]) = spsugar[i];
8533: #else
8534: w[i] = (pointer)vect_to_ndv_q(spmat[i],spcol,col,rhead,s0vect);
8535: SG((NDV)w[i]) = spsugar[i];
8536: #endif
8537: /* GCFREE(spmat[i]); */
8538: }
8539: #if 0
8540: qsort(w,rank,sizeof(NDV),
8541: (int (*)(const void *,const void *))ndv_compare);
8542: #endif
8543: r0 = 0;
8544: for ( i = 0; i < rank; i++ ) {
8545: NEXTNODE(r0,r); BDY(r) = w[i];
8546: }
8547: if ( r0 ) NEXT(r) = 0;
8548:
8549: /* for ( ; i < sprow; i++ ) GCFREE(spmat[i]); */
8550: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2);
8551: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
8552: if ( DP_Print ) {
1.5 noro 8553: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
1.1 noro 8554: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
8555: nsp,nred,sprow,spcol,rank);
1.5 noro 8556: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
1.1 noro 8557: }
8558: return r0;
8559: }
8560:
8561: FILE *nd_write,*nd_read;
8562:
8563: void nd_send_int(int a) {
8564: write_int(nd_write,(unsigned int *)&a);
8565: }
8566:
8567: void nd_send_intarray(int *p,int len) {
8568: write_intarray(nd_write,(unsigned int *)p,len);
8569: }
8570:
8571: int nd_recv_int() {
8572: int a;
8573:
8574: read_int(nd_read,(unsigned int *)&a);
8575: return a;
8576: }
8577:
8578: void nd_recv_intarray(int *p,int len) {
8579: read_intarray(nd_read,(unsigned int *)p,len);
8580: }
8581:
8582: void nd_send_ndv(NDV p) {
8583: int len,i;
8584: NMV m;
8585:
8586: if ( !p ) nd_send_int(0);
8587: else {
8588: len = LEN(p);
8589: nd_send_int(len);
8590: m = BDY(p);
8591: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
8592: nd_send_int(CM(m));
8593: nd_send_intarray((int *)DL(m),nd_wpd);
8594: }
8595: }
8596: }
8597:
8598: void nd_send_nd(ND p) {
8599: int len,i;
8600: NM m;
8601:
8602: if ( !p ) nd_send_int(0);
8603: else {
8604: len = LEN(p);
8605: nd_send_int(len);
8606: m = BDY(p);
8607: for ( i = 0; i < len; i++, m = NEXT(m) ) {
8608: nd_send_int(CM(m));
8609: nd_send_intarray((int *)DL(m),nd_wpd);
8610: }
8611: }
8612: }
8613:
8614: NDV nd_recv_ndv()
8615: {
8616: int len,i;
8617: NMV m,m0;
8618: NDV r;
8619:
8620: len = nd_recv_int();
8621: if ( !len ) return 0;
8622: else {
8623: m0 = m = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
8624: #if 0
8625: ndv_alloc += len*nmv_adv;
8626: #endif
8627: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
8628: CM(m) = nd_recv_int();
8629: nd_recv_intarray((int *)DL(m),nd_wpd);
8630: }
8631: MKNDV(nd_nvar,m0,len,r);
8632: return r;
8633: }
8634: }
8635:
8636: int nd_gauss_elim_q(Z **mat0,int *sugar,int row,int col,int *colstat)
8637: {
8638: int i,j,t,c,rank,inv;
8639: int *ci,*ri;
8640: Z dn;
8641: MAT m,nm;
8642:
8643: NEWMAT(m); m->row = row; m->col = col; m->body = (pointer **)mat0;
8644: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
8645: for ( i = 0; i < row; i++ )
8646: for ( j = 0; j < col; j++ )
8647: mat0[i][j] = 0;
8648: c = col-rank;
8649: for ( i = 0; i < rank; i++ ) {
8650: mat0[i][ri[i]] = dn;
8651: for ( j = 0; j < c; j++ )
8652: mat0[i][ci[j]] = (Z)BDY(nm)[i][j];
8653: }
8654: return rank;
8655: }
8656:
8657: int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
8658: {
8659: int i,j,k,l,inv,a,rank,s;
8660: unsigned int *t,*pivot,*pk;
8661: unsigned int **mat;
8662: ND_pairs pair;
8663:
8664: mat = (unsigned int **)mat0;
8665: for ( rank = 0, j = 0; j < col; j++ ) {
8666: for ( i = rank; i < row; i++ )
8667: mat[i][j] %= md;
8668: for ( i = rank; i < row; i++ )
8669: if ( mat[i][j] )
8670: break;
8671: if ( i == row ) {
8672: colstat[j] = 0;
8673: continue;
8674: } else
8675: colstat[j] = 1;
8676: if ( i != rank ) {
8677: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8678: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8679: if ( spactive ) {
8680: pair = spactive[i]; spactive[i] = spactive[rank];
8681: spactive[rank] = pair;
8682: }
8683: }
8684: pivot = mat[rank];
8685: s = sugar[rank];
8686: inv = invm(pivot[j],md);
8687: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8688: if ( *pk ) {
8689: if ( *pk >= (unsigned int)md )
8690: *pk %= md;
8691: DMAR(*pk,inv,0,md,*pk)
8692: }
8693: for ( i = rank+1; i < row; i++ ) {
8694: t = mat[i];
8695: if ( (a = t[j]) != 0 ) {
8696: sugar[i] = MAX(sugar[i],s);
8697: red_by_vect(md,t+j,pivot+j,md-a,col-j);
8698: }
8699: }
8700: rank++;
8701: }
8702: for ( j = col-1, l = rank-1; j >= 0; j-- )
8703: if ( colstat[j] ) {
8704: pivot = mat[l];
8705: s = sugar[l];
8706: for ( i = 0; i < l; i++ ) {
8707: t = mat[i];
8708: t[j] %= md;
8709: if ( (a = t[j]) != 0 ) {
8710: sugar[i] = MAX(sugar[i],s);
8711: red_by_vect(md,t+j,pivot+j,md-a,col-j);
8712: }
8713: }
8714: l--;
8715: }
8716: for ( j = 0, l = 0; l < rank; j++ )
8717: if ( colstat[j] ) {
8718: t = mat[l];
8719: for ( k = j; k < col; k++ )
8720: if ( t[k] >= (unsigned int)md )
8721: t[k] %= md;
8722: l++;
8723: }
8724: return rank;
8725: }
8726:
8727:
1.7 noro 8728: int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat)
1.1 noro 8729: {
1.7 noro 8730: int i,j,k,l,inv,a,rank,s;
8731: unsigned int *t,*pivot,*pk;
8732: unsigned int **mat;
8733:
8734: mat = (unsigned int **)mat0;
8735: for ( rank = 0, j = 0; j < col; j++ ) {
8736: for ( i = rank; i < row; i++ )
8737: if ( mat[i][j] )
8738: break;
8739: if ( i == row ) {
8740: colstat[j] = 0;
8741: continue;
8742: } else
8743: colstat[j] = 1;
8744: if ( i != rank ) {
8745: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
8746: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
8747: }
8748: pivot = mat[rank];
8749: s = sugar[rank];
8750: inv = _invsf(pivot[j]);
8751: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
8752: if ( *pk )
8753: *pk = _mulsf(*pk,inv);
8754: for ( i = rank+1; i < row; i++ ) {
8755: t = mat[i];
8756: if ( (a = t[j]) != 0 ) {
8757: sugar[i] = MAX(sugar[i],s);
8758: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
8759: }
8760: }
8761: rank++;
8762: }
8763: for ( j = col-1, l = rank-1; j >= 0; j-- )
8764: if ( colstat[j] ) {
8765: pivot = mat[l];
8766: s = sugar[l];
8767: for ( i = 0; i < l; i++ ) {
8768: t = mat[i];
8769: if ( (a = t[j]) != 0 ) {
8770: sugar[i] = MAX(sugar[i],s);
8771: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
8772: }
8773: }
8774: l--;
8775: }
8776: return rank;
8777: }
1.1 noro 8778:
1.7 noro 8779: int ndv_ishomo(NDV p)
8780: {
8781: NMV m;
8782: int len,h;
1.1 noro 8783:
8784: if ( !p ) return 1;
8785: len = LEN(p);
8786: m = BDY(p);
8787: h = TD(DL(m));
8788: NMV_ADV(m);
8789: for ( len--; len; len--, NMV_ADV(m) )
1.20 noro 8790: if ( TD(DL(m)) != h ) {
8791: return 0;
8792: }
1.1 noro 8793: return 1;
8794: }
8795:
8796: void ndv_save(NDV p,int index)
8797: {
8798: FILE *s;
8799: char name[BUFSIZ];
8800: short id;
8801: int nv,sugar,len,n,i,td,e,j;
8802: NMV m;
8803: unsigned int *dl;
8804: int mpos;
8805:
8806: sprintf(name,"%s/%d",Demand,index);
8807: s = fopen(name,"w");
8808: savevl(s,0);
8809: if ( !p ) {
8810: saveobj(s,0);
8811: return;
8812: }
8813: id = O_DP;
8814: nv = NV(p);
8815: sugar = SG(p);
8816: len = LEN(p);
8817: write_short(s,(unsigned short *)&id); write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar);
8818: write_int(s,(unsigned int *)&len);
8819:
8820: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 8821: saveobj(s,(Obj)CZ(m));
1.1 noro 8822: dl = DL(m);
8823: td = TD(dl);
8824: write_int(s,(unsigned int *)&td);
8825: for ( j = 0; j < nv; j++ ) {
8826: e = GET_EXP(dl,j);
8827: write_int(s,(unsigned int *)&e);
8828: }
8829: if ( nd_module ) {
8830: mpos = MPOS(dl); write_int(s,(unsigned int *)&mpos);
8831: }
8832: }
8833: fclose(s);
8834: }
8835:
8836: void nd_save_mod(ND p,int index)
8837: {
8838: FILE *s;
8839: char name[BUFSIZ];
8840: int nv,sugar,len,c;
8841: NM m;
8842:
8843: sprintf(name,"%s/%d",Demand,index);
8844: s = fopen(name,"w");
8845: if ( !p ) {
8846: len = 0;
8847: write_int(s,(unsigned int *)&len);
8848: fclose(s);
8849: return;
8850: }
8851: nv = NV(p);
8852: sugar = SG(p);
8853: len = LEN(p);
8854: write_int(s,(unsigned int *)&nv); write_int(s,(unsigned int *)&sugar); write_int(s,(unsigned int *)&len);
8855: for ( m = BDY(p); m; m = NEXT(m) ) {
8856: c = CM(m); write_int(s,(unsigned int *)&c);
8857: write_intarray(s,(unsigned int *)DL(m),nd_wpd);
8858: }
8859: fclose(s);
8860: }
8861:
8862: NDV ndv_load(int index)
8863: {
8864: FILE *s;
8865: char name[BUFSIZ];
8866: short id;
8867: int nv,sugar,len,n,i,td,e,j;
8868: NDV d;
8869: NMV m0,m;
8870: unsigned int *dl;
8871: Obj obj;
8872: int mpos;
8873:
8874: sprintf(name,"%s/%d",Demand,index);
8875: s = fopen(name,"r");
8876: if ( !s ) return 0;
8877:
8878: skipvl(s);
8879: read_short(s,(unsigned short *)&id);
8880: if ( !id ) return 0;
8881: read_int(s,(unsigned int *)&nv);
8882: read_int(s,(unsigned int *)&sugar);
8883: read_int(s,(unsigned int *)&len);
8884:
8885: m0 = m = MALLOC(len*nmv_adv);
8886: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
1.6 noro 8887: loadobj(s,&obj); CZ(m) = (Z)obj;
1.1 noro 8888: dl = DL(m);
8889: ndl_zero(dl);
8890: read_int(s,(unsigned int *)&td); TD(dl) = td;
8891: for ( j = 0; j < nv; j++ ) {
8892: read_int(s,(unsigned int *)&e);
8893: PUT_EXP(dl,j,e);
8894: }
8895: if ( nd_module ) {
8896: read_int(s,(unsigned int *)&mpos); MPOS(dl) = mpos;
8897: }
8898: if ( nd_blockmask ) ndl_weight_mask(dl);
8899: }
8900: fclose(s);
8901: MKNDV(nv,m0,len,d);
8902: SG(d) = sugar;
8903: return d;
8904: }
8905:
8906: ND nd_load_mod(int index)
8907: {
8908: FILE *s;
8909: char name[BUFSIZ];
8910: int nv,sugar,len,i,c;
8911: ND d;
8912: NM m0,m;
8913:
8914: sprintf(name,"%s/%d",Demand,index);
8915: s = fopen(name,"r");
8916: /* if the file does not exist, it means p[index]=0 */
8917: if ( !s ) return 0;
8918:
8919: read_int(s,(unsigned int *)&nv);
8920: if ( !nv ) { fclose(s); return 0; }
8921:
8922: read_int(s,(unsigned int *)&sugar);
8923: read_int(s,(unsigned int *)&len);
8924: for ( m0 = 0, i = 0; i < len; i++ ) {
8925: NEXTNM(m0,m);
8926: read_int(s,(unsigned int *)&c); CM(m) = c;
8927: read_intarray(s,(unsigned int *)DL(m),nd_wpd);
8928: }
8929: NEXT(m) = 0;
8930: MKND(nv,m0,len,d);
8931: SG(d) = sugar;
8932: fclose(s);
8933: return d;
8934: }
8935:
8936: void nd_det(int mod,MAT f,P *rp)
8937: {
8938: VL fv,tv;
8939: int n,i,j,max,e,nvar,sgn,k0,l0,len0,len,k,l,a;
8940: pointer **m;
8941: P **w;
8942: P mp,r;
8943: NDV **dm;
8944: NDV *t,*mi,*mj;
8945: NDV d,s,mij,mjj;
8946: ND u;
8947: NMV nmv;
8948: UINT *bound;
8949: PGeoBucket bucket;
8950: struct order_spec *ord;
8951: Z dq,dt,ds;
8952: Z mone;
8953: Z gn,qn,dn0,nm,dn;
8954:
8955: create_order_spec(0,0,&ord);
8956: nd_init_ord(ord);
8957: get_vars((Obj)f,&fv);
8958: if ( f->row != f->col )
8959: error("nd_det : non-square matrix");
8960: n = f->row;
8961: m = f->body;
8962: for ( nvar = 0, tv = fv; tv; tv = NEXT(tv), nvar++ );
8963:
8964: if ( !nvar ) {
8965: if ( !mod )
8966: detp(CO,(P **)m,n,rp);
8967: else {
8968: w = (P **)almat_pointer(n,n);
8969: for ( i = 0; i < n; i++ )
8970: for ( j = 0; j < n; j++ )
8971: ptomp(mod,(P)m[i][j],&w[i][j]);
8972: detmp(CO,mod,w,n,&mp);
8973: mptop(mp,rp);
8974: }
8975: return;
8976: }
8977:
8978: if ( !mod ) {
8979: w = (P **)almat_pointer(n,n);
8980: dq = ONE;
8981: for ( i = 0; i < n; i++ ) {
8982: dn0 = ONE;
8983: for ( j = 0; j < n; j++ ) {
8984: if ( !m[i][j] ) continue;
8985: lgp(m[i][j],&nm,&dn);
1.6 noro 8986: gcdz(dn0,dn,&gn); divsz(dn0,gn,&qn); mulz(qn,dn,&dn0);
1.1 noro 8987: }
8988: if ( !UNIZ(dn0) ) {
8989: ds = dn0;
8990: for ( j = 0; j < n; j++ )
8991: mulp(CO,(P)m[i][j],(P)ds,&w[i][j]);
8992: mulz(dq,ds,&dt); dq = dt;
8993: } else
8994: for ( j = 0; j < n; j++ )
8995: w[i][j] = (P)m[i][j];
8996: }
8997: m = (pointer **)w;
8998: }
8999:
9000: for ( i = 0, max = 1; i < n; i++ )
9001: for ( j = 0; j < n; j++ )
9002: for ( tv = fv; tv; tv = NEXT(tv) ) {
9003: e = getdeg(tv->v,(P)m[i][j]);
9004: max = MAX(e,max);
9005: }
9006: nd_setup_parameters(nvar,max);
9007: dm = (NDV **)almat_pointer(n,n);
9008: for ( i = 0, max = 1; i < n; i++ )
9009: for ( j = 0; j < n; j++ ) {
9010: dm[i][j] = ptondv(CO,fv,m[i][j]);
9011: if ( mod ) ndv_mod(mod,dm[i][j]);
9012: if ( dm[i][j] && !LEN(dm[i][j]) ) dm[i][j] = 0;
9013: }
9014: d = ptondv(CO,fv,(P)ONE);
9015: if ( mod ) ndv_mod(mod,d);
9016: chsgnz(ONE,&mone);
9017: for ( j = 0, sgn = 1; j < n; j++ ) {
9018: if ( DP_Print ) {
9019: fprintf(asir_out,".");
9020: }
9021: for ( i = j; i < n && !dm[i][j]; i++ );
9022: if ( i == n ) {
9023: *rp = 0;
9024: return;
9025: }
9026: k0 = i; l0 = j; len0 = LEN(dm[k0][l0]);
9027: for ( k = j; k < n; k++ )
9028: for ( l = j; l < n; l++ )
9029: if ( dm[k][l] && LEN(dm[k][l]) < len0 ) {
9030: k0 = k; l0 = l; len0 = LEN(dm[k][l]);
9031: }
9032: if ( k0 != j ) {
9033: t = dm[j]; dm[j] = dm[k0]; dm[k0] = t;
9034: sgn = -sgn;
9035: }
9036: if ( l0 != j ) {
9037: for ( k = j; k < n; k++ ) {
9038: s = dm[k][j]; dm[k][j] = dm[k][l0]; dm[k][l0] = s;
9039: }
9040: sgn = -sgn;
9041: }
9042: bound = nd_det_compute_bound(dm,n,j);
9043: for ( k = 0; k < nd_nvar; k++ )
9044: if ( bound[k]*2 > nd_mask0 ) break;
9045: if ( k < nd_nvar )
9046: nd_det_reconstruct(dm,n,j,d);
9047:
9048: for ( i = j+1, mj = dm[j], mjj = mj[j]; i < n; i++ ) {
9049: /* if ( DP_Print ) fprintf(asir_out," i=%d\n ",i); */
9050: mi = dm[i]; mij = mi[j];
9051: if ( mod )
9052: ndv_mul_c(mod,mij,mod-1);
9053: else
9054: ndv_mul_c_q(mij,mone);
9055: for ( k = j+1; k < n; k++ ) {
9056: /* if ( DP_Print ) fprintf(asir_out,"k=%d ",k); */
9057: bucket = create_pbucket();
9058: if ( mi[k] ) {
9059: nmv = BDY(mjj); len = LEN(mjj);
9060: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9061: u = ndv_mul_nmv_trunc(mod,nmv,mi[k],DL(BDY(d)));
9062: add_pbucket(mod,bucket,u);
9063: }
9064: }
9065: if ( mj[k] && mij ) {
9066: nmv = BDY(mij); len = LEN(mij);
9067: for ( a = 0; a < len; a++, NMV_ADV(nmv) ) {
9068: u = ndv_mul_nmv_trunc(mod,nmv,mj[k],DL(BDY(d)));
9069: add_pbucket(mod,bucket,u);
9070: }
9071: }
9072: u = nd_quo(mod,bucket,d);
9073: mi[k] = ndtondv(mod,u);
9074: }
9075: /* if ( DP_Print ) fprintf(asir_out,"\n",k); */
9076: }
9077: d = mjj;
9078: }
9079: if ( DP_Print ) {
9080: fprintf(asir_out,"\n");
9081: }
9082: if ( sgn < 0 ) {
9083: if ( mod )
9084: ndv_mul_c(mod,d,mod-1);
9085: else
9086: ndv_mul_c_q(d,mone);
9087: }
9088: r = ndvtop(mod,CO,fv,d);
9089: if ( !mod && !UNIQ(dq) )
9090: divsp(CO,r,(P)dq,rp);
9091: else
9092: *rp = r;
9093: }
9094:
9095: ND ndv_mul_nmv_trunc(int mod,NMV m0,NDV p,UINT *d)
9096: {
9097: NM mr,mr0;
9098: NM tnm;
9099: NMV m;
9100: UINT *d0,*dt,*dm;
9101: int c,n,td,i,c1,c2,len;
9102: Z q;
9103: ND r;
9104:
9105: if ( !p ) return 0;
9106: else {
9107: n = NV(p); m = BDY(p); len = LEN(p);
9108: d0 = DL(m0);
9109: td = TD(d);
9110: mr0 = 0;
9111: NEWNM(tnm);
9112: if ( mod ) {
9113: c = CM(m0);
9114: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9115: ndl_add(DL(m),d0,DL(tnm));
9116: if ( ndl_reducible(DL(tnm),d) ) {
9117: NEXTNM(mr0,mr);
9118: c1 = CM(m); DMAR(c1,c,0,mod,c2); CM(mr) = c2;
9119: ndl_copy(DL(tnm),DL(mr));
9120: }
9121: }
9122: } else {
1.6 noro 9123: q = CZ(m0);
1.1 noro 9124: for ( i = 0; i < len; i++, NMV_ADV(m) ) {
9125: ndl_add(DL(m),d0,DL(tnm));
9126: if ( ndl_reducible(DL(tnm),d) ) {
9127: NEXTNM(mr0,mr);
1.6 noro 9128: mulz(CZ(m),q,&CZ(mr));
1.1 noro 9129: ndl_copy(DL(tnm),DL(mr));
9130: }
9131: }
9132: }
9133: if ( !mr0 )
9134: return 0;
9135: else {
9136: NEXT(mr) = 0;
9137: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9138: MKND(NV(p),mr0,len,r);
9139: SG(r) = SG(p) + TD(d0);
9140: return r;
9141: }
9142: }
9143: }
9144:
9145: void nd_det_reconstruct(NDV **dm,int n,int j,NDV d)
9146: {
9147: int i,obpe,oadv,h,k,l;
9148: static NM prev_nm_free_list;
9149: EPOS oepos;
9150:
9151: obpe = nd_bpe;
9152: oadv = nmv_adv;
9153: oepos = nd_epos;
9154: if ( obpe < 2 ) nd_bpe = 2;
9155: else if ( obpe < 3 ) nd_bpe = 3;
9156: else if ( obpe < 4 ) nd_bpe = 4;
9157: else if ( obpe < 5 ) nd_bpe = 5;
9158: else if ( obpe < 6 ) nd_bpe = 6;
9159: else if ( obpe < 8 ) nd_bpe = 8;
9160: else if ( obpe < 10 ) nd_bpe = 10;
9161: else if ( obpe < 16 ) nd_bpe = 16;
9162: else if ( obpe < 32 ) nd_bpe = 32;
9163: else error("nd_det_reconstruct : exponent too large");
9164:
9165: nd_setup_parameters(nd_nvar,0);
9166: prev_nm_free_list = _nm_free_list;
9167: _nm_free_list = 0;
9168: for ( k = j; k < n; k++ )
9169: for (l = j; l < n; l++ )
9170: ndv_realloc(dm[k][l],obpe,oadv,oepos);
9171: ndv_realloc(d,obpe,oadv,oepos);
9172: prev_nm_free_list = 0;
9173: #if 0
9174: GC_gcollect();
9175: #endif
9176: }
9177:
9178: /* returns a UINT array containing degree bounds */
9179:
9180: UINT *nd_det_compute_bound(NDV **dm,int n,int j)
9181: {
9182: UINT *d0,*d1,*d,*t,*r;
9183: int k,l,i;
9184:
9185: d0 = (UINT *)MALLOC(nd_nvar*sizeof(UINT));
9186: for ( k = 0; k < nd_nvar; k++ ) d0[k] = 0;
9187: for ( k = j; k < n; k++ )
9188: for ( l = j; l < n; l++ )
9189: if ( dm[k][l] ) {
9190: d = ndv_compute_bound(dm[k][l]);
9191: for ( i = 0; i < nd_nvar; i++ )
9192: d0[i] = MAX(d0[i],d[i]);
9193: }
9194: return d0;
9195: }
9196:
9197: DL nd_separate_d(UINT *d,UINT *trans)
9198: {
9199: int n,td,i,e,j;
9200: DL a;
9201:
9202: ndl_zero(trans);
9203: td = 0;
9204: for ( i = 0; i < nd_ntrans; i++ ) {
9205: e = GET_EXP(d,i);
9206: PUT_EXP(trans,i,e);
9207: td += MUL_WEIGHT(e,i);
9208: }
9209: if ( nd_ntrans+nd_nalg < nd_nvar ) {
9210: /* homogenized */
9211: i = nd_nvar-1;
9212: e = GET_EXP(d,i);
9213: PUT_EXP(trans,i,e);
9214: td += MUL_WEIGHT(e,i);
9215: }
9216: TD(trans) = td;
9217: if ( nd_blockmask) ndl_weight_mask(trans);
9218: NEWDL(a,nd_nalg);
9219: td = 0;
9220: for ( i = 0; i < nd_nalg; i++ ) {
9221: j = nd_ntrans+i;
9222: e = GET_EXP(d,j);
9223: a->d[i] = e;
9224: td += e;
9225: }
9226: a->td = td;
9227: return a;
9228: }
9229:
9230: int nd_monic(int mod,ND *p)
9231: {
9232: UINT *trans,*t;
9233: DL alg;
9234: MP mp0,mp;
9235: NM m,m0,m1,ma0,ma,mb,mr0,mr;
9236: ND r;
9237: DL dl;
9238: DP nm;
9239: NDV ndv;
9240: DAlg inv,cd;
9241: ND s,c;
9242: Z l,mul;
9243: Z ln;
9244: int n,ntrans,i,e,td,is_lc,len;
9245: NumberField nf;
9246: struct oEGT eg0,eg1;
9247:
9248: if ( !(nf = get_numberfield()) )
9249: error("nd_monic : current_numberfield is not set");
9250:
9251: /* Q coef -> DAlg coef */
9252: NEWNM(ma0); ma = ma0;
9253: m = BDY(*p);
9254: is_lc = 1;
9255: while ( 1 ) {
9256: NEWMP(mp0); mp = mp0;
1.6 noro 9257: mp->c = (Obj)CZ(m);
1.1 noro 9258: mp->dl = nd_separate_d(DL(m),DL(ma));
9259: NEWNM(mb);
9260: for ( m = NEXT(m); m; m = NEXT(m) ) {
9261: alg = nd_separate_d(DL(m),DL(mb));
9262: if ( !ndl_equal(DL(ma),DL(mb)) )
9263: break;
1.6 noro 9264: NEXTMP(mp0,mp); mp->c = (Obj)CZ(m); mp->dl = alg;
1.1 noro 9265: }
9266: NEXT(mp) = 0;
9267: MKDP(nd_nalg,mp0,nm);
9268: MKDAlg(nm,ONE,cd);
9269: if ( is_lc == 1 ) {
9270: /* if the lc is a rational number, we have nothing to do */
9271: if ( !mp0->dl->td )
9272: return 1;
9273:
9274: get_eg(&eg0);
9275: invdalg(cd,&inv);
9276: get_eg(&eg1); add_eg(&eg_invdalg,&eg0,&eg1);
9277: /* check the validity of inv */
9278: if ( mod && !remqi((Q)inv->dn,mod) )
9279: return 0;
9280: CA(ma) = nf->one;
9281: is_lc = 0;
9282: ln = ONE;
9283: } else {
9284: muldalg(cd,inv,&CA(ma));
9285: lcmz(ln,CA(ma)->dn,&ln);
9286: }
9287: if ( m ) {
9288: NEXT(ma) = mb; ma = mb;
9289: } else {
9290: NEXT(ma) = 0;
9291: break;
9292: }
9293: }
9294: /* l = lcm(denoms) */
9295: l = ln;
9296: for ( mr0 = 0, m = ma0; m; m = NEXT(m) ) {
1.6 noro 9297: divsz(l,CA(m)->dn,&mul);
1.1 noro 9298: for ( mp = BDY(CA(m)->nm); mp; mp = NEXT(mp) ) {
9299: NEXTNM(mr0,mr);
1.6 noro 9300: mulz((Z)mp->c,mul,&CZ(mr));
1.1 noro 9301: dl = mp->dl;
9302: td = TD(DL(m));
9303: ndl_copy(DL(m),DL(mr));
9304: for ( i = 0; i < nd_nalg; i++ ) {
9305: e = dl->d[i];
9306: PUT_EXP(DL(mr),i+nd_ntrans,e);
9307: td += MUL_WEIGHT(e,i+nd_ntrans);
9308: }
9309: if ( nd_module ) MPOS(DL(mr)) = MPOS(DL(m));
9310: TD(DL(mr)) = td;
9311: if ( nd_blockmask) ndl_weight_mask(DL(mr));
9312: }
9313: }
9314: NEXT(mr) = 0;
9315: for ( len = 0, mr = mr0; mr; mr = NEXT(mr), len++ );
9316: MKND(NV(*p),mr0,len,r);
9317: /* XXX */
9318: SG(r) = SG(*p);
9319: nd_free(*p);
9320: *p = r;
9321: return 1;
9322: }
9323:
9324: NODE reverse_node(NODE n)
9325: {
9326: NODE t,t1;
9327:
9328: for ( t = 0; n; n = NEXT(n) ) {
9329: MKNODE(t1,BDY(n),t); t = t1;
9330: }
9331: return t;
9332: }
9333:
9334: P ndc_div(int mod,union oNDC a,union oNDC b)
9335: {
9336: union oNDC c;
9337: int inv,t;
9338:
9339: if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m));
1.10 noro 9340: else if ( mod == -2 ) divlf(a.z,b.z,&c.z);
1.1 noro 9341: else if ( mod ) {
9342: inv = invm(b.m,mod);
9343: DMAR(a.m,inv,0,mod,t); c.m = t;
9344: } else if ( nd_vc )
9345: divsp(nd_vc,a.p,b.p,&c.p);
9346: else
9347: divsz(a.z,b.z,&c.z);
9348: return ndctop(mod,c);
9349: }
9350:
9351: P ndctop(int mod,union oNDC c)
9352: {
9353: Z q;
9354: int e;
9355: GFS gfs;
9356:
9357: if ( mod == -1 ) {
9358: e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs;
9359: } else if ( mod == -2 ) {
1.10 noro 9360: q = c.z; return (P)q;
1.1 noro 9361: } else if ( mod > 0 ) {
1.6 noro 9362: STOZ(c.m,q); return (P)q;
1.1 noro 9363: } else
9364: return (P)c.p;
9365: }
9366:
9367: /* [0,0,0,cont] = p -> p/cont */
9368:
9369: void finalize_tracelist(int i,P cont)
9370: {
9371: LIST l;
9372: NODE node;
9373: Z iq;
9374:
9375: if ( !UNIQ(cont) ) {
9376: node = mknode(4,NULLP,NULLP,NULLP,cont);
9377: MKLIST(l,node); MKNODE(node,l,nd_tracelist);
9378: nd_tracelist = node;
9379: }
1.6 noro 9380: STOZ(i,iq);
1.1 noro 9381: nd_tracelist = reverse_node(nd_tracelist);
9382: MKLIST(l,nd_tracelist);
9383: node = mknode(2,iq,l); MKLIST(l,node);
9384: MKNODE(node,l,nd_alltracelist); MKLIST(l,node);
9385: nd_alltracelist = node; nd_tracelist = 0;
9386: }
9387:
9388: void conv_ilist(int demand,int trace,NODE g,int **indp)
9389: {
9390: int n,i,j;
9391: int *ind;
9392: NODE t;
9393:
9394: n = length(g);
9395: ind = (int *)MALLOC(n*sizeof(int));
9396: for ( i = 0, t = g; i < n; i++, t = NEXT(t) ) {
9397: j = (long)BDY(t); ind[i] = j;
9398: BDY(t) = (pointer)(demand?ndv_load(j):(trace?nd_ps_trace[j]:nd_ps[j]));
9399: }
9400: if ( indp ) *indp = ind;
9401: }
9402:
9403: void parse_nd_option(NODE opt)
9404: {
9405: NODE t,p,u;
9406: int i,s,n;
9407: char *key;
9408: Obj value;
9409:
9410: nd_gentrace = 0; nd_gensyz = 0; nd_nora = 0; nd_gbblock = 0;
9411: nd_newelim = 0; nd_intersect = 0; nd_nzlist = 0;
9412: nd_splist = 0; nd_check_splist = 0;
9413: nd_sugarweight = 0;
9414: nd_f4red =0;
9415: nd_rank0 = 0;
9416: for ( t = opt; t; t = NEXT(t) ) {
9417: p = BDY((LIST)BDY(t));
9418: key = BDY((STRING)BDY(p));
9419: value = (Obj)BDY(NEXT(p));
9420: if ( !strcmp(key,"gentrace") )
9421: nd_gentrace = value?1:0;
9422: else if ( !strcmp(key,"gensyz") )
9423: nd_gensyz = value?1:0;
9424: else if ( !strcmp(key,"nora") )
9425: nd_nora = value?1:0;
9426: else if ( !strcmp(key,"gbblock") ) {
9427: if ( value && OID(value) == O_LIST ) {
9428: u = BDY((LIST)value);
9429: nd_gbblock = MALLOC((2*length(u)+1)*sizeof(int));
9430: for ( i = 0; u; u = NEXT(u) ) {
9431: p = BDY((LIST)BDY(u));
1.6 noro 9432: s = nd_gbblock[i++] = ZTOS((Q)BDY(p));
9433: nd_gbblock[i++] = s+ZTOS((Q)BDY(NEXT(p)))-1;
1.1 noro 9434: }
9435: nd_gbblock[i] = -1;
9436: } else
9437: nd_gbblock = 0;
9438: } else if ( !strcmp(key,"newelim") )
9439: nd_newelim = value?1:0;
9440: else if ( !strcmp(key,"intersect") )
9441: nd_intersect = value?1:0;
1.17 noro 9442: else if ( !strcmp(key,"syzgen") )
9443: nd_intersect = ZTOS((Q)value);
1.1 noro 9444: else if ( !strcmp(key,"lf") )
9445: nd_lf = value?1:0;
9446: else if ( !strcmp(key,"trace") ) {
9447: if ( value ) {
9448: u = BDY((LIST)value);
9449: nd_nzlist = BDY((LIST)ARG2(u));
1.6 noro 9450: nd_bpe = ZTOS((Q)ARG3(u));
1.1 noro 9451: }
9452: } else if ( !strcmp(key,"f4red") ) {
1.6 noro 9453: nd_f4red = ZTOS((Q)value);
1.1 noro 9454: } else if ( !strcmp(key,"rank0") ) {
9455: nd_rank0 = value?1:0;
9456: } else if ( !strcmp(key,"splist") ) {
9457: nd_splist = value?1:0;
9458: } else if ( !strcmp(key,"check_splist") ) {
9459: nd_check_splist = BDY((LIST)value);
9460: } else if ( !strcmp(key,"sugarweight") ) {
9461: u = BDY((LIST)value);
9462: n = length(u);
9463: nd_sugarweight = MALLOC(n*sizeof(int));
9464: for ( i = 0; i < n; i++, u = NEXT(u) )
1.6 noro 9465: nd_sugarweight[i] = ZTOS((Q)BDY(u));
1.1 noro 9466: }
9467: }
9468: }
9469:
9470: ND mdptond(DP d);
9471: ND nd_mul_nm(int mod,NM m0,ND p);
9472: ND nd_mul_nm_lf(NM m0,ND p);
9473: ND *btog(NODE ti,ND **p,int nb,int mod);
9474: ND btog_one(NODE ti,ND *p,int nb,int mod);
9475: MAT nd_btog(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,MAT *rp);
9476: VECT nd_btog_one(LIST f,LIST v,int m,struct order_spec *ord,LIST tlist,int pos,MAT *rp);
9477:
9478: /* d:monomial */
9479: ND mdptond(DP d)
9480: {
9481: NM m;
9482: ND r;
9483:
9484: if ( OID(d) == 1 )
9485: r = ptond(CO,CO,(P)d);
9486: else {
9487: NEWNM(m);
9488: dltondl(NV(d),BDY(d)->dl,DL(m));
1.6 noro 9489: CZ(m) = (Z)BDY(d)->c;
1.1 noro 9490: NEXT(m) = 0;
9491: MKND(NV(d),m,1,r);
9492: }
9493: return r;
9494: }
9495:
9496: ND nd_mul_nm(int mod,NM m0,ND p)
9497: {
9498: UINT *d0;
9499: int c0,c1,c;
9500: NM tm,mr,mr0;
9501: ND r;
9502:
9503: if ( !p ) return 0;
9504: d0 = DL(m0);
9505: c0 = CM(m0);
9506: mr0 = 0;
9507: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
9508: NEXTNM(mr0,mr);
9509: c = CM(tm); DMAR(c0,c,0,mod,c1); CM(mr) = c1;
9510: ndl_add(d0,DL(tm),DL(mr));
9511: }
9512: NEXT(mr) = 0;
9513: MKND(NV(p),mr0,LEN(p),r);
9514: return r;
9515: }
9516:
9517: ND nd_mul_nm_lf(NM m0,ND p)
9518: {
9519: UINT *d0;
9520: Z c0,c1,c;
9521: NM tm,mr,mr0;
9522: ND r;
9523:
9524: if ( !p ) return 0;
9525: d0 = DL(m0);
9526: c0 = CZ(m0);
9527: mr0 = 0;
9528: for ( tm = BDY(p); tm; tm = NEXT(tm) ) {
9529: NEXTNM(mr0,mr);
9530: c = CZ(tm); mullf(c0,CZ(tm),&c1); CZ(mr) = c1;
9531: ndl_add(d0,DL(tm),DL(mr));
9532: }
9533: NEXT(mr) = 0;
9534: MKND(NV(p),mr0,LEN(p),r);
9535: return r;
9536: }
9537:
9538: ND *btog(NODE ti,ND **p,int nb,int mod)
9539: {
9540: PGeoBucket *r;
9541: int i,ci;
9542: NODE t,s;
9543: ND m,tp;
9544: ND *pi,*rd;
9545: P c;
9546:
9547: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
9548: for ( i = 0; i < nb; i++ )
9549: r[i] = create_pbucket();
9550: for ( t = ti; t; t = NEXT(t) ) {
9551: s = BDY((LIST)BDY(t));
9552: if ( ARG0(s) ) {
9553: m = mdptond((DP)ARG2(s));
1.6 noro 9554: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 9555: if ( (ci = ((MQ)c)->cont) != 0 ) {
9556: HCM(m) = ci;
1.6 noro 9557: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 9558: for ( i = 0; i < nb; i++ ) {
9559: tp = nd_mul_nm(mod,BDY(m),pi[i]);
9560: add_pbucket(mod,r[i],tp);
9561: }
9562: }
9563: ci = 1;
9564: } else {
9565: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
9566: ci = invm(ci,mod);
9567: }
9568: }
9569: rd = (ND *)MALLOC(nb*sizeof(ND));
9570: for ( i = 0; i < nb; i++ )
9571: rd[i] = normalize_pbucket(mod,r[i]);
9572: if ( ci != 1 )
9573: for ( i = 0; i < nb; i++ ) nd_mul_c(mod,rd[i],ci);
9574: return rd;
9575: }
9576:
9577: /* YYY */
9578: ND *btog_lf(NODE ti,ND **p,int nb)
9579: {
9580: PGeoBucket *r;
9581: int i;
9582: NODE t,s;
9583: ND m,tp;
9584: ND *pi,*rd;
9585: LM lm;
9586: Z lf,c;
9587:
9588: r = (PGeoBucket *)MALLOC(nb*sizeof(PGeoBucket));
9589: for ( i = 0; i < nb; i++ )
9590: r[i] = create_pbucket();
9591: for ( t = ti; t; t = NEXT(t) ) {
9592: s = BDY((LIST)BDY(t));
9593: if ( ARG0(s) ) {
9594: m = mdptond((DP)ARG2(s));
1.6 noro 9595: simp_ff((Obj)HCZ(m),(Obj *)&lm);
1.1 noro 9596: if ( lm ) {
9597: lmtolf(lm,&lf); HCZ(m) = lf;
1.6 noro 9598: pi = p[ZTOS((Q)ARG1(s))];
1.1 noro 9599: for ( i = 0; i < nb; i++ ) {
9600: tp = nd_mul_nm_lf(BDY(m),pi[i]);
9601: add_pbucket(-2,r[i],tp);
9602: }
9603: }
9604: c = ONE;
9605: } else {
9606: simp_ff((Obj)ARG3(s),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&c);
9607: }
9608: }
9609: rd = (ND *)MALLOC(nb*sizeof(ND));
9610: for ( i = 0; i < nb; i++ )
9611: rd[i] = normalize_pbucket(-2,r[i]);
9612: for ( i = 0; i < nb; i++ ) nd_mul_c_lf(rd[i],c);
9613: return rd;
9614: }
9615:
9616: ND btog_one(NODE ti,ND *p,int nb,int mod)
9617: {
9618: PGeoBucket r;
9619: int i,ci,j;
9620: NODE t,s;
9621: ND m,tp;
9622: ND pi,rd;
9623: P c;
9624:
9625: r = create_pbucket();
9626: for ( t = ti; t; t = NEXT(t) ) {
9627: s = BDY((LIST)BDY(t));
9628: if ( ARG0(s) ) {
9629: m = mdptond((DP)ARG2(s));
1.6 noro 9630: ptomp(mod,(P)HCZ(m),&c);
1.1 noro 9631: if ( (ci = ((MQ)c)->cont) != 0 ) {
9632: HCM(m) = ci;
1.6 noro 9633: pi = p[j=ZTOS((Q)ARG1(s))];
1.1 noro 9634: if ( !pi ) {
9635: pi = nd_load_mod(j);
9636: tp = nd_mul_nm(mod,BDY(m),pi);
9637: nd_free(pi);
9638: add_pbucket(mod,r,tp);
9639: } else {
9640: tp = nd_mul_nm(mod,BDY(m),pi);
9641: add_pbucket(mod,r,tp);
9642: }
9643: }
9644: ci = 1;
9645: } else {
9646: ptomp(mod,(P)ARG3(s),&c); ci = ((MQ)c)->cont;
9647: ci = invm(ci,mod);
9648: }
9649: }
9650: rd = normalize_pbucket(mod,r);
9651: free_pbucket(r);
9652: if ( ci != 1 ) nd_mul_c(mod,rd,ci);
9653: return rd;
9654: }
9655:
9656: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp);
9657:
9658: MAT nd_btog(LIST f,LIST v,int mod,struct order_spec *ord,LIST tlist,MAT *rp)
9659: {
9660: int i,j,n,m,nb,pi0,pi1,nvar;
9661: VL fv,tv,vv;
9662: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
9663: ND **p;
9664: ND *c;
9665: ND u;
9666: P inv;
9667: MAT mat;
9668:
9669: if ( mod == -2 )
9670: return nd_btog_lf(f,v,ord,tlist,rp);
9671:
9672: parse_nd_option(current_option);
9673: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
9674: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
9675: switch ( ord->id ) {
9676: case 1:
9677: if ( ord->nv != nvar )
9678: error("nd_check : invalid order specification");
9679: break;
9680: default:
9681: break;
9682: }
9683: nd_init_ord(ord);
9684: #if 0
1.6 noro 9685: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 9686: #else
9687: nd_bpe = 32;
9688: #endif
9689: nd_setup_parameters(nvar,0);
9690: permtrace = BDY((LIST)ARG2(BDY(tlist)));
9691: intred = BDY((LIST)ARG3(BDY(tlist)));
9692: ind = BDY((LIST)ARG4(BDY(tlist)));
9693: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
9694: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 9695: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 9696: if ( j > i ) i = j;
9697: }
9698: n = i+1;
9699: nb = length(BDY(f));
9700: p = (ND **)MALLOC(n*sizeof(ND *));
9701: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
9702: pi = BDY((LIST)BDY(t));
1.6 noro 9703: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 9704: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
9705: ptomp(mod,(P)ARG2(pi),&inv);
9706: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
9707: u = ptond(CO,vv,(P)ONE);
9708: HCM(u) = ((MQ)inv)->cont;
9709: c[pi1] = u;
9710: }
9711: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
9712: printf("%d ",i); fflush(stdout);
9713: ti = BDY((LIST)BDY(t));
1.6 noro 9714: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 9715: }
9716: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
9717: printf("%d ",i); fflush(stdout);
9718: ti = BDY((LIST)BDY(t));
1.6 noro 9719: p[j=ZTOS((Q)ARG0(ti))] = btog(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 9720: }
9721: m = length(ind);
9722: MKMAT(mat,nb,m);
9723: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 9724: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 9725: BDY(mat)[i][j] = ndtodp(mod,c[i]);
9726: return mat;
9727: }
9728:
9729: MAT nd_btog_lf(LIST f,LIST v,struct order_spec *ord,LIST tlist,MAT *rp)
9730: {
9731: int i,j,n,m,nb,pi0,pi1,nvar;
9732: VL fv,tv,vv;
9733: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
9734: ND **p;
9735: ND *c;
9736: ND u;
9737: MAT mat;
9738: LM lm;
9739: Z lf,inv;
9740:
9741: parse_nd_option(current_option);
9742: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
9743: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
9744: switch ( ord->id ) {
9745: case 1:
9746: if ( ord->nv != nvar )
9747: error("nd_check : invalid order specification");
9748: break;
9749: default:
9750: break;
9751: }
9752: nd_init_ord(ord);
9753: #if 0
1.6 noro 9754: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 9755: #else
9756: nd_bpe = 32;
9757: #endif
9758: nd_setup_parameters(nvar,0);
9759: permtrace = BDY((LIST)ARG2(BDY(tlist)));
9760: intred = BDY((LIST)ARG3(BDY(tlist)));
9761: ind = BDY((LIST)ARG4(BDY(tlist)));
9762: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
9763: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 9764: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 9765: if ( j > i ) i = j;
9766: }
9767: n = i+1;
9768: nb = length(BDY(f));
9769: p = (ND **)MALLOC(n*sizeof(ND *));
9770: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
9771: pi = BDY((LIST)BDY(t));
1.6 noro 9772: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 9773: p[pi0] = c = (ND *)MALLOC(nb*sizeof(ND));
9774: simp_ff((Obj)ARG2(pi),(Obj *)&lm); lmtolf(lm,&lf); invz(lf,current_mod_lf,&inv);
9775: u = ptond(CO,vv,(P)ONE);
9776: HCZ(u) = inv;
9777: c[pi1] = u;
9778: }
9779: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
9780: printf("%d ",i); fflush(stdout);
9781: ti = BDY((LIST)BDY(t));
1.6 noro 9782: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 9783: }
9784: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
9785: printf("%d ",i); fflush(stdout);
9786: ti = BDY((LIST)BDY(t));
1.6 noro 9787: p[j=ZTOS((Q)ARG0(ti))] = btog_lf(BDY((LIST)ARG1(ti)),p,nb);
1.1 noro 9788: }
9789: m = length(ind);
9790: MKMAT(mat,nb,m);
9791: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) )
1.6 noro 9792: for ( i = 0, c = p[ZTOS((Q)BDY(t))]; i < nb; i++ )
1.1 noro 9793: BDY(mat)[i][j] = ndtodp(-2,c[i]);
9794: return mat;
9795: }
9796:
9797: VECT nd_btog_one(LIST f,LIST v,int mod,struct order_spec *ord,
9798: LIST tlist,int pos,MAT *rp)
9799: {
9800: int i,j,n,m,nb,pi0,pi1,nvar;
9801: VL fv,tv,vv;
9802: NODE permtrace,perm,trace,intred,ind,t,pi,ti;
9803: ND *p;
9804: ND *c;
9805: ND u;
9806: P inv;
9807: VECT vect;
9808:
9809: if ( mod == -2 )
9810: error("nd_btog_one : not implemented yet for a large finite field");
9811:
9812: parse_nd_option(current_option);
9813: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
9814: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
9815: switch ( ord->id ) {
9816: case 1:
9817: if ( ord->nv != nvar )
9818: error("nd_check : invalid order specification");
9819: break;
9820: default:
9821: break;
9822: }
9823: nd_init_ord(ord);
9824: #if 0
1.6 noro 9825: nd_bpe = ZTOS((Q)ARG7(BDY(tlist)));
1.1 noro 9826: #else
9827: nd_bpe = 32;
9828: #endif
9829: nd_setup_parameters(nvar,0);
9830: permtrace = BDY((LIST)ARG2(BDY(tlist)));
9831: intred = BDY((LIST)ARG3(BDY(tlist)));
9832: ind = BDY((LIST)ARG4(BDY(tlist)));
9833: perm = BDY((LIST)BDY(permtrace)); trace =NEXT(permtrace);
9834: for ( i = length(perm)-1, t = trace; t; t = NEXT(t) ) {
1.6 noro 9835: j = ZTOS((Q)BDY(BDY((LIST)BDY(t))));
1.1 noro 9836: if ( j > i ) i = j;
9837: }
9838: n = i+1;
9839: nb = length(BDY(f));
9840: p = (ND *)MALLOC(n*sizeof(ND *));
9841: for ( t = perm, i = 0; t; t = NEXT(t), i++ ) {
9842: pi = BDY((LIST)BDY(t));
1.6 noro 9843: pi0 = ZTOS((Q)ARG0(pi)); pi1 = ZTOS((Q)ARG1(pi));
1.1 noro 9844: if ( pi1 == pos ) {
9845: ptomp(mod,(P)ARG2(pi),&inv);
9846: ((MQ)inv)->cont = invm(((MQ)inv)->cont,mod);
9847: u = ptond(CO,vv,(P)ONE);
9848: HCM(u) = ((MQ)inv)->cont;
9849: p[pi0] = u;
9850: }
9851: }
9852: for ( t = trace,i=0; t; t = NEXT(t), i++ ) {
9853: printf("%d ",i); fflush(stdout);
9854: ti = BDY((LIST)BDY(t));
1.6 noro 9855: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 9856: if ( Demand ) {
9857: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
9858: }
9859: }
9860: for ( t = intred, i=0; t; t = NEXT(t), i++ ) {
9861: printf("%d ",i); fflush(stdout);
9862: ti = BDY((LIST)BDY(t));
1.6 noro 9863: p[j=ZTOS((Q)ARG0(ti))] = btog_one(BDY((LIST)ARG1(ti)),p,nb,mod);
1.1 noro 9864: if ( Demand ) {
9865: nd_save_mod(p[j],j); nd_free(p[j]); p[j] = 0;
9866: }
9867: }
9868: m = length(ind);
9869: MKVECT(vect,m);
9870: for ( j = 0, t = ind; j < m; j++, t = NEXT(t) ) {
1.6 noro 9871: u = p[ZTOS((Q)BDY(t))];
1.1 noro 9872: if ( !u ) {
1.6 noro 9873: u = nd_load_mod(ZTOS((Q)BDY(t)));
1.1 noro 9874: BDY(vect)[j] = ndtodp(mod,u);
9875: nd_free(u);
9876: } else
9877: BDY(vect)[j] = ndtodp(mod,u);
9878: }
9879: return vect;
9880: }
9881:
9882: void ndv_print_lf(NDV p)
9883: {
9884: NMV m;
9885: int i,len;
9886:
9887: if ( !p ) printf("0\n");
9888: else {
9889: len = LEN(p);
9890: for ( m = BDY(p), i = 0; i < len; i++, NMV_ADV(m) ) {
9891: printf("+");
9892: mpz_out_str(asir_out,10,BDY(CZ(m)));
9893: printf("*");
9894: ndl_print(DL(m));
9895: }
9896: printf("\n");
9897: }
9898: }
9899:
9900: void nd_f4_lf_trace(LIST f,LIST v,int trace,int homo,struct order_spec *ord,LIST *rp)
9901: {
9902: VL tv,fv,vv,vc,av;
9903: NODE fd,fd0,in0,in,r,r0,t,s,cand,alist;
9904: int m,nocheck,nvar,mindex,e,max;
9905: NDV c;
9906: NMV a;
9907: P p,zp;
9908: Q dmy;
9909: EPOS oepos;
9910: int obpe,oadv,wmax,i,len,cbpe,ishomo,nalg,mrank,trank,ompos;
9911: Alg alpha,dp;
9912: P poly;
9913: LIST f1,f2,zpl;
9914: Obj obj;
9915: NumberField nf;
9916: struct order_spec *ord1;
9917: struct oEGT eg_check,eg0,eg1;
9918: NODE tr,tl1,tl2,tl3,tl4;
9919: LIST l1,l2,l3,l4,l5;
9920: int *perm;
9921: int j,ret;
9922: NODE retn;
9923: Q jq,bpe;
9924:
9925: nd_module = 0;
9926: parse_nd_option(current_option);
9927: get_vars((Obj)f,&fv); pltovl(v,&vv); vlminus(fv,vv,&nd_vc);
9928: if ( nd_vc )
9929: error("nd_f4_lf_trace : computation over a rational function field is not implemented");
9930: for ( nvar = 0, tv = vv; tv; tv = NEXT(tv), nvar++ );
9931: switch ( ord->id ) {
9932: case 1:
9933: if ( ord->nv != nvar )
9934: error("nd_f4_lf_trace : invalid order specification");
9935: break;
9936: default:
9937: break;
9938: }
9939:
9940: nd_ntrans = nvar;
9941: nd_nalg = 0;
9942:
9943: nocheck = 0;
9944: mindex = 0;
9945:
9946: /* do not use on-demand load/save */
9947: nd_demand = 0;
9948: m = trace > 1 ? trace : get_lprime(mindex);
9949: nd_init_ord(ord);
9950: mrank = 0;
9951: for ( t = BDY(f), max = 1; t; t = NEXT(t) )
9952: for ( tv = vv; tv; tv = NEXT(tv) ) {
9953: if ( nd_module ) {
9954: s = BDY((LIST)BDY(t));
9955: trank = length(s);
9956: mrank = MAX(mrank,trank);
9957: for ( ; s; s = NEXT(s) ) {
9958: e = getdeg(tv->v,(P)BDY(s));
9959: max = MAX(e,max);
9960: }
9961: } else {
9962: e = getdeg(tv->v,(P)BDY(t));
9963: max = MAX(e,max);
9964: }
9965: }
9966: nd_setup_parameters(nvar,max);
9967: obpe = nd_bpe; oadv = nmv_adv; oepos = nd_epos; ompos = nd_mpos;
9968: ishomo = 1;
9969: /* XXX */
9970: for ( in0 = 0, fd0 = 0, t = BDY(f); t; t = NEXT(t) ) {
9971: if ( nd_module ) {
9972: c = (pointer)pltondv(CO,vv,(LIST)BDY(t));
9973: } else {
9974: c = (pointer)ptondv(CO,vv,(P)BDY(t));
9975: }
9976: if ( ishomo )
9977: ishomo = ishomo && ndv_ishomo(c);
9978: if ( c ) {
9979: NEXTNODE(fd0,fd); BDY(fd) = (pointer)ndv_dup(0,c);
9980: ndv_mod(-2,c);
9981: NEXTNODE(in0,in); BDY(in) = (pointer)c;
9982: }
9983: }
9984: if ( in0 ) NEXT(in) = 0;
9985: if ( fd0 ) NEXT(fd) = 0;
9986: if ( !ishomo && homo ) {
9987: for ( t = in0, wmax = max; t; t = NEXT(t) ) {
9988: c = (NDV)BDY(t); len = LEN(c);
9989: for ( a = BDY(c), i = 0; i < len; i++, NMV_ADV(a) )
9990: wmax = MAX(TD(DL(a)),wmax);
9991: }
9992: homogenize_order(ord,nvar,&ord1);
9993: nd_init_ord(ord1);
9994: nd_setup_parameters(nvar+1,wmax);
9995: for ( t = fd0; t; t = NEXT(t) )
9996: ndv_homogenize((NDV)BDY(t),obpe,oadv,oepos,ompos);
9997: }
9998: if ( MaxDeg > 0 ) nocheck = 1;
1.24 noro 9999: ret = ndv_setup(-2,m,fd0,nd_gbblock?1:0,0,0);
1.1 noro 10000: if ( ret )
10001: cand = nd_f4_lf_trace_main(m,&perm);
10002: if ( !ret || !cand ) {
10003: *rp = 0; return;
10004: }
10005: if ( !ishomo && homo ) {
10006: /* dehomogenization */
10007: for ( t = cand; t; t = NEXT(t) ) ndv_dehomogenize((NDV)BDY(t),ord);
10008: nd_init_ord(ord);
10009: nd_setup_parameters(nvar,0);
10010: }
10011: cand = ndv_reducebase(cand,perm);
10012: cand = ndv_reduceall(-2,cand);
10013: cbpe = nd_bpe;
10014: get_eg(&eg0);
10015: if ( (ret = ndv_check_membership(-2,in0,obpe,oadv,oepos,cand)) != 0 ) {
10016: /* gbcheck : cand is a GB of Id(cand) ? */
10017: retn = nd_f4(-2,0,0);
10018: }
10019: if ( !retn ) {
10020: /* failure */
10021: *rp = 0; return;
10022: }
10023: get_eg(&eg1); init_eg(&eg_check); add_eg(&eg_check,&eg0,&eg1);
10024: if ( DP_Print )
1.5 noro 10025: fprintf(asir_out,"check=%.3fsec\n",eg_check.exectime);
1.1 noro 10026: /* dp->p */
10027: nd_bpe = cbpe;
10028: nd_setup_parameters(nd_nvar,0);
10029: for ( r = cand; r; r = NEXT(r) ) {
10030: if ( nd_module ) BDY(r) = ndvtopl(-2,CO,vv,BDY(r),mrank);
10031: else BDY(r) = (pointer)ndvtop(-2,CO,vv,BDY(r));
10032: }
10033: MKLIST(*rp,cand);
10034: }
10035:
10036: NODE nd_f4_lf_trace_main(int m,int **indp)
10037: {
10038: int i,nh,stat,index;
10039: NODE r,rm,g;
10040: ND_pairs d,l,l0,t;
10041: ND spol,red;
10042: NDV nf,redv,nfqv,nfv;
10043: NM s0,s;
10044: NODE rp0,srp0,nflist,nflist_lf;
10045: int nsp,nred,col,rank,len,k,j,a;
10046: UINT c;
10047: UINT **spmat;
10048: UINT *s0vect,*svect,*p,*v;
10049: int *colstat;
10050: IndArray *imat;
10051: int *rhead;
10052: int spcol,sprow;
10053: int sugar;
10054: PGeoBucket bucket;
10055: struct oEGT eg0,eg1,eg_f4;
10056:
10057: g = 0; d = 0;
10058: for ( i = 0; i < nd_psn; i++ ) {
10059: d = update_pairs(d,g,i,0);
10060: g = update_base(g,i);
10061: }
10062: while ( d ) {
10063: get_eg(&eg0);
10064: l = nd_minsugarp(d,&d);
10065: sugar = SG(l);
10066: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
10067: bucket = create_pbucket();
10068: stat = nd_sp_f4(m,0,l,bucket);
10069: if ( !stat ) {
10070: for ( t = l; NEXT(t); t = NEXT(t) );
10071: NEXT(t) = d; d = l;
10072: d = nd_reconstruct(1,d);
10073: continue;
10074: }
10075: if ( bucket->m < 0 ) continue;
10076: col = nd_symbolic_preproc(bucket,0,&s0vect,&rp0);
10077: if ( !col ) {
10078: for ( t = l; NEXT(t); t = NEXT(t) );
10079: NEXT(t) = d; d = l;
10080: d = nd_reconstruct(1,d);
10081: continue;
10082: }
10083: get_eg(&eg1); init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg1);
10084: if ( DP_Print )
1.5 noro 10085: fprintf(asir_out,"\nsugar=%d,symb=%.3fsec,",sugar,eg_f4.exectime);
1.1 noro 10086: nflist = nd_f4_red(m,l,0,s0vect,col,rp0,&l0);
10087: if ( !l0 ) continue;
10088: l = l0;
10089:
10090: /* over LF */
10091: bucket = create_pbucket();
10092: stat = nd_sp_f4(-2,1,l,bucket);
10093: if ( !stat ) {
10094: for ( t = l; NEXT(t); t = NEXT(t) );
10095: NEXT(t) = d; d = l;
10096: d = nd_reconstruct(1,d);
10097: continue;
10098: }
10099: if ( bucket->m < 0 ) continue;
10100: col = nd_symbolic_preproc(bucket,1,&s0vect,&rp0);
10101: if ( !col ) {
10102: for ( t = l; NEXT(t); t = NEXT(t) );
10103: NEXT(t) = d; d = l;
10104: d = nd_reconstruct(1,d);
10105: continue;
10106: }
10107: nflist_lf = nd_f4_red(-2,l,1,s0vect,col,rp0,0);
10108: /* adding new bases */
10109: for ( rm = nflist, r = nflist_lf; r && rm; rm = NEXT(rm), r = NEXT(r) ) {
10110: nfv = (NDV)BDY(rm);
10111: nfqv = (NDV)BDY(r);
10112: if ( DL_COMPARE(HDL(nfv),HDL(nfqv)) ) return 0;
10113: ndv_removecont(m,nfv);
10114: ndv_removecont(-2,nfqv);
1.24 noro 10115: nh = ndv_newps(-2,nfv,nfqv);
1.1 noro 10116: d = update_pairs(d,g,nh,0);
10117: g = update_base(g,nh);
10118: }
10119: if ( r || rm ) return 0;
10120: }
10121: conv_ilist(nd_demand,1,g,indp);
10122: return g;
10123: }
10124:
1.7 noro 10125: #if SIZEOF_LONG==8
10126:
10127: NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect)
10128: {
10129: int j,k,len;
10130: UINT *p;
10131: UINT c;
10132: NDV r;
10133: NMV mr0,mr;
10134:
10135: for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++;
10136: if ( !len ) return 0;
10137: else {
10138: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
10139: #if 0
10140: ndv_alloc += nmv_adv*len;
10141: #endif
10142: mr = mr0;
10143: p = s0vect;
10144: for ( j = k = 0; j < col; j++, p += nd_wpd )
10145: if ( !rhead[j] ) {
10146: if ( (c = (UINT)vect[k++]) != 0 ) {
10147: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
10148: }
10149: }
10150: MKNDV(nd_nvar,mr0,len,r);
10151: return r;
10152: }
10153: }
10154:
1.28 ! noro 10155: NDV vect64_to_ndv_s(mp_limb_t *vect,int col,UINT *s0vect)
! 10156: {
! 10157: int j,k,len;
! 10158: UINT *p;
! 10159: UINT c;
! 10160: NDV r;
! 10161: NMV mr0,mr;
! 10162:
! 10163: for ( j = 0, len = 0; j < col; j++ ) if ( vect[j] ) len++;
! 10164: if ( !len ) return 0;
! 10165: else {
! 10166: mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len);
! 10167: mr = mr0;
! 10168: p = s0vect;
! 10169: for ( j = k = 0; j < col; j++, p += nd_wpd )
! 10170: if ( (c = (UINT)vect[k++]) != 0 ) {
! 10171: ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr);
! 10172: }
! 10173: MKNDV(nd_nvar,mr0,len,r);
! 10174: return r;
! 10175: }
! 10176: }
! 10177:
1.7 noro 10178: int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r)
10179: {
10180: NM m;
1.11 noro 10181: UINT *t,*s,*u;
10182: int i,st,ed,md,prev,c;
1.7 noro 10183:
10184: for ( i = 0; i < n; i++ ) r[i] = 0;
1.11 noro 10185: prev = 0;
10186: for ( i = 0, m = BDY(d); m; m = NEXT(m) ) {
10187: t = DL(m);
10188: st = prev;
10189: ed = n;
10190: while ( ed > st ) {
10191: md = (st+ed)/2;
10192: u = s0+md*nd_wpd;
10193: c = DL_COMPARE(u,t);
10194: if ( c == 0 ) break;
10195: else if ( c > 0 ) st = md;
10196: else ed = md;
10197: }
10198: r[md] = (mp_limb_t)CM(m);
10199: prev = md;
1.7 noro 10200: }
10201: for ( i = 0; !r[i]; i++ );
10202: return i;
10203: }
10204:
10205: #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a)))
10206:
1.28 ! noro 10207: 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 10208: {
10209: int i,j,k,len,pos,prev;
10210: mp_limb_t a,c,c1,c2;
10211: IndArray ivect;
10212: unsigned char *ivc;
10213: unsigned short *ivs;
10214: unsigned int *ivi;
10215: NDV redv;
10216: NMV mr;
10217: NODE rp;
10218: int maxrs;
10219:
10220: for ( i = 0; i < col; i++ ) cvect[i] = 0;
10221: maxrs = 0;
10222: for ( i = 0; i < nred; i++ ) {
10223: ivect = imat[i];
10224: k = ivect->head;
10225: a = svect[k]; c = cvect[k];
10226: MOD128(a,c,m);
10227: svect[k] = a; cvect[k] = 0;
1.28 ! noro 10228: if ( (c = svect[k]) != 0 && (sig == 0 || comp_sig(sig,rp0[i]->sig) > 0 ) ) {
1.11 noro 10229: Nf4_red++;
1.7 noro 10230: maxrs = MAX(maxrs,rp0[i]->sugar);
10231: c = m-c; redv = nd_ps[rp0[i]->index];
10232: len = LEN(redv); mr = BDY(redv);
10233: svect[k] = 0; prev = k;
10234: switch ( ivect->width ) {
10235: case 1:
10236: ivc = ivect->index.c;
10237: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10238: pos = prev+ivc[j]; c1 = CM(mr); prev = pos;
1.12 noro 10239: c2 = svect[pos]+c1*c;
10240: if ( c2 < svect[pos] ) cvect[pos]++;
10241: svect[pos] = c2;
1.7 noro 10242: }
10243: break;
10244: case 2:
10245: ivs = ivect->index.s;
10246: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10247: pos = prev+ivs[j]; c1 = CM(mr); prev = pos;
1.12 noro 10248: c2 = svect[pos]+c1*c;
10249: if ( c2 < svect[pos] ) cvect[pos]++;
10250: svect[pos] = c2;
1.7 noro 10251: }
10252: break;
10253: case 4:
10254: ivi = ivect->index.i;
10255: for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) {
10256: pos = prev+ivi[j]; c1 = CM(mr); prev = pos;
1.12 noro 10257: c2 = svect[pos]+c1*c;
10258: if ( c2 < svect[pos] ) cvect[pos]++;
10259: svect[pos] = c2;
1.7 noro 10260: }
10261: break;
10262: }
10263: }
10264: }
10265: for ( i = 0; i < col; i++ ) {
10266: a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a;
10267: }
10268: return maxrs;
10269: }
10270:
10271: /* for Fp, 2^15=<p<2^29 */
10272:
10273: NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
10274: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz)
10275: {
10276: int spcol,sprow,a;
10277: int i,j,k,l,rank;
10278: NODE r0,r;
10279: ND_pairs sp;
10280: ND spol;
10281: mp_limb_t **spmat;
10282: mp_limb_t *svect,*cvect;
10283: mp_limb_t *v;
10284: int *colstat;
10285: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
10286: int maxrs;
10287: int *spsugar;
10288: ND_pairs *spactive;
10289:
10290: spcol = col-nred;
10291: get_eg(&eg0);
10292: /* elimination (1st step) */
10293: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
10294: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10295: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
10296: spsugar = (int *)MALLOC(nsp*sizeof(int));
10297: spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs));
10298: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
10299: nd_sp(m,0,sp,&spol);
10300: if ( !spol ) continue;
10301: nd_to_vect64(m,s0vect,col,spol,svect);
1.28 ! noro 10302: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,0);
1.7 noro 10303: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
10304: if ( i < col ) {
10305: spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t));
10306: for ( j = k = 0; j < col; j++ )
10307: if ( !rhead[j] ) v[k++] = (UINT)svect[j];
10308: spsugar[sprow] = MAX(maxrs,SG(spol));
10309: if ( nz )
10310: spactive[sprow] = sp;
10311: sprow++;
10312: }
10313: nd_free(spol);
10314: }
1.12 noro 10315: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
1.7 noro 10316: if ( DP_Print ) {
10317: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
10318: fflush(asir_out);
10319: }
10320: /* free index arrays */
10321: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
10322:
10323: /* elimination (2nd step) */
10324: colstat = (int *)MALLOC(spcol*sizeof(int));
10325: rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat);
10326: r0 = 0;
10327: for ( i = 0; i < rank; i++ ) {
10328: NEXTNODE(r0,r); BDY(r) =
10329: (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect);
10330: SG((NDV)BDY(r)) = spsugar[i];
10331: GCFREE(spmat[i]);
10332: }
10333: if ( r0 ) NEXT(r) = 0;
10334:
10335: for ( ; i < sprow; i++ ) GCFREE(spmat[i]);
1.12 noro 10336: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
1.7 noro 10337: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
10338: if ( DP_Print ) {
10339: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
10340: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
10341: nsp,nred,sprow,spcol,rank);
10342: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
10343: }
10344: if ( nz ) {
10345: for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1];
10346: if ( rank > 0 ) {
10347: NEXT(spactive[rank-1]) = 0;
10348: *nz = spactive[0];
10349: } else
10350: *nz = 0;
10351: }
10352: return r0;
10353: }
10354:
10355: int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat)
10356: {
10357: int i,j,k,l,rank,s;
10358: mp_limb_t inv;
10359: mp_limb_t a;
10360: UINT c;
10361: mp_limb_t *t,*pivot,*pk;
10362: UINT *ck;
10363: UINT **cmat;
10364: UINT *ct;
10365: ND_pairs pair;
10366:
10367: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
10368: for ( i = 0; i < row; i++ ) {
10369: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
10370: bzero(cmat[i],col*sizeof(UINT));
10371: }
10372:
10373: for ( rank = 0, j = 0; j < col; j++ ) {
10374: for ( i = rank; i < row; i++ ) {
10375: a = mat[i][j]; c = cmat[i][j];
10376: MOD128(a,c,md);
10377: mat[i][j] = a; cmat[i][j] = 0;
10378: }
10379: for ( i = rank; i < row; i++ )
10380: if ( mat[i][j] )
10381: break;
10382: if ( i == row ) {
10383: colstat[j] = 0;
10384: continue;
10385: } else
10386: colstat[j] = 1;
10387: if ( i != rank ) {
10388: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
10389: ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct;
10390: s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s;
10391: if ( spactive ) {
10392: pair = spactive[i]; spactive[i] = spactive[rank];
10393: spactive[rank] = pair;
10394: }
10395: }
10396: /* column j is normalized */
10397: s = sugar[rank];
10398: inv = invm((UINT)mat[rank][j],md);
10399: /* normalize pivot row */
10400: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
10401: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
10402: }
10403: for ( i = rank+1; i < row; i++ ) {
10404: if ( (a = mat[i][j]) != 0 ) {
10405: sugar[i] = MAX(sugar[i],s);
10406: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
1.11 noro 10407: Nf4_red++;
1.7 noro 10408: }
10409: }
10410: rank++;
10411: }
10412: for ( j = col-1, l = rank-1; j >= 0; j-- )
10413: if ( colstat[j] ) {
10414: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
10415: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
10416: }
10417: s = sugar[l];
10418: for ( i = 0; i < l; i++ ) {
10419: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
10420: if ( a ) {
10421: sugar[i] = MAX(sugar[i],s);
10422: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
1.11 noro 10423: Nf4_red++;
1.7 noro 10424: }
10425: }
10426: l--;
10427: }
10428: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
10429: GCFREE(cmat);
10430: return rank;
10431: }
10432: #endif
10433:
1.28 ! noro 10434: 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)
! 10435: {
! 10436: int i,j,k,l,rank,s,imin;
! 10437: mp_limb_t inv;
! 10438: mp_limb_t a;
! 10439: UINT c;
! 10440: mp_limb_t *t,*pivot,*pk;
! 10441: UINT *ck;
! 10442: UINT **cmat;
! 10443: UINT *ct;
! 10444: ND_pairs pair;
! 10445: SIG sg;
! 10446:
! 10447: cmat = (UINT **)MALLOC(row*sizeof(UINT *));
! 10448: for ( i = 0; i < row; i++ ) {
! 10449: cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT));
! 10450: bzero(cmat[i],col*sizeof(UINT));
! 10451: }
! 10452:
! 10453: for ( rank = 0, j = 0; j < col; j++ ) {
! 10454: for ( i = rank; i < row; i++ ) {
! 10455: a = mat[i][j]; c = cmat[i][j];
! 10456: MOD128(a,c,md);
! 10457: mat[i][j] = a; cmat[i][j] = 0;
! 10458: }
! 10459: imin = -1;
! 10460: for ( i = rank; i < row; i++ )
! 10461: if ( mat[i][j] && (imin < 0 || comp_sig(sig[imin],sig[i]) > 0) ) imin = i;
! 10462: if ( imin == -1 ) {
! 10463: colstat[j] = 0;
! 10464: continue;
! 10465: } else
! 10466: colstat[j] = 1;
! 10467: if ( imin != rank ) {
! 10468: t = mat[imin]; mat[imin] = mat[rank]; mat[rank] = t;
! 10469: ct = cmat[imin]; cmat[imin] = cmat[rank]; cmat[rank] = ct;
! 10470: s = sugar[imin]; sugar[imin] = sugar[rank]; sugar[rank] = s;
! 10471: sg = sig[imin]; sig[imin] = sig[rank]; sig[rank] = sg;
! 10472: if ( spactive ) {
! 10473: pair = spactive[imin]; spactive[imin] = spactive[rank];
! 10474: spactive[rank] = pair;
! 10475: }
! 10476: }
! 10477: /* column j is normalized */
! 10478: s = sugar[rank];
! 10479: inv = invm((UINT)mat[rank][j],md);
! 10480: /* normalize pivot row */
! 10481: for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) {
! 10482: a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0;
! 10483: }
! 10484: for ( i = rank+1; i < row; i++ ) {
! 10485: if ( (a = mat[i][j]) != 0 ) {
! 10486: sugar[i] = MAX(sugar[i],s);
! 10487: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j);
! 10488: Nf4_red++;
! 10489: }
! 10490: }
! 10491: rank++;
! 10492: }
! 10493: #if 1
! 10494: for ( j = col-1, l = rank-1; j >= 0; j-- )
! 10495: if ( colstat[j] ) {
! 10496: for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) {
! 10497: a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0;
! 10498: }
! 10499: s = sugar[l];
! 10500: for ( i = 0; i < l; i++ ) {
! 10501: a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0;
! 10502: if ( a && comp_sig(sig[i],sig[l]) > 0 ) {
! 10503: sugar[i] = MAX(sugar[i],s);
! 10504: red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j);
! 10505: Nf4_red++;
! 10506: }
! 10507: }
! 10508: l--;
! 10509: }
! 10510: #endif
! 10511: for ( i = 0; i < row; i++ ) GCFREE(cmat[i]);
! 10512: GCFREE(cmat);
! 10513: return rank;
! 10514: }
! 10515:
! 10516: NODE nd_f4_red_mod64_main_s(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col,
! 10517: NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,NODE *syzlistp)
! 10518: {
! 10519: int spcol,sprow,a;
! 10520: int i,j,k,l,rank;
! 10521: NODE r0,r;
! 10522: ND_pairs sp;
! 10523: ND spol;
! 10524: mp_limb_t **spmat;
! 10525: mp_limb_t *svect,*cvect;
! 10526: mp_limb_t *v;
! 10527: int *colstat;
! 10528: struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2;
! 10529: int maxrs;
! 10530: int *spsugar;
! 10531: ND_pairs *spactive;
! 10532: SIG *spsig;
! 10533:
! 10534: get_eg(&eg0);
! 10535: /* elimination (1st step) */
! 10536: spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *));
! 10537: cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
! 10538: spsugar = (int *)MALLOC(nsp*sizeof(int));
! 10539: spsig = (SIG *)MALLOC(nsp*sizeof(SIG));
! 10540: for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) {
! 10541: nd_sp(m,0,sp,&spol);
! 10542: if ( !spol ) {
! 10543: *syzlistp = insert_sig(*syzlistp,sp->sig);
! 10544: continue;
! 10545: }
! 10546: svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t));
! 10547: nd_to_vect64(m,s0vect,col,spol,svect);
! 10548: maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred,spol->sig);
! 10549: for ( i = 0; i < col; i++ ) if ( svect[i] ) break;
! 10550: if ( i < col ) {
! 10551: spmat[sprow] = svect;
! 10552: spsugar[sprow] = MAX(maxrs,SG(spol));
! 10553: spsig[sprow] = sp->sig;
! 10554: sprow++;
! 10555: } else {
! 10556: *syzlistp = insert_sig(*syzlistp,sp->sig);
! 10557: }
! 10558: nd_free(spol);
! 10559: }
! 10560: get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); add_eg(&f4_elim1,&eg0,&eg1);
! 10561: if ( DP_Print ) {
! 10562: fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime);
! 10563: fflush(asir_out);
! 10564: }
! 10565: /* free index arrays */
! 10566: for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c);
! 10567:
! 10568: /* elimination (2nd step) */
! 10569: colstat = (int *)MALLOC(col*sizeof(int));
! 10570: rank = nd_gauss_elim_mod64_s(spmat,spsugar,0,sprow,col,m,colstat,spsig);
! 10571: r0 = 0;
! 10572: for ( i = 0; i < rank; i++ ) {
! 10573: NEXTNODE(r0,r);
! 10574: BDY(r) = vect64_to_ndv_s(spmat[i],col,s0vect);
! 10575: SG((NDV)BDY(r)) = spsugar[i];
! 10576: ((NDV)BDY(r))->sig = spsig[i];
! 10577: GCFREE(spmat[i]);
! 10578: }
! 10579: if ( r0 ) NEXT(r) = 0;
! 10580:
! 10581: for ( ; i < sprow; i++ ) {
! 10582: GCFREE(spmat[i]);
! 10583: *syzlistp = insert_sig(*syzlistp,spsig[i]);
! 10584: }
! 10585: get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); add_eg(&f4_elim2,&eg1,&eg2);
! 10586: init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2);
! 10587: if ( DP_Print ) {
! 10588: fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime);
! 10589: fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ",
! 10590: nsp,nred,sprow,col,rank);
! 10591: fprintf(asir_out,"%.3fsec,",eg_f4.exectime);
! 10592: }
! 10593: return r0;
! 10594: }
! 10595:
! 10596: NODE nd_f4_red_s(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,NODE *syzlistp)
! 10597: {
! 10598: IndArray *imat;
! 10599: int nsp,nred,i,start;
! 10600: int *rhead;
! 10601: NODE r0,rp;
! 10602: ND_pairs sp;
! 10603: NM_ind_pair *rvect;
! 10604: UINT *s;
! 10605: int *s0hash;
! 10606: struct oEGT eg0,eg1,eg_conv;
! 10607:
! 10608: for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ );
! 10609: nred = length(rp0);
! 10610: imat = (IndArray *)MALLOC(nred*sizeof(IndArray));
! 10611: rhead = (int *)MALLOC(col*sizeof(int));
! 10612: for ( i = 0; i < col; i++ ) rhead[i] = 0;
! 10613:
! 10614: /* construction of index arrays */
! 10615: get_eg(&eg0);
! 10616: if ( DP_Print ) {
! 10617: fprintf(asir_out,"%dx%d,",nsp+nred,col);
! 10618: fflush(asir_out);
! 10619: }
! 10620: rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair));
! 10621: for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) {
! 10622: rvect[i] = (NM_ind_pair)BDY(rp);
! 10623: imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start);
! 10624: rhead[imat[i]->head] = 1;
! 10625: start = imat[i]->head;
! 10626: }
! 10627: get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); add_eg(&f4_conv,&eg0,&eg1);
! 10628: if ( DP_Print ) {
! 10629: fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime);
! 10630: fflush(asir_out);
! 10631: }
! 10632: if ( m > 0 )
! 10633: r0 = nd_f4_red_mod64_main_s(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,syzlistp);
! 10634: else
! 10635: // r0 = nd_f4_red_q_main_s(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred);
! 10636: error("nd_f4_red_q_main_s : not implemented yet");
! 10637: return r0;
! 10638: }
! 10639:
! 10640: INLINE int ndl_find_reducer_minsig(UINT *dg)
! 10641: {
! 10642: RHist r;
! 10643: int i,singular,ret,d,k,imin;
! 10644: SIG t;
! 10645: static int wpd,nvar;
! 10646: static SIG quo,quomin;
! 10647: static UINT *tmp;
! 10648:
! 10649: if ( !quo || nvar != nd_nvar ) { NEWSIG(quo); NEWSIG(quomin); }
! 10650: if ( wpd != nd_wpd ) {
! 10651: wpd = nd_wpd;
! 10652: tmp = (UINT *)MALLOC(wpd*sizeof(UINT));
! 10653: }
! 10654: #if 0
! 10655: d = ndl_hash_value(dg);
! 10656: for ( r = nd_red[d], k = 0; r; r = NEXT(r), k++ ) {
! 10657: if ( ndl_equal(dg,DL(r)) ) {
! 10658: return r->index;
! 10659: }
! 10660: }
! 10661: #endif
! 10662: imin = -1;
! 10663: for ( i = 0; i < nd_psn; i++ ) {
! 10664: r = nd_psh[i];
! 10665: if ( ndl_reducible(dg,DL(r)) ) {
! 10666: ndl_sub(dg,DL(r),tmp);
! 10667: _ndltodl(tmp,DL(quo));
! 10668: _addtodl(nd_nvar,DL(nd_psh[i]->sig),DL(quo));
! 10669: quo->pos = nd_psh[i]->sig->pos;
! 10670: if ( imin < 0 || comp_sig(quomin,quo) > 0 ) {
! 10671: t = quo; quo = quomin; quomin = t;
! 10672: imin = i;
! 10673: }
! 10674: }
! 10675: }
! 10676: if ( imin == -1 ) return nd_psn;
! 10677: else {
! 10678: #if 0
! 10679: nd_append_red(dg,i);
! 10680: #endif
! 10681: return imin;
! 10682: }
! 10683: }
! 10684:
! 10685: int nd_symbolic_preproc_s(PGeoBucket bucket,int trace,UINT **s0vect,NODE *r)
! 10686: {
! 10687: NODE rp0,rp;
! 10688: NM mul,head,s0,s;
! 10689: int index,col,i,sugar;
! 10690: RHist h;
! 10691: UINT *s0v,*p;
! 10692: NM_ind_pair pair;
! 10693: ND red;
! 10694: NDV *ps;
! 10695: SIG sig;
! 10696:
! 10697: s0 = 0; rp0 = 0; col = 0;
! 10698: if ( nd_demand )
! 10699: ps = trace?nd_ps_trace_sym:nd_ps_sym;
! 10700: else
! 10701: ps = trace?nd_ps_trace:nd_ps;
! 10702: while ( 1 ) {
! 10703: head = remove_head_pbucket_symbolic(bucket);
! 10704: if ( !head ) break;
! 10705: if ( !s0 ) s0 = head;
! 10706: else NEXT(s) = head;
! 10707: s = head;
! 10708: index = ndl_find_reducer_minsig(DL(head));
! 10709: if ( index >= 0 && index < nd_psn ) {
! 10710: h = nd_psh[index];
! 10711: NEWNM(mul);
! 10712: ndl_sub(DL(head),DL(h),DL(mul));
! 10713: if ( ndl_check_bound2(index,DL(mul)) )
! 10714: return 0;
! 10715: sugar = TD(DL(mul))+SG(ps[index]);
! 10716: NEWSIG(sig);
! 10717: _ndltodl(DL(mul),DL(sig));
! 10718: _addtodl(nd_nvar,DL(nd_psh[index]->sig),DL(sig));
! 10719: sig->pos = nd_psh[index]->sig->pos;
! 10720: MKNM_ind_pair(pair,mul,index,sugar,sig);
! 10721: red = ndv_mul_nm_symbolic(mul,ps[index]);
! 10722: add_pbucket_symbolic(bucket,nd_remove_head(red));
! 10723: NEXTNODE(rp0,rp); BDY(rp) = (pointer)pair;
! 10724: }
! 10725: col++;
! 10726: }
! 10727: if ( rp0 ) NEXT(rp) = 0;
! 10728: NEXT(s) = 0;
! 10729: s0v = (UINT *)MALLOC_ATOMIC(col*nd_wpd*sizeof(UINT));
! 10730: for ( i = 0, p = s0v, s = s0; i < col;
! 10731: i++, p += nd_wpd, s = NEXT(s) ) ndl_copy(DL(s),p);
! 10732: *s0vect = s0v;
! 10733: *r = rp0;
! 10734:
! 10735: return col;
! 10736: }
! 10737:
! 10738: NODE nd_sba_f4(int m,int **indp)
! 10739: {
! 10740: int i,nh,stat,index,f4red;
! 10741: NODE r,g,tn0,tn,node;
! 10742: ND_pairs d,l,t,ll0,ll,lh;
! 10743: LIST l0,l1;
! 10744: ND spol,red;
! 10745: NDV nf,redv;
! 10746: NM s0,s;
! 10747: NODE rp0,srp0,nflist;
! 10748: int nsp,nred,col,rank,len,k,j,a,i1s,i2s;
! 10749: UINT c;
! 10750: UINT **spmat;
! 10751: UINT *s0vect,*svect,*p,*v;
! 10752: int *colstat;
! 10753: IndArray *imat;
! 10754: int *rhead;
! 10755: int spcol,sprow;
! 10756: int sugar,sugarh;
! 10757: PGeoBucket bucket;
! 10758: struct oEGT eg0,eg1,eg_f4;
! 10759: Z i1,i2,sugarq;
! 10760: NODE syzlist;
! 10761:
! 10762: Nf4_red=0;
! 10763: g = 0; d = 0;
! 10764: syzlist = 0;
! 10765: for ( i = 0; i < nd_psn; i++ ) {
! 10766: d = update_pairs_s(d,g,i,syzlist);
! 10767: g = append_one(g,i);
! 10768: }
! 10769: f4red = 1;
! 10770: while ( d ) {
! 10771: l = nd_minsugarp_s(d,&d);
! 10772: if ( !l ) continue;
! 10773: sugar = nd_sugarweight?l->sugar2:SG(l);
! 10774: if ( MaxDeg > 0 && sugar > MaxDeg ) break;
! 10775: bucket = create_pbucket();
! 10776: stat = nd_sp_f4(m,0,l,bucket);
! 10777: if ( !stat ) {
! 10778: for ( t = l; NEXT(t); t = NEXT(t) );
! 10779: NEXT(t) = d; d = l;
! 10780: d = nd_reconstruct(0,d);
! 10781: continue;
! 10782: }
! 10783: if ( bucket->m < 0 ) continue;
! 10784: col = nd_symbolic_preproc_s(bucket,0,&s0vect,&rp0);
! 10785: if ( !col ) {
! 10786: for ( t = l; NEXT(t); t = NEXT(t) );
! 10787: NEXT(t) = d; d = l;
! 10788: d = nd_reconstruct(0,d);
! 10789: continue;
! 10790: }
! 10791: if ( DP_Print ) fprintf(asir_out,"sugar=%d,",sugar);
! 10792: l = remove_large_lcm(l);
! 10793: nflist = nd_f4_red_s(m,l,0,s0vect,col,rp0,&syzlist);
! 10794: /* adding new bases */
! 10795: for ( r = nflist; r; r = NEXT(r) ) {
! 10796: ND tmp,tmpred;
! 10797: SIG sig;
! 10798:
! 10799: nf = (NDV)BDY(r);
! 10800: sig = nf->sig;
! 10801: tmp = ndvtond(m,nf);
! 10802: stat = nd_nf_s(m,0,tmp,nd_ps,!Top,&tmpred);
! 10803: if ( stat < 0 ) {
! 10804: // top reducible
! 10805: if ( DP_Print ) { fprintf(asir_out,"S"); fflush(asir_out); }
! 10806: } else if ( tmpred ) {
! 10807: nf = ndtondv(m,tmpred);
! 10808: ndv_removecont(m,nf);
! 10809: nh = ndv_newps(m,nf,0);
! 10810: d = update_pairs_s(d,g,nh,syzlist);
! 10811: g = append_one(g,nh);
! 10812: } else {
! 10813: syzlist = insert_sig(syzlist,sig);
! 10814: }
! 10815: }
! 10816: for ( r = syzlist; r; r = NEXT(r) )
! 10817: d = remove_spair_s(d,(SIG)BDY(r));
! 10818: if ( DP_Print ) {
! 10819: fprintf(asir_out,"f4red=%d,gblen=%d\n",f4red,length(g)); fflush(asir_out);
! 10820: }
! 10821: f4red++;
! 10822: if ( nd_f4red && f4red > nd_f4red ) break;
! 10823: if ( nd_rank0 && !nflist ) break;
! 10824: }
! 10825: if ( DP_Print ) {
! 10826: fprintf(asir_out,"number of red=%d,",Nf4_red);
! 10827: }
! 10828: conv_ilist(nd_demand,0,g,indp);
! 10829: return g;
! 10830: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>