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

Annotation of OpenXM_contrib2/asir2000/builtin/int.c, Revision 1.3

1.3     ! noro        1: /* $OpenXM: OpenXM_contrib2/asir2000/builtin/int.c,v 1.2 2000/01/11 06:43:35 noro Exp $ */
1.1       noro        2: #include "ca.h"
                      3: #include "parse.h"
                      4: #include "base.h"
                      5:
                      6: void Pidiv(), Pirem(), Pigcd(), Pilcm(), Pfac(), Prandom(), Pinv();
                      7: void Pup2_inv(),Pgf2nton(), Pntogf2n();
                      8: void Pup2_init_eg(), Pup2_show_eg();
                      9: void Piqr(), Pprime(), Plprime(), Pinttorat();
                     10: void Piand(), Pior(), Pixor(), Pishift();
                     11: void Pisqrt();
                     12: void iand(), ior(), ixor();
                     13: void isqrt();
                     14: void Plrandom();
                     15: void Pset_upkara(), Pset_uptkara(), Pset_up2kara(), Pset_upfft();
                     16: void Pmt_save(), Pmt_load();
                     17: void Psmall_jacobi();
                     18: void Pdp_set_mpi();
1.2       noro       19: void Pntoint32(),Pint32ton();
1.1       noro       20:
                     21: #ifdef HMEXT
                     22: void Pigcdbin(), Pigcdbmod(), PigcdEuc(), Pigcdacc(), Pigcdcntl();
                     23:
                     24: void Pihex();
                     25: void Pimaxrsh(), Pilen();
                     26: void Ptype_t_NB();
                     27:
                     28: #endif /* HMEXT */
                     29:
                     30: struct ftab int_tab[] = {
                     31:        {"dp_set_mpi",Pdp_set_mpi,-1},
                     32:        {"isqrt",Pisqrt,1},
                     33:        {"idiv",Pidiv,2},
                     34:        {"irem",Pirem,2},
                     35:        {"iqr",Piqr,2},
                     36:        {"igcd",Pigcd,-2},
                     37:        {"ilcm",Pilcm,2},
                     38:        {"up2_inv",Pup2_inv,2},
                     39:        {"up2_init_eg",Pup2_init_eg,0},
                     40:        {"up2_show_eg",Pup2_show_eg,0},
                     41:        {"type_t_NB",Ptype_t_NB,2},
                     42:        {"gf2nton",Pgf2nton,1},
                     43:        {"ntogf2n",Pntogf2n,1},
                     44:        {"set_upkara",Pset_upkara,-1},
                     45:        {"set_uptkara",Pset_uptkara,-1},
                     46:        {"set_up2kara",Pset_up2kara,-1},
                     47:        {"set_upfft",Pset_upfft,-1},
                     48:        {"inv",Pinv,2},
                     49:        {"inttorat",Pinttorat,3},
                     50:        {"fac",Pfac,1},
                     51:        {"prime",Pprime,1},
                     52:        {"lprime",Plprime,1},
                     53:        {"random",Prandom,-1},
                     54:        {"lrandom",Plrandom,1},
                     55:        {"iand",Piand,2},
                     56:        {"ior",Pior,2},
                     57:        {"ixor",Pixor,2},
                     58:        {"ishift",Pishift,2},
                     59:        {"small_jacobi",Psmall_jacobi,2},
                     60: #ifdef HMEXT
                     61:        {"igcdbin",Pigcdbin,2},         /* HM@CCUT extension */
                     62:        {"igcdbmod",Pigcdbmod,2},       /* HM@CCUT extension */
                     63:        {"igcdeuc",PigcdEuc,2},         /* HM@CCUT extension */
                     64:        {"igcdacc",Pigcdacc,2},         /* HM@CCUT extension */
                     65:        {"igcdcntl",Pigcdcntl,-1},      /* HM@CCUT extension */
                     66:        {"ihex",Pihex,1},       /* HM@CCUT extension */
                     67:        {"imaxrsh",Pimaxrsh,1}, /* HM@CCUT extension */
                     68:        {"ilen",Pilen,1},       /* HM@CCUT extension */
                     69: #endif /* HMEXT */
                     70:        {"mt_save",Pmt_save,1},
                     71:        {"mt_load",Pmt_load,1},
1.2       noro       72:        {"ntoint32",Pntoint32,1},
                     73:        {"int32ton",Pint32ton,1},
1.1       noro       74:        {0,0,0},
                     75: };
                     76:
                     77: static int is_prime_small(unsigned int);
                     78: static unsigned int gcd_small(unsigned int,unsigned int);
                     79: int TypeT_NB_check(unsigned int, unsigned int);
                     80: int mpi_mag;
1.2       noro       81:
                     82: void Pntoint32(arg,rp)
                     83: NODE arg;
                     84: USINT *rp;
                     85: {
                     86:        Q q;
1.3     ! noro       87:        unsigned int t;
1.2       noro       88:
                     89:        asir_assert(ARG0(arg),O_N,"ntoint32");
                     90:        q = (Q)ARG0(arg);
                     91:        if ( !q ) {
                     92:                MKUSINT(*rp,0);
                     93:                return;
                     94:        }
1.3     ! noro       95:        if ( NID(q)!=N_Q || !INT(q) || PL(NM(q))>1 )
1.2       noro       96:                error("ntoint32 : invalid argument");
1.3     ! noro       97:        t = BD(NM(q))[0];
        !            98:        if ( SGN(q) < 0 )
        !            99:                t = -t;
        !           100:        MKUSINT(*rp,t);
1.2       noro      101: }
                    102:
                    103: void Pint32ton(arg,rp)
                    104: NODE arg;
                    105: Q *rp;
                    106: {
1.3     ! noro      107:        int t;
1.2       noro      108:
                    109:        asir_assert(ARG0(arg),O_USINT,"int32ton");
1.3     ! noro      110:        t = (int)BDY((USINT)ARG0(arg));
        !           111:        STOQ(t,*rp);
1.2       noro      112: }
1.1       noro      113:
                    114: void Pdp_set_mpi(arg,rp)
                    115: NODE arg;
                    116: Q *rp;
                    117: {
                    118:        if ( arg ) {
                    119:                asir_assert(ARG0(arg),O_N,"dp_set_mpi");
                    120:                mpi_mag = QTOS((Q)ARG0(arg));
                    121:        }
                    122:        STOQ(mpi_mag,*rp);
                    123: }
                    124:
                    125: void Psmall_jacobi(arg,rp)
                    126: NODE arg;
                    127: Q *rp;
                    128: {
                    129:        Q a,m;
                    130:        int a0,m0,s;
                    131:
                    132:        a = (Q)ARG0(arg);
                    133:        m = (Q)ARG1(arg);
                    134:        asir_assert(a,O_N,"small_jacobi");
                    135:        asir_assert(m,O_N,"small_jacobi");
                    136:        if ( !a )
                    137:                 *rp = ONE;
                    138:        else if ( !m || !INT(m) || !INT(a)
                    139:                || PL(NM(m))>1 || PL(NM(a))>1 || SGN(m) < 0 || EVENN(NM(m)) )
                    140:                error("small_jacobi : invalid input");
                    141:        else {
                    142:                a0 = QTOS(a); m0 = QTOS(m);
                    143:                s = small_jacobi(a0,m0);
                    144:                STOQ(s,*rp);
                    145:        }
                    146: }
                    147:
                    148: int small_jacobi(a,m)
                    149: int a,m;
                    150: {
                    151:        int m4,m8,a4,j1,i,s;
                    152:
                    153:        a %= m;
                    154:        if ( a == 0 || a == 1 )
                    155:                return 1;
                    156:        else if ( a < 0 ) {
                    157:                j1 = small_jacobi(-a,m);
                    158:                m4 = m%4;
                    159:                return m4==1?j1:-j1;
                    160:        } else {
                    161:                for ( i = 0; a && !(a&1); i++, a >>= 1 );
                    162:                if ( i&1 ) {
                    163:                        m8 = m%8;
                    164:                        s = (m8==1||m8==7) ? 1 : -1;
                    165:                } else
                    166:                        s = 1;
                    167:                /* a, m are odd */
                    168:                j1 = small_jacobi(m%a,a);
                    169:                m4 = m%4; a4 = a%4;
                    170:                s *= (m4==1||a4==1) ? 1 : -1;
                    171:                return j1*s;
                    172:        }
                    173: }
                    174:
                    175: void Ptype_t_NB(arg,rp)
                    176: NODE arg;
                    177: Q *rp;
                    178: {
                    179:        if ( TypeT_NB_check(QTOS((Q)ARG0(arg)),QTOS((Q)ARG1(arg))))
                    180:                *rp = ONE;
                    181:        else
                    182:                *rp = 0;
                    183: }
                    184:
                    185: int TypeT_NB_check(unsigned int m, unsigned int t)
                    186: {
                    187:        unsigned int p,k,u,h,d;
                    188:
                    189:        if ( !(m%8) )
                    190:                return 0;
                    191:        p = t*m+1;
                    192:        if ( !is_prime_small(p) )
                    193:                return 0;
                    194:        for ( k = 1, u = 2%p; ; k++ )
                    195:                if ( u == 1 )
                    196:                        break;
                    197:                else
                    198:                        u = (2*u)%p;
                    199:        h = t*m/k;
                    200:        d = gcd_small(h,m);
                    201:        return d == 1 ? 1 : 0;
                    202: }
                    203:
                    204: /*
                    205:  * a simple prime checker
                    206:  * return value: 1  ---  prime number
                    207:  *               0  ---  composite number
                    208:  */
                    209:
                    210: static int is_prime_small(unsigned int a)
                    211: {
                    212:        unsigned int b,t,i;
                    213:
                    214:        if ( !(a%2) ) return 0;
                    215:        for ( t = a, i = 0; t; i++, t >>= 1 );
                    216:        /* b >= sqrt(a) */
                    217:        b = 1<<((i+1)/2);
                    218:
                    219:        /* divisibility test by all odd numbers <= b */
                    220:        for ( i = 3; i <= b; i += 2 )
                    221:                if ( !(a%i) )
                    222:                        return 0;
                    223:        return 1;
                    224: }
                    225:
                    226: /*
                    227:  * gcd for unsigned int as integers
                    228:  * return value: GCD(a,b)
                    229:  *
                    230:  */
                    231:
                    232:
                    233: static unsigned int gcd_small(unsigned int a,unsigned int b)
                    234: {
                    235:        unsigned int t;
                    236:
                    237:        if ( b > a ) {
                    238:                t = a; a = b; b = t;
                    239:        }
                    240:        /* Euclid's algorithm */
                    241:        while ( 1 )
                    242:                if ( !(t = a%b) ) return b;
                    243:                else {
                    244:                        a = b; b = t;
                    245:                }
                    246: }
                    247:
                    248: void Pmt_save(arg,rp)
                    249: NODE arg;
                    250: Q *rp;
                    251: {
                    252:        int ret;
                    253:
                    254:        ret = mt_save(BDY((STRING)ARG0(arg)));
                    255:        STOQ(ret,*rp);
                    256: }
                    257:
                    258: void Pmt_load(arg,rp)
                    259: NODE arg;
                    260: Q *rp;
                    261: {
                    262:        int ret;
                    263:
                    264:        ret = mt_load(BDY((STRING)ARG0(arg)));
                    265:        STOQ(ret,*rp);
                    266: }
                    267:
                    268: void Pisqrt(arg,rp)
                    269: NODE arg;
                    270: Q *rp;
                    271: {
                    272:        Q a;
                    273:        N r;
                    274:
                    275:        a = (Q)ARG0(arg);
                    276:        asir_assert(a,O_N,"isqrt");
                    277:        if ( !a )
                    278:                *rp = 0;
                    279:        else if ( SGN(a) < 0 )
                    280:                error("isqrt : negative argument");
                    281:        else {
                    282:                isqrt(NM(a),&r);
                    283:                NTOQ(r,1,*rp);
                    284:        }
                    285: }
                    286:
                    287: void Pidiv(arg,rp)
                    288: NODE arg;
                    289: Obj *rp;
                    290: {
                    291:        N q,r;
                    292:        Q a;
                    293:        Q dnd,dvr;
                    294:
                    295:        dnd = (Q)ARG0(arg); dvr = (Q)ARG1(arg);
                    296:        asir_assert(dnd,O_N,"idiv");
                    297:        asir_assert(dvr,O_N,"idiv");
                    298:        if ( !dvr )
                    299:                error("idiv: division by 0");
                    300:        else if ( !dnd )
                    301:                *rp = 0;
                    302:        else {
                    303:                divn(NM(dnd),NM(dvr),&q,&r);
                    304:                NTOQ(q,SGN(dnd)*SGN(dvr),a); *rp = (Obj)a;
                    305:        }
                    306: }
                    307:
                    308: void Pirem(arg,rp)
                    309: NODE arg;
                    310: Obj *rp;
                    311: {
                    312:        N q,r;
                    313:        Q a;
                    314:        Q dnd,dvr;
                    315:
                    316:        dnd = (Q)ARG0(arg); dvr = (Q)ARG1(arg);
                    317:        asir_assert(dnd,O_N,"irem");
                    318:        asir_assert(dvr,O_N,"irem");
                    319:        if ( !dvr )
                    320:                error("irem: division by 0");
                    321:        else if ( !dnd )
                    322:                *rp = 0;
                    323:        else {
                    324:                divn(NM(dnd),NM(dvr),&q,&r);
                    325:                NTOQ(r,SGN(dnd),a); *rp = (Obj)a;
                    326:        }
                    327: }
                    328:
                    329: void Piqr(arg,rp)
                    330: NODE arg;
                    331: LIST *rp;
                    332: {
                    333:        N q,r;
                    334:        Q a,b;
                    335:        Q dnd,dvr;
                    336:        NODE node1,node2;
                    337:
                    338:        dnd = (Q)ARG0(arg); dvr = (Q)ARG1(arg);
                    339:        if ( !dvr )
                    340:                error("iqr: division by 0");
                    341:        else if ( !dnd )
                    342:                a = b = 0;
                    343:        else if ( OID(dnd) == O_VECT ) {
                    344:                iqrv((VECT)dnd,dvr,rp); return;
                    345:        } else {
                    346:                asir_assert(dnd,O_N,"iqr");
                    347:                asir_assert(dvr,O_N,"iqr");
                    348:                divn(NM(dnd),NM(dvr),&q,&r);
                    349:                NTOQ(q,SGN(dnd)*SGN(dvr),a);
                    350:                NTOQ(r,SGN(dnd),b);
                    351:        }
                    352:        MKNODE(node2,b,0); MKNODE(node1,a,node2); MKLIST(*rp,node1);
                    353: }
                    354:
                    355: void Pinttorat(arg,rp)
                    356: NODE arg;
                    357: LIST *rp;
                    358: {
                    359:        Q cq,qq,t,u1,v1,r1,nm;
                    360:        N m,b,q,r,c,u2,v2,r2;
                    361:        NODE node1,node2;
                    362:        P p;
                    363:
                    364:        asir_assert(ARG0(arg),O_N,"inttorat");
                    365:        asir_assert(ARG1(arg),O_N,"inttorat");
                    366:        asir_assert(ARG2(arg),O_N,"inttorat");
                    367:        cq = (Q)ARG0(arg); m = NM((Q)ARG1(arg)); b = NM((Q)ARG2(arg));
                    368:        if ( !cq ) {
                    369:                MKNODE(node2,(pointer)ONE,0); MKNODE(node1,0,node2); MKLIST(*rp,node1);
                    370:                return;
                    371:        }
                    372:        divn(NM(cq),m,&q,&r);
                    373:        if ( !r ) {
                    374:                MKNODE(node2,(pointer)ONE,0); MKNODE(node1,0,node2); MKLIST(*rp,node1);
                    375:                return;
                    376:        } else if ( SGN(cq) < 0 ) {
                    377:                subn(m,r,&c);
                    378:        } else
                    379:                c = r;
                    380:        u1 = 0; v1 = ONE; u2 = m; v2 = c;
                    381:        while ( cmpn(v2,b) >= 0 ) {
                    382:                divn(u2,v2,&q,&r2); u2 = v2; v2 = r2;
                    383:                NTOQ(q,1,qq); mulq(qq,v1,&t); subq(u1,t,&r1); u1 = v1; v1 = r1;
                    384:        }
                    385:        if ( cmpn(NM(v1),b) >= 0 )
                    386:                *rp = 0;
                    387:        else {
                    388:                if ( SGN(v1) < 0 ) {
                    389:                        chsgnp((P)v1,&p); v1 = (Q)p; NTOQ(v2,-1,nm);
                    390:                } else
                    391:                        NTOQ(v2,1,nm);
                    392:                MKNODE(node2,v1,0); MKNODE(node1,nm,node2); MKLIST(*rp,node1);
                    393:        }
                    394: }
                    395:
                    396: void Pigcd(arg,rp)
                    397: NODE arg;
                    398: Q *rp;
                    399: {
                    400:        N g;
                    401:        Q n1,n2,a;
                    402:
                    403:        if ( argc(arg) == 1 ) {
                    404:                igcdv((VECT)ARG0(arg),rp);
                    405:                return;
                    406:        }
                    407:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    408:        asir_assert(n1,O_N,"igcd");
                    409:        asir_assert(n2,O_N,"igcd");
                    410:        if ( !n1 )
                    411:                *rp = n2;
                    412:        else if ( !n2 )
                    413:                *rp = n1;
                    414:        else {
                    415:                gcdn(NM(n1),NM(n2),&g);
                    416:                NTOQ(g,1,a); *rp = a;
                    417:        }
                    418: }
                    419:
                    420: int comp_n(a,b)
                    421: N *a,*b;
                    422: {
                    423:        return cmpn(*a,*b);
                    424: }
                    425:
                    426: void iqrv(a,dvr,rp)
                    427: VECT a;
                    428: Q dvr;
                    429: LIST *rp;
                    430: {
                    431:        int i,n;
                    432:        VECT q,r;
                    433:        Q dnd,qi,ri;
                    434:        Q *b;
                    435:        N qn,rn;
                    436:        NODE n0,n1;
                    437:
                    438:        if ( !dvr )
                    439:                error("iqrv: division by 0");
                    440:        n = a->len; b = (Q *)BDY(a);
                    441:        MKVECT(q,n); MKVECT(r,n);
                    442:        for ( i = 0; i < n; i++ ) {
                    443:                dnd = b[i];
                    444:                if ( !dnd ) {
                    445:                        qi = ri = 0;
                    446:                } else {
                    447:                        divn(NM(dnd),NM(dvr),&qn,&rn);
                    448:                        NTOQ(qn,SGN(dnd)*SGN(dvr),qi);
                    449:                        NTOQ(rn,SGN(dnd),ri);
                    450:                }
                    451:                BDY(q)[i] = (pointer)qi; BDY(r)[i] = (pointer)ri;
                    452:        }
                    453:        MKNODE(n1,r,0); MKNODE(n0,q,n1); MKLIST(*rp,n0);
                    454: }
                    455:
                    456: void igcdv(a,rp)
                    457: VECT a;
                    458: Q *rp;
                    459: {
                    460:        int i,j,n,nz;
                    461:        N g,gt,q,r;
                    462:        N *c;
                    463:
                    464:        n = a->len;
                    465:        c = (N *)ALLOCA(n*sizeof(N));
                    466:        for ( i = 0; i < n; i++ )
                    467:                c[i] = BDY(a)[i]?NM((Q)(BDY(a)[i])):0;
                    468:        qsort(c,n,sizeof(N),(int (*) (const void *,const void *))comp_n);
                    469:        for ( ; n && ! *c; n--, c++ );
                    470:
                    471:        if ( !n ) {
                    472:                *rp = 0; return;
                    473:        } else if ( n == 1 ) {
                    474:                NTOQ(*c,1,*rp); return;
                    475:        }
                    476:        gcdn(c[0],c[1],&g);
                    477:        for ( i = 2; i < n; i++ ) {
                    478:                divn(c[i],g,&q,&r);
                    479:                gcdn(g,r,&gt);
                    480:                if ( !cmpn(g,gt) ) {
                    481:                        for ( j = i+1, nz = 0; j < n; j++ ) {
                    482:                                divn(c[j],g,&q,&r); c[j] = r;
                    483:                                if ( r )
                    484:                                        nz = 1;
                    485:                        }
                    486:                } else
                    487:                        g = gt;
                    488:        }
                    489:        NTOQ(g,1,*rp);
                    490: }
                    491:
                    492: void igcdv_estimate(a,rp)
                    493: VECT a;
                    494: Q *rp;
                    495: {
                    496:        int n,i,m;
                    497:        N s,t,u,g;
                    498:        Q *q;
                    499:
                    500:        n = a->len; q = (Q *)a->body;
                    501:        if ( n == 1 ) {
                    502:                NTOQ(NM(q[0]),1,*rp); return;
                    503:        }
                    504:
                    505:        m = n/2;
                    506:        for ( i = 0 , s = 0; i < m; i++ ) {
                    507:                addn(s,NM(q[i]),&u); s = u;
                    508:        }
                    509:        for ( t = 0; i < n; i++ ) {
                    510:                addn(t,NM(q[i]),&u); t = u;
                    511:        }
                    512:        gcdn(s,t,&g); NTOQ(g,1,*rp);
                    513: }
                    514:
                    515: void Pilcm(arg,rp)
                    516: NODE arg;
                    517: Obj *rp;
                    518: {
                    519:        N g,q,r,l;
                    520:        Q n1,n2,a;
                    521:
                    522:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    523:        asir_assert(n1,O_N,"ilcm");
                    524:        asir_assert(n2,O_N,"ilcm");
                    525:        if ( !n1 || !n2 )
                    526:                *rp = 0;
                    527:        else {
                    528:                gcdn(NM(n1),NM(n2),&g); divn(NM(n1),g,&q,&r);
                    529:                muln(q,NM(n2),&l); NTOQ(l,1,a); *rp = (Obj)a;
                    530:        }
                    531: }
                    532:
                    533: void Piand(arg,rp)
                    534: NODE arg;
                    535: Q *rp;
                    536: {
                    537:        N g;
                    538:        Q n1,n2,a;
                    539:
                    540:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    541:        asir_assert(n1,O_N,"iand");
                    542:        asir_assert(n2,O_N,"iand");
                    543:        if ( !n1 || !n2 )
                    544:                *rp = 0;
                    545:        else {
                    546:                iand(NM(n1),NM(n2),&g);
                    547:                NTOQ(g,1,a); *rp = a;
                    548:        }
                    549: }
                    550:
                    551: void Pior(arg,rp)
                    552: NODE arg;
                    553: Q *rp;
                    554: {
                    555:        N g;
                    556:        Q n1,n2,a;
                    557:
                    558:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    559:        asir_assert(n1,O_N,"ior");
                    560:        asir_assert(n2,O_N,"ior");
                    561:        if ( !n1 )
                    562:                *rp = n2;
                    563:        else if ( !n2 )
                    564:                *rp = n1;
                    565:        else {
                    566:                ior(NM(n1),NM(n2),&g);
                    567:                NTOQ(g,1,a); *rp = a;
                    568:        }
                    569: }
                    570:
                    571: void Pixor(arg,rp)
                    572: NODE arg;
                    573: Q *rp;
                    574: {
                    575:        N g;
                    576:        Q n1,n2,a;
                    577:
                    578:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    579:        asir_assert(n1,O_N,"ixor");
                    580:        asir_assert(n2,O_N,"ixor");
                    581:        if ( !n1 )
                    582:                *rp = n2;
                    583:        else if ( !n2 )
                    584:                *rp = n1;
                    585:        else {
                    586:                ixor(NM(n1),NM(n2),&g);
                    587:                NTOQ(g,1,a); *rp = a;
                    588:        }
                    589: }
                    590:
                    591: void Pishift(arg,rp)
                    592: NODE arg;
                    593: Q *rp;
                    594: {
                    595:        N g;
                    596:        Q n1,s,a;
                    597:
                    598:        n1 = (Q)ARG0(arg); s = (Q)ARG1(arg);
                    599:        asir_assert(n1,O_N,"ixor");
                    600:        asir_assert(s,O_N,"ixor");
                    601:        if ( !n1 )
                    602:                *rp = 0;
                    603:        else if ( !s )
                    604:                *rp = n1;
                    605:        else {
                    606:                bshiftn(NM(n1),QTOS(s),&g);
                    607:                NTOQ(g,1,a); *rp = a;
                    608:        }
                    609: }
                    610:
                    611: void isqrt(a,r)
                    612: N a,*r;
                    613: {
                    614:        int k;
                    615:        N x,t,x2,xh,quo,rem;
                    616:
                    617:        if ( !a )
                    618:                *r = 0;
                    619:        else if ( UNIN(a) )
                    620:                *r = ONEN;
                    621:        else {
                    622:                k = n_bits(a); /* a <= 2^k-1 */
                    623:                bshiftn(ONEN,-((k>>1)+(k&1)),&x); /* a <= x^2 */
                    624:                while ( 1 ) {
                    625:                        pwrn(x,2,&t);
                    626:                        if ( cmpn(t,a) <= 0 ) {
                    627:                                *r = x; return;
                    628:                        } else {
                    629:                                if ( BD(x)[0] & 1 )
                    630:                                        addn(x,a,&t);
                    631:                                else
                    632:                                        t = a;
                    633:                                bshiftn(x,-1,&x2); divn(t,x2,&quo,&rem);
                    634:                                bshiftn(x,1,&xh); addn(quo,xh,&x);
                    635:                        }
                    636:                }
                    637:        }
                    638: }
                    639:
                    640: void iand(n1,n2,r)
                    641: N n1,n2,*r;
                    642: {
                    643:        int d1,d2,d,i;
                    644:        N nr;
                    645:        int *p1,*p2,*pr;
                    646:
                    647:        d1 = PL(n1); d2 = PL(n2);
                    648:        d = MIN(d1,d2);
                    649:        nr = NALLOC(d);
                    650:        for ( i = 0, p1 = BD(n1), p2 = BD(n2), pr = BD(nr); i < d; i++ )
                    651:                pr[i] = p1[i] & p2[i];
                    652:        for ( i = d-1; i >= 0 && !pr[i]; i-- );
                    653:        if ( i < 0 )
                    654:                *r = 0;
                    655:        else {
                    656:                PL(nr) = i+1; *r = nr;
                    657:        }
                    658: }
                    659:
                    660: void ior(n1,n2,r)
                    661: N n1,n2,*r;
                    662: {
                    663:        int d1,d2,i;
                    664:        N nr;
                    665:        int *p1,*p2,*pr;
                    666:
                    667:        if ( PL(n1) < PL(n2) ) {
                    668:                nr = n1; n1 = n2; n2 = nr;
                    669:        }
                    670:        d1 = PL(n1); d2 = PL(n2);
                    671:        *r = nr = NALLOC(d1);
                    672:        for ( i = 0, p1 = BD(n1), p2 = BD(n2), pr = BD(nr); i < d2; i++ )
                    673:                pr[i] = p1[i] | p2[i];
                    674:        for ( ; i < d1; i++ )
                    675:                pr[i] = p1[i];
                    676:        for ( i = d1-1; i >= 0 && !pr[i]; i-- );
                    677:        if ( i < 0 )
                    678:                *r = 0;
                    679:        else {
                    680:                PL(nr) = i+1; *r = nr;
                    681:        }
                    682: }
                    683:
                    684: void ixor(n1,n2,r)
                    685: N n1,n2,*r;
                    686: {
                    687:        int d1,d2,i;
                    688:        N nr;
                    689:        int *p1,*p2,*pr;
                    690:
                    691:        if ( PL(n1) < PL(n2) ) {
                    692:                nr = n1; n1 = n2; n2 = nr;
                    693:        }
                    694:        d1 = PL(n1); d2 = PL(n2);
                    695:        *r = nr = NALLOC(d1);
                    696:        for ( i = 0, p1 = BD(n1), p2 = BD(n2), pr = BD(nr); i < d2; i++ )
                    697:                pr[i] = p1[i] ^ p2[i];
                    698:        for ( ; i < d1; i++ )
                    699:                pr[i] = p1[i];
                    700:        for ( i = d1-1; i >= 0 && !pr[i]; i-- );
                    701:        if ( i < 0 )
                    702:                *r = 0;
                    703:        else {
                    704:                PL(nr) = i+1; *r = nr;
                    705:        }
                    706: }
                    707:
                    708: void Pup2_init_eg(rp)
                    709: Obj *rp;
                    710: {
                    711:        up2_init_eg();
                    712:        *rp = 0;
                    713: }
                    714:
                    715: void Pup2_show_eg(rp)
                    716: Obj *rp;
                    717: {
                    718:        up2_show_eg();
                    719:        *rp = 0;
                    720: }
                    721:
                    722: void Pgf2nton(arg,rp)
                    723: NODE arg;
                    724: Q *rp;
                    725: {
                    726:        if ( !ARG0(arg) )
                    727:                *rp = 0;
                    728:        else
                    729:                up2ton(((GF2N)ARG0(arg))->body,rp);
                    730: }
                    731:
                    732: void Pntogf2n(arg,rp)
                    733: NODE arg;
                    734: GF2N *rp;
                    735: {
                    736:        UP2 t;
                    737:
                    738:        ntoup2(ARG0(arg),&t);
                    739:        MKGF2N(t,*rp);
                    740: }
                    741:
                    742: void Pup2_inv(arg,rp)
                    743: NODE arg;
                    744: P *rp;
                    745: {
                    746:        UP2 a,b,t;
                    747:
                    748:        ptoup2(ARG0(arg),&a);
                    749:        ptoup2(ARG1(arg),&b);
                    750:        invup2(a,b,&t);
                    751:        up2top(t,rp);
                    752: }
                    753:
                    754: void Pinv(arg,rp)
                    755: NODE arg;
                    756: Num *rp;
                    757: {
                    758:        Num n;
                    759:        Q mod;
                    760:        MQ r;
                    761:        int inv;
                    762:
                    763:        n = (Num)ARG0(arg); mod = (Q)ARG1(arg);
                    764:        asir_assert(n,O_N,"inv");
                    765:        asir_assert(mod,O_N,"inv");
                    766:        if ( !n || !mod )
                    767:                error("inv: invalid input");
                    768:        else
                    769:                switch ( NID(n) ) {
                    770:                        case N_Q:
                    771:                                invl((Q)n,mod,(Q *)rp);
                    772:                                break;
                    773:                        case N_M:
                    774:                                inv = invm(CONT((MQ)n),QTOS(mod));
                    775:                                STOMQ(inv,r);
                    776:                                *rp = (Num)r;
                    777:                                break;
                    778:                        default:
                    779:                                error("inv: invalid input");
                    780:                }
                    781: }
                    782:
                    783: void Pfac(arg,rp)
                    784: NODE arg;
                    785: Q *rp;
                    786: {
                    787:        asir_assert(ARG0(arg),O_N,"fac");
                    788:        factorial(QTOS((Q)ARG0(arg)),rp);
                    789: }
                    790:
                    791: void Plrandom(arg,rp)
                    792: NODE arg;
                    793: Q *rp;
                    794: {
                    795:        N r;
                    796:
                    797:        asir_assert(ARG0(arg),O_N,"lrandom");
                    798:        randomn(QTOS((Q)ARG0(arg)),&r);
                    799:        NTOQ(r,1,*rp);
                    800: }
                    801:
                    802: void Prandom(arg,rp)
                    803: NODE arg;
                    804: Q *rp;
                    805: {
                    806:        unsigned int r;
                    807:
                    808: #if 0
                    809: #if defined(_PA_RISC1_1)
                    810:        r = mrand48()&BMASK;
                    811: #else
                    812:        if ( arg )
                    813:                srandom(QTOS((Q)ARG0(arg)));
                    814:        r = random()&BMASK;
                    815: #endif
                    816: #endif
                    817:        if ( arg )
                    818:                mt_sgenrand(QTOS((Q)ARG0(arg)));
                    819:        r = mt_genrand();
                    820:        UTOQ(r,*rp);
                    821: }
                    822:
                    823: #if defined(VISUAL) || defined(THINK_C)
                    824: void srandom(unsigned int);
                    825:
                    826: static unsigned int R_Next;
                    827:
                    828: unsigned int random() {
                    829:         if ( !R_Next )
                    830:                 R_Next = 1;
                    831:         return R_Next = (R_Next * 1103515245 + 12345);
                    832: }
                    833:
                    834: void srandom(s)
                    835: unsigned int s;
                    836: {
                    837:                if ( s )
                    838:                        R_Next = s;
                    839:         else if ( !R_Next )
                    840:             R_Next = 1;
                    841: }
                    842: #endif
                    843:
                    844: void Pprime(arg,rp)
                    845: NODE arg;
                    846: Q *rp;
                    847: {
                    848:        int i;
                    849:
                    850:        asir_assert(ARG0(arg),O_N,"prime");
                    851:        i = QTOS((Q)ARG0(arg));
                    852:        if ( i < 0 || i >= 1900 )
                    853:                *rp = 0;
                    854:        else
                    855:                STOQ(sprime[i],*rp);
                    856: }
                    857:
                    858: void Plprime(arg,rp)
                    859: NODE arg;
                    860: Q *rp;
                    861: {
                    862:        int i;
                    863:
                    864:        asir_assert(ARG0(arg),O_N,"lprime");
                    865:        i = QTOS((Q)ARG0(arg));
                    866:        if ( i < 0 || i >= 1000 )
                    867:                *rp = 0;
                    868:        else
                    869:                STOQ(lprime[i],*rp);
                    870: }
                    871:
                    872: extern int up_kara_mag, up_tkara_mag, up_fft_mag;
                    873:
                    874: void Pset_upfft(arg,rp)
                    875: NODE arg;
                    876: Q *rp;
                    877: {
                    878:        if ( arg ) {
                    879:                asir_assert(ARG0(arg),O_N,"set_upfft");
                    880:                up_fft_mag = QTOS((Q)ARG0(arg));
                    881:        }
                    882:        STOQ(up_fft_mag,*rp);
                    883: }
                    884:
                    885: void Pset_upkara(arg,rp)
                    886: NODE arg;
                    887: Q *rp;
                    888: {
                    889:        if ( arg ) {
                    890:                asir_assert(ARG0(arg),O_N,"set_upkara");
                    891:                up_kara_mag = QTOS((Q)ARG0(arg));
                    892:        }
                    893:        STOQ(up_kara_mag,*rp);
                    894: }
                    895:
                    896: void Pset_uptkara(arg,rp)
                    897: NODE arg;
                    898: Q *rp;
                    899: {
                    900:        if ( arg ) {
                    901:                asir_assert(ARG0(arg),O_N,"set_uptkara");
                    902:                up_tkara_mag = QTOS((Q)ARG0(arg));
                    903:        }
                    904:        STOQ(up_tkara_mag,*rp);
                    905: }
                    906:
                    907: extern int up2_kara_mag;
                    908:
                    909: void Pset_up2kara(arg,rp)
                    910: NODE arg;
                    911: Q *rp;
                    912: {
                    913:        if ( arg ) {
                    914:                asir_assert(ARG0(arg),O_N,"set_up2kara");
                    915:                up2_kara_mag = QTOS((Q)ARG0(arg));
                    916:        }
                    917:        STOQ(up2_kara_mag,*rp);
                    918: }
                    919:
                    920: #ifdef HMEXT
                    921: void Pigcdbin(arg,rp)
                    922: NODE arg;
                    923: Obj *rp;
                    924: {
                    925:        N g;
                    926:        Q n1,n2,a;
                    927:
                    928:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    929:        asir_assert(n1,O_N,"igcd");
                    930:        asir_assert(n2,O_N,"igcd");
                    931:        if ( !n1 )
                    932:                *rp = (Obj)n2;
                    933:        else if ( !n2 )
                    934:                *rp = (Obj)n1;
                    935:        else {
                    936:                gcdbinn(NM(n1),NM(n2),&g);
                    937:                NTOQ(g,1,a); *rp = (Obj)a;
                    938:        }
                    939: }
                    940:
                    941: void Pigcdbmod(arg,rp)
                    942: NODE arg;
                    943: Obj *rp;
                    944: {
                    945:        N g;
                    946:        Q n1,n2,a;
                    947:
                    948:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    949:        asir_assert(n1,O_N,"igcdbmod");
                    950:        asir_assert(n2,O_N,"igcdbmod");
                    951:        if ( !n1 )
                    952:                *rp = (Obj)n2;
                    953:        else if ( !n2 )
                    954:                *rp = (Obj)n1;
                    955:        else {
                    956:                gcdbmodn(NM(n1),NM(n2),&g);
                    957:                NTOQ(g,1,a); *rp = (Obj)a;
                    958:        }
                    959: }
                    960:
                    961: void Pigcdacc(arg,rp)
                    962: NODE arg;
                    963: Obj *rp;
                    964: {
                    965:        N g;
                    966:        Q n1,n2,a;
                    967:
                    968:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    969:        asir_assert(n1,O_N,"igcdacc");
                    970:        asir_assert(n2,O_N,"igcdacc");
                    971:        if ( !n1 )
                    972:                *rp = (Obj)n2;
                    973:        else if ( !n2 )
                    974:                *rp = (Obj)n1;
                    975:        else {
                    976:                gcdaccn(NM(n1),NM(n2),&g);
                    977:                NTOQ(g,1,a); *rp = (Obj)a;
                    978:        }
                    979: }
                    980:
                    981: void PigcdEuc(arg,rp)
                    982: NODE arg;
                    983: Obj *rp;
                    984: {
                    985:        N g;
                    986:        Q n1,n2,a;
                    987:
                    988:        n1 = (Q)ARG0(arg); n2 = (Q)ARG1(arg);
                    989:        asir_assert(n1,O_N,"igcdbmod");
                    990:        asir_assert(n2,O_N,"igcdbmod");
                    991:        if ( !n1 )
                    992:                *rp = (Obj)n2;
                    993:        else if ( !n2 )
                    994:                *rp = (Obj)n1;
                    995:        else {
                    996:                gcdEuclidn(NM(n1),NM(n2),&g);
                    997:                NTOQ(g,1,a); *rp = (Obj)a;
                    998:        }
                    999: }
                   1000:
                   1001: extern int igcd_algorithm;
                   1002:     /* == 0 : Euclid,
                   1003:      * == 1 : binary,
                   1004:      * == 2 : bmod,
                   1005:      * >= 3 : (Weber's accelerated)/(Jebelean's generalized binary) algorithm,
                   1006:      */
                   1007: extern int igcd_thre_inidiv;
                   1008:     /*
                   1009:      *  In the non-Euclidean algorithms, if the ratio of the lengths (number
                   1010:      *  of words) of two integers is >= igcd_thre_inidiv, we first perform
                   1011:      *  remainder calculation.
                   1012:      *  If == 0, this remainder calculation is not performed.
                   1013:      */
                   1014: extern int igcdacc_thre;
                   1015:     /*
                   1016:      *  In the accelerated algorithm, if the bit-lengths of two integers is
                   1017:      *  > igcdacc_thre, "bmod" reduction is done.
                   1018:      */
                   1019:
                   1020: void Pigcdcntl(arg,rp)
                   1021: NODE arg;
                   1022: Obj *rp;
                   1023: {
                   1024:        Obj p;
                   1025:        Q a;
                   1026:        int k, m;
                   1027:
                   1028:        if ( arg ) {
                   1029:                p = (Obj)ARG0(arg);
                   1030:                if ( !p ) {
                   1031:                        igcd_algorithm = 0;
                   1032:                        *rp = p;
                   1033:                        return;
                   1034:                } else if ( OID(p) == O_N ) {
                   1035:                        k = QTOS((Q)p);
                   1036:                        a = (Q)p;
                   1037:                        if ( k >= 0 ) igcd_algorithm = k;
                   1038:                        else if ( k == -1 ) {
                   1039:                        ret_thre:
                   1040:                                k = - igcd_thre_inidiv - igcdacc_thre*10000;
                   1041:                                STOQ(k,a);
                   1042:                                *rp = (Obj)a;
                   1043:                                return;
                   1044:                        } else {
                   1045:                                if ( (m = (-k)%10000) != 0 ) igcd_thre_inidiv = m;
                   1046:                                if ( (m = -k/10000) != 0 ) igcdacc_thre = m;
                   1047:                                goto ret_thre;
                   1048:                        }
                   1049:                } else if ( OID(p) == O_STR ) {
                   1050:                        char *n = BDY((STRING) p);
                   1051:
                   1052:                        if ( !strcmp( n, "binary" ) || !strcmp( n, "Binary" )
                   1053:                             || !strcmp( n, "bin" ) || !strcmp( n, "Bin" ) )
                   1054:                                k = igcd_algorithm = 1;
                   1055:                        else if ( !strcmp( n, "bmod" ) || !strcmp( n, "Bmod" ) )
                   1056:                                igcd_algorithm = 2;
                   1057:                        else if ( !strcmp( n, "euc" ) || !strcmp( n, "Euc" )
                   1058:                                  || !strcmp( n, "euclid" ) || !strcmp( n, "Euclid" ) )
                   1059:                                igcd_algorithm = 0;
                   1060:                        else if ( !strcmp( n, "acc" ) || !strcmp( n, "Acc" )
                   1061:                             || !strcmp( n, "gen" ) || !strcmp( n, "Gen" )
                   1062:                             || !strcmp( n, "genbin" ) || !strcmp( n, "GenBin" ) )
                   1063:                                igcd_algorithm = 3;
                   1064:                        else error( "igcdhow : invalid algorithm specification" );
                   1065:                }
                   1066:        }
                   1067:        STOQ(igcd_algorithm,a);
                   1068:        *rp = (Obj)a;
                   1069:        return;
                   1070: }
                   1071:
                   1072:
                   1073: void Pimaxrsh(arg,rp)
                   1074: NODE arg;
                   1075: LIST *rp;
                   1076: {
                   1077:        N n1, n2;
                   1078:        Q q;
                   1079:        NODE node1, node2;
                   1080:        int bits;
                   1081:        N maxrshn();
                   1082:
                   1083:        q = (Q)ARG0(arg);
                   1084:        asir_assert(q,O_N,"imaxrsh");
                   1085:        if ( !q ) n1 = n2 = 0;
                   1086:        else {
                   1087:                n1 = maxrshn( NM(q), &bits );
                   1088:                STON( bits, n2 );
                   1089:        }
                   1090:        NTOQ( n2, 1, q );
                   1091:        MKNODE( node2, q, 0 );
                   1092:        NTOQ( n1, 1, q );
                   1093:        MKNODE( node1, q, node2 );
                   1094:        MKLIST( *rp, node1 );
                   1095: }
                   1096: void Pilen(arg,rp)
                   1097: NODE arg;
                   1098: Obj *rp;
                   1099: {
                   1100:        Q q;
                   1101:        int l;
                   1102:
                   1103:        q = (Q)ARG0(arg);
                   1104:        asir_assert(q,O_N,"ilenh");
                   1105:        if ( !q ) l = 0;
                   1106:        else l = PL(NM(q));
                   1107:        STOQ(l,q);
                   1108:        *rp = (Obj)q;
                   1109: }
                   1110:
                   1111: void Pihex(arg,rp)
                   1112: NODE arg;
                   1113: Obj *rp;
                   1114: {
                   1115:        Q n1;
                   1116:
                   1117:        n1 = (Q)ARG0(arg);
                   1118:        asir_assert(n1,O_N,"ihex");
                   1119:        if ( n1 ) {
                   1120:                int i, l = PL(NM(n1)), *p = BD(NM(n1));
                   1121:
                   1122:                for ( i = 0; i < l; i++ ) printf( " 0x%08x", p[i] );
                   1123:                printf( "\n" );
                   1124:        } else printf( " 0x%08x\n", 0 );
                   1125:        *rp = (Obj)n1;
                   1126: }
                   1127: #endif /* HMEXT */

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