Annotation of OpenXM_contrib2/asir2018/engine/Q.c, Revision 1.22
1.22 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2018/engine/Q.c,v 1.21 2021/10/08 07:27:05 noro Exp $ */
1.1 noro 2: #include "ca.h"
1.22 ! noro 3: #include "parse.h"
1.1 noro 4: #include "gmp.h"
5: #include "base.h"
6: #include "inline.h"
7:
8: mpz_t ONEMPZ;
1.17 noro 9: extern Z ONE;
1.1 noro 10: int lf_lazy;
11: Z current_mod_lf;
12: int current_mod_lf_size;
13: gmp_randstate_t GMP_RAND;
14:
1.9 noro 15: #define F4_INTRAT_PERIOD 4
1.6 noro 16:
17: extern int DP_Print;
18:
1.1 noro 19: void isqrtz(Z a,Z *r);
20: void bshiftz(Z a,int n,Z *r);
1.18 noro 21: int mpz_inttorat(mpz_t c,mpz_t m,mpz_t b,mpz_t nm,mpz_t dn);
22: int generic_gauss_elim_hensel64(MAT mat,MAT *nmmat,Z *dn,int **rindp,int **cindp,DP *mb);
23: int find_lhs_and_lu_mod64(mp_limb_t **a,int row,int col,mp_limb_t md,int **rinfo,int **cinfo);
24: void solve_by_lu_mod64(mp_limb_t **a,int n,mp_limb_t md,mp_limb_signed_t **b,int l,int normalize);
1.1 noro 25:
26: void *gc_realloc(void *p,size_t osize,size_t nsize)
27: {
28: return (void *)Risa_GC_realloc(p,nsize);
29: }
30:
31: void gc_free(void *p,size_t size)
32: {
33: Risa_GC_free(p);
34: }
35:
36: void init_gmpq()
37: {
1.10 noro 38: mp_set_memory_functions(Risa_GC_malloc,gc_realloc,gc_free);
1.1 noro 39:
40: mpz_init(ONEMPZ); mpz_set_ui(ONEMPZ,1); MPZTOZ(ONEMPZ,ONE);
41: gmp_randinit_default(GMP_RAND);
42: }
43:
1.7 noro 44: void printexpr(VL,Obj);
45:
1.3 noro 46: void pmat(Z **a,int row,int col)
47: {
48: int i,j;
49:
50: for ( i = 0; i < row; i++, printf("\n") )
51: for ( j = 0; j < col; j++, printf(" ") )
1.7 noro 52: printexpr(CO,(Obj)a[i][j]);
1.3 noro 53: printf("\n");
54: }
55:
1.1 noro 56: Z utoz(unsigned int u)
57: {
58: mpz_t z;
59: Z r;
60:
61: if ( !u ) return 0;
62: mpz_init(z); mpz_set_ui(z,u); MPZTOZ(z,r); return r;
63: }
64:
65: Z stoz(int s)
66: {
67: mpz_t z;
68: Z r;
69:
70: if ( !s ) return 0;
71: mpz_init(z); mpz_set_si(z,s); MPZTOZ(z,r); return r;
72: }
73:
74: int sgnz(Z z)
75: {
76: if ( !z ) return 0;
77: else return mpz_sgn(BDY(z));
78: }
79:
80: void nmq(Q q,Z *r)
81: {
82: if ( !q ) *r = 0;
83: else if ( INT(q) ) *r = (Z)q;
84: else {
85: MPZTOZ(mpq_numref(BDY(q)),*r);
86: }
87: }
88:
89: void dnq(Q q,Z *r)
90: {
91: if ( !q ) *r = 0;
92: else if ( INT(q) ) *r = ONE;
93: else {
94: MPZTOZ(mpq_denref(BDY(q)),*r);
95: }
96: }
97:
98: int sgnq(Q q)
99: {
100: if ( !q ) return 0;
1.21 noro 101: else if ( q->z ) {
102: int sgn;
103: sgn = mpz_sgn(BDY((Z)q));
104: return sgn;
105: } else return mpz_sgn(mpq_numref(BDY(q)));
1.1 noro 106: }
107:
108: Q mpqtozq(mpq_t a)
109: {
110: Z z;
111: Q q;
112:
113: if ( INTMPQ(a) ) {
114: MPZTOZ(mpq_numref(a),z); return (Q)z;
115: } else {
116: MPQTOQ(a,q); return q;
117: }
118: }
119:
120: void dupz(Z a,Z *b)
121: {
122: mpz_t t;
123:
124: if ( !a ) *b = a;
125: else {
126: mpz_init(t); mpz_set(t,BDY(a)); MPZTOZ(t,*b);
127: }
128: }
129:
130: int n_bits_z(Z a)
131: {
132: return a ? mpz_sizeinbase(BDY(a),2) : 0;
133: }
134:
135: void addz(Z n1,Z n2,Z *nr)
136: {
137: mpz_t t;
138: int s1,s2;
139:
140: if ( !n1 ) *nr = n2;
141: else if ( !n2 ) *nr = n1;
142: else if ( !n1->z || !n2->z )
143: error("addz : invalid argument");
144: else {
145: mpz_init(t); mpz_add(t,BDY(n1),BDY(n2)); MPZTOZ(t,*nr);
146: }
147: }
148:
149: void subz(Z n1,Z n2,Z *nr)
150: {
151: mpz_t t;
152:
153: if ( !n1 ) {
154: if ( !n2 )
155: *nr = 0;
156: else
157: chsgnz(n2,nr);
158: } else if ( !n2 )
159: *nr = n1;
160: else if ( n1 == n2 )
161: *nr = 0;
162: else if ( !n1->z || !n2->z )
163: error("subz : invalid argument");
164: else {
165: mpz_init(t); mpz_sub(t,BDY(n1),BDY(n2)); MPZTOZ(t,*nr);
166: }
167: }
168:
169: void mulz(Z n1,Z n2,Z *nr)
170: {
171: mpz_t t;
172:
173: if ( !n1 || !n2 ) *nr = 0;
174: else if ( !n1->z || !n2->z )
175: error("mulz : invalid argument");
176: else if ( UNIQ(n1) ) *nr = n2;
177: else if ( UNIQ(n2) ) *nr = n1;
178: else if ( MUNIQ(n1) ) chsgnz(n2,nr);
179: else if ( MUNIQ(n2) ) chsgnz(n1,nr);
180: else {
181: mpz_init(t); mpz_mul(t,BDY(n1),BDY(n2)); MPZTOZ(t,*nr);
182: }
183: }
184:
185: /* nr += n1*n2 */
186:
187: void muladdtoz(Z n1,Z n2,Z *nr)
188: {
1.3 noro 189: #if 0
1.1 noro 190: Z t;
191:
192: if ( n1 && n2 ) {
193: if ( !(*nr) ) {
194: NEWZ(t); mpz_init(BDY(t)); *nr = t;
195: }
196: mpz_addmul(BDY(*nr),BDY(n1),BDY(n2));
1.2 noro 197: if ( !mpz_sgn(BDY(*nr)) )
198: *nr = 0;
1.3 noro 199: }
1.2 noro 200: #else
201: Z t,s;
202:
203: mulz(n1,n2,&t); addz(*nr,t,&s); *nr = s;
204: #endif
1.1 noro 205: }
206:
207: /* nr += n1*u */
208:
209: void mul1addtoz(Z n1,long u,Z *nr)
210: {
1.3 noro 211: #if 0
1.1 noro 212: Z t;
213:
214: if ( n1 && u ) {
215: if ( !(*nr) ) {
216: NEWZ(t); mpz_init(BDY(t)); *nr = t;
217: }
218: if ( u >= 0 )
219: mpz_addmul_ui(BDY(*nr),BDY(n1),(unsigned long)u);
220: else
221: mpz_submul_ui(BDY(*nr),BDY(n1),(unsigned long)(-u));
1.2 noro 222: if ( !mpz_sgn(BDY(*nr)) )
223: *nr = 0;
1.1 noro 224: }
1.3 noro 225: #else
226: Z t,s;
227:
228: mul1z(n1,u,&t); addz(*nr,t,&s); *nr = s;
229: #endif
1.1 noro 230: }
231:
232: void mul1z(Z n1,long n2,Z *nr)
233: {
234: mpz_t t;
235:
236: if ( !n1 || !n2 ) *nr = 0;
237: else {
238: mpz_init(t); mpz_mul_si(t,BDY(n1),n2); MPZTOZ(t,*nr);
239: }
240: }
241:
242: void divz(Z n1,Z n2,Z *nq)
243: {
244: mpz_t t;
245: mpq_t a, b, q;
246:
247: if ( !n2 ) {
248: error("division by 0");
249: *nq = 0;
250: } else if ( !n1 )
251: *nq = 0;
252: else if ( n1 == n2 ) {
253: mpz_init(t); mpz_set_ui(t,1); MPZTOZ(t,*nq);
254: } else {
255: MPZTOMPQ(BDY(n1),a); MPZTOMPQ(BDY(n2),b);
256: mpq_init(q); mpq_div(q,a,b); *nq = (Z)mpqtozq(q);
257: }
258: }
259:
260: void remz(Z n1,Z n2,Z *nr)
261: {
262: mpz_t r;
263:
264: if ( !n2 ) {
265: error("division by 0");
266: *nr = 0;
267: } else if ( !n1 || n1 == n2 )
268: *nr = 0;
269: else if ( !n1->z || !n2->z )
270: error("remz : invalid argument");
271: else {
272: mpz_init(r);
273: mpz_mod(r,BDY(n1),BDY(n2));
274: if ( !mpz_sgn(r) ) *nr = 0;
275: else MPZTOZ(r,*nr);
276: }
277: }
278:
279: void divqrz(Z n1,Z n2,Z *nq,Z *nr)
280: {
281: mpz_t t, a, b, q, r;
282:
283: if ( !n2 ) {
284: error("division by 0");
285: *nq = 0; *nr = 0;
286: } else if ( !n1 ) {
287: *nq = 0; *nr = 0;
288: } else if ( !n1->z || !n2->z )
289: error("divqrz : invalid argument");
290: else if ( n1 == n2 ) {
291: mpz_init(t); mpz_set_ui(t,1); MPZTOZ(t,*nq); *nr = 0;
292: } else {
293: mpz_init(q); mpz_init(r);
294: mpz_fdiv_qr(q,r,BDY(n1),BDY(n2));
295: if ( !mpz_sgn(q) ) *nq = 0;
296: else MPZTOZ(q,*nq);
297: if ( !mpz_sgn(r) ) *nr = 0;
298: else MPZTOZ(r,*nr);
299: }
300: }
301:
302: void divsz(Z n1,Z n2,Z *nq)
303: {
304: mpz_t t;
305: mpq_t a, b, q;
306:
307: if ( !n2 ) {
308: error("division by 0");
309: *nq = 0;
310: } else if ( !n1 )
311: *nq = 0;
312: else if ( !n1->z || !n2->z )
313: error("divsz : invalid argument");
314: else if ( n1 == n2 ) {
315: mpz_init(t); mpz_set_ui(t,1); MPZTOZ(t,*nq);
316: } else {
317: mpz_init(t); mpz_divexact(t,BDY(n1),BDY(n2)); MPZTOZ(t,*nq);
318: }
319: }
320:
321: void chsgnz(Z n,Z *nr)
322: {
323: mpz_t t;
324:
325: if ( !n )
326: *nr = 0;
327: else if ( !n->z )
328: error("chsgnz : invalid argument");
329: else {
330: t[0] = BDY(n)[0]; mpz_neg(t,t); MPZTOZ(t,*nr);
331: }
332: }
333:
334: void absz(Z n,Z *nr)
335: {
336: if ( !n ) *nr = 0;
337: else if ( !n->z )
338: error("absz : invalid argument");
339: else if ( sgnz(n) < 0 ) chsgnz(n,nr);
340: else *nr = n;
341: }
342:
343: int evenz(Z n)
344: {
345: return !n ? 1 : mpz_even_p(BDY(n));
346: }
347:
348: int smallz(Z n)
349: {
350: if ( !n ) return 1;
351: else if ( INT(n) && mpz_fits_sint_p(BDY(n)) ) return 1;
352: else return 0;
353: }
354:
355: void pwrz(Z n1,Z n,Z *nr)
356: {
357: mpq_t t,q;
358: mpz_t z;
359: Q p,r;
360:
361: if ( !n || UNIQ(n1) ) *nr = ONE;
362: else if ( !n1 ) *nr = 0;
363: else if ( !n->z || !n1->z )
364: error("pwrz : invalid argument");
365: else if ( MUNIQ(n1) ) {
366: if ( mpz_even_p(BDY((Z)n)) ) *nr = ONE;
367: else *nr = n1;
368: } else if ( !smallz(n) ) {
369: error("exponent too big."); *nr = 0;
370: } else if ( n1->z && mpz_sgn(BDY((Z)n))>0 ) {
1.5 noro 371: mpz_init(z); mpz_pow_ui(z,BDY(n1),ZTOS(n)); MPZTOZ(z,*nr);
1.1 noro 372: } else {
373: MPZTOMPQ(BDY(n1),q); MPQTOQ(q,r);
374: pwrq(r,(Q)n,&p); *nr = (Z)p;
375: }
376: }
377:
378: int cmpz(Z q1,Z q2)
379: {
380: int sgn;
381:
382: if ( !q1 ) {
383: if ( !q2 )
384: return 0;
385: else
386: return -mpz_sgn(BDY(q2));
387: } else if ( !q2 )
388: return mpz_sgn(BDY(q1));
389: else if ( !q1->z || !q2->z )
390: error("mpqz : invalid argument");
391: else if ( (sgn = mpz_sgn(BDY(q1))) != mpz_sgn(BDY(q2)) )
392: return sgn;
393: else {
394: sgn = mpz_cmp(BDY(q1),BDY(q2));
395: if ( sgn > 0 ) return 1;
396: else if ( sgn < 0 ) return -1;
397: else return 0;
398: }
1.19 noro 399: /* XXX */
400: return 0;
1.1 noro 401: }
402:
403: void gcdz(Z n1,Z n2,Z *nq)
404: {
405: mpz_t t;
406:
407: if ( !n1 ) *nq = n2;
408: else if ( !n2 ) *nq = n1;
409: else if ( !n1->z || !n2->z )
410: error("gcdz : invalid argument");
411: else {
412: mpz_init(t); mpz_gcd(t,BDY(n1),BDY(n2));
413: MPZTOZ(t,*nq);
414: }
415: }
416:
417: void invz(Z n1,Z n2,Z *nq)
418: {
419: mpz_t t;
420:
421: if ( !n1 || !n2 || !n1->z || !n2->z )
422: error("invz : invalid argument");
423: mpz_init(t); mpz_invert(t,BDY(n1),BDY(n2));
424: MPZTOZ(t,*nq);
425: }
426:
427: void lcmz(Z n1,Z n2,Z *nq)
428: {
429: Z g,t;
430:
431: if ( !n1 || !n2 ) *nq = 0;
432: else if ( !n1->z || !n2->z )
433: error("lcmz : invalid argument");
434: else {
435: gcdz(n1,n2,&g); divsz(n1,g,&t);
436: mulz(n2,t,nq);
437: }
438: }
439:
440: void gcdvz(VECT v,Z *q)
441: {
442: int n,i;
443: Z *b;
444: Z g,g1;
445:
446: n = v->len;
447: b = (Z *)v->body;
448: g = b[0];
449: for ( i = 1; i < n; i++ ) {
450: gcdz(g,b[i],&g1); g = g1;
451: }
452: *q = g;
453: }
454:
455: void gcdvz_estimate(VECT v,Z *q)
456: {
457: int n,m,i;
458: Z s,t,u;
459: Z *b;
460:
461: n = v->len;
462: b = (Z *)v->body;
463: if ( n == 1 ) {
464: if ( mpz_sgn(BDY(b[0]))<0 ) chsgnz(b[0],q);
465: else *q = b[0];
466: }
467: m = n/2;
468: for ( i = 0, s = 0; i < m; i++ ) {
469: if ( b[i] && mpz_sgn(BDY(b[i]))<0 ) subz(s,b[i],&u);
470: else addz(s,b[i],&u);
471: s = u;
472: }
1.4 noro 473: for ( t = 0; i < n; i++ ) {
1.1 noro 474: if ( b[i] && mpz_sgn(BDY(b[i]))<0 ) subz(t,b[i],&u);
475: else addz(t,b[i],&u);
476: t = u;
477: }
478: gcdz(s,t,q);
479: }
480:
1.4 noro 481: void gcdv_mpz_estimate(mpz_t g,mpz_t *b,int n)
482: {
483: int m,m2,i,j;
484: mpz_t s,t;
485:
486: mpz_init(g);
487: for ( i = 0, m = 0; i < n; i++ )
488: if ( mpz_sgn(b[i]) ) m++;
489: if ( !m ) {
490: mpz_set_ui(g,0);
491: return;
492: }
493: if ( m == 1 ) {
494: for ( i = 0, m = 0; i < n; i++ )
495: if ( mpz_sgn(b[i]) ) break;
496: if ( mpz_sgn(b[i])<0 ) mpz_neg(g,b[i]);
497: else mpz_set(g,b[i]);
498: return ;
499: }
500: m2 = m/2;
501: mpz_init_set_ui(s,0);
502: for ( i = j = 0; j < m2; i++ ) {
503: if ( mpz_sgn(b[i]) ) {
504: if ( mpz_sgn(b[i])<0 )
505: mpz_sub(s,s,b[i]);
506: else
507: mpz_add(s,s,b[i]);
508: j++;
509: }
510: }
511: mpz_init_set_ui(t,0);
512: for ( ; i < n; i++ ) {
513: if ( mpz_sgn(b[i]) ) {
514: if ( mpz_sgn(b[i])<0 )
515: mpz_sub(t,t,b[i]);
516: else
517: mpz_add(t,t,b[i]);
518: }
519: }
520: mpz_gcd(g,s,t);
521: }
522:
523:
1.1 noro 524: void factorialz(unsigned int n,Z *nr)
525: {
526: mpz_t a;
527: mpz_init(a);
1.13 noro 528: mpz_fac_ui(a,(unsigned long)n);
1.1 noro 529: MPZTOZ(a,*nr);
530: }
531:
532: void randomz(int blen,Z *nr)
533: {
534: mpz_t z;
535:
536: mpz_init(z);
537: mpz_urandomb(z,GMP_RAND,blen);
538: MPZTOZ(z,*nr);
539: }
540:
541: int tstbitz(Z n,int k)
542: {
543: if ( !n || !n->z )
544: error("tstbitz : invalid argument");
545: return !n ? 0 : mpz_tstbit(BDY(n),k);
546: }
547:
548: void addq(Q n1,Q n2,Q *nr)
549: {
550: mpq_t q1,q2,t;
551:
552: if ( !n1 ) *nr = n2;
553: else if ( !n2 ) *nr = n1;
554: else if ( n1->z && n2->z )
555: addz((Z)n1,(Z)n2,(Z *)nr);
556: else {
557: if ( n1->z ) MPZTOMPQ(BDY((Z)n1),q1);
558: else q1[0] = BDY(n1)[0];
559: if ( n2->z ) MPZTOMPQ(BDY((Z)n2),q2);
560: else q2[0] = BDY(n2)[0];
561: mpq_init(t); mpq_add(t,q1,q2); *nr = mpqtozq(t);
562: }
563: }
564:
565: void subq(Q n1,Q n2,Q *nr)
566: {
567: mpq_t q1,q2,t;
568:
569: if ( !n1 ) {
570: if ( !n2 ) *nr = 0;
1.15 noro 571: else if ( n2->z ) chsgnz((Z)n2,(Z *)nr);
1.1 noro 572: else {
573: mpq_init(t); mpq_neg(t,BDY(n2)); MPQTOQ(t,*nr);
574: }
575: } else if ( !n2 ) *nr = n1;
576: else if ( n1 == n2 ) *nr = 0;
577: else if ( n1->z && n2->z )
578: subz((Z)n1,(Z)n2,(Z *)nr);
579: else {
580: if ( n1->z ) MPZTOMPQ(BDY((Z)n1),q1);
581: else q1[0] = BDY(n1)[0];
582: if ( n2->z ) MPZTOMPQ(BDY((Z)n2),q2);
583: else q2[0] = BDY(n2)[0];
584: mpq_init(t); mpq_sub(t,q1,q2); *nr = mpqtozq(t);
585: }
586: }
587:
588: void mulq(Q n1,Q n2,Q *nr)
589: {
590: mpq_t t,q1,q2;
591:
592: if ( !n1 || !n2 ) *nr = 0;
593: else if ( n1->z && n2->z )
594: mulz((Z)n1,(Z)n2,(Z *)nr);
595: else {
596: if ( n1->z ) MPZTOMPQ(BDY((Z)n1),q1);
597: else q1[0] = BDY(n1)[0];
598: if ( n2->z ) MPZTOMPQ(BDY((Z)n2),q2);
599: else q2[0] = BDY(n2)[0];
600: mpq_init(t); mpq_mul(t,q1,q2); *nr = mpqtozq(t);
601: }
602: }
603:
604: void divq(Q n1,Q n2,Q *nq)
605: {
606: mpq_t t,q1,q2;
607:
608: if ( !n2 ) {
609: error("division by 0");
610: *nq = 0;
611: return;
612: } else if ( !n1 ) *nq = 0;
613: else if ( n1 == n2 ) *nq = (Q)ONE;
614: else {
615: if ( n1->z ) MPZTOMPQ(BDY((Z)n1),q1);
616: else q1[0] = BDY(n1)[0];
617: if ( n2->z ) MPZTOMPQ(BDY((Z)n2),q2);
618: else q2[0] = BDY(n2)[0];
619: mpq_init(t); mpq_div(t,q1,q2); *nq = mpqtozq(t);
620: }
621: }
622:
623: void invq(Q n,Q *nr)
624: {
625: Z nm,dn;
626:
627: if ( INT(n) )
628: divq((Q)ONE,n,nr);
629: else {
630: nmq(n,&nm);
631: dnq(n,&dn);
632: divq((Q)dn,(Q)nm,nr);
633: }
634: }
635:
636: void chsgnq(Q n,Q *nr)
637: {
638: mpq_t t;
639:
640: if ( !n ) *nr = 0;
641: else if (n->z ) chsgnz((Z)n,(Z *)nr);
642: else {
643: mpq_init(t); mpq_neg(t,BDY(n)); MPQTOQ(t,*nr);
644: }
645: }
646:
647: void absq(Q n,Q *nr)
648: {
649: if ( !n ) *nr = 0;
650: else if ( n->z ) absz((Z)n,(Z *)nr);
651: else if ( sgnq(n) < 0 ) chsgnq(n,nr);
652: else *nr = n;
653: }
654:
655: void pwrq(Q n1,Q n,Q *nr)
656: {
657: int e;
658: mpz_t nm,dn;
659: mpq_t t;
660:
661: if ( !n || UNIQ((Z)n1) || UNIQ(n1) ) *nr = (Q)ONE;
662: else if ( !n1 ) *nr = 0;
663: else if ( !INT(n) ) {
664: error("can't calculate fractional power."); *nr = 0;
665: } else if ( !smallz((Z)n) ) {
666: error("exponent too big."); *nr = 0;
667: } else {
1.5 noro 668: e = ZTOS(n);
1.1 noro 669: if ( e < 0 ) {
670: e = -e;
671: if ( n1->z ) {
672: nm[0] = ONEMPZ[0];
673: dn[0] = BDY((Z)n1)[0];
674: } else {
675: nm[0] = mpq_denref(BDY(n1))[0];
676: dn[0] = mpq_numref(BDY(n1))[0];
677: }
1.20 noro 678: if ( mpz_sgn(dn)<0 ) {
679: mpz_neg(nm,nm);
680: mpz_neg(dn,dn);
681: }
1.1 noro 682: } else {
683: if ( n1->z ) {
684: nm[0] = BDY((Z)n1)[0];
685: dn[0] = ONEMPZ[0];
686: } else {
687: nm[0] = mpq_numref(BDY(n1))[0];
688: dn[0] = mpq_denref(BDY(n1))[0];
689: }
690: }
691: mpq_init(t);
692: mpz_pow_ui(mpq_numref(t),nm,e); mpz_pow_ui(mpq_denref(t),dn,e);
693: *nr = mpqtozq(t);
694: }
695: }
696:
697: int cmpq(Q n1,Q n2)
698: {
699: mpq_t q1,q2;
700: int sgn;
701:
702: if ( !n1 ) {
703: if ( !n2 ) return 0;
704: else return (n2->z) ? -mpz_sgn(BDY((Z)n2)) : -mpq_sgn(BDY(n2));
705: } if ( !n2 ) return (n1->z) ? mpz_sgn(BDY((Z)n1)) : mpq_sgn(BDY(n1));
706: else if ( n1->z && n2->z )
707: return cmpz((Z)n1,(Z)n2);
708: else if ( (sgn = mpq_sgn(BDY(n1))) != mpq_sgn(BDY(n2)) ) return sgn;
709: else {
710: if ( n1->z ) MPZTOMPQ(BDY((Z)n1),q1);
711: else q1[0] = BDY(n1)[0];
712: if ( n2->z ) MPZTOMPQ(BDY((Z)n2),q2);
713: else q2[0] = BDY(n2)[0];
714: sgn = mpq_cmp(q1,q2);
715: if ( sgn > 0 ) return 1;
716: else if ( sgn < 0 ) return -1;
717: else return 0;
718: }
719: }
720:
721: /* t = [nC0 nC1 ... nCn] */
722:
723: void mkbc(int n,Z *t)
724: {
725: int i;
726: Z c,d,iq;
727:
728: for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
1.5 noro 729: STOZ(n-i+1,c); mulz(t[i-1],c,&d);
730: STOZ(i,iq); divsz(d,iq,&t[i]);
1.1 noro 731: }
732: for ( ; i <= n; i++ )
733: t[i] = t[n-i];
734: }
735:
736: /*
737: * Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
738: *
739: * t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
740: * where W(k,l,i) = i! * kCi * lCi
741: */
742:
743: /* mod m table */
744: /* XXX : should be optimized */
745:
746: void mkwcm(int k,int l,int m,int *t)
747: {
748: int i,n;
749: Z *s;
750:
751: n = MIN(k,l);
752: s = (Z *)ALLOCA((n+1)*sizeof(Q));
753: mkwc(k,l,s);
754: for ( i = 0; i <= n; i++ ) {
755: t[i] = remqi((Q)s[i],m);
756: }
757: }
758:
759: void mkwc(int k,int l,Z *t)
760: {
761: mpz_t a,b,q,nm,z,u;
762: int i,n;
763:
764: n = MIN(k,l);
765: mpz_init_set_ui(z,1);
766: mpz_init(u); mpz_set(u,z); MPZTOZ(u,t[0]);
767: mpz_init(a); mpz_init(b); mpz_init(nm);
768: for ( i = 1; i <= n; i++ ) {
769: mpz_set_ui(a,k-i+1); mpz_set_ui(b,l-i+1); mpz_mul(nm,a,b);
770: mpz_mul(z,BDY(t[i-1]),nm); mpz_fdiv_q_ui(z,z,i);
771: mpz_init(u); mpz_set(u,z); MPZTOZ(u,t[i]);
772: }
773: }
774:
775: void lgp(P p,Z *g,Z *l);
776:
777: void ptozp(P p,int sgn,Q *c,P *pr)
778: {
1.16 noro 779: Z nm,dn,nm1;
1.1 noro 780:
781: if ( !p ) {
782: *c = 0; *pr = 0;
783: } else {
784: lgp(p,&nm,&dn);
1.16 noro 785: if ( sgn < 0 ) {
786: chsgnz(nm,&nm1); nm = nm1;
787: }
1.1 noro 788: divz(nm,dn,(Z *)c);
789: divsp(CO,p,(P)*c,pr);
790: }
791: }
792:
793: void lgp(P p,Z *g,Z *l)
794: {
795: DCP dc;
796: Z g1,g2,l1,l2,l3,l4;
797:
798: if ( NUM(p) ) {
799: if ( ((Q)p)->z ) {
1.21 noro 800: absz((Z)p,g);
1.1 noro 801: *l = ONE;
802: } else {
1.21 noro 803: MPZTOZ(mpq_numref(BDY((Q)p)),g1); absz(g1,g);
1.1 noro 804: MPZTOZ(mpq_denref(BDY((Q)p)),*l);
805: }
806: } else {
807: dc = DC(p); lgp(COEF(dc),g,l);
808: for ( dc = NEXT(dc); dc; dc = NEXT(dc) ) {
809: lgp(COEF(dc),&g1,&l1); gcdz(*g,g1,&g2); *g = g2;
810: gcdz(*l,l1,&l2); mulz(*l,l1,&l3); divz(l3,l2,l);
811: }
812: }
813: }
814:
815: void qltozl(Q *w,int n,Z *dvr)
816: {
817: Z nm,dn;
818: Z g,g1,l1,l2,l3;
819: Q c;
820: int i;
821: struct oVECT v;
822:
823: for ( i = 0; i < n; i++ )
824: if ( w[i] && !w[i]->z )
825: break;
826: if ( i == n ) {
827: v.id = O_VECT; v.len = n; v.body = (pointer *)w;
828: gcdvz(&v,dvr); return;
829: }
830: for ( i = 0; !w[i]; i++ );
831: c = w[i];
832: if ( !c->z ) {
833: MPZTOZ(mpq_numref(BDY(c)),nm); MPZTOZ(mpq_denref(BDY(c)),dn);
834: } else {
835: MPZTOZ(BDY((Z)c),nm); dn = ONE;
836: }
837: for ( i++; i < n; i++ ) {
838: c = w[i];
839: if ( !c ) continue;
840: if ( !c->z ) {
841: MPZTOZ(mpq_numref(BDY(c)),g1); MPZTOZ(mpq_denref(BDY(c)),l1);
842: } else {
843: MPZTOZ(BDY((Z)c),g1); l1 = ONE;
844: }
845: gcdz(nm,g1,&g); nm = g;
846: gcdz(dn,l1,&l2); mulz(dn,l1,&l3); divz(l3,l2,&dn);
847: }
848: divz(nm,dn,dvr);
849: }
850:
851: int z_bits(Q q)
852: {
853: if ( !q ) return 0;
854: else if ( q->z ) return mpz_sizeinbase(BDY((Z)q),2);
855: else
856: return mpz_sizeinbase(mpq_numref(BDY(q)),2)
857: + mpz_sizeinbase(mpq_denref(BDY(q)),2);
858: }
859:
860: int zp_mag(P p)
861: {
862: int s;
863: DCP dc;
864:
865: if ( !p ) return 0;
866: else if ( OID(p) == O_N ) return z_bits((Q)p);
867: else {
868: for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) s += zp_mag(COEF(dc));
869: return s;
870: }
871: }
872:
873: void makesubstz(VL v,NODE *s)
874: {
875: NODE r,r0;
876: Z q;
877: unsigned int n;
878:
879: for ( r0 = 0; v; v = NEXT(v) ) {
880: NEXTNODE(r0,r); BDY(r) = (pointer)v->v;
881: #if defined(_PA_RISC1_1)
882: n = mrand48()&BMASK; q = utoz(n);
883: #else
884: n = random(); q = utoz(n);
885: #endif
886: NEXTNODE(r0,r); BDY(r) = (pointer)q;
887: }
888: if ( r0 ) NEXT(r) = 0;
889: *s = r0;
890: }
891:
892: unsigned int remqi(Q a,unsigned int mod)
893: {
894: unsigned int c,nm,dn;
895: mpz_t r;
896:
897: if ( !a ) return 0;
898: else if ( a->z ) {
899: mpz_init(r);
900: c = mpz_fdiv_r_ui(r,BDY((Z)a),mod);
901: } else {
902: mpz_init(r);
903: nm = mpz_fdiv_r_ui(r,mpq_numref(BDY(a)),mod);
904: dn = mpz_fdiv_r_ui(r,mpq_denref(BDY(a)),mod);
905: dn = invm(dn,mod);
906: DMAR(nm,dn,0,mod,c);
907: }
908: return c;
909: }
910:
911: int generic_gauss_elim(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp)
912: {
913: int **wmat;
914: Z **bmat,**tmat,*bmi,*tmi;
915: Z q,m1,m2,m3,s,u;
916: int *wmi,*colstat,*wcolstat,*rind,*cind;
917: int row,col,ind,md,i,j,k,l,t,t1,rank,rank0,inv;
918: MAT r,crmat;
919: int ret;
1.8 noro 920: MAT mat2,nm2;
921: Z dn2;
922: int *rind2,*cind2;
923: int ret2;
1.1 noro 924:
1.6 noro 925: #if SIZEOF_LONG == 8
1.8 noro 926: ret = generic_gauss_elim64(mat,nm,dn,rindp,cindp);
927: return ret;
1.6 noro 928: #endif
1.1 noro 929: bmat = (Z **)mat->body;
930: row = mat->row; col = mat->col;
931: wmat = (int **)almat(row,col);
932: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
933: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
934: for ( ind = 0; ; ind++ ) {
935: if ( DP_Print ) {
936: fprintf(asir_out,"."); fflush(asir_out);
937: }
938: md = get_lprime(ind);
939: for ( i = 0; i < row; i++ )
940: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
941: wmi[j] = remqi((Q)bmi[j],md);
942: rank = generic_gauss_elim_mod(wmat,row,col,md,wcolstat);
943: if ( !ind ) {
944: RESET:
945: m1 = utoz(md);
946: rank0 = rank;
947: bcopy(wcolstat,colstat,col*sizeof(int));
948: MKMAT(crmat,rank,col-rank);
949: MKMAT(r,rank,col-rank); *nm = r;
950: tmat = (Z **)crmat->body;
951: for ( i = 0; i < rank; i++ )
952: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
953: if ( !colstat[j] ) tmi[k++] = utoz(wmi[j]);
954: } else {
955: if ( rank < rank0 ) {
956: if ( DP_Print ) {
957: fprintf(asir_out,"lower rank matrix; continuing...\n");
958: fflush(asir_out);
959: }
960: continue;
961: } else if ( rank > rank0 ) {
962: if ( DP_Print ) {
963: fprintf(asir_out,"higher rank matrix; resetting...\n");
964: fflush(asir_out);
965: }
966: goto RESET;
967: } else {
968: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
969: if ( j < col ) {
970: if ( DP_Print ) {
971: fprintf(asir_out,"inconsitent colstat; resetting...\n");
972: fflush(asir_out);
973: }
974: goto RESET;
975: }
976: }
977:
978: inv = invm(remqi((Q)m1,md),md);
979: m2 = utoz(md); mulz(m1,m2,&m3);
980: for ( i = 0; i < rank; i++ )
981: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
982: if ( !colstat[j] ) {
983: if ( tmi[k] ) {
984: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
985: t = remqi((Q)tmi[k],md);
986: if ( wmi[j] >= t ) t = wmi[j]-t;
987: else t = md-(t-wmi[j]);
988: DMAR(t,inv,0,md,t1)
989: u = utoz(t1); mulz(m1,u,&s);
990: addz(tmi[k],s,&u); tmi[k] = u;
991: } else if ( wmi[j] ) {
992: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
993: DMAR(wmi[j],inv,0,md,t)
994: u = utoz(t); mulz(m1,u,&s); tmi[k] = s;
995: }
996: k++;
997: }
998: m1 = m3;
999: if ( ind % F4_INTRAT_PERIOD )
1000: ret = 0;
1001: else
1002: ret = intmtoratm(crmat,m1,*nm,dn);
1003: if ( ret ) {
1004: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
1005: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
1006: for ( j = k = l = 0; j < col; j++ )
1007: if ( colstat[j] ) rind[k++] = j;
1008: else cind[l++] = j;
1009: if ( gensolve_check(mat,*nm,*dn,rind,cind) )
1010: return rank;
1011: }
1012: }
1013: }
1014: }
1015:
1016: int generic_gauss_elim2(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp)
1017: {
1018:
1019: MAT full;
1020: Z **bmat,**b;
1021: Z *bmi;
1022: Z dn0;
1023: int row,col,md,i,j,rank,ret;
1024: int **wmat;
1025: int *wmi;
1026: int *colstat,*rowstat;
1027:
1028: bmat = (Z **)mat->body;
1029: row = mat->row; col = mat->col;
1030: wmat = (int **)almat(row,col);
1031: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1032: rowstat = (int *)MALLOC_ATOMIC(row*sizeof(int));
1033: /* XXX */
1034: md = get_lprime(0);
1035: for ( i = 0; i < row; i++ )
1036: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
1037: wmi[j] = remqi((Q)bmi[j],md);
1038: rank = generic_gauss_elim_mod2(wmat,row,col,md,colstat,rowstat);
1039: b = (Z **)MALLOC(rank*sizeof(Z));
1040: for ( i = 0; i < rank; i++ ) b[i] = bmat[rowstat[i]];
1041: NEWMAT(full); full->row = rank; full->col = col; full->body = (pointer **)b;
1042: ret = generic_gauss_elim_full(full,nm,dn,rindp,cindp);
1043: if ( !ret ) {
1044: rank = generic_gauss_elim(mat,nm,&dn0,rindp,cindp);
1045: for ( i = 0; i < rank; i++ ) dn[i] = dn0;
1046: }
1047: return rank;
1048: }
1049:
1050: int generic_gauss_elim_full(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp)
1051: {
1052: int **wmat;
1053: int *stat;
1054: Z **bmat,**tmat,*bmi,*tmi,*ri;
1055: Z q,m1,m2,m3,s,u;
1056: int *wmi,*colstat,*wcolstat,*rind,*cind;
1057: int row,col,ind,md,i,j,k,l,t,t1,rank,rank0,inv,h;
1058: MAT r,crmat;
1059: int ret,initialized,done;
1060:
1061: initialized = 0;
1062: bmat = (Z **)mat->body;
1063: row = mat->row; col = mat->col;
1064: wmat = (int **)almat(row,col);
1065: stat = (int *)MALLOC_ATOMIC(row*sizeof(int));
1066: for ( i = 0; i < row; i++ ) stat[i] = 0;
1067: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1068: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1069: for ( ind = 0; ; ind++ ) {
1070: if ( DP_Print ) {
1071: fprintf(asir_out,"."); fflush(asir_out);
1072: }
1073: md = get_lprime(ind);
1074: for ( i = 0; i < row; i++ )
1075: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
1076: wmi[j] = remqi((Q)bmi[j],md);
1077: rank = generic_gauss_elim_mod(wmat,row,col,md,wcolstat);
1078: if ( rank < row ) continue;
1079: if ( !initialized ) {
1080: m1 = utoz(md);
1081: bcopy(wcolstat,colstat,col*sizeof(int));
1082: MKMAT(crmat,row,col-row);
1083: MKMAT(r,row,col-row); *nm = r;
1084: tmat = (Z **)crmat->body;
1085: for ( i = 0; i < row; i++ )
1086: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
1087: if ( !colstat[j] ) tmi[k++] = utoz(wmi[j]);
1088: initialized = 1;
1089: } else {
1090: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
1091: if ( j < col ) continue;
1092:
1093: inv = invm(remqi((Q)m1,md),md);
1094: m2 = utoz(md); mulz(m1,m2,&m3);
1095: for ( i = 0; i < row; i++ )
1096: switch ( stat[i] ) {
1097: case 1:
1098: /* consistency check */
1099: ri = (Z *)BDY(r)[i]; wmi = wmat[i];
1100: for ( j = 0; j < col; j++ ) if ( colstat[j] ) break;
1101: h = md-remqi((Q)dn[i],md);
1102: for ( j++, k = 0; j < col; j++ )
1103: if ( !colstat[j] ) {
1104: t = remqi((Q)ri[k],md);
1105: DMAR(wmi[i],h,t,md,t1);
1106: if ( t1 ) break;
1107: }
1108: if ( j == col ) { stat[i]++; break; }
1109: else {
1110: /* fall to the case 0 */
1111: stat[i] = 0;
1112: }
1113: case 0:
1114: tmi = tmat[i]; wmi = wmat[i];
1115: for ( j = k = 0; j < col; j++ )
1116: if ( !colstat[j] ) {
1117: if ( tmi[k] ) {
1118: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
1119: t = remqi((Q)tmi[k],md);
1120: if ( wmi[j] >= t ) t = wmi[j]-t;
1121: else t = md-(t-wmi[j]);
1122: DMAR(t,inv,0,md,t1)
1123: u = utoz(t1); mulz(m1,u,&s);
1124: addz(tmi[k],s,&u); tmi[k] = u;
1125: } else if ( wmi[j] ) {
1126: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
1127: DMAR(wmi[j],inv,0,md,t)
1128: u = utoz(t); mulz(m1,u,&s); tmi[k] = s;
1129: }
1130: k++;
1131: }
1132: break;
1133: case 2: default:
1134: break;
1135: }
1136: m1 = m3;
1137: if ( ind % 4 )
1138: ret = 0;
1139: else
1140: ret = intmtoratm2(crmat,m1,*nm,dn,stat);
1141: if ( ret ) {
1142: *rindp = rind = (int *)MALLOC_ATOMIC(row*sizeof(int));
1143: *cindp = cind = (int *)MALLOC_ATOMIC((col-row)*sizeof(int));
1144: for ( j = k = l = 0; j < col; j++ )
1145: if ( colstat[j] ) rind[k++] = j;
1146: else cind[l++] = j;
1147: return gensolve_check2(mat,*nm,dn,rind,cind);
1148: }
1149: }
1150: }
1151: }
1152:
1153: int generic_gauss_elim_direct(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp){
1154: Z **bmat,*s;
1155: Z u,v,w,x,d,t,y;
1156: int row,col,i,j,k,l,m,rank;
1157: int *colstat,*colpos,*cind;
1158: MAT r,in;
1159:
1160: row = mat->row; col = mat->col;
1161: MKMAT(in,row,col);
1162: for ( i = 0; i < row; i++ )
1163: for ( j = 0; j < col; j++ ) in->body[i][j] = mat->body[i][j];
1164: bmat = (Z **)in->body;
1165: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1166: *rindp = colpos = (int *)MALLOC_ATOMIC(row*sizeof(int));
1167: for ( j = 0, rank = 0, d = ONE; j < col; j++ ) {
1168: for ( i = rank; i < row && !bmat[i][j]; i++ );
1169: if ( i == row ) { colstat[j] = 0; continue; }
1170: else { colstat[j] = 1; colpos[rank] = j; }
1171: if ( i != rank )
1172: for ( k = j; k < col; k++ ) {
1173: t = bmat[i][k]; bmat[i][k] = bmat[rank][k]; bmat[rank][k] = t;
1174: }
1175: for ( i = rank+1, v = bmat[rank][j]; i < row; i++ )
1176: for ( k = j, u = bmat[i][j]; k < col; k++ ) {
1177: mulz(bmat[i][k],v,&w); mulz(bmat[rank][k],u,&x);
1178: subz(w,x,&y); divsz(y,d,&bmat[i][k]);
1179: }
1180: d = v; rank++;
1181: }
1182: *dn = d;
1183: s = (Z *)MALLOC(col*sizeof(Z));
1184: for ( i = rank-1; i >= 0; i-- ) {
1185: for ( k = colpos[i]; k < col; k++ ) mulz(bmat[i][k],d,&s[k]);
1186: for ( m = rank-1; m > i; m-- ) {
1187: for ( k = colpos[m], u = bmat[i][k]; k < col; k++ ) {
1188: mulz(bmat[m][k],u,&w); subz(s[k],w,&x); s[k] = x;
1189: }
1190: }
1191: for ( k = colpos[i], u = bmat[i][k]; k < col; k++ )
1192: divz(s[k],u,&bmat[i][k]);
1193: }
1194: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
1195: MKMAT(r,rank,col-rank); *nm = r;
1196: for ( j = 0, k = 0; j < col; j++ )
1197: if ( !colstat[j] ) {
1198: cind[k] = j;
1199: for ( i = 0; i < rank; i++ ) r->body[i][k] = bmat[i][j];
1200: k++;
1201: }
1202: return rank;
1203: }
1204:
1.8 noro 1205: int mpz_intmtoratm(mpz_t **mat,int row,int col,mpz_t md,mpz_t **nm,mpz_t dn)
1206: {
1207: mpz_t t,s,b,u,nm1,dn1;
1208: int i,j,k,l,ret;
1209: mpz_t *mi,*nmk;
1210:
1211: if ( UNIMPZ(md) )
1212: return 0;
1213: mpz_init(t); mpz_init(s); mpz_init(b); mpz_init(u);
1214: mpz_init(nm1); mpz_init(dn1);
1215: mpz_fdiv_q_2exp(t,md,1); mpz_sqrt(s,t); mpz_fdiv_q_2exp(b,s,64);
1216: if ( !mpz_sgn(b) ) mpz_set_ui(b,1);
1217: mpz_set_ui(dn,1);
1218: for ( i = 0; i < row; i++ )
1219: for ( j = 0, mi = mat[i]; j < col; j++ )
1220: if ( mpz_sgn(mi[j]) ) {
1221: mpz_mul(s,mi[j],dn);
1222: mpz_mod(u,s,md);
1223: ret = mpz_inttorat(u,md,b,nm1,dn1);
1224: if ( !ret )
1225: return 0;
1226: else {
1227: if ( !UNIMPZ(dn1) ) {
1228: for ( k = 0; k < i; k++ )
1229: for ( l = 0, nmk = nm[k]; l < col; l++ ) mpz_mul(nmk[l],nmk[l],dn1);
1230: for ( l = 0, nmk = nm[i]; l < j; l++ ) mpz_mul(nmk[l],nmk[l],dn1);
1231: }
1232: mpz_set(nm[i][j],nm1);
1233: mpz_mul(dn,dn,dn1);
1234: }
1235: }
1236: return 1;
1237: }
1238:
1.1 noro 1239: int intmtoratm(MAT mat,Z md,MAT nm,Z *dn)
1240: {
1241: Z t,s,b,dn0,dn1,nm1,q,u,unm,udn,dmy;
1242: int i,j,k,l,row,col,sgn,ret;
1243: Z **rmat,**tmat,*tmi,*nmk;
1244:
1245: if ( UNIQ(md) )
1246: return 0;
1247: row = mat->row; col = mat->col;
1248: bshiftz(md,1,&t);
1.18 noro 1249: isqrtz(t,&s);
1.1 noro 1250: bshiftz(s,64,&b);
1251: if ( !b ) b = ONE;
1252: dn0 = ONE;
1253: tmat = (Z **)mat->body;
1254: rmat = (Z **)nm->body;
1255: for ( i = 0; i < row; i++ )
1256: for ( j = 0, tmi = tmat[i]; j < col; j++ )
1257: if ( tmi[j] ) {
1258: mulz(tmi[j],dn0,&s);
1259: divqrz(s,md,&dmy,&u);
1260: ret = inttorat(u,md,b,&nm1,&dn1);
1261: if ( !ret ) return 0;
1262: else {
1263: if ( !UNIQ(dn1) ) {
1264: for ( k = 0; k < i; k++ )
1265: for ( l = 0, nmk = rmat[k]; l < col; l++ ) {
1266: mulz(nmk[l],dn1,&q); nmk[l] = q;
1267: }
1268: for ( l = 0, nmk = rmat[i]; l < j; l++ ) {
1269: mulz(nmk[l],dn1,&q); nmk[l] = q;
1270: }
1271: }
1272: rmat[i][j] = nm1;
1273: mulz(dn0,dn1,&q); dn0 = q;
1274: }
1275: }
1276: *dn = dn0;
1277: return 1;
1278: }
1279:
1280: int intmtoratm2(MAT mat,Z md,MAT nm,Z *dn,int *stat)
1281: {
1282: int row,col,i,j,ret;
1283: Z dn0,dn1,t,s,b;
1284: Z *w,*tmi;
1285: Z **tmat;
1286:
1287: bshiftz(md,1,&t);
1288: isqrtz(t,&s);
1289: bshiftz(s,64,&b);
1290: tmat = (Z **)mat->body;
1291: if ( UNIQ(md) ) return 0;
1292: row = mat->row; col = mat->col;
1293: dn0 = ONE;
1294: for ( i = 0; i < row; i++ )
1295: if ( cmpz(dn[i],dn0) > 0 ) dn0 = dn[i];
1296: w = (Z *)MALLOC(col*sizeof(Z));
1297: for ( i = 0; i < row; i++ )
1298: if ( stat[i] == 0 ) {
1299: for ( j = 0, tmi = tmat[i]; j < col; j++ )
1300: mulz(tmi[j],dn0,&w[j]);
1301: ret = intvtoratv(w,col,md,b,(Z *)BDY(nm)[i],&dn[i]);
1302: if ( ret ) {
1303: stat[i] = 1;
1304: mulz(dn0,dn[i],&t); dn[i] = t; dn0 = t;
1305: }
1306: }
1307: for ( i = 0; i < row; i++ ) if ( !stat[i] ) break;
1308: if ( i == row ) return 1;
1309: else return 0;
1310: }
1311:
1312: int intvtoratv(Z *v,int n,Z md,Z b,Z *nm,Z *dn)
1313: {
1314: Z dn0,dn1,q,s,u,nm1,unm,udn,dmy;
1315: Z *nmk;
1316: int j,l,col,ret,sgn;
1317:
1318: for ( j = 0; j < n; j++ ) nm[j] = 0;
1319: dn0 = ONE;
1320: for ( j = 0; j < n; j++ ) {
1321: if ( !v[j] ) continue;
1322: mulz(v[j],dn0,&s);
1323: divqrz(s,md,&dmy,&u);
1324: ret = inttorat(u,md,b,&nm1,&dn1);
1325: if ( !ret ) return 0;
1326: if ( !UNIQ(dn1) )
1327: for ( l = 0; l < j; l++ ) {
1328: mulz(nm[l],dn1,&q); nm[l] = q;
1329: }
1330: nm[j] = nm1;
1331: mulz(dn0,dn1,&q); dn0 = q;
1332: }
1333: *dn = dn0;
1334: return 1;
1335: }
1336:
1337: /* assuming 0 < c < m */
1338:
1.8 noro 1339: int mpz_inttorat(mpz_t c,mpz_t m,mpz_t b,mpz_t nm,mpz_t dn)
1340: {
1341: mpz_t u1,v1,u2,v2,r1,r2;
1342: mpz_t q,t;
1343:
1344: mpz_init_set_ui(u1,0); mpz_init_set_ui(v1,1);
1345: mpz_init_set(u2,m); mpz_init_set(v2,c);
1346: mpz_init(q); mpz_init(t); mpz_init(r1); mpz_init(r2);
1347: while ( mpz_cmp(v2,b) >= 0 ) {
1348: /* r2 = u2-q*v2 */
1349: mpz_fdiv_qr(q,r2,u2,v2);
1350: mpz_set(u2,v2); mpz_set(v2,r2);
1351: /* r1 = u1-q*v1 */
1352: mpz_mul(t,q,v1); mpz_sub(r1,u1,t);
1353: mpz_set(u1,v1); mpz_set(v1,r1);
1354: }
1355: if ( mpz_cmp(v1,b) >= 0 ) return 0;
1356: else {
1.14 noro 1357: mpz_gcd(t,v1,v2);
1358: if ( UNIMPZ(t) )
1359: mpz_set_ui(r1,0);
1360: else {
1361: /* v1 /= t, v2 /= t, t=c*v1-v2, r1=t%m */
1362: mpz_divexact(v1,v1,t); mpz_divexact(v2,v2,t);
1363: mpz_mul(t,c,v1); mpz_sub(t,t,v2); mpz_mod(r1,t,m);
1364: }
1365: if ( mpz_sgn(r1) ) return 0;
1.8 noro 1366: if ( mpz_sgn(v1)<0 ) {
1367: mpz_neg(dn,v1); mpz_neg(nm,v2);
1368: } else {
1369: mpz_set(dn,v1); mpz_set(nm,v2);
1370: }
1371: return 1;
1372: }
1373: }
1374:
1.1 noro 1375: int inttorat(Z c,Z m,Z b,Z *nmp,Z *dnp)
1376: {
1.14 noro 1377: Z qq,t,s,r,u1,v1,r1;
1.1 noro 1378: Z q,u2,v2,r2;
1379:
1380: u1 = 0; v1 = ONE; u2 = m; v2 = c;
1381: while ( cmpz(v2,b) >= 0 ) {
1382: divqrz(u2,v2,&q,&r2); u2 = v2; v2 = r2;
1383: mulz(q,v1,&t); subz(u1,t,&r1); u1 = v1; v1 = r1;
1384: }
1385: if ( cmpz(v1,b) >= 0 ) return 0;
1386: else {
1.14 noro 1387: /* reduction and check */
1388: /* v2/v1 = u2/u1, c*u1-u2 = 0 mod m? */
1389: gcdz(v1,v2,&t);
1390: if ( UNIZ(t) ) {
1391: u1 = v1; u2 = v2; r = 0;
1392: } else {
1393: divsz(v1,t,&u1); divsz(v2,t,&u2);
1394: mulz(c,u1,&t); subz(t,u2,&s); remz(s,m,&r);
1395: }
1396: if ( r ) return 0;
1397: if ( mpz_sgn(BDY(u1))<0 ) {
1398: chsgnz(u1,dnp); chsgnz(u2,nmp);
1.1 noro 1399: } else {
1.14 noro 1400: *dnp = u1; *nmp = u2;
1.1 noro 1401: }
1402: return 1;
1403: }
1404: }
1405:
1406: extern int f4_nocheck;
1407:
1.12 noro 1408: int mpz_gensolve_check(MAT mat,mpz_t **nm,mpz_t dn,int rank,int clen,int *rind,int *cind)
1.8 noro 1409: {
1.12 noro 1410: int row,col,i,j,k,l;
1.8 noro 1411: mpz_t t;
1412: mpz_t *w;
1413: Z *mati;
1414: mpz_t *nmk;
1415:
1416: if ( f4_nocheck ) return 1;
1.12 noro 1417: row = mat->row; col = mat->col;
1.8 noro 1418: w = (mpz_t *)MALLOC(clen*sizeof(mpz_t));
1419: mpz_init(t);
1420: for ( i = 0; i < clen; i++ ) mpz_init(w[i]);
1421: for ( i = 0; i < row; i++ ) {
1422: mati = (Z *)mat->body[i];
1423: for ( l = 0; l < clen; l++ ) mpz_set_ui(w[l],0);
1424: for ( k = 0; k < rank; k++ )
1425: for ( l = 0, nmk = (mpz_t *)nm[k]; l < clen; l++ ) {
1426: /* w[l] += mati[rind[k]]*nmk[k] */
1427: if ( mati[rind[k]] ) mpz_addmul(w[l],BDY(mati[rind[k]]),nmk[l]);
1428: }
1429: for ( j = 0; j < clen; j++ ) {
1430: if ( mati[cind[j]] ) mpz_mul(t,dn,BDY(mati[cind[j]]));
1431: else mpz_set_ui(t,0);
1432: if ( mpz_cmp(w[j],t) ) break;
1433: }
1434: if ( j != clen ) break;
1435: }
1436: if ( i != row ) return 0;
1437: else return 1;
1438: }
1439:
1.1 noro 1440: int gensolve_check(MAT mat,MAT nm,Z dn,int *rind,int *cind)
1441: {
1442: int row,col,rank,clen,i,j,k,l;
1443: Z s,t;
1444: Z *w;
1445: Z *mati,*nmk;
1446:
1447: if ( f4_nocheck ) return 1;
1448: row = mat->row; col = mat->col; rank = nm->row; clen = nm->col;
1449: w = (Z *)MALLOC(clen*sizeof(Z));
1450: for ( i = 0; i < row; i++ ) {
1451: mati = (Z *)mat->body[i];
1452: bzero(w,clen*sizeof(Z));
1453: for ( k = 0; k < rank; k++ )
1454: for ( l = 0, nmk = (Z *)nm->body[k]; l < clen; l++ ) {
1455: mulz(mati[rind[k]],nmk[l],&t); addz(w[l],t,&s); w[l] = s;
1456: }
1457: for ( j = 0; j < clen; j++ ) {
1458: mulz(dn,mati[cind[j]],&t);
1459: if ( cmpz(w[j],t) ) break;
1460: }
1461: if ( j != clen ) break;
1462: }
1463: if ( i != row ) return 0;
1464: else return 1;
1465: }
1466:
1467: int gensolve_check2(MAT mat,MAT nm,Z *dn,int *rind,int *cind)
1468: {
1469: int row,col,rank,clen,i,j,k,l;
1470: Z s,t,u,d;
1471: Z *w,*m;
1472: Z *mati,*nmk;
1473:
1474: if ( f4_nocheck ) return 1;
1475: row = mat->row; col = mat->col; rank = nm->row; clen = nm->col;
1476: w = (Z *)MALLOC(clen*sizeof(Z));
1477: m = (Z *)MALLOC(clen*sizeof(Z));
1478: for ( d = dn[0], i = 1; i < rank; i++ ) {
1479: lcmz(d,dn[i],&t); d = t;
1480: }
1481: for ( i = 0; i < rank; i++ ) divsz(d,dn[i],&m[i]);
1482: for ( i = 0; i < row; i++ ) {
1483: mati = (Z *)mat->body[i];
1484: bzero(w,clen*sizeof(Z));
1485: for ( k = 0; k < rank; k++ ) {
1486: mulz(mati[rind[k]],m[k],&u);
1487: for ( l = 0, nmk = (Z *)nm->body[k]; l < clen; l++ ) {
1488: mulz(u,nmk[l],&t); addz(w[l],t,&s); w[l] = s;
1489: }
1490: }
1491: for ( j = 0; j < clen; j++ ) {
1492: mulz(d,mati[cind[j]],&t);
1493: if ( cmpz(w[j],t) ) break;
1494: }
1495: if ( j != clen ) break;
1496: }
1497: if ( i != row ) return 0;
1498: else return 1;
1499: }
1500:
1501: void isqrtz(Z a,Z *r)
1502: {
1503: int k;
1504: Z x,t,x2,xh,quo,rem;
1505: Z two;
1506:
1507: if ( !a ) *r = 0;
1.11 noro 1508: else if ( UNIZ(a) ) *r = ONE;
1.1 noro 1509: else {
1510: k = z_bits((Q)a); /* a <= 2^k-1 */
1511: bshiftz(ONE,-((k>>1)+(k&1)),&x); /* a <= x^2 */
1.5 noro 1512: STOZ(2,two);
1.1 noro 1513: while ( 1 ) {
1514: pwrz(x,two,&t);
1515: if ( cmpz(t,a) <= 0 ) {
1516: *r = x; return;
1517: } else {
1518: if ( mpz_tstbit(BDY(x),0) ) addz(x,a,&t);
1519: else t = a;
1520: bshiftz(x,-1,&x2); divqrz(t,x2,&quo,&rem);
1521: bshiftz(x,1,&xh); addz(quo,xh,&x);
1522: }
1523: }
1524: }
1525: }
1526:
1527: void bshiftz(Z a,int n,Z *r)
1528: {
1529: mpz_t t;
1530:
1531: if ( !a ) *r = 0;
1532: else if ( n == 0 ) *r = a;
1533: else if ( n < 0 ) {
1534: mpz_init(t); mpz_mul_2exp(t,BDY(a),-n); MPZTOZ(t,*r);
1535: } else {
1536: mpz_init(t); mpz_fdiv_q_2exp(t,BDY(a),n);
1537: if ( !mpz_sgn(t) ) *r = 0;
1538: else MPZTOZ(t,*r);
1539: }
1540: }
1541:
1542: void addlf(Z a,Z b,Z *c)
1543: {
1544: addz(a,b,c);
1545: if ( !lf_lazy ) {
1546: if ( cmpz(*c,current_mod_lf) >= 0 ) {
1547: subz(*c,current_mod_lf,c);
1548: }
1549: }
1550: }
1551:
1552: void sublf(Z a,Z b,Z *c)
1553: {
1554: subz(a,b,c);
1555: if ( !lf_lazy ) {
1556: remz(*c,current_mod_lf,c);
1557: }
1558: }
1559:
1560: void mullf(Z a,Z b,Z *c)
1561: {
1562: mulz(a,b,c);
1563: if ( !lf_lazy ) {
1564: remz(*c,current_mod_lf,c);
1565: }
1566: }
1567:
1568: void divlf(Z a,Z b,Z *c)
1569: {
1570: Z inv;
1571:
1572: invz(b,current_mod_lf,&inv);
1573: mulz(a,inv,c);
1574: if ( !lf_lazy ) {
1575: remz(*c,current_mod_lf,c);
1576: }
1577: }
1578:
1579: void chsgnlf(Z a,Z *c)
1580: {
1581: chsgnz(a,c);
1582: if ( !lf_lazy ) {
1583: remz(*c,current_mod_lf,c);
1584: }
1585: }
1586:
1587: void lmtolf(LM a,Z *b)
1588: {
1589: if ( !a ) *b = 0;
1590: else {
1591: MPZTOZ(BDY(a),*b);
1592: }
1593: }
1594:
1595: void setmod_lf(Z p)
1596: {
1597: current_mod_lf = p;
1598: current_mod_lf_size = mpz_size(BDY(current_mod_lf))+1;
1599: }
1600:
1601: void simplf_force(Z a,Z *b)
1602: {
1603: remz(a,current_mod_lf,b);
1604: }
1605:
1606: int generic_gauss_elim_hensel(MAT mat,MAT *nmmat,Z *dn,int **rindp,int **cindp)
1607: {
1608: MAT bmat,xmat;
1609: Z **a0,**a,**b,**x,**nm;
1610: Z *ai,*bi,*xi;
1611: int row,col;
1612: int **w;
1613: int *wi;
1614: int **wc;
1615: Z mdq,q,s,u;
1616: Z tn;
1617: int ind,md,i,j,k,l,li,ri,rank;
1618: unsigned int t;
1619: int *cinfo,*rinfo;
1620: int *rind,*cind;
1621: int count;
1622: int ret;
1.3 noro 1623: struct oEGT eg_mul1,eg_mul2,tmp0,tmp1,tmp2;
1.1 noro 1624: int period;
1625: int *wx,*ptr;
1626: int wxsize,nsize;
1627: Z wn;
1628: Z wq;
1629:
1.9 noro 1630: #if SIZEOF_LONG == 8
1.11 noro 1631: return generic_gauss_elim_hensel64(mat,nmmat,dn,rindp,cindp,0);
1.9 noro 1632: #endif
1.3 noro 1633: init_eg(&eg_mul1); init_eg(&eg_mul2);
1.1 noro 1634: a0 = (Z **)mat->body;
1635: row = mat->row; col = mat->col;
1636: w = (int **)almat(row,col);
1637: for ( ind = 0; ; ind++ ) {
1638: md = get_lprime(ind);
1.5 noro 1639: STOZ(md,mdq);
1.1 noro 1640: for ( i = 0; i < row; i++ )
1641: for ( j = 0, ai = a0[i], wi = w[i]; j < col; j++ )
1642: wi[j] = remqi((Q)ai[j],md);
1643:
1644: if ( DP_Print > 3 ) {
1645: fprintf(asir_out,"LU decomposition.."); fflush(asir_out);
1646: }
1647: rank = find_lhs_and_lu_mod((unsigned int **)w,row,col,md,&rinfo,&cinfo);
1648: if ( DP_Print > 3 ) {
1649: fprintf(asir_out,"done.\n"); fflush(asir_out);
1650: }
1651: a = (Z **)almat_pointer(rank,rank); /* lhs mat */
1652: MKMAT(bmat,rank,col-rank); b = (Z **)bmat->body; /* lhs mat */
1653: for ( j = li = ri = 0; j < col; j++ )
1654: if ( cinfo[j] ) {
1655: /* the column is in lhs */
1656: for ( i = 0; i < rank; i++ ) {
1657: w[i][li] = w[i][j];
1658: a[i][li] = a0[rinfo[i]][j];
1659: }
1660: li++;
1661: } else {
1662: /* the column is in rhs */
1663: for ( i = 0; i < rank; i++ )
1664: b[i][ri] = a0[rinfo[i]][j];
1665: ri++;
1666: }
1667:
1668: /* solve Ax=B; A: rank x rank, B: rank x ri */
1669: /* algorithm
1670: c <- B
1671: x <- 0
1672: q <- 1
1673: do
1674: t <- A^(-1)c mod p
1675: x <- x+qt
1676: c <- (c-At)/p
1677: q <- qp
1678: end do
1679: then Ax-B=0 mod q and b=(B-Ax)/q hold after "do".
1680: */
1681: MKMAT(xmat,rank,ri); x = (Z **)(xmat)->body;
1682: MKMAT(*nmmat,rank,ri); nm = (Z **)(*nmmat)->body;
1683: wc = (int **)almat(rank,ri);
1684: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
1685: *cindp = cind = (int *)MALLOC_ATOMIC((ri)*sizeof(int));
1686:
1687: period = F4_INTRAT_PERIOD;
1688: for ( q = ONE, count = 0; ; ) {
1.3 noro 1689: /* check Ax=B mod q */
1.1 noro 1690: if ( DP_Print > 3 )
1691: fprintf(stderr,"o");
1692: /* wc = b mod md */
1693: for ( i = 0; i < rank; i++ )
1.3 noro 1694: for ( j = 0, bi = b[i], wi = wc[i]; j < ri; j++ )
1.1 noro 1695: wi[j] = remqi((Q)bi[j],md);
1.3 noro 1696: /* wc = A^(-1)wc; wc is not normalized */
1697: solve_by_lu_mod(w,rank,md,wc,ri,0);
1.1 noro 1698: /* x += q*wc */
1.3 noro 1699: get_eg(&tmp0);
1.1 noro 1700: for ( i = 0; i < rank; i++ )
1701: for ( j = 0, wi = wc[i]; j < ri; j++ ) mul1addtoz(q,wi[j],&x[i][j]);
1.3 noro 1702: /* b =(b-A*wc)/md */
1703: get_eg(&tmp1); add_eg(&eg_mul1,&tmp0,&tmp1);
1.1 noro 1704: for ( i = 0; i < rank; i++ )
1705: for ( j = 0; j < ri; j++ ) {
1.3 noro 1706: mpz_t uz;
1707:
1708: if ( b[i][j] )
1709: mpz_init_set(uz,BDY(b[i][j]));
1710: else
1711: mpz_init_set_ui(uz,0);
1712: for ( k = 0; k < rank; k++ ) {
1713: if ( a[i][k] && wc[k][j] ) {
1714: if ( wc[k][j] < 0 )
1715: mpz_addmul_ui(uz,BDY(a[i][k]),-wc[k][j]);
1716: else
1717: mpz_submul_ui(uz,BDY(a[i][k]),wc[k][j]);
1718: }
1719: }
1720: MPZTOZ(uz,u);
1.1 noro 1721: divsz(u,mdq,&b[i][j]);
1722: }
1.3 noro 1723: get_eg(&tmp2); add_eg(&eg_mul2,&tmp1,&tmp2);
1.1 noro 1724: count++;
1725: /* q = q*md */
1726: mulz(q,mdq,&u); q = u;
1727: if ( count == period ) {
1728: ret = intmtoratm(xmat,q,*nmmat,dn);
1729: if ( ret ) {
1.3 noro 1730: print_eg("MUL1",&eg_mul1);
1731: print_eg("MUL2",&eg_mul2);
1.1 noro 1732: for ( j = k = l = 0; j < col; j++ )
1733: if ( cinfo[j] )
1734: rind[k++] = j;
1735: else
1736: cind[l++] = j;
1737: ret = gensolve_check(mat,*nmmat,*dn,rind,cind);
1738: if ( ret ) {
1739: *rindp = rind;
1740: *cindp = cind;
1741: for ( j = k = 0; j < col; j++ )
1742: if ( !cinfo[j] )
1743: cind[k++] = j;
1744: return rank;
1.11 noro 1745: } else
1746: goto reset;
1.1 noro 1747: } else {
1.11 noro 1748: reset:
1.1 noro 1749: period = period*3/2;
1750: count = 0;
1751: }
1752: }
1753: }
1754: }
1755: }
1756:
1757: /* for inv_or_split_dalg */
1758:
1759: int generic_gauss_elim_hensel_dalg(MAT mat,DP *mb,MAT *nmmat,Z *dn,int **rindp,int **cindp)
1760: {
1761: MAT bmat,xmat;
1762: Z **a0,**a,**b,**x,**nm;
1763: Z *ai,*bi,*xi;
1764: int row,col;
1765: int **w;
1766: int *wi;
1767: int **wc;
1768: Z mdq,q,s,u;
1769: Z tn;
1770: int ind,md,i,j,k,l,li,ri,rank;
1771: unsigned int t;
1772: int *cinfo,*rinfo;
1773: int *rind,*cind;
1774: int count;
1775: int ret;
1776: struct oEGT eg_mul,eg_inv,eg_intrat,eg_check,tmp0,tmp1;
1777: int period;
1778: int *wx,*ptr;
1779: int wxsize,nsize;
1780: Z wn;
1781: Z wq;
1782: DP m;
1783:
1.11 noro 1784: #if SIZEOF_LONG == 8
1785: return generic_gauss_elim_hensel64(mat,nmmat,dn,rindp,cindp,mb);
1786: #endif
1.1 noro 1787: a0 = (Z **)mat->body;
1788: row = mat->row; col = mat->col;
1789: w = (int **)almat(row,col);
1790: for ( ind = 0; ; ind++ ) {
1791: md = get_lprime(ind);
1.5 noro 1792: STOZ(md,mdq);
1.1 noro 1793: for ( i = 0; i < row; i++ )
1794: for ( j = 0, ai = a0[i], wi = w[i]; j < col; j++ )
1795: wi[j] = remqi((Q)ai[j],md);
1796:
1797: if ( DP_Print > 3 ) {
1798: fprintf(asir_out,"LU decomposition.."); fflush(asir_out);
1799: }
1800: rank = find_lhs_and_lu_mod((unsigned int **)w,row,col,md,&rinfo,&cinfo);
1801: if ( DP_Print > 3 ) {
1802: fprintf(asir_out,"done.\n"); fflush(asir_out);
1803: }
1804:
1805: /* this part is added for inv_or_split_dalg */
1806: for ( i = 0; i < col-1; i++ ) {
1807: if ( !cinfo[i] ) {
1808: m = mb[i];
1809: for ( j = i+1; j < col-1; j++ )
1810: if ( dp_redble(mb[j],m) )
1811: cinfo[j] = -1;
1812: }
1813: }
1814:
1815: a = (Z **)almat_pointer(rank,rank); /* lhs mat */
1816: MKMAT(bmat,rank,col-rank); b = (Z **)bmat->body; /* lhs mat */
1817: for ( j = li = ri = 0; j < col; j++ )
1.4 noro 1818: if ( cinfo[j] > 0 ) {
1.1 noro 1819: /* the column is in lhs */
1820: for ( i = 0; i < rank; i++ ) {
1821: w[i][li] = w[i][j];
1822: a[i][li] = a0[rinfo[i]][j];
1823: }
1824: li++;
1.4 noro 1825: } else if ( !cinfo[j] ) {
1.1 noro 1826: /* the column is in rhs */
1827: for ( i = 0; i < rank; i++ )
1828: b[i][ri] = a0[rinfo[i]][j];
1829: ri++;
1830: }
1831:
1832: /* solve Ax=B; A: rank x rank, B: rank x ri */
1833: /* algorithm
1834: c <- B
1835: x <- 0
1836: q <- 1
1837: do
1838: t <- A^(-1)c mod p
1839: x <- x+qt
1840: c <- (c-At)/p
1841: q <- qp
1842: end do
1843: then Ax-B=0 mod q and b=(B-Ax)/q hold after "do".
1844: */
1845: MKMAT(xmat,rank,ri); x = (Z **)(xmat)->body;
1846: MKMAT(*nmmat,rank,ri); nm = (Z **)(*nmmat)->body;
1847: wc = (int **)almat(rank,ri);
1848: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
1849: *cindp = cind = (int *)MALLOC_ATOMIC((ri)*sizeof(int));
1850:
1851: period = F4_INTRAT_PERIOD;
1852: for ( q = ONE, count = 0; ; ) {
1853: if ( DP_Print > 3 )
1854: fprintf(stderr,"o");
1855: /* wc = b mod md */
1856: for ( i = 0; i < rank; i++ )
1.3 noro 1857: for ( j = 0, bi = b[i], wi = wc[i]; j < ri; j++ )
1.1 noro 1858: wi[j] = remqi((Q)bi[j],md);
1.11 noro 1859: /* wc = A^(-1)wc; wc is not normalized */
1860: solve_by_lu_mod(w,rank,md,wc,ri,0);
1.1 noro 1861: /* x += q*wc */
1862: for ( i = 0; i < rank; i++ )
1863: for ( j = 0, wi = wc[i]; j < ri; j++ ) mul1addtoz(q,wi[j],&x[i][j]);
1.3 noro 1864: /* b =(b-A*wc)/md */
1.1 noro 1865: for ( i = 0; i < rank; i++ )
1866: for ( j = 0; j < ri; j++ ) {
1.3 noro 1867: mpz_t uz;
1868:
1869: if ( b[i][j] )
1870: mpz_init_set(uz,BDY(b[i][j]));
1871: else
1872: mpz_init_set_ui(uz,0);
1.11 noro 1873: for ( k = 0; k < rank; k++ )
1874: if ( a[i][k] && wc[k][j] )
1.3 noro 1875: mpz_submul_ui(uz,BDY(a[i][k]),wc[k][j]);
1876: MPZTOZ(uz,u);
1.1 noro 1877: divsz(u,mdq,&b[i][j]);
1878: }
1.11 noro 1879:
1.1 noro 1880: count++;
1881: /* q = q*md */
1882: mulz(q,mdq,&u); q = u;
1883: if ( count == period ) {
1884: ret = intmtoratm(xmat,q,*nmmat,dn);
1885: if ( ret ) {
1886: for ( j = k = l = 0; j < col; j++ )
1887: if ( cinfo[j] > 0 )
1888: rind[k++] = j;
1889: else if ( !cinfo[j] )
1890: cind[l++] = j;
1891: ret = gensolve_check(mat,*nmmat,*dn,rind,cind);
1892: if ( ret ) {
1893: *rindp = rind;
1894: *cindp = cind;
1895: for ( j = k = 0; j < col; j++ )
1896: if ( !cinfo[j] )
1897: cind[k++] = j;
1898: return rank;
1.11 noro 1899: } else
1900: goto reset;
1.1 noro 1901: } else {
1.11 noro 1902: reset:
1.1 noro 1903: period = period*3/2;
1904: count = 0;
1905: }
1906: }
1907: }
1908: }
1909: }
1.6 noro 1910:
1911: #if SIZEOF_LONG == 8
1912: mp_limb_t remqi64(Q a,mp_limb_t mod)
1913: {
1914: mp_limb_t c,nm,dn;
1915: mpz_t r;
1916:
1917: if ( !a ) return 0;
1918: else if ( a->z ) {
1919: mpz_init(r);
1920: c = mpz_fdiv_r_ui(r,BDY((Z)a),mod);
1921: } else {
1922: mpz_init(r);
1923: nm = mpz_fdiv_r_ui(r,mpq_numref(BDY(a)),mod);
1924: dn = mpz_fdiv_r_ui(r,mpq_denref(BDY(a)),mod);
1925: dn = invmod64(dn,mod);
1926: c = mulmod64(nm,dn,mod);
1927: }
1928: return c;
1929: }
1930:
1931: int generic_gauss_elim_mod64(mp_limb_t **mat,int row,int col,mp_limb_t md,int *colstat);
1932: mp_limb_t get_lprime64(int ind);
1933:
1.8 noro 1934: void mpz_print(mpz_t a)
1935: {
1936: mpz_out_str(stdout,10,a); printf("\n");
1937: }
1938:
1939: void mpz_printmat(mpz_t **a,int row,int col)
1940: {
1941: int i,j;
1942: for ( i = 0; i < row; i++ ) {
1943: for ( j = 0; j < col; j++ ) {
1944: mpz_out_str(stdout,10,a[i][j]); printf(" ");
1945: }
1946: printf("\n");
1947: }
1948: }
1949:
1950: mpz_t **mpz_allocmat(int row,int col)
1951: {
1952: mpz_t **p;
1953: int i,j;
1954:
1955: p = (mpz_t **)MALLOC(row*sizeof(mpz_t *));
1956: for ( i = 0; i < row; i++ ) {
1957: p[i] = (mpz_t *)MALLOC(col*sizeof(mpz_t));
1958: for ( j = 0; j < col; j++ ) mpz_init(p[i][j]);
1959: }
1960: return p;
1961: }
1962:
1963: #if 1
1964: int generic_gauss_elim64(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp)
1965: {
1966: mp_limb_t **wmat;
1967: mp_limb_t *wmi;
1968: mp_limb_t md,inv,t,t1;
1969: Z z;
1970: Z **bmat,*bmi;
1971: mpz_t **tmat,**num;
1972: mpz_t *tmi;
1973: mpz_t den;
1974: mpz_t q,m1,m3,s,u;
1975: int *colstat,*wcolstat,*rind,*cind;
1976: int row,col,ind,i,j,k,l,rank,rank0;
1977: MAT r;
1978: int ret;
1979:
1980: bmat = (Z **)mat->body;
1981: row = mat->row; col = mat->col;
1982: wmat = (mp_limb_t **)almat64(row,col);
1983: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1984: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1985: mpz_init(m1); mpz_init(m3); mpz_init(den);
1986: for ( ind = 0; ; ind++ ) {
1987: if ( DP_Print ) {
1988: fprintf(asir_out,"."); fflush(asir_out);
1989: }
1990: md = get_lprime64(ind);
1991: for ( i = 0; i < row; i++ )
1992: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
1993: wmi[j] = bmi[j]==0?0:mpz_fdiv_ui(BDY(bmi[j]),md);
1994: rank = generic_gauss_elim_mod64(wmat,row,col,md,wcolstat);
1995: if ( !ind ) {
1996: RESET:
1997: mpz_set_ui(m1,md);
1998: rank0 = rank;
1999: bcopy(wcolstat,colstat,col*sizeof(int));
2000: // crmat
2001: tmat = mpz_allocmat(rank,col-rank);
2002: //
2003: num = mpz_allocmat(rank,col-rank);
2004: for ( i = 0; i < rank; i++ )
2005: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
2006: if ( !colstat[j] ) { mpz_set_ui(tmi[k],wmi[j]); k++; }
2007: } else {
2008: if ( rank < rank0 ) {
2009: if ( DP_Print ) {
2010: fprintf(asir_out,"lower rank matrix; continuing...\n");
2011: fflush(asir_out);
2012: }
2013: continue;
2014: } else if ( rank > rank0 ) {
2015: if ( DP_Print ) {
2016: fprintf(asir_out,"higher rank matrix; resetting...\n");
2017: fflush(asir_out);
2018: }
2019: goto RESET;
2020: } else {
2021: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
2022: if ( j < col ) {
2023: if ( DP_Print ) {
2024: fprintf(asir_out,"inconsitent colstat; resetting...\n");
2025: fflush(asir_out);
2026: }
2027: goto RESET;
2028: }
2029: }
2030:
2031: inv = invmod64(mpz_fdiv_ui(m1,md),md);
2032: mpz_mul_ui(m3,m1,md);
2033: for ( i = 0; i < rank; i++ )
2034: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
2035: if ( !colstat[j] ) {
2036: if ( mpz_sgn(tmi[k]) ) {
2037: /* f3 = f1+m1*(m1 mod md)^(-1)*(f2 - f1 mod md) */
2038: t = mpz_fdiv_ui(tmi[k],md);
2039: if ( wmi[j] >= t ) t = wmi[j]-t;
2040: else t = md-(t-wmi[j]);
2041: mpz_addmul_ui(tmi[k],m1,mulmod64(t,inv,md));
2042: } else if ( wmi[j] ) {
2043: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
2044: mpz_mul_ui(tmi[k],m1,mulmod64(wmi[j],inv,md));
2045: }
2046: k++;
2047: }
2048: mpz_set(m1,m3);
2049: if ( ind % F4_INTRAT_PERIOD )
2050: ret = 0;
2051: else
2052: ret = mpz_intmtoratm(tmat,rank,col-rank,m1,num,den);
2053: if ( ret ) {
2054: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
2055: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
2056: for ( j = k = l = 0; j < col; j++ )
2057: if ( colstat[j] ) rind[k++] = j;
2058: else cind[l++] = j;
1.12 noro 2059: if ( mpz_gensolve_check(mat,num,den,rank,col-rank,rind,cind) ) {
1.8 noro 2060: MKMAT(r,rank,col-rank); *nm = r;
2061: for ( i = 0; i < rank; i++ )
2062: for ( j = 0; j < col-rank; j++ ) {
2063: MPZTOZ(num[i][j],z); BDY(r)[i][j] = z;
2064: }
2065: MPZTOZ(den,*dn);
2066: return rank;
2067: }
2068: }
2069: }
2070: }
2071: }
2072: #else
1.6 noro 2073: int generic_gauss_elim64(MAT mat,MAT *nm,Z *dn,int **rindp,int **cindp)
2074: {
2075: mp_limb_t **wmat;
2076: mp_limb_t *wmi;
2077: mp_limb_t md,inv,t,t1;
2078: Z **bmat,**tmat,*bmi,*tmi;
2079: Z q,m1,m2,m3,s,u;
2080: int *colstat,*wcolstat,*rind,*cind;
2081: int row,col,ind,i,j,k,l,rank,rank0;
2082: MAT r,crmat;
2083: int ret;
2084:
2085: bmat = (Z **)mat->body;
2086: row = mat->row; col = mat->col;
2087: wmat = (mp_limb_t **)almat64(row,col);
2088: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
2089: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
2090: for ( ind = 0; ; ind++ ) {
2091: if ( DP_Print ) {
2092: fprintf(asir_out,"."); fflush(asir_out);
2093: }
2094: md = get_lprime64(ind);
2095: for ( i = 0; i < row; i++ )
2096: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
2097: wmi[j] = remqi64((Q)bmi[j],md);
2098: rank = generic_gauss_elim_mod64(wmat,row,col,md,wcolstat);
2099: if ( !ind ) {
2100: RESET:
2101: UTOZ(md,m1);
2102: rank0 = rank;
2103: bcopy(wcolstat,colstat,col*sizeof(int));
2104: MKMAT(crmat,rank,col-rank);
2105: MKMAT(r,rank,col-rank); *nm = r;
2106: tmat = (Z **)crmat->body;
2107: for ( i = 0; i < rank; i++ )
2108: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
2109: if ( !colstat[j] ) { UTOZ(wmi[j],tmi[k]); k++; }
2110: } else {
2111: if ( rank < rank0 ) {
2112: if ( DP_Print ) {
2113: fprintf(asir_out,"lower rank matrix; continuing...\n");
2114: fflush(asir_out);
2115: }
2116: continue;
2117: } else if ( rank > rank0 ) {
2118: if ( DP_Print ) {
2119: fprintf(asir_out,"higher rank matrix; resetting...\n");
2120: fflush(asir_out);
2121: }
2122: goto RESET;
2123: } else {
2124: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
2125: if ( j < col ) {
2126: if ( DP_Print ) {
2127: fprintf(asir_out,"inconsitent colstat; resetting...\n");
2128: fflush(asir_out);
2129: }
2130: goto RESET;
2131: }
2132: }
2133:
2134: inv = invmod64(remqi64((Q)m1,md),md);
2135: UTOZ(md,m2); mulz(m1,m2,&m3);
2136: for ( i = 0; i < rank; i++ )
2137: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
2138: if ( !colstat[j] ) {
2139: if ( tmi[k] ) {
2140: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
2141: t = remqi64((Q)tmi[k],md);
2142: if ( wmi[j] >= t ) t = wmi[j]-t;
2143: else t = md-(t-wmi[j]);
2144: t1 = mulmod64(t,inv,md);
2145: UTOZ(t1,u); mulz(m1,u,&s);
2146: addz(tmi[k],s,&u); tmi[k] = u;
2147: } else if ( wmi[j] ) {
2148: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
2149: t = mulmod64(wmi[j],inv,md);
2150: UTOZ(t,u); mulz(m1,u,&s); tmi[k] = s;
2151: }
2152: k++;
2153: }
2154: m1 = m3;
2155: if ( ind % F4_INTRAT_PERIOD )
2156: ret = 0;
2157: else
2158: ret = intmtoratm(crmat,m1,*nm,dn);
2159: if ( ret ) {
2160: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
2161: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
2162: for ( j = k = l = 0; j < col; j++ )
2163: if ( colstat[j] ) rind[k++] = j;
2164: else cind[l++] = j;
2165: if ( gensolve_check(mat,*nm,*dn,rind,cind) )
2166: return rank;
2167: }
2168: }
2169: }
2170: }
2171: #endif
1.8 noro 2172:
1.11 noro 2173: int generic_gauss_elim_hensel64(MAT mat,MAT *nmmat,Z *dn,int **rindp,int **cindp,DP *mb)
1.9 noro 2174: {
2175: MAT r;
2176: Z z;
2177: Z **a0;
2178: Z *ai;
2179: mpz_t **a,**b,**x,**nm;
2180: mpz_t *bi,*xi;
2181: mpz_t q,u,den;
2182: mp_limb_t **w;
2183: mp_limb_t *wi;
2184: mp_limb_t **wc;
2185: mp_limb_t md;
2186: int row,col;
2187: int ind,i,j,k,l,li,ri,rank;
2188: int *cinfo,*rinfo;
2189: int *rind,*cind;
2190: int count;
2191: int ret;
2192: int period;
1.11 noro 2193: DP m;
1.9 noro 2194:
2195: a0 = (Z **)mat->body;
2196: row = mat->row; col = mat->col;
2197: w = (mp_limb_t **)almat64(row,col);
2198: for ( ind = 0; ; ind++ ) {
2199: md = get_lprime64(ind);
2200: for ( i = 0; i < row; i++ )
2201: for ( j = 0, ai = a0[i], wi = w[i]; j < col; j++ )
2202: wi[j] = remqi64((Q)ai[j],md);
2203:
2204: if ( DP_Print > 3 ) {
2205: fprintf(asir_out,"LU decomposition.."); fflush(asir_out);
2206: }
2207: rank = find_lhs_and_lu_mod64(w,row,col,md,&rinfo,&cinfo);
2208: if ( DP_Print > 3 ) {
2209: fprintf(asir_out,"done.\n"); fflush(asir_out);
2210: }
1.11 noro 2211:
2212: if ( mb ) {
2213: /* this part is added for inv_or_split_dalg */
2214: for ( i = 0; i < col-1; i++ ) {
2215: if ( !cinfo[i] ) {
2216: m = mb[i];
2217: for ( j = i+1; j < col-1; j++ )
2218: if ( dp_redble(mb[j],m) )
2219: cinfo[j] = -1;
2220: }
2221: }
2222: }
2223:
1.9 noro 2224: a = (mpz_t **)mpz_allocmat(rank,rank); /* lhs mat */
2225: b = (mpz_t **)mpz_allocmat(rank,col-rank);
2226: for ( j = li = ri = 0; j < col; j++ )
1.11 noro 2227: if ( cinfo[j] > 0 ) {
1.9 noro 2228: /* the column is in lhs */
2229: for ( i = 0; i < rank; i++ ) {
2230: w[i][li] = w[i][j];
2231: if ( a0[rinfo[i]][j] )
2232: mpz_set(a[i][li],BDY(a0[rinfo[i]][j]));
2233: else
2234: mpz_set_ui(a[i][li],0);
2235: }
2236: li++;
1.11 noro 2237: } else if ( !cinfo[j] ) {
1.9 noro 2238: /* the column is in rhs */
2239: for ( i = 0; i < rank; i++ ) {
2240: if ( a0[rinfo[i]][j] )
2241: mpz_set(b[i][ri],BDY(a0[rinfo[i]][j]));
2242: else
2243: mpz_set_ui(b[i][ri],0);
2244: }
2245: ri++;
2246: }
2247:
2248: /* solve Ax=B; A: rank x rank, B: rank x ri */
2249: /* algorithm
2250: c <- B
2251: x <- 0
2252: q <- 1
2253: do
2254: t <- A^(-1)c mod p
2255: x <- x+qt
2256: c <- (c-At)/p
2257: q <- qp
2258: end do
2259: then Ax-B=0 mod q and b=(B-Ax)/q hold after "do".
2260: */
2261: x = (mpz_t **)mpz_allocmat(rank,ri);
2262: nm = (mpz_t **)mpz_allocmat(rank,ri);
2263: wc = (mp_limb_t **)almat64(rank,ri);
2264: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
2265: *cindp = cind = (int *)MALLOC_ATOMIC((ri)*sizeof(int));
2266:
2267: period = F4_INTRAT_PERIOD;
2268: mpz_init_set_ui(q,1);
2269: mpz_init(u);
2270: mpz_init(den);
2271: for ( count = 0; ; ) {
2272: /* check Ax=B mod q */
2273: if ( DP_Print > 3 )
2274: fprintf(stderr,"o");
2275: /* wc = b mod md */
2276: for ( i = 0; i < rank; i++ )
2277: for ( j = 0, bi = b[i], wi = wc[i]; j < ri; j++ )
2278: wi[j] = mpz_fdiv_ui(bi[j],md);
2279: /* wc = A^(-1)wc; wc is not normalized */
1.19 noro 2280: solve_by_lu_mod64(w,rank,md,(mp_limb_signed_t **)wc,ri,0);
1.9 noro 2281: /* x += q*wc */
2282: for ( i = 0; i < rank; i++ )
2283: for ( j = 0, wi = wc[i]; j < ri; j++ )
2284: if ( wi[j] > 0 )
2285: mpz_addmul_ui(x[i][j],q,wi[j]);
2286: else if ( wi[j] < 0 )
2287: mpz_submul_ui(x[i][j],q,-wi[j]);
2288: /* b =(b-A*wc)/md */
2289: for ( i = 0; i < rank; i++ )
2290: for ( j = 0; j < ri; j++ ) {
2291: mpz_set(u,b[i][j]);
2292: for ( k = 0; k < rank; k++ ) {
2293: if ( a[i][k] && wc[k][j] ) {
2294: if ( wc[k][j] < 0 )
2295: mpz_addmul_ui(u,a[i][k],-wc[k][j]);
2296: else
2297: mpz_submul_ui(u,a[i][k],wc[k][j]);
2298: }
2299: }
2300: mpz_divexact_ui(b[i][j],u,md);
2301: }
2302: count++;
2303: /* q = q*md */
2304: mpz_mul_ui(q,q,md);
2305: if ( count == period ) {
2306: ret = mpz_intmtoratm(x,rank,ri,q,nm,den);
2307: if ( ret ) {
2308: for ( j = k = l = 0; j < col; j++ )
1.11 noro 2309: if ( cinfo[j] > 0 )
1.9 noro 2310: rind[k++] = j;
1.11 noro 2311: else if ( !cinfo[j] )
1.9 noro 2312: cind[l++] = j;
1.12 noro 2313: ret = mpz_gensolve_check(mat,nm,den,rank,ri,rind,cind);
1.9 noro 2314: if ( ret ) {
2315: *rindp = rind;
2316: *cindp = cind;
2317: for ( j = k = 0; j < col; j++ )
2318: if ( !cinfo[j] )
2319: cind[k++] = j;
2320: MKMAT(r,rank,ri); *nmmat = r;
2321: for ( i = 0; i < rank; i++ )
2322: for ( j = 0; j < ri; j++ ) {
2323: MPZTOZ(nm[i][j],z); BDY(r)[i][j] = z;
2324: }
2325: MPZTOZ(den,*dn);
2326: return rank;
1.11 noro 2327: } else
2328: goto reset;
1.9 noro 2329: } else {
1.11 noro 2330: reset:
1.9 noro 2331: fprintf(stderr,"F");
2332: period = period*3/2;
2333: count = 0;
2334: }
2335: }
2336: }
2337: }
2338: }
2339:
1.8 noro 2340: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>