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

Annotation of OpenXM_contrib2/asir2000/engine/gmpq.c, Revision 1.8

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

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