Annotation of OpenXM_contrib2/asir2000/engine/gmpq.c, Revision 1.6
1.1 noro 1: #include "ca.h"
2: #include "gmp.h"
3: #include "base.h"
4: #include "inline.h"
5:
6: mpz_t ONEMPZ;
7: GZ ONEGZ;
1.5 noro 8: int lf_lazy;
9: GZ current_mod_lf;
1.6 ! noro 10: int current_mod_lf_size;
1.1 noro 11:
12: void isqrtgz(GZ a,GZ *r);
13: void bshiftgz(GZ a,int n,GZ *r);
14:
15: void *gc_realloc(void *p,size_t osize,size_t nsize)
16: {
1.2 noro 17: return (void *)Risa_GC_realloc(p,nsize);
1.1 noro 18: }
19:
20: void gc_free(void *p,size_t size)
21: {
1.2 noro 22: Risa_GC_free(p);
1.1 noro 23: }
24:
25: void init_gmpq()
26: {
1.4 noro 27: mp_set_memory_functions(Risa_GC_malloc,gc_realloc,gc_free);
1.1 noro 28:
29: mpz_init(ONEMPZ); mpz_set_ui(ONEMPZ,1); MPZTOGZ(ONEMPZ,ONEGZ);
30: }
31:
32: GZ utogz(unsigned int u)
33: {
34: mpz_t z;
35: GZ r;
36:
37: if ( !u ) return 0;
38: mpz_init(z); mpz_set_ui(z,u); MPZTOGZ(z,r); return r;
39: }
40:
41: GZ stogz(int s)
42: {
43: mpz_t z;
44: GZ r;
45:
46: if ( !s ) return 0;
47: mpz_init(z); mpz_set_si(z,s); MPZTOGZ(z,r); return r;
48: }
49:
50: GQ mpqtogzq(mpq_t a)
51: {
52: GZ z;
53: GQ q;
54:
55: if ( INTMPQ(a) ) {
56: MPZTOGZ(mpq_numref(a),z); return (GQ)z;
57: } else {
58: MPQTOGQ(a,q); return q;
59: }
60: }
61:
62: GZ ztogz(Q a)
63: {
64: mpz_t z;
65: mpq_t b;
66: N nm;
67: GZ s;
68:
69: if ( !a ) return 0;
70: nm = NM(a);
71: mpz_init(z);
72: mpz_import(z,PL(nm),-1,sizeof(BD(nm)[0]),0,0,BD(nm));
73: if ( SGN(a)<0 ) mpz_neg(z,z);
74: MPZTOGZ(z,s);
75: return s;
76: }
77:
78: Q gztoz(GZ a)
79: {
80: N nm;
81: Q q;
82: int sgn;
83: size_t len;
84:
85: if ( !a ) return 0;
86: len = WORDSIZE_IN_N(BDY((GZ)a)); nm = NALLOC(len);
87: mpz_export(BD(nm),&len,-1,sizeof(int),0,0,BDY((GZ)a));
88: PL(nm) = len;
89: sgn = mpz_sgn(BDY((GZ)a)); NTOQ(nm,sgn,q);
90: return q;
91: }
92:
1.5 noro 93: void dupgz(GZ a,GZ *b)
94: {
95: mpz_t t;
96:
97: if ( !a ) *b = a;
98: else {
99: mpz_init(t); mpz_set(t,BDY(a)); MPZTOGZ(t,*b);
100: }
101: }
102:
1.1 noro 103: int n_bits_gz(GZ a)
104: {
105: return a ? mpz_sizeinbase(BDY(a),2) : 0;
106: }
107:
108: GQ qtogq(Q a)
109: {
110: mpz_t z;
111: mpq_t b;
112: N nm,dn;
113: GZ s;
114: GQ r;
115:
116: if ( !a ) return 0;
117: if ( INT(a) ) {
118: nm = NM(a);
119: mpz_init(z);
120: mpz_import(z,PL(nm),-1,sizeof(BD(nm)[0]),0,0,BD(nm));
121: if ( SGN(a)<0 ) mpz_neg(z,z);
122: MPZTOGZ(z,s);
123: return (GQ)s;
124: } else {
125: nm = NM(a); dn = DN(a);
126: mpq_init(b);
127: mpz_import(mpq_numref(b),PL(nm),-1,sizeof(BD(nm)[0]),0,0,BD(nm));
128: mpz_import(mpq_denref(b),PL(dn),-1,sizeof(BD(dn)[0]),0,0,BD(dn));
129: if ( SGN(a)<0 ) mpq_neg(b,b);
130: MPQTOGQ(b,r);
131: return r;
132: }
133: }
134:
135: Q gqtoq(GQ a)
136: {
137: N nm,dn;
138: Q q;
139: int sgn;
140: size_t len;
141:
142: if ( !a ) return 0;
143: if ( NID(a) == N_GZ ) {
144: len = WORDSIZE_IN_N(BDY((GZ)a)); nm = NALLOC(len);
145: mpz_export(BD(nm),&len,-1,sizeof(int),0,0,BDY((GZ)a));
146: PL(nm) = len;
147: sgn = mpz_sgn(BDY((GZ)a)); NTOQ(nm,sgn,q);
148: } else {
149: len = WORDSIZE_IN_N(mpq_numref(BDY(a))); nm = NALLOC(len);
150: mpz_export(BD(nm),&len,-1,sizeof(int),0,0,mpq_numref(BDY(a)));
151: PL(nm) = len;
152: len = WORDSIZE_IN_N(mpq_denref(BDY(a))); dn = NALLOC(len);
153: mpz_export(BD(dn),&len,-1,sizeof(int),0,0,mpq_denref(BDY(a)));
154: PL(dn) = len;
155: sgn = mpz_sgn(mpq_numref(BDY(a))); NDTOQ(nm,dn,sgn,q);
156: }
157: return q;
158: }
159:
160: P ptogp(P a)
161: {
162: DCP dc,dcr,dcr0;
163: P b;
164:
165: if ( !a ) return 0;
166: if ( NUM(a) ) return (P)qtogq((Q)a);
167: for ( dc = DC(a), dcr0 = 0; dc; dc = NEXT(dc) ) {
168: NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc); COEF(dcr) = (P)ptogp(COEF(dc));
169: }
170: NEXT(dcr) = 0; MKP(VR(a),dcr0,b);
171: return b;
172: }
173:
174: P gptop(P a)
175: {
176: DCP dc,dcr,dcr0;
177: P b;
178:
179: if ( !a ) return 0;
180: if ( NUM(a) ) b = (P)gqtoq((GQ)a);
181: else {
182: for ( dc = DC(a), dcr0 = 0; dc; dc = NEXT(dc) ) {
183: NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc);
184: COEF(dcr) = (P)gptop(COEF(dc));
185: }
186: NEXT(dcr) = 0; MKP(VR(a),dcr0,b);
187: }
188: return b;
189: }
190:
191: void addgz(GZ n1,GZ n2,GZ *nr)
192: {
193: mpz_t t;
194: int s1,s2;
195:
196: if ( !n1 ) *nr = n2;
197: else if ( !n2 ) *nr = n1;
198: else {
199: mpz_init(t); mpz_add(t,BDY(n1),BDY(n2)); MPZTOGZ(t,*nr);
200: }
201: }
202:
203: void subgz(GZ n1,GZ n2,GZ *nr)
204: {
205: mpz_t t;
206:
207: if ( !n1 )
208: if ( !n2 )
209: *nr = 0;
210: else {
211: t[0] = BDY(n2)[0]; mpz_neg(t,t); MPZTOGZ(t,*nr);
212: }
213: else if ( !n2 )
214: *nr = n1;
215: else if ( n1 == n2 )
216: *nr = 0;
217: else {
218: mpz_init(t); mpz_sub(t,BDY(n1),BDY(n2)); MPZTOGZ(t,*nr);
219: }
220: }
221:
222: void mulgz(GZ n1,GZ n2,GZ *nr)
223: {
224: mpz_t t;
225:
226: if ( !n1 || !n2 ) *nr = 0;
1.5 noro 227: #if 1
1.1 noro 228: else if ( UNIGZ(n1) ) *nr = n2;
229: else if ( UNIGZ(n2) ) *nr = n1;
230: else if ( MUNIGZ(n1) ) chsgngz(n2,nr);
231: else if ( MUNIGZ(n2) ) chsgngz(n1,nr);
1.5 noro 232: #endif
1.1 noro 233: else {
234: mpz_init(t); mpz_mul(t,BDY(n1),BDY(n2)); MPZTOGZ(t,*nr);
235: }
236: }
237:
1.5 noro 238: /* nr += n1*n2 */
239:
240: void muladdtogz(GZ n1,GZ n2,GZ *nr)
241: {
242: GZ t;
243:
244: if ( n1 && n2 ) {
245: if ( !(*nr) ) {
246: NEWGZ(t); mpz_init(BDY(t)); *nr = t;
247: }
248: mpz_addmul(BDY(*nr),BDY(n1),BDY(n2));
249: }
250: }
251:
1.3 noro 252: void mul1gz(GZ n1,int n2,GZ *nr)
253: {
254: mpz_t t;
255:
256: if ( !n1 || !n2 ) *nr = 0;
257: else {
258: mpz_init(t); mpz_mul_ui(t,BDY(n1),(long)n2); MPZTOGZ(t,*nr);
259: }
260: }
261:
1.1 noro 262: void divgz(GZ n1,GZ n2,GZ *nq)
263: {
264: mpz_t t;
265: mpq_t a, b, q;
266:
267: if ( !n2 ) {
268: error("division by 0");
269: *nq = 0;
270: } else if ( !n1 )
271: *nq = 0;
272: else if ( n1 == n2 ) {
273: mpz_init(t); mpz_set_ui(t,1); MPZTOGZ(t,*nq);
274: } else {
275: MPZTOMPQ(BDY(n1),a); MPZTOMPQ(BDY(n2),b);
276: mpq_init(q); mpq_div(q,a,b); *nq = (GZ)mpqtogzq(q);
277: }
278: }
279:
1.5 noro 280: void remgz(GZ n1,GZ n2,GZ *nr)
281: {
282: mpz_t r;
283:
284: if ( !n2 ) {
285: error("division by 0");
286: *nr = 0;
287: } else if ( !n1 || n1 == n2 )
288: *nr = 0;
289: else {
290: mpz_init(r);
291: mpz_mod(r,BDY(n1),BDY(n2));
292: if ( !mpz_sgn(r) ) *nr = 0;
293: else MPZTOGZ(r,*nr);
294: }
295: }
296:
1.1 noro 297: void divqrgz(GZ n1,GZ n2,GZ *nq,GZ *nr)
298: {
299: mpz_t t, a, b, q, r;
300:
301: if ( !n2 ) {
302: error("division by 0");
303: *nq = 0; *nr = 0;
304: } else if ( !n1 ) {
305: *nq = 0; *nr = 0;
306: } else if ( n1 == n2 ) {
307: mpz_init(t); mpz_set_ui(t,1); MPZTOGZ(t,*nq); *nr = 0;
308: } else {
309: mpz_init(q); mpz_init(r);
310: mpz_fdiv_qr(q,r,BDY(n1),BDY(n2));
311: if ( !mpz_sgn(q) ) *nq = 0;
312: else MPZTOGZ(q,*nq);
313: if ( !mpz_sgn(r) ) *nr = 0;
314: else MPZTOGZ(r,*nr);
315: }
316: }
317:
318: void divsgz(GZ n1,GZ n2,GZ *nq)
319: {
320: mpz_t t;
321: mpq_t a, b, q;
322:
323: if ( !n2 ) {
324: error("division by 0");
325: *nq = 0;
326: } else if ( !n1 )
327: *nq = 0;
328: else if ( n1 == n2 ) {
329: mpz_init(t); mpz_set_ui(t,1); MPZTOGZ(t,*nq);
330: } else {
331: mpz_init(t); mpz_divexact(t,BDY(n1),BDY(n2)); MPZTOGZ(t,*nq);
332: }
333: }
334:
335: void chsgngz(GZ n,GZ *nr)
336: {
337: mpz_t t;
338:
339: if ( !n )
340: *nr = 0;
341: else {
342: t[0] = BDY(n)[0]; mpz_neg(t,t); MPZTOGZ(t,*nr);
343: }
344: }
345:
346: void pwrgz(GZ n1,Q n,GZ *nr)
347: {
348: mpq_t t,q;
349: mpz_t z;
350: GQ p,r;
351:
352: if ( !n || UNIGZ(n1) ) *nr = ONEGZ;
353: else if ( !n1 ) *nr = 0;
354: else if ( !INT(n) ) {
355: error("can't calculate fractional power."); *nr = 0;
356: } else if ( MUNIGZ(n1) ) *nr = BD(NM(n))[0]%2 ? n1 : ONEGZ;
357: else if ( PL(NM(n)) > 1 ) {
358: error("exponent too big."); *nr = 0;
359: } else if ( NID(n1)==N_GZ && SGN(n)>0 ) {
360: mpz_init(z); mpz_pow_ui(z,BDY(n1),QTOS(n)); MPZTOGZ(z,*nr);
361: } else {
362: MPZTOMPQ(BDY(n1),q); MPQTOGQ(q,r);
363: pwrgq(r,n,&p); *nr = (GZ)p;
364: }
365: }
366:
367: int cmpgz(GZ q1,GZ q2)
368: {
369: int sgn;
370:
371: if ( !q1 )
372: if ( !q2 )
373: return 0;
374: else
375: return -mpz_sgn(BDY(q2));
376: else if ( !q2 )
377: return mpz_sgn(BDY(q1));
378: else if ( (sgn = mpz_sgn(BDY(q1))) != mpz_sgn(BDY(q2)) )
379: return sgn;
380: else {
381: sgn = mpz_cmp(BDY(q1),BDY(q2));
382: if ( sgn > 0 ) return 1;
383: else if ( sgn < 0 ) return -1;
384: else return 0;
385: }
386: }
387:
388: void gcdgz(GZ n1,GZ n2,GZ *nq)
389: {
390: mpz_t t;
391:
392: if ( !n1 ) *nq = n2;
393: else if ( !n2 ) *nq = n1;
394: else {
395: mpz_init(t); mpz_gcd(t,BDY(n1),BDY(n2));
396: MPZTOGZ(t,*nq);
397: }
398: }
399:
1.5 noro 400: void invgz(GZ n1,GZ *nq)
401: {
402: mpz_t t;
403:
404: mpz_init(t); mpz_invert(t,BDY(n1),BDY(current_mod_lf));
405: MPZTOGZ(t,*nq);
406: }
407:
1.1 noro 408: void lcmgz(GZ n1,GZ n2,GZ *nq)
409: {
410: GZ g,t;
411:
412: if ( !n1 || !n2 ) *nq = 0;
413: else {
414: gcdgz(n1,n2,&g); divsgz(n1,g,&t);
415: mulgz(n2,t,nq);
416: }
417: }
418:
419: void gcdvgz(VECT v,GZ *q)
420: {
421: int n,i;
422: GZ *b;
423: GZ g,g1;
424:
425: n = v->len;
426: b = (GZ *)v->body;
427: g = b[0];
428: for ( i = 1; i < n; i++ ) {
429: gcdgz(g,b[i],&g1); g = g1;
430: }
431: *q = g;
432: }
433:
434: void gcdvgz_estimate(VECT v,GZ *q)
435: {
436: int n,m,i;
437: GZ s,t,u;
438: GZ *b;
439:
440: n = v->len;
441: b = (GZ *)v->body;
442: if ( n == 1 ) {
443: if ( mpz_sgn(BDY(b[0]))<0 ) chsgngz(b[0],q);
444: else *q = b[0];
445: }
446: m = n/2;
447: for ( i = 0, s = 0; i < m; i++ ) {
448: if ( b[i] && mpz_sgn(BDY(b[i]))<0 ) subgz(s,b[i],&u);
449: else addgz(s,b[i],&u);
450: s = u;
451: }
452: for ( i = 0, t = 0; i < n; i++ ) {
453: if ( b[i] && mpz_sgn(BDY(b[i]))<0 ) subgz(t,b[i],&u);
454: else addgz(t,b[i],&u);
455: t = u;
456: }
457: gcdgz(s,t,q);
458: }
459:
460: void addgq(GQ n1,GQ n2,GQ *nr)
461: {
462: mpq_t q1,q2,t;
463:
464: if ( !n1 ) *nr = n2;
465: else if ( !n2 ) *nr = n1;
466: else {
467: if ( NID(n1) == N_GZ ) MPZTOMPQ(BDY((GZ)n1),q1);
468: else q1[0] = BDY(n1)[0];
469: if ( NID(n2) == N_GZ ) MPZTOMPQ(BDY((GZ)n2),q2);
470: else q2[0] = BDY(n2)[0];
471: mpq_init(t); mpq_add(t,q1,q2); *nr = mpqtogzq(t);
472: }
473: }
474:
475: void subgq(GQ n1,GQ n2,GQ *nr)
476: {
477: mpq_t q1,q2,t;
478:
479: if ( !n1 )
480: if ( !n2 ) *nr = 0;
481: else {
482: if ( NID(n1) == N_GZ ) chsgngz((GZ)n1,(GZ *)nr);
483: else {
484: mpq_init(t); mpq_neg(t,BDY(n2)); MPQTOGQ(t,*nr);
485: }
486: }
487: else if ( !n2 ) *nr = n1;
488: else if ( n1 == n2 ) *nr = 0;
489: else {
490: if ( NID(n1) == N_GZ ) MPZTOMPQ(BDY((GZ)n1),q1);
491: else q1[0] = BDY(n1)[0];
492: if ( NID(n2) == N_GZ ) MPZTOMPQ(BDY((GZ)n2),q2);
493: else q2[0] = BDY(n2)[0];
494: mpq_init(t); mpq_sub(t,q1,q2); *nr = mpqtogzq(t);
495: }
496: }
497:
498: void mulgq(GQ n1,GQ n2,GQ *nr)
499: {
500: mpq_t t,q1,q2;
501:
502: if ( !n1 || !n2 ) *nr = 0;
503: else {
504: if ( NID(n1) == N_GZ ) MPZTOMPQ(BDY((GZ)n1),q1);
505: else q1[0] = BDY(n1)[0];
506: if ( NID(n2) == N_GZ ) MPZTOMPQ(BDY((GZ)n2),q2);
507: else q2[0] = BDY(n2)[0];
508: mpq_init(t); mpq_mul(t,q1,q2); *nr = mpqtogzq(t);
509: }
510: }
511:
512: void divgq(GQ n1,GQ n2,GQ *nq)
513: {
514: mpq_t t,q1,q2;
515:
516: if ( !n2 ) {
517: error("division by 0");
518: *nq = 0;
519: return;
520: } else if ( !n1 ) *nq = 0;
521: else if ( n1 == n2 ) *nq = (GQ)ONEGZ;
522: else {
523: if ( NID(n1) == N_GZ ) MPZTOMPQ(BDY((GZ)n1),q1);
524: else q1[0] = BDY(n1)[0];
525: if ( NID(n2) == N_GZ ) MPZTOMPQ(BDY((GZ)n2),q2);
526: else q2[0] = BDY(n2)[0];
527: mpq_init(t); mpq_div(t,q1,q2); *nq = mpqtogzq(t);
528: }
529: }
530:
531: void chsgngq(GQ n,GQ *nr)
532: {
533: mpq_t t;
534:
535: if ( !n ) *nr = 0;
536: else if ( NID(n) == N_GZ ) chsgngz((GZ)n,(GZ *)nr);
537: else {
538: mpq_init(t); mpq_neg(t,BDY(n)); MPQTOGQ(t,*nr);
539: }
540: }
541:
542: void pwrgq(GQ n1,Q n,GQ *nr)
543: {
544: int e;
545: mpz_t nm,dn;
546: mpq_t t;
547:
548: if ( !n || UNIGZ((GZ)n1) || UNIGQ(n1) ) *nr = (GQ)ONEGZ;
549: else if ( !n1 ) *nr = 0;
550: else if ( !INT(n) ) {
551: error("can't calculate fractional power."); *nr = 0;
552: } else if ( PL(NM(n)) > 1 ) {
553: error("exponent too big."); *nr = 0;
554: } else {
555: e = QTOS(n);
556: if ( e < 0 ) {
557: e = -e;
558: if ( NID(n1)==N_GZ ) {
559: nm[0] = ONEMPZ[0];
560: dn[0] = BDY((GZ)n1)[0];
561: } else {
562: nm[0] = mpq_denref(BDY(n1))[0]; dn[0] = mpq_numref(BDY(n1))[0];
563: }
564: } else {
565: if ( NID(n1)==N_GZ ) {
566: nm[0] = BDY((GZ)n1)[0]; dn[0] = ONEMPZ[0];
567: } else {
568: nm[0] = mpq_numref(BDY(n1))[0]; dn[0] = mpq_denref(BDY(n1))[0];
569: }
570: }
571: mpq_init(t);
572: mpz_pow_ui(mpq_numref(t),nm,e); mpz_pow_ui(mpq_denref(t),dn,e);
573: *nr = mpqtogzq(t);
574: }
575: }
576:
577: int cmpgq(GQ n1,GQ n2)
578: {
579: mpq_t q1,q2;
580: int sgn;
581:
582: if ( !n1 )
583: if ( !n2 ) return 0;
584: else return (NID(n2)==N_GZ) ? -mpz_sgn(BDY((GZ)n2)) : -mpq_sgn(BDY(n2));
585: if ( !n2 ) return (NID(n1)==N_GZ) ? mpz_sgn(BDY((GZ)n1)) : mpq_sgn(BDY(n1));
586: else if ( (sgn = mpq_sgn(BDY(n1))) != mpq_sgn(BDY(n2)) ) return sgn;
587: else {
588: if ( NID(n1) == N_GZ ) MPZTOMPQ(BDY((GZ)n1),q1);
589: else q1[0] = BDY(n1)[0];
590: if ( NID(n2) == N_GZ ) MPZTOMPQ(BDY((GZ)n2),q2);
591: else q2[0] = BDY(n2)[0];
592: sgn = mpq_cmp(q1,q2);
593: if ( sgn > 0 ) return 1;
594: else if ( sgn < 0 ) return -1;
595: else return 0;
596: }
597: }
598:
599: void mkgwc(int k,int l,GZ *t)
600: {
601: mpz_t a,b,q,nm,z,u;
602: int i,n;
603:
604: n = MIN(k,l);
605: mpz_init_set_ui(z,1);
606: mpz_init(u); mpz_set(u,z); MPZTOGZ(u,t[0]);
607: mpz_init(a); mpz_init(b); mpz_init(nm);
608: for ( i = 1; i <= n; i++ ) {
609: mpz_set_ui(a,k-i+1); mpz_set_ui(b,l-i+1); mpz_mul(nm,a,b);
610: mpz_mul(z,BDY(t[i-1]),nm); mpz_fdiv_q_ui(z,z,i);
611: mpz_init(u); mpz_set(u,z); MPZTOGZ(u,t[i]);
612: }
613: }
614:
615: void gz_lgp(P p,GZ *g,GZ *l);
616:
617: void gz_ptozp(P p,int sgn,GQ *c,P *pr)
618: {
619: GZ nm,dn;
620:
621: if ( !p ) {
622: *c = 0; *pr = 0;
623: } else {
624: gz_lgp(p,&nm,&dn);
625: divgz(nm,dn,(GZ *)c);
626: divsp(CO,p,(P)*c,pr);
627: }
628: }
629:
630: void gz_lgp(P p,GZ *g,GZ *l)
631: {
632: DCP dc;
633: GZ g1,g2,l1,l2,l3,l4;
634:
635: if ( NUM(p) ) {
636: if ( NID((GZ)p)==N_GZ ) {
637: MPZTOGZ(BDY((GZ)p),*g);
638: *l = ONEGZ;
639: } else {
640: MPZTOGZ(mpq_numref(BDY((GQ)p)),*g);
641: MPZTOGZ(mpq_denref(BDY((GQ)p)),*l);
642: }
643: } else {
644: dc = DC(p); gz_lgp(COEF(dc),g,l);
645: for ( dc = NEXT(dc); dc; dc = NEXT(dc) ) {
646: gz_lgp(COEF(dc),&g1,&l1); gcdgz(*g,g1,&g2); *g = g2;
647: gcdgz(*l,l1,&l2); mulgz(*l,l1,&l3); divgz(l3,l2,l);
648: }
649: }
650: }
651:
652: void gz_qltozl(GQ *w,int n,GZ *dvr)
653: {
654: GZ nm,dn;
655: GZ g,g1,l1,l2,l3;
656: GQ c;
657: int i;
658: struct oVECT v;
659:
660: for ( i = 0; i < n; i++ )
661: if ( w[i] && NID(w[i])==N_GQ )
662: break;
663: if ( i == n ) {
664: v.id = O_VECT; v.len = n; v.body = (pointer *)w;
665: gcdvgz(&v,dvr); return;
666: }
667: for ( i = 0; !w[i]; i++ );
668: c = w[i];
669: if ( NID(c)==N_GQ ) {
670: MPZTOGZ(mpq_numref(BDY(c)),nm); MPZTOGZ(mpq_denref(BDY(c)),dn);
671: } else {
672: MPZTOGZ(BDY((GZ)c),nm); dn = ONEGZ;
673: }
674: for ( i++; i < n; i++ ) {
675: c = w[i];
676: if ( !c ) continue;
677: if ( NID(c)==N_GQ ) {
678: MPZTOGZ(mpq_numref(BDY(c)),g1); MPZTOGZ(mpq_denref(BDY(c)),l1);
679: } else {
680: MPZTOGZ(BDY((GZ)c),g1); l1 = ONEGZ;
681: }
682: gcdgz(nm,g1,&g); nm = g;
683: gcdgz(dn,l1,&l2); mulgz(dn,l1,&l3); divgz(l3,l2,&dn);
684: }
685: divgz(nm,dn,dvr);
686: }
687:
688: int gz_bits(GQ q)
689: {
690: if ( !q ) return 0;
691: else if ( NID(q)==N_Q )
692: return n_bits(NM((Q)q))+(INT((Q)q)?0:n_bits(DN((Q)q)));
693: else if ( NID(q)==N_GZ ) return mpz_sizeinbase(BDY((GZ)q),2);
694: else
695: return mpz_sizeinbase(mpq_numref(BDY(q)),2)
696: + mpz_sizeinbase(mpq_denref(BDY(q)),2);
697: }
698:
699: int gzp_mag(P p)
700: {
701: int s;
702: DCP dc;
703:
704: if ( !p ) return 0;
705: else if ( OID(p) == O_N ) return gz_bits((GQ)p);
706: else {
707: for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) s += gzp_mag(COEF(dc));
708: return s;
709: }
710: }
711:
712: void makesubstgz(VL v,NODE *s)
713: {
714: NODE r,r0;
715: GZ q;
716: unsigned int n;
717:
718: for ( r0 = 0; v; v = NEXT(v) ) {
719: NEXTNODE(r0,r); BDY(r) = (pointer)v->v;
720: #if defined(_PA_RISC1_1)
721: n = mrand48()&BMASK; q = utogz(n);
722: #else
723: n = random(); q = utogz(n);
724: #endif
725: NEXTNODE(r0,r); BDY(r) = (pointer)q;
726: }
727: if ( r0 ) NEXT(r) = 0;
728: *s = r0;
729: }
730:
731: unsigned int remgq(GQ a,unsigned int mod)
732: {
733: unsigned int c,nm,dn;
734: mpz_t r;
735:
736: if ( !a ) return 0;
737: else if ( NID(a)==N_GZ ) {
738: mpz_init(r);
739: c = mpz_fdiv_r_ui(r,BDY((GZ)a),mod);
740: } else {
741: mpz_init(r);
742: nm = mpz_fdiv_r_ui(r,mpq_numref(BDY(a)),mod);
743: dn = mpz_fdiv_r_ui(r,mpq_denref(BDY(a)),mod);
744: dn = invm(dn,mod);
745: DMAR(nm,dn,0,mod,c);
746: }
747: return c;
748: }
749:
750: extern int DP_Print;
751:
752: #define GZ_F4_INTRAT_PERIOD 8
753:
754: int gz_generic_gauss_elim(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp)
755: {
756: int **wmat;
757: GZ **bmat,**tmat,*bmi,*tmi;
758: GZ q,m1,m2,m3,s,u;
759: int *wmi,*colstat,*wcolstat,*rind,*cind;
760: int row,col,ind,md,i,j,k,l,t,t1,rank,rank0,inv;
761: MAT r,crmat;
762: int ret;
763:
764: bmat = (GZ **)mat->body;
765: row = mat->row; col = mat->col;
766: wmat = (int **)almat(row,col);
767: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
768: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
769: for ( ind = 0; ; ind++ ) {
770: if ( DP_Print ) {
771: fprintf(asir_out,"."); fflush(asir_out);
772: }
773: md = get_lprime(ind);
774: for ( i = 0; i < row; i++ )
775: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
776: wmi[j] = remgq((GQ)bmi[j],md);
777: rank = generic_gauss_elim_mod(wmat,row,col,md,wcolstat);
778: if ( !ind ) {
779: RESET:
780: m1 = utogz(md);
781: rank0 = rank;
782: bcopy(wcolstat,colstat,col*sizeof(int));
783: MKMAT(crmat,rank,col-rank);
784: MKMAT(r,rank,col-rank); *nm = r;
785: tmat = (GZ **)crmat->body;
786: for ( i = 0; i < rank; i++ )
787: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
788: if ( !colstat[j] ) tmi[k++] = utogz(wmi[j]);
789: } else {
790: if ( rank < rank0 ) {
791: if ( DP_Print ) {
792: fprintf(asir_out,"lower rank matrix; continuing...\n");
793: fflush(asir_out);
794: }
795: continue;
796: } else if ( rank > rank0 ) {
797: if ( DP_Print ) {
798: fprintf(asir_out,"higher rank matrix; resetting...\n");
799: fflush(asir_out);
800: }
801: goto RESET;
802: } else {
803: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
804: if ( j < col ) {
805: if ( DP_Print ) {
806: fprintf(asir_out,"inconsitent colstat; resetting...\n");
807: fflush(asir_out);
808: }
809: goto RESET;
810: }
811: }
812:
813: inv = invm(remgq((GQ)m1,md),md);
814: m2 = utogz(md); mulgz(m1,m2,&m3);
815: for ( i = 0; i < rank; i++ )
816: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
817: if ( !colstat[j] ) {
818: if ( tmi[k] ) {
819: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
820: t = remgq((GQ)tmi[k],md);
821: if ( wmi[j] >= t ) t = wmi[j]-t;
822: else t = md-(t-wmi[j]);
823: DMAR(t,inv,0,md,t1)
824: u = utogz(t1); mulgz(m1,u,&s);
825: addgz(tmi[k],s,&u); tmi[k] = u;
826: } else if ( wmi[j] ) {
827: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
828: DMAR(wmi[j],inv,0,md,t)
829: u = utogz(t); mulgz(m1,u,&s); tmi[k] = s;
830: }
831: k++;
832: }
833: m1 = m3;
834: if ( ind % GZ_F4_INTRAT_PERIOD )
835: ret = 0;
836: else
837: ret = gz_intmtoratm(crmat,m1,*nm,dn);
838: if ( ret ) {
839: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
840: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
841: for ( j = k = l = 0; j < col; j++ )
842: if ( colstat[j] ) rind[k++] = j;
843: else cind[l++] = j;
844: if ( gz_gensolve_check(mat,*nm,*dn,rind,cind) )
845: return rank;
846: }
847: }
848: }
849: }
850:
851: int gz_generic_gauss_elim2(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp)
852: {
853:
854: MAT full;
855: GZ **bmat,**b;
856: GZ *bmi;
857: GZ dn0;
858: int row,col,md,i,j,rank,ret;
859: int **wmat;
860: int *wmi;
861: int *colstat,*rowstat;
862:
863: bmat = (GZ **)mat->body;
864: row = mat->row; col = mat->col;
865: wmat = (int **)almat(row,col);
866: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
867: rowstat = (int *)MALLOC_ATOMIC(row*sizeof(int));
868: /* XXX */
869: md = get_lprime(0);
870: for ( i = 0; i < row; i++ )
871: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
872: wmi[j] = remgq((GQ)bmi[j],md);
873: rank = generic_gauss_elim_mod2(wmat,row,col,md,colstat,rowstat);
874: b = (GZ **)MALLOC(rank*sizeof(GZ));
875: for ( i = 0; i < rank; i++ ) b[i] = bmat[rowstat[i]];
876: NEWMAT(full); full->row = rank; full->col = col; full->body = (pointer **)b;
877: ret = gz_generic_gauss_elim_full(full,nm,dn,rindp,cindp);
878: if ( !ret ) {
879: rank = gz_generic_gauss_elim(mat,nm,&dn0,rindp,cindp);
880: for ( i = 0; i < rank; i++ ) dn[i] = dn0;
881: }
882: return rank;
883: }
884:
885: int gz_generic_gauss_elim_full(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp)
886: {
887: int **wmat;
888: int *stat;
889: GZ **bmat,**tmat,*bmi,*tmi,*ri;
890: GZ q,m1,m2,m3,s,u;
891: int *wmi,*colstat,*wcolstat,*rind,*cind;
892: int row,col,ind,md,i,j,k,l,t,t1,rank,rank0,inv,h;
893: MAT r,crmat;
894: int ret,initialized,done;
895:
896: initialized = 0;
897: bmat = (GZ **)mat->body;
898: row = mat->row; col = mat->col;
899: wmat = (int **)almat(row,col);
900: stat = (int *)MALLOC_ATOMIC(row*sizeof(int));
901: for ( i = 0; i < row; i++ ) stat[i] = 0;
902: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
903: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
904: for ( ind = 0; ; ind++ ) {
905: if ( DP_Print ) {
906: fprintf(asir_out,"."); fflush(asir_out);
907: }
908: md = get_lprime(ind);
909: for ( i = 0; i < row; i++ )
910: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
911: wmi[j] = remgq((GQ)bmi[j],md);
912: rank = generic_gauss_elim_mod(wmat,row,col,md,wcolstat);
913: if ( rank < row ) continue;
914: if ( !initialized ) {
915: m1 = utogz(md);
916: bcopy(wcolstat,colstat,col*sizeof(int));
917: MKMAT(crmat,row,col-row);
918: MKMAT(r,row,col-row); *nm = r;
919: tmat = (GZ **)crmat->body;
920: for ( i = 0; i < row; i++ )
921: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
922: if ( !colstat[j] ) tmi[k++] = utogz(wmi[j]);
923: initialized = 1;
924: } else {
925: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
926: if ( j < col ) continue;
927:
928: inv = invm(remgq((GQ)m1,md),md);
929: m2 = utogz(md); mulgz(m1,m2,&m3);
930: for ( i = 0; i < row; i++ )
931: switch ( stat[i] ) {
932: case 1:
933: /* consistency check */
934: ri = (GZ *)BDY(r)[i]; wmi = wmat[i];
935: for ( j = 0; j < col; j++ ) if ( colstat[j] ) break;
936: h = md-remgq((GQ)dn[i],md);
937: for ( j++, k = 0; j < col; j++ )
938: if ( !colstat[j] ) {
939: t = remgq((GQ)ri[k],md);
940: DMAR(wmi[i],h,t,md,t1);
941: if ( t1 ) break;
942: }
943: if ( j == col ) { stat[i]++; break; }
944: else {
945: /* fall to the case 0 */
946: stat[i] = 0;
947: }
948: case 0:
949: tmi = tmat[i]; wmi = wmat[i];
950: for ( j = k = 0; j < col; j++ )
951: if ( !colstat[j] ) {
952: if ( tmi[k] ) {
953: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
954: t = remgq((GQ)tmi[k],md);
955: if ( wmi[j] >= t ) t = wmi[j]-t;
956: else t = md-(t-wmi[j]);
957: DMAR(t,inv,0,md,t1)
958: u = utogz(t1); mulgz(m1,u,&s);
959: addgz(tmi[k],s,&u); tmi[k] = u;
960: } else if ( wmi[j] ) {
961: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
962: DMAR(wmi[j],inv,0,md,t)
963: u = utogz(t); mulgz(m1,u,&s); tmi[k] = s;
964: }
965: k++;
966: }
967: break;
968: case 2: default:
969: break;
970: }
971: m1 = m3;
972: if ( ind % 4 )
973: ret = 0;
974: else
975: ret = gz_intmtoratm2(crmat,m1,*nm,dn,stat);
976: if ( ret ) {
977: *rindp = rind = (int *)MALLOC_ATOMIC(row*sizeof(int));
978: *cindp = cind = (int *)MALLOC_ATOMIC((col-row)*sizeof(int));
979: for ( j = k = l = 0; j < col; j++ )
980: if ( colstat[j] ) rind[k++] = j;
981: else cind[l++] = j;
982: return gz_gensolve_check2(mat,*nm,dn,rind,cind);
983: }
984: }
985: }
986: }
987:
988: int gz_generic_gauss_elim_direct(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp){
989: GZ **bmat,*s;
990: GZ u,v,w,x,d,t,y;
991: int row,col,i,j,k,l,m,rank;
992: int *colstat,*colpos,*cind;
993: MAT r,in;
994:
995: row = mat->row; col = mat->col;
996: MKMAT(in,row,col);
997: for ( i = 0; i < row; i++ )
998: for ( j = 0; j < col; j++ ) in->body[i][j] = mat->body[i][j];
999: bmat = (GZ **)in->body;
1000: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1001: *rindp = colpos = (int *)MALLOC_ATOMIC(row*sizeof(int));
1002: for ( j = 0, rank = 0, d = ONEGZ; j < col; j++ ) {
1003: for ( i = rank; i < row && !bmat[i][j]; i++ );
1004: if ( i == row ) { colstat[j] = 0; continue; }
1005: else { colstat[j] = 1; colpos[rank] = j; }
1006: if ( i != rank )
1007: for ( k = j; k < col; k++ ) {
1008: t = bmat[i][k]; bmat[i][k] = bmat[rank][k]; bmat[rank][k] = t;
1009: }
1010: for ( i = rank+1, v = bmat[rank][j]; i < row; i++ )
1011: for ( k = j, u = bmat[i][j]; k < col; k++ ) {
1012: mulgz(bmat[i][k],v,&w); mulgz(bmat[rank][k],u,&x);
1013: subgz(w,x,&y); divsgz(y,d,&bmat[i][k]);
1014: }
1015: d = v; rank++;
1016: }
1017: *dn = d;
1018: s = (GZ *)MALLOC(col*sizeof(GZ));
1019: for ( i = rank-1; i >= 0; i-- ) {
1020: for ( k = colpos[i]; k < col; k++ ) mulgz(bmat[i][k],d,&s[k]);
1021: for ( m = rank-1; m > i; m-- ) {
1022: for ( k = colpos[m], u = bmat[i][k]; k < col; k++ ) {
1023: mulgz(bmat[m][k],u,&w); subgz(s[k],w,&x); s[k] = x;
1024: }
1025: }
1026: for ( k = colpos[i], u = bmat[i][k]; k < col; k++ )
1027: divgz(s[k],u,&bmat[i][k]);
1028: }
1029: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
1030: MKMAT(r,rank,col-rank); *nm = r;
1031: for ( j = 0, k = 0; j < col; j++ )
1032: if ( !colstat[j] ) {
1033: cind[k] = j;
1034: for ( i = 0; i < rank; i++ ) r->body[i][k] = bmat[i][j];
1035: k++;
1036: }
1037: return rank;
1038: }
1039:
1040: int gz_intmtoratm(MAT mat,GZ md,MAT nm,GZ *dn)
1041: {
1042: GZ t,s,b,dn0,dn1,nm1,q,u,unm,udn,dmy;
1043: int i,j,k,l,row,col,sgn,ret;
1044: GZ **rmat,**tmat,*tmi,*nmk;
1045:
1046: if ( UNIGZ(md) )
1047: return 0;
1048: row = mat->row; col = mat->col;
1049: bshiftgz(md,1,&t);
1050: isqrtgz(t,&s);
1051: bshiftgz(s,64,&b);
1052: if ( !b ) b = ONEGZ;
1053: dn0 = ONEGZ;
1054: tmat = (GZ **)mat->body;
1055: rmat = (GZ **)nm->body;
1056: for ( i = 0; i < row; i++ )
1057: for ( j = 0, tmi = tmat[i]; j < col; j++ )
1058: if ( tmi[j] ) {
1059: mulgz(tmi[j],dn0,&s);
1060: divqrgz(s,md,&dmy,&u);
1061: ret = gz_inttorat(u,md,b,&sgn,&unm,&udn);
1062: if ( !ret ) return 0;
1063: else {
1064: if ( sgn < 0 ) chsgngz(unm,&nm1);
1065: else nm1 = unm;
1066: dn1 = udn;
1067: if ( !UNIGZ(dn1) ) {
1068: for ( k = 0; k < i; k++ )
1069: for ( l = 0, nmk = rmat[k]; l < col; l++ ) {
1070: mulgz(nmk[l],dn1,&q); nmk[l] = q;
1071: }
1072: for ( l = 0, nmk = rmat[i]; l < j; l++ ) {
1073: mulgz(nmk[l],dn1,&q); nmk[l] = q;
1074: }
1075: }
1076: rmat[i][j] = nm1;
1077: mulgz(dn0,dn1,&q); dn0 = q;
1078: }
1079: }
1080: *dn = dn0;
1081: return 1;
1082: }
1083:
1084: int gz_intmtoratm2(MAT mat,GZ md,MAT nm,GZ *dn,int *stat)
1085: {
1086: int row,col,i,j,ret;
1087: GZ dn0,dn1,t,s,b;
1088: GZ *w,*tmi;
1089: GZ **tmat;
1090:
1091: bshiftgz(md,1,&t);
1092: isqrtgz(t,&s);
1093: bshiftgz(s,64,&b);
1094: tmat = (GZ **)mat->body;
1095: if ( UNIGZ(md) ) return 0;
1096: row = mat->row; col = mat->col;
1097: dn0 = ONEGZ;
1098: for ( i = 0; i < row; i++ )
1099: if ( cmpgz(dn[i],dn0) > 0 ) dn0 = dn[i];
1100: w = (GZ *)MALLOC(col*sizeof(GZ));
1101: for ( i = 0; i < row; i++ )
1102: if ( stat[i] == 0 ) {
1103: for ( j = 0, tmi = tmat[i]; j < col; j++ )
1104: mulgz(tmi[j],dn0,&w[j]);
1105: ret = gz_intvtoratv(w,col,md,b,BDY(nm)[i],&dn[i]);
1106: if ( ret ) {
1107: stat[i] = 1;
1108: mulgz(dn0,dn[i],&t); dn[i] = t; dn0 = t;
1109: }
1110: }
1111: for ( i = 0; i < row; i++ ) if ( !stat[i] ) break;
1112: if ( i == row ) return 1;
1113: else return 0;
1114: }
1115:
1116: int gz_intvtoratv(GZ *v,int n,GZ md,GZ b,GZ *nm,GZ *dn)
1117: {
1118: GZ dn0,dn1,q,s,u,nm1,unm,udn,dmy;
1119: GZ *nmk;
1120: int j,l,col,ret,sgn;
1121:
1122: for ( j = 0; j < n; j++ ) nm[j] = 0;
1123: dn0 = ONEGZ;
1124: for ( j = 0; j < n; j++ ) {
1125: if ( !v[j] ) continue;
1126: mulgz(v[j],dn0,&s);
1127: divqrgz(s,md,&dmy,&u);
1128: ret = gz_inttorat(u,md,b,&sgn,&unm,&udn);
1129: if ( !ret ) return 0;
1130: if ( sgn < 0 ) chsgngz(unm,&nm1);
1131: else nm1 = unm;
1132: dn1 = udn;
1133: if ( !UNIGZ(dn1) )
1134: for ( l = 0; l < j; l++ ) {
1135: mulgz(nm[l],dn1,&q); nm[l] = q;
1136: }
1137: nm[j] = nm1;
1138: mulgz(dn0,dn1,&q); dn0 = q;
1139: }
1140: *dn = dn0;
1141: return 1;
1142: }
1143:
1144: /* assuming 0 < c < m */
1145:
1146: int gz_inttorat(GZ c,GZ m,GZ b,int *sgnp,GZ *nmp,GZ *dnp)
1147: {
1148: GZ qq,t,u1,v1,r1;
1149: GZ q,u2,v2,r2;
1150:
1151: u1 = 0; v1 = ONEGZ; u2 = m; v2 = c;
1152: while ( cmpgz(v2,b) >= 0 ) {
1153: divqrgz(u2,v2,&q,&r2); u2 = v2; v2 = r2;
1154: mulgz(q,v1,&t); subgz(u1,t,&r1); u1 = v1; v1 = r1;
1155: }
1156: if ( cmpgz(v1,b) >= 0 ) return 0;
1157: else {
1158: *nmp = v2;
1159: if ( mpz_sgn(BDY(v1))<0 ) {
1160: *sgnp = -1; chsgngz(v1,dnp);
1161: } else {
1162: *sgnp = 1; *dnp = v1;
1163: }
1164: return 1;
1165: }
1166: }
1167:
1168: extern int f4_nocheck;
1169:
1170: int gz_gensolve_check(MAT mat,MAT nm,GZ dn,int *rind,int *cind)
1171: {
1172: int row,col,rank,clen,i,j,k,l;
1173: GZ s,t;
1174: GZ *w;
1175: GZ *mati,*nmk;
1176:
1177: if ( f4_nocheck ) return 1;
1178: row = mat->row; col = mat->col; rank = nm->row; clen = nm->col;
1179: w = (GZ *)MALLOC(clen*sizeof(GZ));
1180: for ( i = 0; i < row; i++ ) {
1181: mati = (GZ *)mat->body[i];
1182: bzero(w,clen*sizeof(GZ));
1183: for ( k = 0; k < rank; k++ )
1184: for ( l = 0, nmk = (GZ *)nm->body[k]; l < clen; l++ ) {
1185: mulgz(mati[rind[k]],nmk[l],&t); addgz(w[l],t,&s); w[l] = s;
1186: }
1187: for ( j = 0; j < clen; j++ ) {
1188: mulgz(dn,mati[cind[j]],&t);
1189: if ( cmpgz(w[j],t) ) break;
1190: }
1191: if ( j != clen ) break;
1192: }
1193: if ( i != row ) return 0;
1194: else return 1;
1195: }
1196:
1197: int gz_gensolve_check2(MAT mat,MAT nm,GZ *dn,int *rind,int *cind)
1198: {
1199: int row,col,rank,clen,i,j,k,l;
1200: GZ s,t,u,d;
1201: GZ *w,*m;
1202: GZ *mati,*nmk;
1203:
1204: if ( f4_nocheck ) return 1;
1205: row = mat->row; col = mat->col; rank = nm->row; clen = nm->col;
1206: w = (GZ *)MALLOC(clen*sizeof(GZ));
1207: m = (GZ *)MALLOC(clen*sizeof(GZ));
1208: for ( d = dn[0], i = 1; i < rank; i++ ) {
1209: lcmgz(d,dn[i],&t); d = t;
1210: }
1211: for ( i = 0; i < rank; i++ ) divsgz(d,dn[i],&m[i]);
1212: for ( i = 0; i < row; i++ ) {
1213: mati = (GZ *)mat->body[i];
1214: bzero(w,clen*sizeof(GZ));
1215: for ( k = 0; k < rank; k++ ) {
1216: mulgz(mati[rind[k]],m[k],&u);
1217: for ( l = 0, nmk = (GZ *)nm->body[k]; l < clen; l++ ) {
1218: mulgz(u,nmk[l],&t); addgz(w[l],t,&s); w[l] = s;
1219: }
1220: }
1221: for ( j = 0; j < clen; j++ ) {
1222: mulgz(d,mati[cind[j]],&t);
1223: if ( cmpgz(w[j],t) ) break;
1224: }
1225: if ( j != clen ) break;
1226: }
1227: if ( i != row ) return 0;
1228: else return 1;
1229: }
1230:
1231: void isqrtgz(GZ a,GZ *r)
1232: {
1233: int k;
1234: GZ x,t,x2,xh,quo,rem;
1235: Q two;
1236:
1237: if ( !a ) *r = 0;
1238: else if ( UNIGZ(a) ) *r = ONEGZ;
1239: else {
1240: k = gz_bits((GQ)a); /* a <= 2^k-1 */
1241: bshiftgz(ONEGZ,-((k>>1)+(k&1)),&x); /* a <= x^2 */
1242: STOQ(2,two);
1243: while ( 1 ) {
1244: pwrgz(x,two,&t);
1245: if ( cmpgz(t,a) <= 0 ) {
1246: *r = x; return;
1247: } else {
1248: if ( mpz_tstbit(BDY(x),0) ) addgz(x,a,&t);
1249: else t = a;
1250: bshiftgz(x,-1,&x2); divqrgz(t,x2,&quo,&rem);
1251: bshiftgz(x,1,&xh); addgz(quo,xh,&x);
1252: }
1253: }
1254: }
1255: }
1256:
1257: void bshiftgz(GZ a,int n,GZ *r)
1258: {
1259: mpz_t t;
1260:
1261: if ( !a ) *r = 0;
1262: else if ( n == 0 ) *r = a;
1263: else if ( n < 0 ) {
1264: mpz_init(t); mpz_mul_2exp(t,BDY(a),-n); MPZTOGZ(t,*r);
1265: } else {
1266: mpz_init(t); mpz_fdiv_q_2exp(t,BDY(a),n);
1267: if ( !mpz_sgn(t) ) *r = 0;
1268: else MPZTOGZ(t,*r);
1269: }
1270: }
1271:
1.5 noro 1272: void addlf(GZ a,GZ b,GZ *c)
1273: {
1274: GZ t;
1275:
1276: addgz(a,b,c);
1277: if ( !lf_lazy ) {
1278: remgz(*c,current_mod_lf,&t); *c = t;
1279: }
1280: }
1281:
1282: void sublf(GZ a,GZ b,GZ *c)
1283: {
1284: GZ t;
1285:
1286: subgz(a,b,c);
1287: if ( !lf_lazy ) {
1288: remgz(*c,current_mod_lf,&t); *c = t;
1289: }
1290: }
1291:
1292: void mullf(GZ a,GZ b,GZ *c)
1293: {
1294: GZ t;
1295:
1296: mulgz(a,b,c);
1297: if ( !lf_lazy ) {
1298: remgz(*c,current_mod_lf,&t); *c = t;
1299: }
1300: }
1301:
1302: void divlf(GZ a,GZ b,GZ *c)
1303: {
1304: GZ t,inv;
1305:
1306: invgz(b,&inv);
1307: mulgz(a,inv,c);
1308: if ( !lf_lazy ) {
1309: remgz(*c,current_mod_lf,&t); *c = t;
1310: }
1311: }
1312:
1313: void chsgnlf(GZ a,GZ *c)
1314: {
1315: GZ t;
1316:
1317: chsgngz(a,c);
1318: if ( !lf_lazy ) {
1319: remgz(*c,current_mod_lf,&t); *c = t;
1320: }
1321: }
1322:
1323: void lmtolf(LM a,GZ *b)
1324: {
1325: Q q;
1326:
1327: NTOQ(BDY(a),1,q); *b = ztogz(q);
1328: }
1329:
1330: void setmod_lf(N p)
1331: {
1332: Q q;
1333:
1334: NTOQ(p,1,q); current_mod_lf = ztogz(q);
1.6 ! noro 1335: current_mod_lf_size = mpz_size(BDY(current_mod_lf))+1;
1.5 noro 1336: }
1337:
1338: void simplf_force(GZ a,GZ *b)
1339: {
1340: GZ t;
1341:
1342: remgz(a,current_mod_lf,&t); *b = t;
1343: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>