[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.9

1.4       noro        1: /*
                      2:  * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
                      3:  * All rights reserved.
                      4:  *
                      5:  * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
                      6:  * non-exclusive and royalty-free license to use, copy, modify and
                      7:  * redistribute, solely for non-commercial and non-profit purposes, the
                      8:  * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
                      9:  * conditions of this Agreement. For the avoidance of doubt, you acquire
                     10:  * only a limited right to use the SOFTWARE hereunder, and FLL or any
                     11:  * third party developer retains all rights, including but not limited to
                     12:  * copyrights, in and to the SOFTWARE.
                     13:  *
                     14:  * (1) FLL does not grant you a license in any way for commercial
                     15:  * purposes. You may use the SOFTWARE only for non-commercial and
                     16:  * non-profit purposes only, such as academic, research and internal
                     17:  * business use.
                     18:  * (2) The SOFTWARE is protected by the Copyright Law of Japan and
                     19:  * international copyright treaties. If you make copies of the SOFTWARE,
                     20:  * with or without modification, as permitted hereunder, you shall affix
                     21:  * to all such copies of the SOFTWARE the above copyright notice.
                     22:  * (3) An explicit reference to this SOFTWARE and its copyright owner
                     23:  * shall be made on your publication or presentation in any form of the
                     24:  * results obtained by use of the SOFTWARE.
                     25:  * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.5       noro       26:  * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.4       noro       27:  * for such modification or the source code of the modified part of the
                     28:  * SOFTWARE.
                     29:  *
                     30:  * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
                     31:  * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
                     32:  * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
                     33:  * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
                     34:  * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
                     35:  * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
                     36:  * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
                     37:  * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
                     38:  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
                     39:  * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
                     40:  * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
                     41:  * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
                     42:  * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
                     43:  * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
                     44:  * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
                     45:  * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
                     46:  * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
                     47:  *
1.9     ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2000/engine/Q.c,v 1.8 2002/08/08 10:57:01 noro Exp $
1.4       noro       49: */
1.1       noro       50: #include "ca.h"
                     51: #include "base.h"
                     52: #include "inline.h"
                     53:
1.7       noro       54: void addq(Q n1,Q n2,Q *nr)
1.1       noro       55: {
                     56:        N nm,dn,nm1,nm2,nm3,dn0,dn1,dn2,g,g1,g0,m;
                     57:        int sgn;
                     58:        unsigned t,t1;
                     59:
                     60:        if ( !n1 )
                     61:                *nr = n2;
                     62:        else if ( !n2 )
                     63:                *nr = n1;
                     64:        else if ( INT(n1) )
                     65:                if ( INT(n2) ) {
                     66:                        nm1 = NM(n1); nm2 = NM(n2);
                     67:                        if ( SGN(n1) == SGN(n2) ) {
                     68:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                     69:                                        t1 = BD(nm1)[0]; t = t1+BD(nm2)[0];
                     70:                                        if ( t < t1 ) {
                     71:                                                m = NALLOC(2); PL(m) = 2; BD(m)[0] = t; BD(m)[1] = 1;
                     72:                                        } else
                     73:                                                UTON(t,m);
                     74:                                } else
                     75:                                        addn(NM(n1),NM(n2),&m);
                     76:                                NTOQ(m,SGN(n1),*nr);
                     77:                        } else {
                     78:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                     79:                                        t1 = BD(nm1)[0]; t = t1-BD(nm2)[0];
                     80:                                        if ( !t )
                     81:                                                sgn = 0;
                     82:                                        else if ( t > t1 ) {
                     83:                                                sgn = -1; t = -((int)t); UTON(t,m);
                     84:                                        } else {
                     85:                                                sgn = 1; UTON(t,m);
                     86:                                        }
                     87:                                } else
                     88:                                        sgn = subn(NM(n1),NM(n2),&m);
                     89:                                if ( sgn ) {
                     90:                                        if ( SGN(n1) == sgn )
                     91:                                                NTOQ(m,1,*nr);
                     92:                                        else
                     93:                                                NTOQ(m,-1,*nr);
                     94:                                } else
                     95:                                        *nr = 0;
                     96:                        }
                     97:                } else {
                     98:                        kmuln(NM(n1),DN(n2),&m);
                     99:                        if ( SGN(n1) == SGN(n2) ) {
                    100:                                sgn = SGN(n1); addn(m,NM(n2),&nm);
                    101:                        } else
                    102:                                sgn = SGN(n1)*subn(m,NM(n2),&nm);
                    103:                        if ( sgn ) {
                    104:                                dn = DN(n2); NDTOQ(nm,dn,sgn,*nr);
                    105:                        } else
                    106:                                *nr = 0;
                    107:                }
                    108:        else if ( INT(n2) ) {
                    109:                kmuln(NM(n2),DN(n1),&m);
                    110:                if ( SGN(n1) == SGN(n2) ) {
                    111:                        sgn = SGN(n1); addn(m,NM(n1),&nm);
                    112:                } else
                    113:                        sgn = SGN(n1)*subn(NM(n1),m,&nm);
                    114:                if ( sgn ) {
                    115:                        dn = DN(n1); NDTOQ(nm,dn,sgn,*nr);
                    116:                } else
                    117:                        *nr = 0;
                    118:        } else {
                    119:                gcdn(DN(n1),DN(n2),&g); divsn(DN(n1),g,&dn1); divsn(DN(n2),g,&dn2);
                    120:                kmuln(NM(n1),dn2,&nm1); kmuln(NM(n2),dn1,&nm2);
                    121:                if ( SGN(n1) == SGN(n2) ) {
                    122:                        sgn = SGN(n1); addn(nm1,nm2,&nm3);
                    123:                } else
                    124:                        sgn = SGN(n1)*subn(nm1,nm2,&nm3);
                    125:                if ( sgn ) {
                    126:                        gcdn(nm3,g,&g1); divsn(nm3,g1,&nm); divsn(g,g1,&g0);
                    127:                        kmuln(dn1,dn2,&dn0); kmuln(g0,dn0,&dn);
                    128:                        if ( UNIN(dn) )
                    129:                                NTOQ(nm,sgn,*nr);
                    130:                        else
                    131:                                NDTOQ(nm,dn,sgn,*nr);
                    132:                } else
                    133:                        *nr = 0;
                    134:        }
                    135: }
                    136:
1.7       noro      137: void subq(Q n1,Q n2,Q *nr)
1.1       noro      138: {
                    139:        Q m;
                    140:
                    141:        if ( !n1 )
                    142:                if ( !n2 )
                    143:                        *nr = 0;
                    144:                else {
                    145:                        DUPQ(n2,*nr); SGN(*nr) = -SGN(n2);
                    146:                }
                    147:        else if ( !n2 )
                    148:                *nr = n1;
                    149:        else if ( n1 == n2 )
                    150:                *nr = 0;
                    151:        else {
                    152:                DUPQ(n2,m); SGN(m) = -SGN(n2); addq(n1,m,nr);
                    153:        }
                    154: }
                    155:
1.7       noro      156: void mulq(Q n1,Q n2,Q *nr)
1.1       noro      157: {
                    158:        N nm,nm1,nm2,dn,dn1,dn2,g;
                    159:        int sgn;
                    160:        unsigned u,l;
                    161:
                    162:        if ( !n1 || !n2 ) *nr = 0;
                    163:        else if ( INT(n1) )
                    164:                if ( INT(n2) ) {
                    165:                        nm1 = NM(n1); nm2 = NM(n2);
                    166:                        if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                    167:                                DM(BD(NM(n1))[0],BD(NM(n2))[0],u,l)
                    168:                                if ( u ) {
                    169:                                        nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = l; BD(nm)[1] = u;
                    170:                                } else {
                    171:                                        nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = l;
                    172:                                }
                    173:                        } else
                    174:                                kmuln(nm1,nm2,&nm);
                    175:                        sgn = (SGN(n1)==SGN(n2)?1:-1); NTOQ(nm,sgn,*nr);
                    176:                } else {
                    177:                        gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn);
                    178:                        kmuln(nm1,NM(n2),&nm); sgn = SGN(n1)*SGN(n2);
                    179:                        if ( UNIN(dn) )
                    180:                                NTOQ(nm,sgn,*nr);
                    181:                        else
                    182:                                NDTOQ(nm,dn,sgn,*nr);
                    183:                }
                    184:        else if ( INT(n2) ) {
                    185:                gcdn(NM(n2),DN(n1),&g); divsn(NM(n2),g,&nm2); divsn(DN(n1),g,&dn);
                    186:                kmuln(nm2,NM(n1),&nm); sgn = SGN(n1)*SGN(n2);
                    187:                if ( UNIN(dn) )
                    188:                        NTOQ(nm,sgn,*nr);
                    189:                else
                    190:                        NDTOQ(nm,dn,sgn,*nr);
                    191:        } else {
                    192:                gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn2);
                    193:                gcdn(DN(n1),NM(n2),&g); divsn(DN(n1),g,&dn1); divsn(NM(n2),g,&nm2);
                    194:                kmuln(nm1,nm2,&nm); kmuln(dn1,dn2,&dn); sgn = SGN(n1) * SGN(n2);
                    195:                if ( UNIN(dn) )
                    196:                        NTOQ(nm,sgn,*nr);
                    197:                else
                    198:                        NDTOQ(nm,dn,sgn,*nr);
                    199:        }
                    200: }
                    201:
1.7       noro      202: void divq(Q n1,Q n2,Q *nq)
1.1       noro      203: {
                    204:        Q m;
                    205:
                    206:        if ( !n2 ) {
                    207:                error("division by 0");
                    208:                *nq = 0;
                    209:                return;
                    210:        } else if ( !n1 )
                    211:                *nq = 0;
                    212:        else if ( n1 == n2 )
                    213:                *nq = ONE;
                    214:        else {
                    215:                invq(n2,&m); mulq(n1,m,nq);
1.6       noro      216:        }
                    217: }
                    218:
1.7       noro      219: void divsq(Q n1,Q n2,Q *nq)
1.6       noro      220: {
                    221:        int sgn;
                    222:        N tn;
                    223:
                    224:        if ( !n2 ) {
                    225:                error("division by 0");
                    226:                *nq = 0;
                    227:                return;
                    228:        } else if ( !n1 )
                    229:                *nq = 0;
                    230:        else if ( n1 == n2 )
                    231:                *nq = ONE;
                    232:        else {
                    233:                divsn(NM(n1),NM(n2),&tn);
                    234:                sgn = SGN(n1)*SGN(n2);
                    235:                NTOQ(tn,sgn,*nq);
1.1       noro      236:        }
                    237: }
                    238:
1.7       noro      239: void invq(Q n,Q *nr)
1.1       noro      240: {
                    241:        N nm,dn;
                    242:
                    243:        if ( INT(n) )
                    244:                if ( UNIN(NM(n)) )
                    245:                        if ( SGN(n) > 0 )
                    246:                                *nr = ONE;
                    247:                        else {
                    248:                                nm = ONEN; NTOQ(nm,SGN(n),*nr);
                    249:                        }
                    250:                else {
                    251:                        nm = ONEN; dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
                    252:                }
                    253:        else if ( UNIN(NM(n)) ) {
                    254:                nm = DN(n); NTOQ(nm,SGN(n),*nr);
                    255:        } else {
                    256:                nm = DN(n); dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
                    257:        }
                    258: }
                    259:
1.7       noro      260: void chsgnq(Q n,Q *nr)
1.1       noro      261: {
                    262:        Q t;
                    263:
                    264:        if ( !n )
                    265:                *nr = 0;
                    266:        else {
                    267:                DUPQ(n,t); SGN(t) = -SGN(t); *nr = t;
                    268:        }
                    269: }
                    270:
1.7       noro      271: void pwrq(Q n1,Q n,Q *nr)
1.1       noro      272: {
                    273:        N nm,dn;
                    274:        int sgn;
                    275:
                    276:        if ( !n || UNIQ(n1) )
                    277:                *nr = ONE;
                    278:        else if ( !n1 )
                    279:                *nr = 0;
                    280:        else if ( !INT(n) ) {
                    281:                error("can't calculate fractional power."); *nr = 0;
                    282:        } else if ( MUNIQ(n1) )
                    283:                *nr = BD(NM(n))[0]%2 ? n1 : ONE;
                    284:        else if ( PL(NM(n)) > 1 ) {
                    285:                error("exponent too big."); *nr = 0;
                    286:        } else {
                    287:                sgn = ((SGN(n1)>0)||EVENN(NM(n))?1:-1);
                    288:                pwrn(NM(n1),BD(NM(n))[0],&nm);
                    289:                if ( INT(n1) ) {
                    290:                        if ( UNIN(nm) )
                    291:                                if ( sgn == 1 )
                    292:                                        *nr = ONE;
                    293:                                else
                    294:                                        NTOQ(ONEN,sgn,*nr);
                    295:                        else if ( SGN(n) > 0 )
                    296:                                NTOQ(nm,sgn,*nr);
                    297:                        else
                    298:                                NDTOQ(ONEN,nm,sgn,*nr);
                    299:                } else {
                    300:                        pwrn(DN(n1),BD(NM(n))[0],&dn);
                    301:                        if ( SGN(n) > 0 )
                    302:                                NDTOQ(nm,dn,sgn,*nr);
                    303:                        else if ( UNIN(nm) )
                    304:                                NTOQ(dn,sgn,*nr);
                    305:                        else
                    306:                                NDTOQ(dn,nm,sgn,*nr);
                    307:                }
                    308:        }
                    309: }
                    310:
1.7       noro      311: int cmpq(Q q1,Q q2)
1.1       noro      312: {
                    313:        int sgn;
                    314:        N t,s;
                    315:
                    316:        if ( !q1 )
                    317:                if ( !q2 )
                    318:                        return ( 0 );
                    319:                else
                    320:                        return ( -SGN(q2) );
                    321:        else if ( !q2 )
                    322:                return ( SGN(q1) );
                    323:        else if ( SGN(q1) != SGN(q2) )
                    324:                        return ( SGN(q1) );
                    325:        else if ( INT(q1) )
                    326:                        if ( INT(q2) ) {
                    327:                                sgn = cmpn(NM(q1),NM(q2));
                    328:                                if ( !sgn )
                    329:                                        return ( 0 );
                    330:                                else
                    331:                                        return ( SGN(q1)==sgn?1:-1 );
                    332:                        } else {
                    333:                                kmuln(NM(q1),DN(q2),&t); sgn = cmpn(t,NM(q2));
                    334:                                return ( SGN(q1) * sgn );
                    335:                        }
                    336:        else if ( INT(q2) ) {
                    337:                kmuln(NM(q2),DN(q1),&t); sgn = cmpn(NM(q1),t);
                    338:                return ( SGN(q1) * sgn );
                    339:        } else {
                    340:                kmuln(NM(q1),DN(q2),&t); kmuln(NM(q2),DN(q1),&s); sgn = cmpn(t,s);
                    341:                return ( SGN(q1) * sgn );
                    342:        }
                    343: }
                    344:
1.7       noro      345: void remq(Q n,Q m,Q *nr)
1.1       noro      346: {
                    347:        N q,r,s;
                    348:
                    349:        if ( !n ) {
                    350:                *nr = 0;
                    351:                return;
                    352:        }
                    353:        divn(NM(n),NM(m),&q,&r);
                    354:        if ( !r )
                    355:                *nr = 0;
                    356:        else if ( SGN(n) > 0 )
                    357:                NTOQ(r,1,*nr);
                    358:        else {
                    359:                subn(NM(m),r,&s); NTOQ(s,1,*nr);
                    360:        }
                    361: }
                    362:
1.2       noro      363: /* t = [nC0 nC1 ... nCn] */
                    364:
1.7       noro      365: void mkbc(int n,Q *t)
1.1       noro      366: {
                    367:        int i;
                    368:        N c,d;
                    369:
                    370:        for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
                    371:                c = NALLOC(1); PL(c) = 1; BD(c)[0] = n-i+1;
                    372:                kmuln(NM(t[i-1]),c,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
                    373:        }
                    374:        for ( ; i <= n; i++ )
                    375:                t[i] = t[n-i];
1.2       noro      376: }
                    377:
                    378: /*
                    379:  *  Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
                    380:  *
                    381:  *  t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
                    382:  *  where W(k,l,i) = i! * kCi * lCi
                    383:  */
                    384:
1.7       noro      385: void mkwc(int k,int l,Q *t)
1.2       noro      386: {
                    387:        int i,n,up,low;
                    388:        N nm,d,c;
                    389:
                    390:        n = MIN(k,l);
                    391:        for ( t[0] = ONE, i = 1; i <= n; i++ ) {
                    392:                DM(k-i+1,l-i+1,up,low);
                    393:                if ( up ) {
                    394:                        nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = low; BD(nm)[1] = up;
                    395:                } else {
                    396:                        nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = low;
                    397:                }
                    398:                kmuln(NM(t[i-1]),nm,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
1.3       noro      399:        }
                    400: }
                    401:
                    402: /* mod m table */
                    403: /* XXX : should be optimized */
                    404:
1.7       noro      405: void mkwcm(int k,int l,int m,int *t)
1.3       noro      406: {
                    407:        int i,n;
                    408:        Q *s;
                    409:
                    410:        n = MIN(k,l);
                    411:        s = (Q *)ALLOCA((n+1)*sizeof(Q));
                    412:        mkwc(k,l,s);
                    413:        for ( i = 0; i <= n; i++ ) {
                    414:                t[i] = rem(NM(s[i]),m);
1.2       noro      415:        }
1.1       noro      416: }
                    417:
1.8       noro      418: #if 0
1.7       noro      419: void factorial(int n,Q *r)
1.1       noro      420: {
                    421:        Q t,iq,s;
                    422:        unsigned int i,m,m0;
                    423:        unsigned int c;
                    424:
                    425:        if ( !n )
                    426:                *r = ONE;
                    427:        else if ( n < 0 )
                    428:                *r = 0;
                    429:        else {
                    430:                for ( i = 1, t = ONE; (int)i <= n; ) {
                    431:                        for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
                    432:                                m0 = m; DM(m0,i,c,m)
                    433:                        }
                    434:                        if ( c ) {
                    435:                                m = m0; i--;
                    436:                        }
                    437:                        UTOQ(m,iq); mulq(t,iq,&s); t = s;
                    438:                }
                    439:                *r = t;
                    440:        }
1.8       noro      441: }
                    442: #endif
                    443:
                    444: void partial_factorial(int s,int e,N *r);
                    445:
                    446: void factorial(int n,Q *r)
                    447: {
                    448:        N nm;
                    449:
                    450:        if ( !n )
                    451:                *r = ONE;
                    452:        else if ( n < 0 )
                    453:                *r = 0;
                    454:        else {
                    455:                partial_factorial(1,n,&nm);
                    456:                NTOQ(nm,1,*r);
                    457:        }
                    458: }
                    459:
                    460: /* s*(s+1)*...*e */
                    461: void partial_factorial(int s,int e,N *r)
                    462: {
                    463:        unsigned int len,i,m,m0,c;
                    464:        unsigned int *p,*p1,*p2;
                    465:        N nm,r1,r2;
                    466:
                    467:        /* XXX */
                    468:        if ( e-s > 2000 ) {
                    469:                m = (e+s)/2;
                    470:                partial_factorial(s,m,&r1);
                    471:                partial_factorial(m+1,e,&r2);
                    472:                kmuln(r1,r2,r);
                    473:                return;
                    474:        }
                    475:        /* find i s.t. 2^(i-1) < m <= 2^i */
                    476:        for ( i = 0, m = 1; m < e; m <<=1, i++ );
                    477:         /* XXX estimate of word length of the result */
                    478:        len = (i*(e-s+1)+1+31)/32;
1.9     ! noro      479:        p = ALLOCA((len+1)*sizeof(int));
        !           480:        p1 = ALLOCA((len+1)*sizeof(int));
1.8       noro      481:        p[0] = s;
                    482:        len = 1;
                    483:        for ( i = s+1; (int)i <= e; ) {
                    484:                for ( m0 = m = 1, c = 0; ((int)i <= e) && !c; i++ ) {
                    485:                        m0 = m; DM(m0,i,c,m)
                    486:                }
                    487:                if ( c ) {
                    488:                        m = m0; i--;
                    489:                }
                    490:                bzero(p1,(len+1)*sizeof(int));
                    491:                muln_1(p,len,m,p1);
                    492:                if ( p1[len] )
                    493:                        len++;
                    494:                p2 = p; p = p1; p1 = p2;
                    495:        }
                    496:        *r = nm = NALLOC(len);
                    497:        bcopy(p,BD(nm),sizeof(int)*len);
                    498:        PL(nm) = len;
1.1       noro      499: }
                    500:
1.7       noro      501: void invl(Q a,Q mod,Q *ar)
1.1       noro      502: {
                    503:        Q f1,f2,a1,a2,q,m,s;
                    504:        N qn,rn;
                    505:
                    506:        a1 = ONE; a2 = 0;
                    507:        DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
                    508:
                    509:        while ( 1 ) {
                    510:                divn(NM(f1),NM(f2),&qn,&rn);
                    511:                if ( !qn )
                    512:                        q = 0;
                    513:                else
                    514:                        NTOQ(qn,1,q);
                    515:
                    516:                f1 = f2;
                    517:                if ( !rn )
                    518:                        break;
                    519:                else
                    520:                        NTOQ(rn,1,f2);
                    521:
                    522:                mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
                    523:                if ( !s )
                    524:                        a2 = 0;
                    525:                else
                    526:                        remq(s,mod,&a2);
                    527:        }
                    528:        if ( SGN(a) < 0 )
                    529:                chsgnq(a2,&m);
                    530:        else
                    531:                m = a2;
                    532:
                    533:        if ( SGN(m) >= 0 )
                    534:                *ar = m;
                    535:        else
                    536:                addq(m,mod,ar);
                    537: }
                    538:
                    539: int kara_mag=100;
                    540:
1.7       noro      541: void kmuln(N n1,N n2,N *nr)
1.1       noro      542: {
                    543:        N n,t,s,m,carry;
                    544:        int d,d1,d2,len,i,l;
                    545:        int *r,*r0;
                    546:
                    547:        if ( !n1 || !n2 ) {
                    548:                *nr = 0; return;
                    549:        }
                    550:        d1 = PL(n1); d2 = PL(n2);
                    551:        if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
                    552:                muln(n1,n2,nr); return;
                    553:        }
                    554:        if ( d1 < d2 ) {
                    555:                n = n1; n1 = n2; n2 = n;
                    556:                d = d1; d1 = d2; d2 = d;
                    557:        }
                    558:        if ( d2 > (d1+1)/2 ) {
                    559:                kmulnmain(n1,n2,nr); return;
                    560:        }
                    561:        d = (d1/d2)+((d1%d2)!=0);
                    562:        len = (d+1)*d2;
                    563:        r0 = (int *)ALLOCA(len*sizeof(int));
                    564:        bzero((char *)r0,len*sizeof(int));
                    565:        for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
                    566:                extractn(n1,i*d2,d2,&m);
                    567:                if ( m ) {
                    568:                        kmuln(m,n2,&t);
                    569:                        addn(t,carry,&s);
                    570:                        copyn(s,d2,r);
                    571:                        extractn(s,d2,d2,&carry);
                    572:                } else {
                    573:                        copyn(carry,d2,r);
                    574:                        carry = 0;
                    575:                }
                    576:        }
                    577:        copyn(carry,d2,r);
                    578:        for ( l = len - 1; !r0[l]; l-- );
                    579:        l++;
                    580:        *nr = t = NALLOC(l); PL(t) = l;
                    581:        bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
                    582: }
                    583:
1.7       noro      584: void extractn(N n,int index,int len,N *nr)
1.1       noro      585: {
                    586:        unsigned int *m;
                    587:        int l;
                    588:        N t;
                    589:
                    590:        if ( !n ) {
                    591:                *nr = 0; return;
                    592:        }
                    593:        m = BD(n)+index;
                    594:        if ( (l = PL(n)-index) >= len ) {
                    595:                for ( l = len - 1; (l >= 0) && !m[l]; l-- );
                    596:                l++;
                    597:        }
                    598:        if ( l <= 0 ) {
                    599:                *nr = 0; return;
                    600:        } else {
                    601:                *nr = t = NALLOC(l); PL(t) = l;
                    602:                bcopy((char *)m,(char *)BD(t),l*sizeof(int));
                    603:        }
                    604: }
                    605:
1.7       noro      606: void copyn(N n,int len,int *p)
1.1       noro      607: {
                    608:        if ( n )
                    609:                bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
                    610: }
                    611:
1.7       noro      612: void dupn(N n,N p)
1.1       noro      613: {
                    614:        if ( n )
                    615:                bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
                    616: }
                    617:
1.7       noro      618: void kmulnmain(N n1,N n2,N *nr)
1.1       noro      619: {
                    620:        int d1,d2,h,sgn,sgn1,sgn2,len;
                    621:        N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
                    622:
                    623:        d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
                    624:        extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
                    625:        extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
                    626:        kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
                    627:        len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
                    628:        bzero((char *)BD(t1),len*sizeof(int));
                    629:        if ( lo )
                    630:                bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
                    631:        if ( hi )
                    632:                bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
                    633:
                    634:        addn(hi,lo,&mid1);
                    635:        sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
                    636:        kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
                    637:        if ( sgn > 0 )
                    638:                addn(mid1,mid2,&mid);
                    639:        else
                    640:                subn(mid1,mid2,&mid);
                    641:        if ( mid ) {
                    642:                len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
                    643:                bzero((char *)BD(t2),len*sizeof(int));
                    644:                bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
                    645:                addn(t1,t2,nr);
                    646:        } else
                    647:                *nr = t1;
                    648: }

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