[BACK]Return to Q.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2018 / engine

Annotation of OpenXM_contrib2/asir2018/engine/Q.c, Revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>