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

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.6     ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2000/engine/Q.c,v 1.5 2000/08/22 05:04:04 noro Exp $
1.4       noro       49: */
1.1       noro       50: #include "ca.h"
                     51: #include "base.h"
                     52: #include "inline.h"
                     53:
                     54: void addq(n1,n2,nr)
                     55: Q n1,n2,*nr;
                     56: {
                     57:        N nm,dn,nm1,nm2,nm3,dn0,dn1,dn2,g,g1,g0,m;
                     58:        int sgn;
                     59:        unsigned t,t1;
                     60:
                     61:        if ( !n1 )
                     62:                *nr = n2;
                     63:        else if ( !n2 )
                     64:                *nr = n1;
                     65:        else if ( INT(n1) )
                     66:                if ( INT(n2) ) {
                     67:                        nm1 = NM(n1); nm2 = NM(n2);
                     68:                        if ( SGN(n1) == SGN(n2) ) {
                     69:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                     70:                                        t1 = BD(nm1)[0]; t = t1+BD(nm2)[0];
                     71:                                        if ( t < t1 ) {
                     72:                                                m = NALLOC(2); PL(m) = 2; BD(m)[0] = t; BD(m)[1] = 1;
                     73:                                        } else
                     74:                                                UTON(t,m);
                     75:                                } else
                     76:                                        addn(NM(n1),NM(n2),&m);
                     77:                                NTOQ(m,SGN(n1),*nr);
                     78:                        } else {
                     79:                                if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                     80:                                        t1 = BD(nm1)[0]; t = t1-BD(nm2)[0];
                     81:                                        if ( !t )
                     82:                                                sgn = 0;
                     83:                                        else if ( t > t1 ) {
                     84:                                                sgn = -1; t = -((int)t); UTON(t,m);
                     85:                                        } else {
                     86:                                                sgn = 1; UTON(t,m);
                     87:                                        }
                     88:                                } else
                     89:                                        sgn = subn(NM(n1),NM(n2),&m);
                     90:                                if ( sgn ) {
                     91:                                        if ( SGN(n1) == sgn )
                     92:                                                NTOQ(m,1,*nr);
                     93:                                        else
                     94:                                                NTOQ(m,-1,*nr);
                     95:                                } else
                     96:                                        *nr = 0;
                     97:                        }
                     98:                } else {
                     99:                        kmuln(NM(n1),DN(n2),&m);
                    100:                        if ( SGN(n1) == SGN(n2) ) {
                    101:                                sgn = SGN(n1); addn(m,NM(n2),&nm);
                    102:                        } else
                    103:                                sgn = SGN(n1)*subn(m,NM(n2),&nm);
                    104:                        if ( sgn ) {
                    105:                                dn = DN(n2); NDTOQ(nm,dn,sgn,*nr);
                    106:                        } else
                    107:                                *nr = 0;
                    108:                }
                    109:        else if ( INT(n2) ) {
                    110:                kmuln(NM(n2),DN(n1),&m);
                    111:                if ( SGN(n1) == SGN(n2) ) {
                    112:                        sgn = SGN(n1); addn(m,NM(n1),&nm);
                    113:                } else
                    114:                        sgn = SGN(n1)*subn(NM(n1),m,&nm);
                    115:                if ( sgn ) {
                    116:                        dn = DN(n1); NDTOQ(nm,dn,sgn,*nr);
                    117:                } else
                    118:                        *nr = 0;
                    119:        } else {
                    120:                gcdn(DN(n1),DN(n2),&g); divsn(DN(n1),g,&dn1); divsn(DN(n2),g,&dn2);
                    121:                kmuln(NM(n1),dn2,&nm1); kmuln(NM(n2),dn1,&nm2);
                    122:                if ( SGN(n1) == SGN(n2) ) {
                    123:                        sgn = SGN(n1); addn(nm1,nm2,&nm3);
                    124:                } else
                    125:                        sgn = SGN(n1)*subn(nm1,nm2,&nm3);
                    126:                if ( sgn ) {
                    127:                        gcdn(nm3,g,&g1); divsn(nm3,g1,&nm); divsn(g,g1,&g0);
                    128:                        kmuln(dn1,dn2,&dn0); kmuln(g0,dn0,&dn);
                    129:                        if ( UNIN(dn) )
                    130:                                NTOQ(nm,sgn,*nr);
                    131:                        else
                    132:                                NDTOQ(nm,dn,sgn,*nr);
                    133:                } else
                    134:                        *nr = 0;
                    135:        }
                    136: }
                    137:
                    138: void subq(n1,n2,nr)
                    139: Q n1,n2,*nr;
                    140: {
                    141:        Q m;
                    142:
                    143:        if ( !n1 )
                    144:                if ( !n2 )
                    145:                        *nr = 0;
                    146:                else {
                    147:                        DUPQ(n2,*nr); SGN(*nr) = -SGN(n2);
                    148:                }
                    149:        else if ( !n2 )
                    150:                *nr = n1;
                    151:        else if ( n1 == n2 )
                    152:                *nr = 0;
                    153:        else {
                    154:                DUPQ(n2,m); SGN(m) = -SGN(n2); addq(n1,m,nr);
                    155:        }
                    156: }
                    157:
                    158: void mulq(n1,n2,nr)
                    159: Q n1,n2,*nr;
                    160: {
                    161:        N nm,nm1,nm2,dn,dn1,dn2,g;
                    162:        int sgn;
                    163:        unsigned u,l;
                    164:
                    165:        if ( !n1 || !n2 ) *nr = 0;
                    166:        else if ( INT(n1) )
                    167:                if ( INT(n2) ) {
                    168:                        nm1 = NM(n1); nm2 = NM(n2);
                    169:                        if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
                    170:                                DM(BD(NM(n1))[0],BD(NM(n2))[0],u,l)
                    171:                                if ( u ) {
                    172:                                        nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = l; BD(nm)[1] = u;
                    173:                                } else {
                    174:                                        nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = l;
                    175:                                }
                    176:                        } else
                    177:                                kmuln(nm1,nm2,&nm);
                    178:                        sgn = (SGN(n1)==SGN(n2)?1:-1); NTOQ(nm,sgn,*nr);
                    179:                } else {
                    180:                        gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn);
                    181:                        kmuln(nm1,NM(n2),&nm); sgn = SGN(n1)*SGN(n2);
                    182:                        if ( UNIN(dn) )
                    183:                                NTOQ(nm,sgn,*nr);
                    184:                        else
                    185:                                NDTOQ(nm,dn,sgn,*nr);
                    186:                }
                    187:        else if ( INT(n2) ) {
                    188:                gcdn(NM(n2),DN(n1),&g); divsn(NM(n2),g,&nm2); divsn(DN(n1),g,&dn);
                    189:                kmuln(nm2,NM(n1),&nm); sgn = SGN(n1)*SGN(n2);
                    190:                if ( UNIN(dn) )
                    191:                        NTOQ(nm,sgn,*nr);
                    192:                else
                    193:                        NDTOQ(nm,dn,sgn,*nr);
                    194:        } else {
                    195:                gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn2);
                    196:                gcdn(DN(n1),NM(n2),&g); divsn(DN(n1),g,&dn1); divsn(NM(n2),g,&nm2);
                    197:                kmuln(nm1,nm2,&nm); kmuln(dn1,dn2,&dn); sgn = SGN(n1) * SGN(n2);
                    198:                if ( UNIN(dn) )
                    199:                        NTOQ(nm,sgn,*nr);
                    200:                else
                    201:                        NDTOQ(nm,dn,sgn,*nr);
                    202:        }
                    203: }
                    204:
                    205: void divq(n1,n2,nq)
                    206: Q n1,n2,*nq;
                    207: {
                    208:        Q m;
                    209:
                    210:        if ( !n2 ) {
                    211:                error("division by 0");
                    212:                *nq = 0;
                    213:                return;
                    214:        } else if ( !n1 )
                    215:                *nq = 0;
                    216:        else if ( n1 == n2 )
                    217:                *nq = ONE;
                    218:        else {
                    219:                invq(n2,&m); mulq(n1,m,nq);
1.6     ! noro      220:        }
        !           221: }
        !           222:
        !           223: void divsq(n1,n2,nq)
        !           224: Q n1,n2,*nq;
        !           225: {
        !           226:        Q m;
        !           227:        int sgn;
        !           228:        N tn;
        !           229:
        !           230:        if ( !n2 ) {
        !           231:                error("division by 0");
        !           232:                *nq = 0;
        !           233:                return;
        !           234:        } else if ( !n1 )
        !           235:                *nq = 0;
        !           236:        else if ( n1 == n2 )
        !           237:                *nq = ONE;
        !           238:        else {
        !           239:                divsn(NM(n1),NM(n2),&tn);
        !           240:                sgn = SGN(n1)*SGN(n2);
        !           241:                NTOQ(tn,sgn,*nq);
1.1       noro      242:        }
                    243: }
                    244:
                    245: void invq(n,nr)
                    246: Q n,*nr;
                    247: {
                    248:        N nm,dn;
                    249:
                    250:        if ( INT(n) )
                    251:                if ( UNIN(NM(n)) )
                    252:                        if ( SGN(n) > 0 )
                    253:                                *nr = ONE;
                    254:                        else {
                    255:                                nm = ONEN; NTOQ(nm,SGN(n),*nr);
                    256:                        }
                    257:                else {
                    258:                        nm = ONEN; dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
                    259:                }
                    260:        else if ( UNIN(NM(n)) ) {
                    261:                nm = DN(n); NTOQ(nm,SGN(n),*nr);
                    262:        } else {
                    263:                nm = DN(n); dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
                    264:        }
                    265: }
                    266:
                    267: void chsgnq(n,nr)
                    268: Q n,*nr;
                    269: {
                    270:        Q t;
                    271:
                    272:        if ( !n )
                    273:                *nr = 0;
                    274:        else {
                    275:                DUPQ(n,t); SGN(t) = -SGN(t); *nr = t;
                    276:        }
                    277: }
                    278:
                    279: void pwrq(n1,n,nr)
                    280: Q n1,n,*nr;
                    281: {
                    282:        N nm,dn;
                    283:        int sgn;
                    284:
                    285:        if ( !n || UNIQ(n1) )
                    286:                *nr = ONE;
                    287:        else if ( !n1 )
                    288:                *nr = 0;
                    289:        else if ( !INT(n) ) {
                    290:                error("can't calculate fractional power."); *nr = 0;
                    291:        } else if ( MUNIQ(n1) )
                    292:                *nr = BD(NM(n))[0]%2 ? n1 : ONE;
                    293:        else if ( PL(NM(n)) > 1 ) {
                    294:                error("exponent too big."); *nr = 0;
                    295:        } else {
                    296:                sgn = ((SGN(n1)>0)||EVENN(NM(n))?1:-1);
                    297:                pwrn(NM(n1),BD(NM(n))[0],&nm);
                    298:                if ( INT(n1) ) {
                    299:                        if ( UNIN(nm) )
                    300:                                if ( sgn == 1 )
                    301:                                        *nr = ONE;
                    302:                                else
                    303:                                        NTOQ(ONEN,sgn,*nr);
                    304:                        else if ( SGN(n) > 0 )
                    305:                                NTOQ(nm,sgn,*nr);
                    306:                        else
                    307:                                NDTOQ(ONEN,nm,sgn,*nr);
                    308:                } else {
                    309:                        pwrn(DN(n1),BD(NM(n))[0],&dn);
                    310:                        if ( SGN(n) > 0 )
                    311:                                NDTOQ(nm,dn,sgn,*nr);
                    312:                        else if ( UNIN(nm) )
                    313:                                NTOQ(dn,sgn,*nr);
                    314:                        else
                    315:                                NDTOQ(dn,nm,sgn,*nr);
                    316:                }
                    317:        }
                    318: }
                    319:
                    320: int cmpq(q1,q2)
                    321: Q q1,q2;
                    322: {
                    323:        int sgn;
                    324:        N t,s;
                    325:
                    326:        if ( !q1 )
                    327:                if ( !q2 )
                    328:                        return ( 0 );
                    329:                else
                    330:                        return ( -SGN(q2) );
                    331:        else if ( !q2 )
                    332:                return ( SGN(q1) );
                    333:        else if ( SGN(q1) != SGN(q2) )
                    334:                        return ( SGN(q1) );
                    335:        else if ( INT(q1) )
                    336:                        if ( INT(q2) ) {
                    337:                                sgn = cmpn(NM(q1),NM(q2));
                    338:                                if ( !sgn )
                    339:                                        return ( 0 );
                    340:                                else
                    341:                                        return ( SGN(q1)==sgn?1:-1 );
                    342:                        } else {
                    343:                                kmuln(NM(q1),DN(q2),&t); sgn = cmpn(t,NM(q2));
                    344:                                return ( SGN(q1) * sgn );
                    345:                        }
                    346:        else if ( INT(q2) ) {
                    347:                kmuln(NM(q2),DN(q1),&t); sgn = cmpn(NM(q1),t);
                    348:                return ( SGN(q1) * sgn );
                    349:        } else {
                    350:                kmuln(NM(q1),DN(q2),&t); kmuln(NM(q2),DN(q1),&s); sgn = cmpn(t,s);
                    351:                return ( SGN(q1) * sgn );
                    352:        }
                    353: }
                    354:
                    355: void remq(n,m,nr)
                    356: Q n,m;
                    357: Q *nr;
                    358: {
                    359:        N q,r,s;
                    360:
                    361:        if ( !n ) {
                    362:                *nr = 0;
                    363:                return;
                    364:        }
                    365:        divn(NM(n),NM(m),&q,&r);
                    366:        if ( !r )
                    367:                *nr = 0;
                    368:        else if ( SGN(n) > 0 )
                    369:                NTOQ(r,1,*nr);
                    370:        else {
                    371:                subn(NM(m),r,&s); NTOQ(s,1,*nr);
                    372:        }
                    373: }
                    374:
1.2       noro      375: /* t = [nC0 nC1 ... nCn] */
                    376:
1.1       noro      377: void mkbc(n,t)
                    378: int n;
                    379: Q *t;
                    380: {
                    381:        int i;
                    382:        N c,d;
                    383:
                    384:        for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
                    385:                c = NALLOC(1); PL(c) = 1; BD(c)[0] = n-i+1;
                    386:                kmuln(NM(t[i-1]),c,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
                    387:        }
                    388:        for ( ; i <= n; i++ )
                    389:                t[i] = t[n-i];
1.2       noro      390: }
                    391:
                    392: /*
                    393:  *  Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
                    394:  *
                    395:  *  t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
                    396:  *  where W(k,l,i) = i! * kCi * lCi
                    397:  */
                    398:
                    399: void mkwc(k,l,t)
                    400: int k,l;
                    401: Q *t;
                    402: {
                    403:        int i,n,up,low;
                    404:        N nm,d,c;
                    405:
                    406:        n = MIN(k,l);
                    407:        for ( t[0] = ONE, i = 1; i <= n; i++ ) {
                    408:                DM(k-i+1,l-i+1,up,low);
                    409:                if ( up ) {
                    410:                        nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = low; BD(nm)[1] = up;
                    411:                } else {
                    412:                        nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = low;
                    413:                }
                    414:                kmuln(NM(t[i-1]),nm,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
1.3       noro      415:        }
                    416: }
                    417:
                    418: /* mod m table */
                    419: /* XXX : should be optimized */
                    420:
                    421: void mkwcm(k,l,m,t)
                    422: int k,l,m;
                    423: int *t;
                    424: {
                    425:        int i,n;
                    426:        Q *s;
                    427:
                    428:        n = MIN(k,l);
                    429:        s = (Q *)ALLOCA((n+1)*sizeof(Q));
                    430:        mkwc(k,l,s);
                    431:        for ( i = 0; i <= n; i++ ) {
                    432:                t[i] = rem(NM(s[i]),m);
1.2       noro      433:        }
1.1       noro      434: }
                    435:
                    436: void factorial(n,r)
                    437: int n;
                    438: Q *r;
                    439: {
                    440:        Q t,iq,s;
                    441:        unsigned int i,m,m0;
                    442:        unsigned int c;
                    443:
                    444:        if ( !n )
                    445:                *r = ONE;
                    446:        else if ( n < 0 )
                    447:                *r = 0;
                    448:        else {
                    449:                for ( i = 1, t = ONE; (int)i <= n; ) {
                    450:                        for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
                    451:                                m0 = m; DM(m0,i,c,m)
                    452:                        }
                    453:                        if ( c ) {
                    454:                                m = m0; i--;
                    455:                        }
                    456:                        UTOQ(m,iq); mulq(t,iq,&s); t = s;
                    457:                }
                    458:                *r = t;
                    459:        }
                    460: }
                    461:
                    462: void invl(a,mod,ar)
                    463: Q a,mod,*ar;
                    464: {
                    465:        Q f1,f2,a1,a2,q,m,s;
                    466:        N qn,rn;
                    467:
                    468:        a1 = ONE; a2 = 0;
                    469:        DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
                    470:
                    471:        while ( 1 ) {
                    472:                divn(NM(f1),NM(f2),&qn,&rn);
                    473:                if ( !qn )
                    474:                        q = 0;
                    475:                else
                    476:                        NTOQ(qn,1,q);
                    477:
                    478:                f1 = f2;
                    479:                if ( !rn )
                    480:                        break;
                    481:                else
                    482:                        NTOQ(rn,1,f2);
                    483:
                    484:                mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
                    485:                if ( !s )
                    486:                        a2 = 0;
                    487:                else
                    488:                        remq(s,mod,&a2);
                    489:        }
                    490:        if ( SGN(a) < 0 )
                    491:                chsgnq(a2,&m);
                    492:        else
                    493:                m = a2;
                    494:
                    495:        if ( SGN(m) >= 0 )
                    496:                *ar = m;
                    497:        else
                    498:                addq(m,mod,ar);
                    499: }
                    500:
                    501: int kara_mag=100;
                    502:
                    503: void kmuln(n1,n2,nr)
                    504: N n1,n2,*nr;
                    505: {
                    506:        N n,t,s,m,carry;
                    507:        int d,d1,d2,len,i,l;
                    508:        int *r,*r0;
                    509:
                    510:        if ( !n1 || !n2 ) {
                    511:                *nr = 0; return;
                    512:        }
                    513:        d1 = PL(n1); d2 = PL(n2);
                    514:        if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
                    515:                muln(n1,n2,nr); return;
                    516:        }
                    517:        if ( d1 < d2 ) {
                    518:                n = n1; n1 = n2; n2 = n;
                    519:                d = d1; d1 = d2; d2 = d;
                    520:        }
                    521:        if ( d2 > (d1+1)/2 ) {
                    522:                kmulnmain(n1,n2,nr); return;
                    523:        }
                    524:        d = (d1/d2)+((d1%d2)!=0);
                    525:        len = (d+1)*d2;
                    526:        r0 = (int *)ALLOCA(len*sizeof(int));
                    527:        bzero((char *)r0,len*sizeof(int));
                    528:        for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
                    529:                extractn(n1,i*d2,d2,&m);
                    530:                if ( m ) {
                    531:                        kmuln(m,n2,&t);
                    532:                        addn(t,carry,&s);
                    533:                        copyn(s,d2,r);
                    534:                        extractn(s,d2,d2,&carry);
                    535:                } else {
                    536:                        copyn(carry,d2,r);
                    537:                        carry = 0;
                    538:                }
                    539:        }
                    540:        copyn(carry,d2,r);
                    541:        for ( l = len - 1; !r0[l]; l-- );
                    542:        l++;
                    543:        *nr = t = NALLOC(l); PL(t) = l;
                    544:        bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
                    545: }
                    546:
                    547: void extractn(n,index,len,nr)
                    548: N n;
                    549: int index,len;
                    550: N *nr;
                    551: {
                    552:        unsigned int *m;
                    553:        int l;
                    554:        N t;
                    555:
                    556:        if ( !n ) {
                    557:                *nr = 0; return;
                    558:        }
                    559:        m = BD(n)+index;
                    560:        if ( (l = PL(n)-index) >= len ) {
                    561:                for ( l = len - 1; (l >= 0) && !m[l]; l-- );
                    562:                l++;
                    563:        }
                    564:        if ( l <= 0 ) {
                    565:                *nr = 0; return;
                    566:        } else {
                    567:                *nr = t = NALLOC(l); PL(t) = l;
                    568:                bcopy((char *)m,(char *)BD(t),l*sizeof(int));
                    569:        }
                    570: }
                    571:
                    572: void copyn(n,len,p)
                    573: N n;
                    574: int len;
                    575: int *p;
                    576: {
                    577:        if ( n )
                    578:                bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
                    579: }
                    580:
                    581: void dupn(n,p)
                    582: N n;
                    583: N p;
                    584: {
                    585:        if ( n )
                    586:                bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
                    587: }
                    588:
                    589: void kmulnmain(n1,n2,nr)
                    590: N n1,n2,*nr;
                    591: {
                    592:        int d1,d2,h,sgn,sgn1,sgn2,len;
                    593:        N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
                    594:
                    595:        d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
                    596:        extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
                    597:        extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
                    598:        kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
                    599:        len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
                    600:        bzero((char *)BD(t1),len*sizeof(int));
                    601:        if ( lo )
                    602:                bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
                    603:        if ( hi )
                    604:                bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
                    605:
                    606:        addn(hi,lo,&mid1);
                    607:        sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
                    608:        kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
                    609:        if ( sgn > 0 )
                    610:                addn(mid1,mid2,&mid);
                    611:        else
                    612:                subn(mid1,mid2,&mid);
                    613:        if ( mid ) {
                    614:                len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
                    615:                bzero((char *)BD(t2),len*sizeof(int));
                    616:                bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
                    617:                addn(t1,t2,nr);
                    618:        } else
                    619:                *nr = t1;
                    620: }

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