Annotation of OpenXM_contrib2/asir2000/engine/gmpq.c, Revision 1.10
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.10 ! 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.10 ! noro 22: Risa_GC_free(p);
1.1 noro 23: }
24:
25: void init_gmpq()
26: {
1.10 ! noro 27: mp_set_memory_functions(Risa_GC_malloc,gc_realloc,gc_free);
1.1 noro 28:
1.10 ! noro 29: mpz_init(ONEMPZ); mpz_set_ui(ONEMPZ,1); MPZTOGZ(ONEMPZ,ONEGZ);
1.1 noro 30: }
31:
32: GZ utogz(unsigned int u)
33: {
1.10 ! noro 34: mpz_t z;
! 35: GZ r;
1.1 noro 36:
1.10 ! noro 37: if ( !u ) return 0;
! 38: mpz_init(z); mpz_set_ui(z,u); MPZTOGZ(z,r); return r;
1.1 noro 39: }
40:
41: GZ stogz(int s)
42: {
1.10 ! noro 43: mpz_t z;
! 44: GZ r;
1.1 noro 45:
1.10 ! noro 46: if ( !s ) return 0;
! 47: mpz_init(z); mpz_set_si(z,s); MPZTOGZ(z,r); return r;
1.1 noro 48: }
49:
50: GQ mpqtogzq(mpq_t a)
51: {
1.10 ! noro 52: GZ z;
! 53: GQ q;
1.1 noro 54:
1.10 ! noro 55: if ( INTMPQ(a) ) {
! 56: MPZTOGZ(mpq_numref(a),z); return (GQ)z;
! 57: } else {
! 58: MPQTOGQ(a,q); return q;
! 59: }
1.1 noro 60: }
61:
62: GZ ztogz(Q a)
63: {
1.10 ! noro 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;
1.1 noro 76: }
77:
78: Q gztoz(GZ a)
79: {
1.10 ! noro 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;
1.1 noro 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: {
1.10 ! noro 105: return a ? mpz_sizeinbase(BDY(a),2) : 0;
1.1 noro 106: }
107:
108: GQ qtogq(Q a)
109: {
1.10 ! noro 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: }
1.1 noro 133: }
134:
135: Q gqtoq(GQ a)
136: {
1.10 ! noro 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;
1.1 noro 158: }
159:
160: P ptogp(P a)
161: {
1.10 ! noro 162: DCP dc,dcr,dcr0;
! 163: P b;
1.1 noro 164:
1.10 ! noro 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;
1.1 noro 172: }
173:
174: P gptop(P a)
175: {
1.10 ! noro 176: DCP dc,dcr,dcr0;
! 177: P b;
1.1 noro 178:
1.10 ! noro 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;
1.1 noro 189: }
190:
191: void addgz(GZ n1,GZ n2,GZ *nr)
192: {
1.10 ! noro 193: mpz_t t;
! 194: int s1,s2;
1.1 noro 195:
1.10 ! noro 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: }
1.1 noro 201: }
202:
203: void subgz(GZ n1,GZ n2,GZ *nr)
204: {
1.10 ! noro 205: mpz_t t;
1.1 noro 206:
1.10 ! noro 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: }
1.1 noro 220: }
221:
222: void mulgz(GZ n1,GZ n2,GZ *nr)
223: {
1.10 ! noro 224: mpz_t t;
1.1 noro 225:
1.10 ! noro 226: if ( !n1 || !n2 ) *nr = 0;
1.5 noro 227: #if 1
1.10 ! 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.10 ! noro 233: else {
! 234: mpz_init(t); mpz_mul(t,BDY(n1),BDY(n2)); MPZTOGZ(t,*nr);
! 235: }
1.1 noro 236: }
237:
1.5 noro 238: /* nr += n1*n2 */
239:
240: void muladdtogz(GZ n1,GZ n2,GZ *nr)
241: {
242: GZ t;
243:
1.10 ! noro 244: if ( n1 && n2 ) {
1.5 noro 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: {
1.10 ! noro 254: mpz_t t;
1.3 noro 255:
1.10 ! noro 256: if ( !n1 || !n2 ) *nr = 0;
! 257: else {
! 258: mpz_init(t); mpz_mul_ui(t,BDY(n1),(long)n2); MPZTOGZ(t,*nr);
! 259: }
1.3 noro 260: }
261:
1.1 noro 262: void divgz(GZ n1,GZ n2,GZ *nq)
263: {
1.10 ! noro 264: mpz_t t;
! 265: mpq_t a, b, q;
1.1 noro 266:
1.10 ! noro 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: }
1.1 noro 278: }
279:
1.5 noro 280: void remgz(GZ n1,GZ n2,GZ *nr)
281: {
1.10 ! noro 282: mpz_t r;
1.5 noro 283:
1.10 ! noro 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: }
1.5 noro 295: }
296:
1.1 noro 297: void divqrgz(GZ n1,GZ n2,GZ *nq,GZ *nr)
298: {
1.10 ! noro 299: mpz_t t, a, b, q, r;
1.1 noro 300:
1.10 ! noro 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: }
1.1 noro 316: }
317:
318: void divsgz(GZ n1,GZ n2,GZ *nq)
319: {
1.10 ! noro 320: mpz_t t;
! 321: mpq_t a, b, q;
1.1 noro 322:
1.10 ! noro 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: }
1.1 noro 333: }
334:
335: void chsgngz(GZ n,GZ *nr)
336: {
1.10 ! noro 337: mpz_t t;
1.1 noro 338:
1.10 ! noro 339: if ( !n )
! 340: *nr = 0;
! 341: else {
! 342: t[0] = BDY(n)[0]; mpz_neg(t,t); MPZTOGZ(t,*nr);
! 343: }
1.1 noro 344: }
345:
346: void pwrgz(GZ n1,Q n,GZ *nr)
347: {
1.10 ! noro 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: }
1.1 noro 365: }
366:
367: int cmpgz(GZ q1,GZ q2)
368: {
1.10 ! noro 369: int sgn;
1.1 noro 370:
1.10 ! noro 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: }
1.1 noro 386: }
387:
388: void gcdgz(GZ n1,GZ n2,GZ *nq)
389: {
1.10 ! noro 390: mpz_t t;
1.1 noro 391:
1.10 ! noro 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: }
1.1 noro 398: }
399:
1.5 noro 400: void invgz(GZ n1,GZ *nq)
401: {
1.10 ! noro 402: mpz_t t;
1.5 noro 403:
1.10 ! noro 404: mpz_init(t); mpz_invert(t,BDY(n1),BDY(current_mod_lf));
! 405: MPZTOGZ(t,*nq);
1.5 noro 406: }
407:
1.1 noro 408: void lcmgz(GZ n1,GZ n2,GZ *nq)
409: {
1.10 ! noro 410: GZ g,t;
1.1 noro 411:
1.10 ! noro 412: if ( !n1 || !n2 ) *nq = 0;
! 413: else {
! 414: gcdgz(n1,n2,&g); divsgz(n1,g,&t);
! 415: mulgz(n2,t,nq);
! 416: }
1.1 noro 417: }
418:
419: void gcdvgz(VECT v,GZ *q)
420: {
1.10 ! noro 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;
1.1 noro 432: }
433:
434: void gcdvgz_estimate(VECT v,GZ *q)
435: {
1.10 ! noro 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);
1.1 noro 458: }
459:
460: void addgq(GQ n1,GQ n2,GQ *nr)
461: {
1.10 ! noro 462: mpq_t q1,q2,t;
1.1 noro 463:
1.10 ! noro 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: }
1.1 noro 473: }
474:
475: void subgq(GQ n1,GQ n2,GQ *nr)
476: {
1.10 ! noro 477: mpq_t q1,q2,t;
1.1 noro 478:
1.10 ! noro 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: }
1.1 noro 496: }
497:
498: void mulgq(GQ n1,GQ n2,GQ *nr)
499: {
1.10 ! noro 500: mpq_t t,q1,q2;
1.1 noro 501:
1.10 ! noro 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: }
1.1 noro 510: }
511:
512: void divgq(GQ n1,GQ n2,GQ *nq)
513: {
1.10 ! noro 514: mpq_t t,q1,q2;
1.1 noro 515:
1.10 ! noro 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: }
1.1 noro 529: }
530:
531: void chsgngq(GQ n,GQ *nr)
532: {
1.10 ! noro 533: mpq_t t;
1.1 noro 534:
1.10 ! noro 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: }
1.1 noro 540: }
541:
542: void pwrgq(GQ n1,Q n,GQ *nr)
543: {
1.10 ! noro 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: }
1.1 noro 575: }
576:
577: int cmpgq(GQ n1,GQ n2)
578: {
1.10 ! noro 579: mpq_t q1,q2;
! 580: int sgn;
1.1 noro 581:
1.10 ! noro 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: }
1.1 noro 597: }
598:
599: void mkgwc(int k,int l,GZ *t)
600: {
1.10 ! noro 601: mpz_t a,b,q,nm,z,u;
! 602: int i,n;
1.1 noro 603:
1.10 ! noro 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: }
1.1 noro 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: {
1.10 ! noro 619: GZ nm,dn;
1.1 noro 620:
1.10 ! noro 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: }
1.1 noro 628: }
629:
630: void gz_lgp(P p,GZ *g,GZ *l)
631: {
1.10 ! noro 632: DCP dc;
! 633: GZ g1,g2,l1,l2,l3,l4;
1.1 noro 634:
1.10 ! noro 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: }
1.1 noro 650: }
651:
652: void gz_qltozl(GQ *w,int n,GZ *dvr)
653: {
1.10 ! noro 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);
1.1 noro 686: }
687:
688: int gz_bits(GQ q)
689: {
1.10 ! noro 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);
1.1 noro 697: }
698:
699: int gzp_mag(P p)
700: {
1.10 ! noro 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: }
1.1 noro 710: }
711:
712: void makesubstgz(VL v,NODE *s)
713: {
1.10 ! noro 714: NODE r,r0;
! 715: GZ q;
! 716: unsigned int n;
1.1 noro 717:
1.10 ! noro 718: for ( r0 = 0; v; v = NEXT(v) ) {
! 719: NEXTNODE(r0,r); BDY(r) = (pointer)v->v;
1.1 noro 720: #if defined(_PA_RISC1_1)
1.10 ! noro 721: n = mrand48()&BMASK; q = utogz(n);
1.1 noro 722: #else
1.10 ! noro 723: n = random(); q = utogz(n);
1.1 noro 724: #endif
1.10 ! noro 725: NEXTNODE(r0,r); BDY(r) = (pointer)q;
! 726: }
! 727: if ( r0 ) NEXT(r) = 0;
! 728: *s = r0;
1.1 noro 729: }
730:
731: unsigned int remgq(GQ a,unsigned int mod)
732: {
1.10 ! noro 733: unsigned int c,nm,dn;
! 734: mpz_t r;
1.1 noro 735:
1.10 ! noro 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;
1.1 noro 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: {
1.10 ! noro 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 ) {
1.1 noro 779: RESET:
1.10 ! noro 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: }
1.1 noro 849: }
850:
851: int gz_generic_gauss_elim2(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp)
852: {
853:
1.10 ! noro 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;
1.1 noro 883: }
884:
885: int gz_generic_gauss_elim_full(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp)
886: {
1.10 ! noro 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: }
1.1 noro 986: }
987:
988: int gz_generic_gauss_elim_direct(MAT mat,MAT *nm,GZ *dn,int **rindp,int **cindp){
1.10 ! noro 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;
1.1 noro 1038: }
1039:
1040: int gz_intmtoratm(MAT mat,GZ md,MAT nm,GZ *dn)
1041: {
1.10 ! noro 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;
1.1 noro 1082: }
1083:
1084: int gz_intmtoratm2(MAT mat,GZ md,MAT nm,GZ *dn,int *stat)
1085: {
1.10 ! noro 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;
1.1 noro 1114: }
1115:
1116: int gz_intvtoratv(GZ *v,int n,GZ md,GZ b,GZ *nm,GZ *dn)
1117: {
1.10 ! noro 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;
1.1 noro 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: {
1.10 ! noro 1148: GZ qq,t,u1,v1,r1;
! 1149: GZ q,u2,v2,r2;
1.1 noro 1150:
1.10 ! noro 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: }
1.1 noro 1166: }
1167:
1168: extern int f4_nocheck;
1169:
1170: int gz_gensolve_check(MAT mat,MAT nm,GZ dn,int *rind,int *cind)
1171: {
1.10 ! noro 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;
1.1 noro 1195: }
1196:
1197: int gz_gensolve_check2(MAT mat,MAT nm,GZ *dn,int *rind,int *cind)
1198: {
1.10 ! noro 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;
1.1 noro 1229: }
1230:
1231: void isqrtgz(GZ a,GZ *r)
1232: {
1.10 ! noro 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: }
1.1 noro 1255: }
1256:
1257: void bshiftgz(GZ a,int n,GZ *r)
1258: {
1.10 ! noro 1259: mpz_t t;
1.1 noro 1260:
1.10 ! noro 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: }
1.1 noro 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:
1.7 noro 1327: if ( !a ) *b = 0;
1328: else {
1329: NTOQ(BDY(a),1,q); *b = ztogz(q);
1330: }
1.5 noro 1331: }
1332:
1333: void setmod_lf(N p)
1334: {
1335: Q q;
1336:
1337: NTOQ(p,1,q); current_mod_lf = ztogz(q);
1.6 noro 1338: current_mod_lf_size = mpz_size(BDY(current_mod_lf))+1;
1.5 noro 1339: }
1340:
1341: void simplf_force(GZ a,GZ *b)
1342: {
1343: GZ t;
1344:
1345: remgz(a,current_mod_lf,&t); *b = t;
1346: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>