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

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

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