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