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

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

1.1     ! noro        1: /* $OpenXM: OpenXM/src/asir99/engine/Q.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
        !             2: #include "ca.h"
        !             3: #include "base.h"
        !             4: #include "inline.h"
        !             5:
        !             6: void addq(n1,n2,nr)
        !             7: Q n1,n2,*nr;
        !             8: {
        !             9:        N nm,dn,nm1,nm2,nm3,dn0,dn1,dn2,g,g1,g0,m;
        !            10:        int sgn;
        !            11:        unsigned t,t1;
        !            12:
        !            13:        if ( !n1 )
        !            14:                *nr = n2;
        !            15:        else if ( !n2 )
        !            16:                *nr = n1;
        !            17:        else if ( INT(n1) )
        !            18:                if ( INT(n2) ) {
        !            19:                        nm1 = NM(n1); nm2 = NM(n2);
        !            20:                        if ( SGN(n1) == SGN(n2) ) {
        !            21:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
        !            22:                                        t1 = BD(nm1)[0]; t = t1+BD(nm2)[0];
        !            23:                                        if ( t < t1 ) {
        !            24:                                                m = NALLOC(2); PL(m) = 2; BD(m)[0] = t; BD(m)[1] = 1;
        !            25:                                        } else
        !            26:                                                UTON(t,m);
        !            27:                                } else
        !            28:                                        addn(NM(n1),NM(n2),&m);
        !            29:                                NTOQ(m,SGN(n1),*nr);
        !            30:                        } else {
        !            31:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
        !            32:                                        t1 = BD(nm1)[0]; t = t1-BD(nm2)[0];
        !            33:                                        if ( !t )
        !            34:                                                sgn = 0;
        !            35:                                        else if ( t > t1 ) {
        !            36:                                                sgn = -1; t = -((int)t); UTON(t,m);
        !            37:                                        } else {
        !            38:                                                sgn = 1; UTON(t,m);
        !            39:                                        }
        !            40:                                } else
        !            41:                                        sgn = subn(NM(n1),NM(n2),&m);
        !            42:                                if ( sgn ) {
        !            43:                                        if ( SGN(n1) == sgn )
        !            44:                                                NTOQ(m,1,*nr);
        !            45:                                        else
        !            46:                                                NTOQ(m,-1,*nr);
        !            47:                                } else
        !            48:                                        *nr = 0;
        !            49:                        }
        !            50:                } else {
        !            51:                        kmuln(NM(n1),DN(n2),&m);
        !            52:                        if ( SGN(n1) == SGN(n2) ) {
        !            53:                                sgn = SGN(n1); addn(m,NM(n2),&nm);
        !            54:                        } else
        !            55:                                sgn = SGN(n1)*subn(m,NM(n2),&nm);
        !            56:                        if ( sgn ) {
        !            57:                                dn = DN(n2); NDTOQ(nm,dn,sgn,*nr);
        !            58:                        } else
        !            59:                                *nr = 0;
        !            60:                }
        !            61:        else if ( INT(n2) ) {
        !            62:                kmuln(NM(n2),DN(n1),&m);
        !            63:                if ( SGN(n1) == SGN(n2) ) {
        !            64:                        sgn = SGN(n1); addn(m,NM(n1),&nm);
        !            65:                } else
        !            66:                        sgn = SGN(n1)*subn(NM(n1),m,&nm);
        !            67:                if ( sgn ) {
        !            68:                        dn = DN(n1); NDTOQ(nm,dn,sgn,*nr);
        !            69:                } else
        !            70:                        *nr = 0;
        !            71:        } else {
        !            72:                gcdn(DN(n1),DN(n2),&g); divsn(DN(n1),g,&dn1); divsn(DN(n2),g,&dn2);
        !            73:                kmuln(NM(n1),dn2,&nm1); kmuln(NM(n2),dn1,&nm2);
        !            74:                if ( SGN(n1) == SGN(n2) ) {
        !            75:                        sgn = SGN(n1); addn(nm1,nm2,&nm3);
        !            76:                } else
        !            77:                        sgn = SGN(n1)*subn(nm1,nm2,&nm3);
        !            78:                if ( sgn ) {
        !            79:                        gcdn(nm3,g,&g1); divsn(nm3,g1,&nm); divsn(g,g1,&g0);
        !            80:                        kmuln(dn1,dn2,&dn0); kmuln(g0,dn0,&dn);
        !            81:                        if ( UNIN(dn) )
        !            82:                                NTOQ(nm,sgn,*nr);
        !            83:                        else
        !            84:                                NDTOQ(nm,dn,sgn,*nr);
        !            85:                } else
        !            86:                        *nr = 0;
        !            87:        }
        !            88: }
        !            89:
        !            90: void subq(n1,n2,nr)
        !            91: Q n1,n2,*nr;
        !            92: {
        !            93:        Q m;
        !            94:
        !            95:        if ( !n1 )
        !            96:                if ( !n2 )
        !            97:                        *nr = 0;
        !            98:                else {
        !            99:                        DUPQ(n2,*nr); SGN(*nr) = -SGN(n2);
        !           100:                }
        !           101:        else if ( !n2 )
        !           102:                *nr = n1;
        !           103:        else if ( n1 == n2 )
        !           104:                *nr = 0;
        !           105:        else {
        !           106:                DUPQ(n2,m); SGN(m) = -SGN(n2); addq(n1,m,nr);
        !           107:        }
        !           108: }
        !           109:
        !           110: void mulq(n1,n2,nr)
        !           111: Q n1,n2,*nr;
        !           112: {
        !           113:        N nm,nm1,nm2,dn,dn1,dn2,g;
        !           114:        int sgn;
        !           115:        unsigned u,l;
        !           116:
        !           117:        if ( !n1 || !n2 ) *nr = 0;
        !           118:        else if ( INT(n1) )
        !           119:                if ( INT(n2) ) {
        !           120:                        nm1 = NM(n1); nm2 = NM(n2);
        !           121:                        if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
        !           122:                                DM(BD(NM(n1))[0],BD(NM(n2))[0],u,l)
        !           123:                                if ( u ) {
        !           124:                                        nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = l; BD(nm)[1] = u;
        !           125:                                } else {
        !           126:                                        nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = l;
        !           127:                                }
        !           128:                        } else
        !           129:                                kmuln(nm1,nm2,&nm);
        !           130:                        sgn = (SGN(n1)==SGN(n2)?1:-1); NTOQ(nm,sgn,*nr);
        !           131:                } else {
        !           132:                        gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn);
        !           133:                        kmuln(nm1,NM(n2),&nm); sgn = SGN(n1)*SGN(n2);
        !           134:                        if ( UNIN(dn) )
        !           135:                                NTOQ(nm,sgn,*nr);
        !           136:                        else
        !           137:                                NDTOQ(nm,dn,sgn,*nr);
        !           138:                }
        !           139:        else if ( INT(n2) ) {
        !           140:                gcdn(NM(n2),DN(n1),&g); divsn(NM(n2),g,&nm2); divsn(DN(n1),g,&dn);
        !           141:                kmuln(nm2,NM(n1),&nm); sgn = SGN(n1)*SGN(n2);
        !           142:                if ( UNIN(dn) )
        !           143:                        NTOQ(nm,sgn,*nr);
        !           144:                else
        !           145:                        NDTOQ(nm,dn,sgn,*nr);
        !           146:        } else {
        !           147:                gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn2);
        !           148:                gcdn(DN(n1),NM(n2),&g); divsn(DN(n1),g,&dn1); divsn(NM(n2),g,&nm2);
        !           149:                kmuln(nm1,nm2,&nm); kmuln(dn1,dn2,&dn); sgn = SGN(n1) * SGN(n2);
        !           150:                if ( UNIN(dn) )
        !           151:                        NTOQ(nm,sgn,*nr);
        !           152:                else
        !           153:                        NDTOQ(nm,dn,sgn,*nr);
        !           154:        }
        !           155: }
        !           156:
        !           157: void divq(n1,n2,nq)
        !           158: Q n1,n2,*nq;
        !           159: {
        !           160:        Q m;
        !           161:
        !           162:        if ( !n2 ) {
        !           163:                error("division by 0");
        !           164:                *nq = 0;
        !           165:                return;
        !           166:        } else if ( !n1 )
        !           167:                *nq = 0;
        !           168:        else if ( n1 == n2 )
        !           169:                *nq = ONE;
        !           170:        else {
        !           171:                invq(n2,&m); mulq(n1,m,nq);
        !           172:        }
        !           173: }
        !           174:
        !           175: void invq(n,nr)
        !           176: Q n,*nr;
        !           177: {
        !           178:        N nm,dn;
        !           179:
        !           180:        if ( INT(n) )
        !           181:                if ( UNIN(NM(n)) )
        !           182:                        if ( SGN(n) > 0 )
        !           183:                                *nr = ONE;
        !           184:                        else {
        !           185:                                nm = ONEN; NTOQ(nm,SGN(n),*nr);
        !           186:                        }
        !           187:                else {
        !           188:                        nm = ONEN; dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
        !           189:                }
        !           190:        else if ( UNIN(NM(n)) ) {
        !           191:                nm = DN(n); NTOQ(nm,SGN(n),*nr);
        !           192:        } else {
        !           193:                nm = DN(n); dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
        !           194:        }
        !           195: }
        !           196:
        !           197: void chsgnq(n,nr)
        !           198: Q n,*nr;
        !           199: {
        !           200:        Q t;
        !           201:
        !           202:        if ( !n )
        !           203:                *nr = 0;
        !           204:        else {
        !           205:                DUPQ(n,t); SGN(t) = -SGN(t); *nr = t;
        !           206:        }
        !           207: }
        !           208:
        !           209: void pwrq(n1,n,nr)
        !           210: Q n1,n,*nr;
        !           211: {
        !           212:        N nm,dn;
        !           213:        int sgn;
        !           214:
        !           215:        if ( !n || UNIQ(n1) )
        !           216:                *nr = ONE;
        !           217:        else if ( !n1 )
        !           218:                *nr = 0;
        !           219:        else if ( !INT(n) ) {
        !           220:                error("can't calculate fractional power."); *nr = 0;
        !           221:        } else if ( MUNIQ(n1) )
        !           222:                *nr = BD(NM(n))[0]%2 ? n1 : ONE;
        !           223:        else if ( PL(NM(n)) > 1 ) {
        !           224:                error("exponent too big."); *nr = 0;
        !           225:        } else {
        !           226:                sgn = ((SGN(n1)>0)||EVENN(NM(n))?1:-1);
        !           227:                pwrn(NM(n1),BD(NM(n))[0],&nm);
        !           228:                if ( INT(n1) ) {
        !           229:                        if ( UNIN(nm) )
        !           230:                                if ( sgn == 1 )
        !           231:                                        *nr = ONE;
        !           232:                                else
        !           233:                                        NTOQ(ONEN,sgn,*nr);
        !           234:                        else if ( SGN(n) > 0 )
        !           235:                                NTOQ(nm,sgn,*nr);
        !           236:                        else
        !           237:                                NDTOQ(ONEN,nm,sgn,*nr);
        !           238:                } else {
        !           239:                        pwrn(DN(n1),BD(NM(n))[0],&dn);
        !           240:                        if ( SGN(n) > 0 )
        !           241:                                NDTOQ(nm,dn,sgn,*nr);
        !           242:                        else if ( UNIN(nm) )
        !           243:                                NTOQ(dn,sgn,*nr);
        !           244:                        else
        !           245:                                NDTOQ(dn,nm,sgn,*nr);
        !           246:                }
        !           247:        }
        !           248: }
        !           249:
        !           250: int cmpq(q1,q2)
        !           251: Q q1,q2;
        !           252: {
        !           253:        int sgn;
        !           254:        N t,s;
        !           255:
        !           256:        if ( !q1 )
        !           257:                if ( !q2 )
        !           258:                        return ( 0 );
        !           259:                else
        !           260:                        return ( -SGN(q2) );
        !           261:        else if ( !q2 )
        !           262:                return ( SGN(q1) );
        !           263:        else if ( SGN(q1) != SGN(q2) )
        !           264:                        return ( SGN(q1) );
        !           265:        else if ( INT(q1) )
        !           266:                        if ( INT(q2) ) {
        !           267:                                sgn = cmpn(NM(q1),NM(q2));
        !           268:                                if ( !sgn )
        !           269:                                        return ( 0 );
        !           270:                                else
        !           271:                                        return ( SGN(q1)==sgn?1:-1 );
        !           272:                        } else {
        !           273:                                kmuln(NM(q1),DN(q2),&t); sgn = cmpn(t,NM(q2));
        !           274:                                return ( SGN(q1) * sgn );
        !           275:                        }
        !           276:        else if ( INT(q2) ) {
        !           277:                kmuln(NM(q2),DN(q1),&t); sgn = cmpn(NM(q1),t);
        !           278:                return ( SGN(q1) * sgn );
        !           279:        } else {
        !           280:                kmuln(NM(q1),DN(q2),&t); kmuln(NM(q2),DN(q1),&s); sgn = cmpn(t,s);
        !           281:                return ( SGN(q1) * sgn );
        !           282:        }
        !           283: }
        !           284:
        !           285: void remq(n,m,nr)
        !           286: Q n,m;
        !           287: Q *nr;
        !           288: {
        !           289:        N q,r,s;
        !           290:
        !           291:        if ( !n ) {
        !           292:                *nr = 0;
        !           293:                return;
        !           294:        }
        !           295:        divn(NM(n),NM(m),&q,&r);
        !           296:        if ( !r )
        !           297:                *nr = 0;
        !           298:        else if ( SGN(n) > 0 )
        !           299:                NTOQ(r,1,*nr);
        !           300:        else {
        !           301:                subn(NM(m),r,&s); NTOQ(s,1,*nr);
        !           302:        }
        !           303: }
        !           304:
        !           305: void mkbc(n,t)
        !           306: int n;
        !           307: Q *t;
        !           308: {
        !           309:        int i;
        !           310:        N c,d;
        !           311:
        !           312:        for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
        !           313:                c = NALLOC(1); PL(c) = 1; BD(c)[0] = n-i+1;
        !           314:                kmuln(NM(t[i-1]),c,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
        !           315:        }
        !           316:        for ( ; i <= n; i++ )
        !           317:                t[i] = t[n-i];
        !           318: }
        !           319:
        !           320: void factorial(n,r)
        !           321: int n;
        !           322: Q *r;
        !           323: {
        !           324:        Q t,iq,s;
        !           325:        unsigned int i,m,m0;
        !           326:        unsigned int c;
        !           327:
        !           328:        if ( !n )
        !           329:                *r = ONE;
        !           330:        else if ( n < 0 )
        !           331:                *r = 0;
        !           332:        else {
        !           333:                for ( i = 1, t = ONE; (int)i <= n; ) {
        !           334:                        for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
        !           335:                                m0 = m; DM(m0,i,c,m)
        !           336:                        }
        !           337:                        if ( c ) {
        !           338:                                m = m0; i--;
        !           339:                        }
        !           340:                        UTOQ(m,iq); mulq(t,iq,&s); t = s;
        !           341:                }
        !           342:                *r = t;
        !           343:        }
        !           344: }
        !           345:
        !           346: void invl(a,mod,ar)
        !           347: Q a,mod,*ar;
        !           348: {
        !           349:        Q f1,f2,a1,a2,q,m,s;
        !           350:        N qn,rn;
        !           351:
        !           352:        a1 = ONE; a2 = 0;
        !           353:        DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
        !           354:
        !           355:        while ( 1 ) {
        !           356:                divn(NM(f1),NM(f2),&qn,&rn);
        !           357:                if ( !qn )
        !           358:                        q = 0;
        !           359:                else
        !           360:                        NTOQ(qn,1,q);
        !           361:
        !           362:                f1 = f2;
        !           363:                if ( !rn )
        !           364:                        break;
        !           365:                else
        !           366:                        NTOQ(rn,1,f2);
        !           367:
        !           368:                mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
        !           369:                if ( !s )
        !           370:                        a2 = 0;
        !           371:                else
        !           372:                        remq(s,mod,&a2);
        !           373:        }
        !           374:        if ( SGN(a) < 0 )
        !           375:                chsgnq(a2,&m);
        !           376:        else
        !           377:                m = a2;
        !           378:
        !           379:        if ( SGN(m) >= 0 )
        !           380:                *ar = m;
        !           381:        else
        !           382:                addq(m,mod,ar);
        !           383: }
        !           384:
        !           385: int kara_mag=100;
        !           386:
        !           387: void kmuln(n1,n2,nr)
        !           388: N n1,n2,*nr;
        !           389: {
        !           390:        N n,t,s,m,carry;
        !           391:        int d,d1,d2,len,i,l;
        !           392:        int *r,*r0;
        !           393:
        !           394:        if ( !n1 || !n2 ) {
        !           395:                *nr = 0; return;
        !           396:        }
        !           397:        d1 = PL(n1); d2 = PL(n2);
        !           398:        if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
        !           399:                muln(n1,n2,nr); return;
        !           400:        }
        !           401:        if ( d1 < d2 ) {
        !           402:                n = n1; n1 = n2; n2 = n;
        !           403:                d = d1; d1 = d2; d2 = d;
        !           404:        }
        !           405:        if ( d2 > (d1+1)/2 ) {
        !           406:                kmulnmain(n1,n2,nr); return;
        !           407:        }
        !           408:        d = (d1/d2)+((d1%d2)!=0);
        !           409:        len = (d+1)*d2;
        !           410:        r0 = (int *)ALLOCA(len*sizeof(int));
        !           411:        bzero((char *)r0,len*sizeof(int));
        !           412:        for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
        !           413:                extractn(n1,i*d2,d2,&m);
        !           414:                if ( m ) {
        !           415:                        kmuln(m,n2,&t);
        !           416:                        addn(t,carry,&s);
        !           417:                        copyn(s,d2,r);
        !           418:                        extractn(s,d2,d2,&carry);
        !           419:                } else {
        !           420:                        copyn(carry,d2,r);
        !           421:                        carry = 0;
        !           422:                }
        !           423:        }
        !           424:        copyn(carry,d2,r);
        !           425:        for ( l = len - 1; !r0[l]; l-- );
        !           426:        l++;
        !           427:        *nr = t = NALLOC(l); PL(t) = l;
        !           428:        bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
        !           429: }
        !           430:
        !           431: void extractn(n,index,len,nr)
        !           432: N n;
        !           433: int index,len;
        !           434: N *nr;
        !           435: {
        !           436:        unsigned int *m;
        !           437:        int l;
        !           438:        N t;
        !           439:
        !           440:        if ( !n ) {
        !           441:                *nr = 0; return;
        !           442:        }
        !           443:        m = BD(n)+index;
        !           444:        if ( (l = PL(n)-index) >= len ) {
        !           445:                for ( l = len - 1; (l >= 0) && !m[l]; l-- );
        !           446:                l++;
        !           447:        }
        !           448:        if ( l <= 0 ) {
        !           449:                *nr = 0; return;
        !           450:        } else {
        !           451:                *nr = t = NALLOC(l); PL(t) = l;
        !           452:                bcopy((char *)m,(char *)BD(t),l*sizeof(int));
        !           453:        }
        !           454: }
        !           455:
        !           456: void copyn(n,len,p)
        !           457: N n;
        !           458: int len;
        !           459: int *p;
        !           460: {
        !           461:        if ( n )
        !           462:                bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
        !           463: }
        !           464:
        !           465: void dupn(n,p)
        !           466: N n;
        !           467: N p;
        !           468: {
        !           469:        if ( n )
        !           470:                bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
        !           471: }
        !           472:
        !           473: void kmulnmain(n1,n2,nr)
        !           474: N n1,n2,*nr;
        !           475: {
        !           476:        int d1,d2,h,sgn,sgn1,sgn2,len;
        !           477:        N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
        !           478:
        !           479:        d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
        !           480:        extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
        !           481:        extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
        !           482:        kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
        !           483:        len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
        !           484:        bzero((char *)BD(t1),len*sizeof(int));
        !           485:        if ( lo )
        !           486:                bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
        !           487:        if ( hi )
        !           488:                bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
        !           489:
        !           490:        addn(hi,lo,&mid1);
        !           491:        sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
        !           492:        kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
        !           493:        if ( sgn > 0 )
        !           494:                addn(mid1,mid2,&mid);
        !           495:        else
        !           496:                subn(mid1,mid2,&mid);
        !           497:        if ( mid ) {
        !           498:                len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
        !           499:                bzero((char *)BD(t2),len*sizeof(int));
        !           500:                bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
        !           501:                addn(t1,t2,nr);
        !           502:        } else
        !           503:                *nr = t1;
        !           504: }

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