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

Annotation of OpenXM_contrib2/asir2000/builtin/poly.c, Revision 1.15

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.15    ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2000/builtin/poly.c,v 1.14 2001/09/03 01:04:25 noro Exp $
1.4       noro       49: */
1.1       noro       50: #include "ca.h"
                     51: #include "parse.h"
                     52: #include "base.h"
                     53:
                     54: void Pranp();
                     55:
                     56: void Pumul(),Pumul_ff(),Pusquare(),Pusquare_ff(),Putmul(),Putmul_ff();
                     57: void Pkmul(),Pksquare(),Pktmul();
                     58: void Pord(), Pcoef0(), Pcoef(), Pdeg(), Pmindeg(), Psetmod();
                     59: void Pcoef_gf2n();
                     60: void getcoef(), getdeglist(), mergedeglist(), change_mvar(), restore_mvar();
                     61:
1.2       noro       62: void Pp_mag(),Pmaxblen();
1.1       noro       63: void Pmergelist(), Pch_mv(), Pre_mv(), Pdeglist();
                     64: void Pptomp(),Pmptop();
                     65: void Pptolmp(),Plmptop();
1.12      noro       66: void Pptosfp(),Psfptop(),Psf_galois_action(),Psf_embed(),Psf_find_root();
1.13      noro       67: void Psf_minipoly(),Psf_log();
1.1       noro       68: void Pptogf2n(),Pgf2ntop(),Pgf2ntovect();
                     69: void Pptogfpn(),Pgfpntop();
                     70: void Pfind_root_gf2n();
1.2       noro       71: void Pumul_specialmod(),Pusquare_specialmod(),Putmul_specialmod();
1.1       noro       72:
                     73: void Pureverse(),Putrunc(),Pudecomp(),Purembymul(),Purembymul_precomp();
                     74: void Puinvmod(),Purevinvmod();
                     75: void Ppwrmod_ff(),Ppwrtab_ff(),Pgeneric_pwrmod_ff();
                     76: void Pkpwrmod_lm(),Pkpwrtab_lm(),Pkgeneric_pwrmod_lm();
                     77:
                     78: void Pkmulum();
                     79: void Pksquareum();
                     80:
                     81: void Pfmultest();
                     82: void Phfmul_lm();
                     83: void Plazy_lm();
                     84:
                     85: void Psetmod_ff();
                     86: void Psimp_ff();
                     87: void Pextdeg_ff();
                     88: void Pcharacteristic_ff();
                     89: void Pfield_type_ff();
                     90: void Pfield_order_ff();
                     91: void Prandom_ff();
                     92:
                     93: void Ptracemod_gf2n();
                     94: void Psparsemod_gf2n();
                     95: void Pmultest_gf2n();
                     96: void Psquaretest_gf2n();
                     97: void Pinvtest_gf2n();
                     98: void Pbininv_gf2n();
                     99: void Prinvtest_gf2n();
                    100: void Pis_irred_gf2();
                    101: void Pis_irred_ddd_gf2();
1.2       noro      102: void Pget_next_fft_prime();
1.3       noro      103: void Puadj_coef();
1.9       noro      104: void Preorder();
                    105: void Phomogeneous_part();
                    106: void Phomogeneous_deg();
1.1       noro      107: void simp_ff(Obj,Obj *);
                    108: void ranp(int,UP *);
                    109: void field_order_ff(N *);
                    110:
                    111: extern int current_mod;
                    112: extern GEN_UP2 current_mod_gf2n;
                    113: extern int lm_lazy;
                    114:
                    115: int current_ff;
                    116:
                    117: struct ftab poly_tab[] = {
1.9       noro      118:        {"homogeneous_deg",Phomogeneous_deg,-2},
                    119:        {"homogeneous_part",Phomogeneous_part,-3},
                    120:        {"reorder",Preorder,3},
1.3       noro      121:        {"uadj_coef",Puadj_coef,3},
1.1       noro      122:        {"ranp",Pranp,2},
                    123:        {"p_mag",Pp_mag,1},
1.2       noro      124:        {"maxblen",Pmaxblen,1},
1.1       noro      125:        {"ord",Pord,-1},
                    126:        {"coef0",Pcoef0,-3},
                    127:        {"coef",Pcoef,-3},
                    128:        {"coef_gf2n",Pcoef_gf2n,2},
                    129:        {"deg",Pdeg,2},
                    130:        {"mindeg",Pmindeg,2},
                    131:        {"setmod",Psetmod,-1},
                    132:
                    133:        {"sparsemod_gf2n",Psparsemod_gf2n,-1},
                    134:
1.15    ! noro      135:        {"setmod_ff",Psetmod_ff,-3},
1.1       noro      136:        {"simp_ff",Psimp_ff,1},
                    137:        {"extdeg_ff",Pextdeg_ff,0},
                    138:        {"characteristic_ff",Pcharacteristic_ff,0},
                    139:        {"field_type_ff",Pfield_type_ff,0},
                    140:        {"field_order_ff",Pfield_order_ff,0},
                    141:        {"random_ff",Prandom_ff,0},
                    142:
                    143:        {"deglist",Pdeglist,2},
                    144:        {"mergelist",Pmergelist,2},
                    145:        {"ch_mv",Pch_mv,2},
                    146:        {"re_mv",Pre_mv,2},
                    147:
                    148:        {"ptomp",Pptomp,2},
                    149:        {"mptop",Pmptop,1},
                    150:
                    151:        {"ptolmp",Pptolmp,1},
                    152:        {"lmptop",Plmptop,1},
                    153:
1.11      noro      154:        {"sf_galois_action",Psf_galois_action,2},
1.12      noro      155:        {"sf_find_root",Psf_find_root,1},
                    156:        {"sf_minipoly",Psf_minipoly,2},
                    157:        {"sf_embed",Psf_embed,3},
1.13      noro      158:        {"sf_log",Psf_log,1},
                    159:
1.11      noro      160:        {"ptosfp",Pptosfp,1},
1.6       noro      161:        {"sfptop",Psfptop,1},
1.1       noro      162:        {"ptogf2n",Pptogf2n,1},
                    163:        {"gf2ntop",Pgf2ntop,-2},
                    164:        {"gf2ntovect",Pgf2ntovect,1},
                    165:
                    166:        {"ptogfpn",Pptogfpn,1},
                    167:        {"gfpntop",Pgfpntop,-2},
                    168:
                    169:        {"kmul",Pkmul,2},
                    170:        {"ksquare",Pksquare,1},
                    171:        {"ktmul",Pktmul,3},
                    172:
                    173:        {"umul",Pumul,2},
                    174:        {"usquare",Pusquare,1},
                    175:        {"ureverse_inv_as_power_series",Purevinvmod,2},
                    176:        {"uinv_as_power_series",Puinvmod,2},
                    177:
1.2       noro      178:        {"umul_specialmod",Pumul_specialmod,3},
                    179:        {"usquare_specialmod",Pusquare_specialmod,2},
                    180:        {"utmul_specialmod",Putmul_specialmod,4},
                    181:
1.1       noro      182:        {"utmul",Putmul,3},
                    183:        {"umul_ff",Pumul_ff,2},
                    184:        {"usquare_ff",Pusquare_ff,1},
                    185:        {"utmul_ff",Putmul_ff,3},
                    186:
                    187:        /* for historical reason */
                    188:        {"trunc",Putrunc,2},
                    189:        {"decomp",Pudecomp,2},
                    190:
                    191:        {"utrunc",Putrunc,2},
                    192:        {"udecomp",Pudecomp,2},
1.3       noro      193:        {"ureverse",Pureverse,-2},
1.1       noro      194:        {"urembymul",Purembymul,2},
                    195:        {"urembymul_precomp",Purembymul_precomp,3},
                    196:
                    197:        {"lazy_lm",Plazy_lm,1},
                    198:        {"lazy_ff",Plazy_lm,1},
                    199:
                    200:        {"pwrmod_ff",Ppwrmod_ff,1},
                    201:        {"generic_pwrmod_ff",Pgeneric_pwrmod_ff,3},
                    202:        {"pwrtab_ff",Ppwrtab_ff,2},
                    203:
                    204:        {"tracemod_gf2n",Ptracemod_gf2n,3},
                    205:        {"b_find_root_gf2n",Pfind_root_gf2n,1},
                    206:
                    207:        {"is_irred_gf2",Pis_irred_gf2,1},
                    208:        {"is_irred_ddd_gf2",Pis_irred_ddd_gf2,1},
                    209:
                    210:        {"kpwrmod_lm",Pkpwrmod_lm,1},
                    211:        {"kgeneric_pwrmod_lm",Pkgeneric_pwrmod_lm,3},
                    212:        {"kpwrtab_lm",Pkpwrtab_lm,2},
                    213:
                    214:        {"kmulum",Pkmulum,3},
                    215:        {"ksquareum",Pksquareum,2},
                    216:
                    217:        {"fmultest",Pfmultest,3},
                    218:        {"hfmul_lm",Phfmul_lm,2},
                    219:
                    220:        {"multest_gf2n",Pmultest_gf2n,2},
                    221:        {"squaretest_gf2n",Psquaretest_gf2n,1},
                    222:        {"bininv_gf2n",Pbininv_gf2n,2},
                    223:        {"invtest_gf2n",Pinvtest_gf2n,1},
                    224:        {"rinvtest_gf2n",Prinvtest_gf2n,0},
1.2       noro      225:        {"get_next_fft_prime",Pget_next_fft_prime,2},
1.1       noro      226:        {0,0,0},
                    227: };
                    228:
                    229: extern V up_var;
1.9       noro      230:
                    231: void Phomogeneous_part(arg,rp)
                    232: NODE arg;
                    233: P *rp;
                    234: {
                    235:        if ( argc(arg) == 2 )
                    236:                exthp(CO,(P)ARG0(arg),QTOS((Q)ARG1(arg)),rp);
                    237:        else
                    238:                exthpc_generic(CO,(P)ARG0(arg),QTOS((Q)ARG2(arg)),
                    239:                        VR((P)ARG1(arg)),rp);
                    240: }
                    241:
                    242: void Phomogeneous_deg(arg,rp)
                    243: NODE arg;
                    244: Q *rp;
                    245: {
                    246:        int d;
                    247:
                    248:        if ( argc(arg) == 1 )
                    249:                d = homdeg((P)ARG0(arg));
                    250:        else
                    251:                d = getchomdeg(VR((P)ARG1(arg)),(P)ARG0(arg));
                    252:        STOQ(d,*rp);
                    253: }
                    254:
                    255: /*
                    256:        p1 = reorder(p,ovl,nvl) => p1 is 'sorted accoding to nvl.
                    257: */
                    258:
                    259: void Preorder(arg,rp)
                    260: NODE arg;
                    261: P *rp;
                    262: {
                    263:        VL ovl,nvl,tvl;
                    264:        NODE n;
                    265:
                    266:        for ( ovl = 0, n = BDY((LIST)ARG1(arg)); n; n = NEXT(n) ) {
                    267:                if ( !ovl ) {
                    268:                        NEWVL(ovl); tvl = ovl;
                    269:                } else {
                    270:                        NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
                    271:                }
                    272:                        VR(tvl) = VR((P)BDY(n));
                    273:        }
                    274:        for ( nvl = 0, n = BDY((LIST)ARG2(arg)); n; n = NEXT(n) ) {
                    275:                if ( !nvl ) {
                    276:                        NEWVL(nvl); tvl = nvl;
                    277:                } else {
                    278:                        NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
                    279:                }
                    280:                        VR(tvl) = VR((P)BDY(n));
                    281:        }
                    282:        reorderp(nvl,ovl,(P)ARG0(arg),rp);
                    283: }
1.3       noro      284:
                    285: /*
                    286:        uadj_coef(F,M,M2)
                    287:        if ( F is a non-negative integer )
                    288:                return F > M2 ? F-M : M2;
                    289:        else
                    290:                F = CN*V^N+...+C0
                    291:                return uadj_coef(CN,M,M2)*V^N+...+uadj_coef(C0,M,M2);
                    292: */
                    293:
                    294: void Puadj_coef(arg,rp)
                    295: NODE arg;
                    296: P *rp;
                    297: {
                    298:        UP f,r;
                    299:        N m,m2;
                    300:
                    301:        ptoup((P)ARG0(arg),&f);
                    302:        m = NM((Q)ARG1(arg));
                    303:        m2 = NM((Q)ARG2(arg));
                    304:        adj_coefup(f,m,m2,&r);
                    305:        uptop(r,rp);
                    306: }
                    307:
1.2       noro      308: /*
                    309:        get_next_fft_prime(StartIndex,Bits)
                    310:        tries to find smallest Index >= StartIndex s.t.
                    311:                2^(Bits-1)|FFTprime[Index]-1
                    312:        return [Index,Mod] or 0 (not exist)
                    313: */
                    314:
                    315: void Pget_next_fft_prime(arg,rp)
                    316: NODE arg;
                    317: LIST *rp;
                    318: {
                    319:        unsigned int mod,d;
                    320:        int start,bits,i;
                    321:        NODE n;
                    322:        Q q,ind;
                    323:
                    324:        start = QTOS((Q)ARG0(arg));
                    325:        bits = QTOS((Q)ARG1(arg));
                    326:        for ( i = start; ; i++ ) {
                    327:                get_fft_prime(i,&mod,&d);
                    328:                if ( !mod ) {
                    329:                        *rp = 0; return;
                    330:                }
                    331:                if ( bits <= d ) {
                    332:                        UTOQ(mod,q);
                    333:                        UTOQ(i,ind);
                    334:                        n = mknode(2,ind,q);
                    335:                        MKLIST(*rp,n);
                    336:                        return;
                    337:                }
                    338:        }
                    339: }
1.1       noro      340:
                    341: void Pranp(arg,rp)
                    342: NODE arg;
                    343: P *rp;
                    344: {
                    345:        int n;
                    346:        UP c;
                    347:
                    348:        n = QTOS((Q)ARG0(arg));
                    349:        ranp(n,&c);
                    350:        if ( c ) {
                    351:                up_var = VR((P)ARG1(arg));
                    352:                uptop(c,rp);
                    353:        } else
                    354:                *rp = 0;
                    355: }
                    356:
                    357: void ranp(n,nr)
                    358: int n;
                    359: UP *nr;
                    360: {
                    361:        int i;
                    362:        unsigned int r;
                    363:        Q q;
                    364:        UP c;
                    365:
                    366:        *nr = c = UPALLOC(n);
                    367:        for ( i = 0; i <= n; i++ ) {
                    368:                r = random();
                    369:                UTOQ(r,q);
                    370:                c->c[i] = (Num)q;
                    371:        }
                    372:        for ( i = n; i >= 0 && !c->c[i]; i-- );
                    373:        if ( i >= 0 )
                    374:                c->d = i;
                    375:        else
                    376:                *nr = 0;
                    377: }
                    378:
1.2       noro      379: void Pmaxblen(arg,rp)
                    380: NODE arg;
                    381: Q *rp;
                    382: {
                    383:        int l;
                    384:        l = maxblenp(ARG0(arg));
                    385:        STOQ(l,*rp);
                    386: }
                    387:
1.1       noro      388: void Pp_mag(arg,rp)
                    389: NODE arg;
                    390: Q *rp;
                    391: {
                    392:        int l;
                    393:        l = p_mag(ARG0(arg));
                    394:        STOQ(l,*rp);
                    395: }
                    396:
                    397: void Pord(arg,listp)
                    398: NODE arg;
                    399: LIST *listp;
                    400: {
                    401:        NODE n,tn;
                    402:        LIST l;
                    403:        VL vl,tvl,svl;
                    404:        P t;
                    405:        int i,j;
                    406:        V *va;
                    407:        V v;
                    408:
                    409:        if ( argc(arg) ) {
                    410:                asir_assert(ARG0(arg),O_LIST,"ord");
                    411:                for ( vl = 0, i = 0, n = BDY((LIST)ARG0(arg));
                    412:                        n; n = NEXT(n), i++ ) {
                    413:                        if ( !vl ) {
                    414:                                NEWVL(vl); tvl = vl;
                    415:                        } else {
                    416:                                NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
                    417:                        }
                    418:                        if ( !(t = (P)BDY(n)) || (OID(t) != O_P) )
                    419:                                error("ord : invalid argument");
                    420:                        VR(tvl) = VR(t);
                    421:                }
                    422:                va = (V *)ALLOCA(i*sizeof(V));
                    423:                for ( j = 0, svl = vl; j < i; j++, svl = NEXT(svl) )
                    424:                        va[j] = VR(svl);
                    425:                for ( svl = CO; svl; svl = NEXT(svl) ) {
                    426:                        v = VR(svl);
                    427:                        for ( j = 0; j < i; j++ )
                    428:                                if ( v == va[j] )
                    429:                                        break;
                    430:                        if ( j == i ) {
                    431:                                if ( !vl ) {
                    432:                                        NEWVL(vl); tvl = vl;
                    433:                                } else {
                    434:                                        NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
                    435:                                }
                    436:                                VR(tvl) = v;
                    437:                        }
                    438:                }
                    439:                if ( vl )
                    440:                        NEXT(tvl) = 0;
                    441:                CO = vl;
                    442:        }
                    443:        for ( n = 0, vl = CO; vl; vl = NEXT(vl) ) {
                    444:                NEXTNODE(n,tn); MKV(VR(vl),t); BDY(tn) = (pointer)t;
                    445:        }
                    446:        NEXT(tn) = 0; MKLIST(l,n); *listp = l;
                    447: }
                    448:
                    449: void Pcoef0(arg,rp)
                    450: NODE arg;
                    451: Obj *rp;
                    452: {
                    453:        Obj t,n;
                    454:        P s;
                    455:        DCP dc;
                    456:        int id;
                    457:        V v;
                    458:        VL vl;
                    459:
                    460:        if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
                    461:                *rp = 0;
                    462:        else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
                    463:                *rp = 0;
                    464:        else if ( id == O_N )
                    465:                if ( !n )
                    466:                        *rp = t;
                    467:                else
                    468:                        *rp = 0;
                    469:        else {
                    470:                if ( argc(arg) == 3 ) {
                    471:                        if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
                    472:                                reordvar(CO,v,&vl); reorderp(vl,CO,(P)t,&s);
                    473:                        } else
                    474:                                s = (P)t;
                    475:                        if ( VR(s) != v ) {
                    476:                                if ( n )
                    477:                                        *rp = 0;
                    478:                                else
                    479:                                        *rp = t;
                    480:                                return;
                    481:                        }
                    482:                } else
                    483:                        s = (P)t;
                    484:                for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
                    485:                if ( dc )
                    486:                        *rp = (Obj)COEF(dc);
                    487:                else
                    488:                        *rp = 0;
                    489:        }
                    490: }
                    491:
                    492: void Pcoef(arg,rp)
                    493: NODE arg;
                    494: Obj *rp;
                    495: {
                    496:        Obj t,n;
                    497:        P s;
                    498:        DCP dc;
                    499:        int id;
                    500:        V v;
                    501:
                    502:        if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
                    503:                *rp = 0;
                    504:        else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
                    505:                *rp = 0;
                    506:        else if ( id == O_N ) {
                    507:                if ( !n )
                    508:                        *rp = t;
                    509:                else
                    510:                        *rp = 0;
                    511:        } else {
                    512:                if ( argc(arg) == 3 ) {
                    513:                        if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
                    514:                                getcoef(CO,(P)t,v,(Q)n,(P *)rp); return;
                    515:                        } else
                    516:                                s = (P)t;
                    517:                        if ( VR(s) != v ) {
                    518:                                if ( n )
                    519:                                        *rp = 0;
                    520:                                else
                    521:                                        *rp = t;
                    522:                                return;
                    523:                        }
                    524:                } else
                    525:                        s = (P)t;
                    526:                for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
                    527:                if ( dc )
                    528:                        *rp = (Obj)COEF(dc);
                    529:                else
                    530:                        *rp = 0;
                    531:        }
                    532: }
                    533:
                    534: void Pcoef_gf2n(arg,rp)
                    535: NODE arg;
                    536: Obj *rp;
                    537: {
                    538:        Obj t,n;
                    539:        int id,d;
                    540:        UP2 up2;
                    541:
                    542:        if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
                    543:                *rp = 0;
                    544:        else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
                    545:                *rp = 0;
                    546:        else if ( id == O_N && NID((Num)t) == N_GF2N ) {
                    547:                d = QTOS((Q)n);
                    548:                up2 = ((GF2N)t)->body;
                    549:                if ( d > degup2(up2) )
                    550:                        *rp = 0;
                    551:                else
                    552:                        *rp = (Obj)(up2->b[d/BSH]&(((unsigned long)1)<<(d%BSH))?ONE:0);
                    553:        } else
                    554:                *rp = 0;
                    555: }
                    556:
                    557: void Pdeg(arg,rp)
                    558: NODE arg;
                    559: Q *rp;
                    560: {
                    561:        Obj t,v;
                    562:        int d;
                    563:
                    564: #if 0
                    565:        if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
                    566:                *rp = 0;
                    567:        else if ( !(v = (Obj)ARG1(arg)) || (VR((P)v) != VR((P)t)) )
                    568:                *rp = 0;
                    569:        else
                    570:                *rp = (Obj)DEG(DC((P)t));
                    571: #endif
                    572:        if ( !(t = (Obj)ARG0(arg)) )
                    573:                STOQ(-1,*rp);
                    574:        else if ( OID(t) != O_P ) {
                    575:                if ( OID(t) == O_N && NID(t) == N_GF2N
                    576:                        && (v=(Obj)ARG1(arg)) && OID(v)== O_N && NID(v) == N_GF2N ) {
                    577:                        d = degup2(((GF2N)t)->body);
                    578:                        STOQ(d,*rp);
                    579:                } else
                    580:                        *rp = 0;
                    581:        } else
                    582:                degp(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
                    583: }
                    584:
                    585: void Pmindeg(arg,rp)
                    586: NODE arg;
                    587: Q *rp;
                    588: {
                    589:        Obj t;
                    590:
                    591:        if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
                    592:                *rp = 0;
                    593:        else
                    594:                getmindeg(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
                    595: }
                    596:
                    597: void Psetmod(arg,rp)
                    598: NODE arg;
                    599: Q *rp;
                    600: {
                    601:        if ( arg ) {
                    602:                asir_assert(ARG0(arg),O_N,"setmod");
                    603:                current_mod = QTOS((Q)ARG0(arg));
                    604:        }
                    605:        STOQ(current_mod,*rp);
                    606: }
                    607:
                    608: void Psparsemod_gf2n(arg,rp)
                    609: NODE arg;
                    610: Q *rp;
                    611: {
                    612:        int id;
                    613:
                    614:        if ( arg && current_mod_gf2n )
                    615:                current_mod_gf2n->id = ARG0(arg)?1:0;
                    616:        if ( !current_mod_gf2n )
                    617:                id = -1;
                    618:        else
                    619:                id = current_mod_gf2n->id;
                    620:        STOQ(id,*rp);
                    621: }
                    622:
                    623: void Pmultest_gf2n(arg,rp)
                    624: NODE arg;
                    625: GF2N *rp;
                    626: {
                    627:        GF2N a,b,c;
                    628:        int i;
                    629:
                    630:        a = (GF2N)ARG0(arg); b = (GF2N)ARG0(arg);
                    631:        for ( i = 0; i < 10000; i++ )
                    632:                mulgf2n(a,b,&c);
                    633:        *rp = c;
                    634: }
                    635:
                    636: void Psquaretest_gf2n(arg,rp)
                    637: NODE arg;
                    638: GF2N *rp;
                    639: {
                    640:        GF2N a,c;
                    641:        int i;
                    642:
                    643:        a = (GF2N)ARG0(arg);
                    644:        for ( i = 0; i < 10000; i++ )
                    645:                squaregf2n(a,&c);
                    646:        *rp = c;
                    647: }
                    648:
                    649: void Pinvtest_gf2n(arg,rp)
                    650: NODE arg;
                    651: GF2N *rp;
                    652: {
                    653:        GF2N a,c;
                    654:        int i;
                    655:
                    656:        a = (GF2N)ARG0(arg);
                    657:        for ( i = 0; i < 10000; i++ )
                    658:                invgf2n(a,&c);
                    659:        *rp = c;
                    660: }
                    661:
                    662: void Pbininv_gf2n(arg,rp)
                    663: NODE arg;
                    664: GF2N *rp;
                    665: {
                    666:        UP2 a,inv;
                    667:        int n;
                    668:
                    669:        a = ((GF2N)ARG0(arg))->body;
                    670:        n = QTOS((Q)ARG1(arg));
                    671:        type1_bin_invup2(a,n,&inv);
                    672:        MKGF2N(inv,*rp);
                    673: }
                    674:
                    675: void Prinvtest_gf2n(rp)
                    676: Real *rp;
                    677: {
                    678:        GF2N *a;
                    679:        GF2N c;
                    680:        double t0,t1,r;
                    681:        int i;
                    682:        double get_clock();
                    683:
                    684:        a = (GF2N *)ALLOCA(1000*sizeof(GF2N));
                    685:        for ( i = 0; i < 1000; i++ ) {
                    686:                randomgf2n(&a[i]);
                    687:        }
                    688:        t0 = get_clock();
                    689:        for ( i = 0; i < 1000; i++ )
                    690:                invgf2n(a[i],&c);
                    691:        t1 = get_clock();
                    692:        r = (t1-t0)/1000;
                    693:        MKReal(r,*rp);
                    694: }
                    695:
                    696: void Pfind_root_gf2n(arg,rp)
                    697: NODE arg;
                    698: GF2N *rp;
                    699: {
                    700:
                    701: #if 0
                    702:        UP p;
                    703:
                    704:        ptoup((P)ARG0(arg),&p);
                    705:        find_root_gf2n(p,rp);
                    706: #else
                    707:        UP2 p;
                    708:
                    709:        ptoup2((P)ARG0(arg),&p);
                    710:        find_root_up2(p,rp);
                    711: #endif
                    712: }
                    713:
                    714: void Pis_irred_gf2(arg,rp)
                    715: NODE arg;
                    716: Q *rp;
                    717: {
                    718:        UP2 t;
                    719:
                    720:        ptoup2(ARG0(arg),&t);
                    721:        *rp = irredcheckup2(t) ? ONE : 0;
                    722: }
                    723:
                    724: void Pis_irred_ddd_gf2(arg,rp)
                    725: NODE arg;
                    726: Q *rp;
                    727: {
                    728:        UP2 t;
                    729:        int ret;
                    730:
                    731:        ptoup2(ARG0(arg),&t);
                    732:        ret = irredcheck_dddup2(t);
                    733:        STOQ(ret,*rp);
                    734: }
                    735:
1.7       noro      736: extern P current_gfs_ext;
                    737: extern int current_gfs_p;
1.6       noro      738: extern int current_gfs_q;
                    739: extern int current_gfs_q1;
                    740: extern int *current_gfs_plus1;
                    741: extern int *current_gfs_ntoi;
                    742: extern int *current_gfs_iton;
                    743:
1.1       noro      744: void Psetmod_ff(arg,rp)
                    745: NODE arg;
                    746: Obj *rp;
                    747: {
                    748:        int ac;
1.7       noro      749:        int d;
1.1       noro      750:        Obj mod,defpoly;
                    751:        N n;
                    752:        UP up;
                    753:        UP2 up2;
1.14      noro      754:        UM dp;
1.6       noro      755:        Q q,r;
1.15    ! noro      756:        P p,p1,y;
1.1       noro      757:        NODE n0,n1;
                    758:        LIST list;
                    759:
                    760:        ac = argc(arg);
                    761:        if ( ac == 1 ) {
                    762:                mod = (Obj)ARG0(arg);
                    763:                if ( !mod )
                    764:                        error("setmod_ff : invalid argument");
                    765:                switch ( OID(mod) ) {
                    766:                        case O_N:
1.7       noro      767:                                current_ff = FF_GFP;
                    768:                                setmod_lm(NM((Q)mod));
1.6       noro      769:                                break;
1.1       noro      770:                        case O_P:
                    771:                                current_ff = FF_GF2N;
                    772:                                setmod_gf2n((P)mod); break;
                    773:                        default:
                    774:                                error("setmod_ff : invalid argument");
                    775:                }
                    776:        } else if ( ac == 2 ) {
1.7       noro      777:                if ( OID(ARG0(arg)) == O_N ) {
                    778:                        /* small finite field; primitive root representation */
                    779:                        current_ff = FF_GFS;
                    780:                        setmod_sf(QTOS((Q)ARG0(arg)),QTOS((Q)ARG1(arg)));
1.6       noro      781:                } else {
1.7       noro      782:                        mod = (Obj)ARG1(arg);
1.6       noro      783:                        current_ff = FF_GFPN;
                    784:                        defpoly = (Obj)ARG0(arg);
                    785:                        if ( !mod || !defpoly )
                    786:                                error("setmod_ff : invalid argument");
                    787:                        setmod_lm(NM((Q)mod));
                    788:                        setmod_gfpn((P)defpoly);
                    789:                }
1.14      noro      790:        } else if ( ac == 3 ) {
                    791:                /* finite extension of a small finite field */
                    792:                current_ff = FF_GFS;
                    793:                setmod_sf(QTOS((Q)ARG0(arg)),QTOS((Q)ARG1(arg)));
                    794:                d = QTOS((Q)ARG2(arg));
                    795:                generate_defpoly_sfum(d,&dp);
1.15    ! noro      796:                setmod_gfsn(dp);
        !           797:                current_ff = FF_GFSN;
1.1       noro      798:        }
                    799:        switch ( current_ff ) {
                    800:                case FF_GFP:
                    801:                        getmod_lm(&n); NTOQ(n,1,q); *rp = (Obj)q; break;
                    802:                case FF_GF2N:
                    803:                        getmod_gf2n(&up2); up2top(up2,&p); *rp = (Obj)p; break;
                    804:                case FF_GFPN:
                    805:                        getmod_lm(&n); NTOQ(n,1,q);
                    806:                        getmod_gfpn(&up); uptop(up,&p);
                    807:                        MKNODE(n1,q,0); MKNODE(n0,p,n1);
                    808:                        MKLIST(list,n0);
                    809:                        *rp = (Obj)list; break;
1.6       noro      810:                case FF_GFS:
1.15    ! noro      811:                case FF_GFSN:
1.7       noro      812:                        STOQ(current_gfs_p,q);
1.15    ! noro      813:                        if ( current_gfs_ext )
1.7       noro      814:                                enc_to_p(current_gfs_p,current_gfs_iton[1],
                    815:                                        VR(current_gfs_ext),&p);
1.15    ! noro      816:                        else {
1.11      noro      817:                                if ( current_gfs_p == 2 )
                    818:                                        r = ONE;
                    819:                                else
                    820:                                        STOQ(current_gfs_iton[1],r);
1.15    ! noro      821:                                p = (P)r;
        !           822:                        }
        !           823:                        switch ( current_ff ) {
        !           824:                                case FF_GFS:
        !           825:                                        n0 = mknode(3,q,current_gfs_ext,p);
        !           826:                                        break;
        !           827:                                case FF_GFSN:
        !           828:                                        getmod_gfsn(&dp);
        !           829:                                        makevar("y",&y);
        !           830:                                        sfumtop(VR(y),dp,&p1);
        !           831:                                        n0 = mknode(4,q,current_gfs_ext,p,p1);
        !           832:                                        break;
1.7       noro      833:                        }
1.6       noro      834:                        MKLIST(list,n0);
                    835:                        *rp = (Obj)list; break;
1.1       noro      836:                default:
                    837:                        *rp = 0; break;
                    838:        }
                    839: }
                    840:
                    841: void Pextdeg_ff(rp)
                    842: Q *rp;
                    843: {
                    844:        int d;
                    845:        UP2 up2;
                    846:        UP up;
1.15    ! noro      847:        UM dp;
1.1       noro      848:
                    849:        switch ( current_ff ) {
                    850:                case FF_GFP:
                    851:                        *rp = ONE; break;
                    852:                case FF_GF2N:
                    853:                        getmod_gf2n(&up2); d = degup2(up2); STOQ(d,*rp); break;
                    854:                case FF_GFPN:
                    855:                        getmod_gfpn(&up); STOQ(up->d,*rp); break;
1.10      noro      856:                case FF_GFS:
                    857:                        if ( !current_gfs_ext )
                    858:                                *rp = ONE;
                    859:                        else
                    860:                                *rp = DEG(DC(current_gfs_ext));
                    861:                        break;
1.15    ! noro      862:                case FF_GFSN:
        !           863:                        getmod_gfsn(&dp);
        !           864:                        STOQ(DEG(dp),*rp);
        !           865:                        break;
1.1       noro      866:                default:
                    867:                        error("extdeg_ff : current_ff is not set");
                    868:        }
                    869: }
                    870:
                    871: void Pcharacteristic_ff(rp)
                    872: Q *rp;
                    873: {
                    874:        N lm;
                    875:
                    876:        switch ( current_ff ) {
                    877:                case FF_GFP:
                    878:                case FF_GFPN:
                    879:                        getmod_lm(&lm); NTOQ(lm,1,*rp); break;
                    880:                case FF_GF2N:
                    881:                        STOQ(2,*rp); break;
1.10      noro      882:                case FF_GFS:
1.15    ! noro      883:                case FF_GFSN:
1.10      noro      884:                        STOQ(current_gfs_p,*rp); break;
1.1       noro      885:                default:
                    886:                        error("characteristic_ff : current_ff is not set");
                    887:        }
                    888: }
                    889:
                    890: void Pfield_type_ff(rp)
                    891: Q *rp;
                    892: {
                    893:        STOQ(current_ff,*rp);
                    894: }
                    895:
                    896: void Pfield_order_ff(rp)
                    897: Q *rp;
                    898: {
                    899:        N n;
                    900:
                    901:        field_order_ff(&n);
                    902:        NTOQ(n,1,*rp);
                    903: }
                    904:
                    905: void field_order_ff(order)
                    906: N *order;
                    907: {
                    908:        UP2 up2;
                    909:        UP up;
1.15    ! noro      910:        UM dp;
1.1       noro      911:        N m;
                    912:        int d,w;
                    913:
                    914:        switch ( current_ff ) {
                    915:                case FF_GFP:
                    916:                        getmod_lm(order); break;
                    917:                case FF_GF2N:
                    918:                        getmod_gf2n(&up2); d = degup2(up2);
                    919:                        w = (d>>5)+1;
                    920:                        *order = m = NALLOC(w);
                    921:                        PL(m)=w;
                    922:                        bzero((char *)BD(m),w*sizeof(unsigned int));
                    923:                        BD(m)[d>>5] |= 1<<(d&31);
                    924:                        break;
                    925:                case FF_GFPN:
                    926:                        getmod_lm(&m);
1.15    ! noro      927:                        getmod_gfpn(&up); pwrn(m,up->d,order);
        !           928:                        break;
1.10      noro      929:                case FF_GFS:
                    930:                        STON(current_gfs_q,*order); break;
1.15    ! noro      931:                case FF_GFSN:
        !           932:                        STON(current_gfs_q,m);
        !           933:                        getmod_gfsn(&dp); pwrn(m,DEG(dp),order);
        !           934:                        break;
1.1       noro      935:                default:
                    936:                        error("field_order_ff : current_ff is not set");
                    937:        }
                    938: }
                    939:
                    940: void Prandom_ff(rp)
                    941: Obj *rp;
                    942: {
                    943:        LM l;
                    944:        GF2N g;
                    945:        GFPN p;
1.7       noro      946:        GFS s;
1.15    ! noro      947:        GFSN spn;
1.1       noro      948:
                    949:        switch ( current_ff ) {
                    950:                case FF_GFP:
                    951:                        random_lm(&l); *rp = (Obj)l; break;
                    952:                case FF_GF2N:
                    953:                        randomgf2n(&g); *rp = (Obj)g; break;
                    954:                case FF_GFPN:
                    955:                        randomgfpn(&p); *rp = (Obj)p; break;
1.7       noro      956:                case FF_GFS:
                    957:                        randomgfs(&s); *rp = (Obj)s; break;
1.15    ! noro      958:                case FF_GFSN:
        !           959:                        randomgfsn(&spn); *rp = (Obj)spn; break;
1.1       noro      960:                default:
                    961:                        error("random_ff : current_ff is not set");
                    962:        }
                    963: }
                    964:
                    965: void Psimp_ff(arg,rp)
                    966: NODE arg;
                    967: Obj *rp;
                    968: {
                    969:        LM r;
                    970:        GF2N rg;
                    971:        extern lm_lazy;
                    972:
                    973:        simp_ff((Obj)ARG0(arg),rp);
                    974: }
                    975:
                    976: void simp_ff(p,rp)
                    977: Obj p;
                    978: Obj *rp;
                    979: {
                    980:        Num n;
                    981:        LM r,s;
                    982:        DCP dc,dcr0,dcr;
                    983:        GF2N rg,sg;
                    984:        GFPN rpn,spn;
1.6       noro      985:        GFS rs;
1.15    ! noro      986:        GFSN rspn,sspn;
1.1       noro      987:        P t;
                    988:        Obj obj;
                    989:
                    990:        lm_lazy = 0;
                    991:        if ( !p )
                    992:                *rp = 0;
                    993:        else if ( OID(p) == O_N ) {
                    994:                switch ( current_ff ) {
                    995:                        case FF_GFP:
                    996:                                ptolmp((P)p,&t); simplm((LM)t,&s); *rp = (Obj)s;
                    997:                                break;
                    998:                        case FF_GF2N:
                    999:                                ptogf2n((Obj)p,&rg); simpgf2n((GF2N)rg,&sg); *rp = (Obj)sg;
                   1000:                                break;
                   1001:                        case FF_GFPN:
                   1002:                                ntogfpn((Obj)p,&rpn); simpgfpn((GFPN)rpn,&spn); *rp = (Obj)spn;
                   1003:                                break;
1.6       noro     1004:                        case FF_GFS:
1.8       noro     1005:                                if ( NID((Num)p) == N_GFS )
                   1006:                                        *rp = p;
                   1007:                                else {
                   1008:                                        ptomp(current_gfs_p,(P)p,&t); mqtogfs(t,&rs);
                   1009:                                        *rp = (Obj)rs;
                   1010:                                }
1.14      noro     1011:                                break;
1.15    ! noro     1012:                        case FF_GFSN:
        !          1013:                                ntogfsn((Obj)p,&rspn); simpgfsn((GFSN)rspn,&sspn);
1.14      noro     1014:                                *rp = (Obj)sspn;
1.6       noro     1015:                                break;
1.1       noro     1016:                        default:
                   1017:                                *rp = (Obj)p;
                   1018:                                break;
                   1019:                }
                   1020:        } else if ( OID(p) == O_P ) {
                   1021:                for ( dc = DC((P)p), dcr0 = 0; dc; dc = NEXT(dc) ) {
                   1022:                        simp_ff((Obj)COEF(dc),&obj);
                   1023:                        if ( obj ) {
                   1024:                                NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc); COEF(dcr) = (P)obj;
                   1025:                        }
                   1026:                }
                   1027:                if ( !dcr0 )
                   1028:                        *rp = 0;
                   1029:                else {
                   1030:                        NEXT(dcr) = 0; MKP(VR((P)p),dcr0,t); *rp = (Obj)t;
                   1031:                }
                   1032:        } else
                   1033:                error("simp_ff : not implemented yet");
                   1034: }
                   1035:
                   1036: void getcoef(vl,p,v,d,r)
                   1037: VL vl;
                   1038: P p;
                   1039: V v;
                   1040: Q d;
                   1041: P *r;
                   1042: {
                   1043:        P s,t,u,a,b,x;
                   1044:        DCP dc;
                   1045:        V w;
                   1046:
                   1047:        if ( !p )
                   1048:                *r = 0;
                   1049:        else if ( NUM(p) )
                   1050:                *r = d ? 0 : p;
                   1051:        else if ( (w=VR(p)) == v ) {
                   1052:                for ( dc = DC(p); dc && cmpq(DEG(dc),d); dc = NEXT(dc) );
                   1053:                *r = dc ? COEF(dc) : 0;
                   1054:        } else {
                   1055:                MKV(w,x);
                   1056:                for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
                   1057:                        getcoef(vl,COEF(dc),v,d,&t);
                   1058:                        if ( t ) {
                   1059:                                pwrp(vl,x,DEG(dc),&u); mulp(vl,t,u,&a);
                   1060:                                addp(vl,s,a,&b); s = b;
                   1061:                        }
                   1062:                }
                   1063:                *r = s;
                   1064:        }
                   1065: }
                   1066:
                   1067: void Pdeglist(arg,rp)
                   1068: NODE arg;
                   1069: LIST *rp;
                   1070: {
                   1071:        NODE d;
                   1072:
                   1073:        getdeglist((P)ARG0(arg),VR((P)ARG1(arg)),&d);
                   1074:        MKLIST(*rp,d);
                   1075: }
                   1076:
                   1077: void Pch_mv(arg,rp)
                   1078: NODE arg;
                   1079: P *rp;
                   1080: {
                   1081:        change_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
                   1082: }
                   1083:
                   1084: void Pre_mv(arg,rp)
                   1085: NODE arg;
                   1086: P *rp;
                   1087: {
                   1088:        restore_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
                   1089: }
                   1090:
                   1091: void change_mvar(vl,p,v,r)
                   1092: VL vl;
                   1093: P p;
                   1094: V v;
                   1095: P *r;
                   1096: {
                   1097:        Q d;
                   1098:        DCP dc,dc0;
                   1099:        NODE dl;
                   1100:
                   1101:        if ( !p || NUM(p) || (VR(p) == v) )
                   1102:                *r = p;
                   1103:        else {
                   1104:                getdeglist(p,v,&dl);
                   1105:                for ( dc0 = 0; dl; dl = NEXT(dl) ) {
                   1106:                        NEXTDC(dc0,dc); DEG(dc) = d = (Q)BDY(dl);
                   1107:                        getcoef(vl,p,v,d,&COEF(dc));
                   1108:                }
                   1109:                NEXT(dc) = 0; MKP(v,dc0,*r);
                   1110:        }
                   1111: }
                   1112:
                   1113: void restore_mvar(vl,p,v,r)
                   1114: VL vl;
                   1115: P p;
                   1116: V v;
                   1117: P *r;
                   1118: {
                   1119:        P s,u,a,b,x;
                   1120:        DCP dc;
                   1121:
                   1122:        if ( !p || NUM(p) || (VR(p) != v) )
                   1123:                *r = p;
                   1124:        else {
                   1125:                MKV(v,x);
                   1126:                for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
                   1127:                        pwrp(vl,x,DEG(dc),&u); mulp(vl,COEF(dc),u,&a);
                   1128:                        addp(vl,s,a,&b); s = b;
                   1129:                }
                   1130:                *r = s;
                   1131:        }
                   1132: }
                   1133:
                   1134: void getdeglist(p,v,d)
                   1135: P p;
                   1136: V v;
                   1137: NODE *d;
                   1138: {
                   1139:        NODE n,n0,d0,d1,d2;
                   1140:        DCP dc;
                   1141:
                   1142:        if ( !p || NUM(p) ) {
                   1143:                MKNODE(n,0,0); *d = n;
                   1144:        } else if ( VR(p) == v ) {
                   1145:                for ( n0 = 0, dc = DC(p); dc; dc = NEXT(dc) ) {
                   1146:                        NEXTNODE(n0,n); BDY(n) = (pointer)DEG(dc);
                   1147:                }
                   1148:                NEXT(n) = 0; *d = n0;
                   1149:        } else {
                   1150:                for ( dc = DC(p), d0 = 0; dc; dc = NEXT(dc) ) {
                   1151:                        getdeglist(COEF(dc),v,&d1); mergedeglist(d0,d1,&d2); d0 = d2;
                   1152:                }
                   1153:                *d = d0;
                   1154:        }
                   1155: }
                   1156: void Pmergelist(arg,rp)
                   1157: NODE arg;
                   1158: LIST *rp;
                   1159: {
                   1160:     NODE n;
                   1161:
                   1162:        asir_assert(ARG0(arg),O_LIST,"mergelist");
                   1163:        asir_assert(ARG1(arg),O_LIST,"mergelist");
                   1164:        mergedeglist(BDY((LIST)ARG0(arg)),BDY((LIST)ARG1(arg)),&n);
                   1165:        MKLIST(*rp,n);
                   1166: }
                   1167:
                   1168: void mergedeglist(d0,d1,dr)
                   1169: NODE d0,d1,*dr;
                   1170: {
                   1171:        NODE t0,t,dt;
                   1172:        Q d;
                   1173:        int c;
                   1174:
                   1175:        if ( !d0 )
                   1176:                *dr = d1;
                   1177:        else {
                   1178:                while ( d1 ) {
                   1179:                        dt = d1; d1 = NEXT(d1); d = (Q)BDY(dt);
                   1180:                        for ( t0 = 0, t = d0; t; t0 = t, t = NEXT(t) ) {
                   1181:                                c = cmpq(d,(Q)BDY(t));
                   1182:                                if ( !c )
                   1183:                                        break;
                   1184:                                else if ( c > 0 ) {
                   1185:                                        if ( !t0 ) {
                   1186:                                                NEXT(dt) = d0; d0 = dt;
                   1187:                                        } else {
                   1188:                                                NEXT(t0) = dt; NEXT(dt) = t;
                   1189:                                        }
                   1190:                                        break;
                   1191:                                }
                   1192:                        }
                   1193:                        if ( !t ) {
                   1194:                                NEXT(t0) = dt; *dr = d0; return;
                   1195:                        }
                   1196:                }
                   1197:                *dr = d0;
                   1198:        }
                   1199: }
                   1200:
                   1201: void Pptomp(arg,rp)
                   1202: NODE arg;
                   1203: P *rp;
                   1204: {
                   1205:        ptomp(QTOS((Q)ARG1(arg)),(P)ARG0(arg),rp);
                   1206: }
                   1207:
                   1208: void Pmptop(arg,rp)
                   1209: NODE arg;
                   1210: P *rp;
                   1211: {
                   1212:        mptop((P)ARG0(arg),rp);
                   1213: }
                   1214:
                   1215: void Pptolmp(arg,rp)
                   1216: NODE arg;
                   1217: P *rp;
                   1218: {
                   1219:        ptolmp((P)ARG0(arg),rp);
                   1220: }
                   1221:
                   1222: void Plmptop(arg,rp)
                   1223: NODE arg;
                   1224: P *rp;
                   1225: {
                   1226:        lmptop((P)ARG0(arg),rp);
1.11      noro     1227: }
                   1228:
                   1229: void Psf_galois_action(arg,rp)
                   1230: NODE arg;
                   1231: P *rp;
                   1232: {
                   1233:        sf_galois_action(ARG0(arg),ARG1(arg),rp);
1.12      noro     1234: }
                   1235:
                   1236: /*
                   1237:   sf_embed(F,B,PM)
                   1238:   F : an element of GF(pn)
                   1239:   B : the image of the primitive root of GF(pn)
                   1240:   PM : order of GF(pm)
                   1241: */
                   1242:
                   1243: void Psf_embed(arg,rp)
                   1244: NODE arg;
                   1245: P *rp;
                   1246: {
                   1247:        int k,pm;
                   1248:
                   1249:        /* GF(pn)={0,1,a,a^2,...}->GF(pm)={0,1,b,b^2,...}; a->b^k */
                   1250:        k = CONT((GFS)ARG1(arg));
                   1251:        pm = QTOS((Q)ARG2(arg));
                   1252:        sf_embed((P)ARG0(arg),k,pm,rp);
1.13      noro     1253: }
                   1254:
                   1255: void Psf_log(arg,rp)
                   1256: NODE arg;
                   1257: Q *rp;
                   1258: {
                   1259:        int k;
                   1260:
                   1261:        if ( !ARG0(arg) )
                   1262:                error("sf_log : invalid armument");
                   1263:        k = CONT((GFS)ARG0(arg));
                   1264:        STOQ(k,*rp);
1.12      noro     1265: }
                   1266:
                   1267: void Psf_find_root(arg,rp)
                   1268: NODE arg;
                   1269: GFS *rp;
                   1270: {
                   1271:        P p;
                   1272:        Obj t;
                   1273:        int d;
                   1274:        UM u;
                   1275:        int *root;
                   1276:
                   1277:        p = (P)ARG0(arg);
                   1278:        simp_ff((Obj)p,&t); p = (P)t;
                   1279:        d = getdeg(VR(p),p);
                   1280:        u = W_UMALLOC(d);
                   1281:        ptosfum(p,u);
                   1282:        root = (int *)ALLOCA(d*sizeof(int));
                   1283:        find_rootsf(u,root);
                   1284:        MKGFS(IFTOF(root[0]),*rp);
                   1285: }
                   1286:
                   1287: void Psf_minipoly(arg,rp)
                   1288: NODE arg;
                   1289: P *rp;
                   1290: {
                   1291:        Obj t;
                   1292:        P p1,p2;
                   1293:        int d1,d2;
                   1294:        UM up1,up2,m;
                   1295:
                   1296:        p1 = (P)ARG0(arg); simp_ff((Obj)p1,&t); p1 = (P)t;
                   1297:        p2 = (P)ARG1(arg); simp_ff((Obj)p2,&t); p2 = (P)t;
                   1298:        d1 = getdeg(VR(p1),p1); up1 = W_UMALLOC(d1); ptosfum(p1,up1);
                   1299:        d2 = getdeg(VR(p2),p2); up2 = W_UMALLOC(d2); ptosfum(p2,up2);
                   1300:        m = W_UMALLOC(d2);
                   1301:        minipolysf(up1,up2,m);
                   1302:        sfumtop(VR(p2),m,&p1);
                   1303:        sfptop(p1,rp);
1.11      noro     1304: }
                   1305:
                   1306: void Pptosfp(arg,rp)
                   1307: NODE arg;
                   1308: P *rp;
                   1309: {
                   1310:        ptosfp(ARG0(arg),rp);
1.6       noro     1311: }
                   1312:
                   1313: void Psfptop(arg,rp)
                   1314: NODE arg;
                   1315: P *rp;
                   1316: {
                   1317:        sfptop((P)ARG0(arg),rp);
1.1       noro     1318: }
                   1319:
                   1320: void Pptogf2n(arg,rp)
                   1321: NODE arg;
                   1322: GF2N *rp;
                   1323: {
                   1324:        ptogf2n((Obj)ARG0(arg),rp);
                   1325: }
                   1326:
                   1327: void Pgf2ntop(arg,rp)
                   1328: NODE arg;
                   1329: P *rp;
                   1330: {
                   1331:        extern V up2_var;
                   1332:
                   1333:        if ( argc(arg) == 2 )
                   1334:                up2_var = VR((P)ARG1(arg));
                   1335:        gf2ntop((GF2N)ARG0(arg),rp);
                   1336: }
                   1337:
                   1338: void Pgf2ntovect(arg,rp)
                   1339: NODE arg;
                   1340: VECT *rp;
                   1341: {
                   1342:        gf2ntovect((GF2N)ARG0(arg),rp);
                   1343: }
                   1344:
                   1345: void Pptogfpn(arg,rp)
                   1346: NODE arg;
                   1347: GF2N *rp;
                   1348: {
                   1349:        ptogfpn((Obj)ARG0(arg),rp);
                   1350: }
                   1351:
                   1352: void Pgfpntop(arg,rp)
                   1353: NODE arg;
                   1354: P *rp;
                   1355: {
                   1356:        extern V up_var;
                   1357:
                   1358:        if ( argc(arg) == 2 )
                   1359:                up_var = VR((P)ARG1(arg));
                   1360:        gfpntop((GFPN)ARG0(arg),rp);
                   1361: }
                   1362:
                   1363: void Pureverse(arg,rp)
                   1364: NODE arg;
                   1365: P *rp;
                   1366: {
                   1367:        UP p,r;
                   1368:
                   1369:        ptoup((P)ARG0(arg),&p);
1.3       noro     1370:        if ( argc(arg) == 1 )
                   1371:                reverseup(p,p->d,&r);
                   1372:        else
                   1373:                reverseup(p,QTOS((Q)ARG1(arg)),&r);
1.1       noro     1374:        uptop(r,rp);
                   1375: }
                   1376:
                   1377: void Putrunc(arg,rp)
                   1378: NODE arg;
                   1379: P *rp;
                   1380: {
                   1381:        UP p,r;
                   1382:
                   1383:        ptoup((P)ARG0(arg),&p);
                   1384:        truncup(p,QTOS((Q)ARG1(arg))+1,&r);
                   1385:        uptop(r,rp);
                   1386: }
                   1387:
                   1388: void Pudecomp(arg,rp)
                   1389: NODE arg;
                   1390: LIST *rp;
                   1391: {
                   1392:        P u,l;
                   1393:        UP p,up,low;
                   1394:        NODE n0,n1;
                   1395:
                   1396:        ptoup((P)ARG0(arg),&p);
                   1397:        decompup(p,QTOS((Q)ARG1(arg))+1,&low,&up);
                   1398:        uptop(low,&l);
                   1399:        uptop(up,&u);
                   1400:        MKNODE(n1,u,0); MKNODE(n0,l,n1);
                   1401:        MKLIST(*rp,n0);
                   1402: }
                   1403:
                   1404: void Purembymul(arg,rp)
                   1405: NODE arg;
                   1406: P *rp;
                   1407: {
                   1408:        UP p1,p2,r;
                   1409:
                   1410:        if ( !ARG0(arg) || !ARG1(arg) )
                   1411:                *rp = 0;
                   1412:        else {
                   1413:                ptoup((P)ARG0(arg),&p1);
                   1414:                ptoup((P)ARG1(arg),&p2);
                   1415:                rembymulup(p1,p2,&r);
                   1416:                uptop(r,rp);
                   1417:        }
                   1418: }
                   1419:
                   1420: /*
                   1421:  * d1 = deg(p1), d2 = deg(p2)
                   1422:  * d1 <= 2*d2-1
                   1423:  * p2*inv = 1 mod x^d2
                   1424:  */
                   1425:
                   1426: void Purembymul_precomp(arg,rp)
                   1427: NODE arg;
                   1428: P *rp;
                   1429: {
                   1430:        UP p1,p2,inv,r;
                   1431:
                   1432:        if ( !ARG0(arg) || !ARG1(arg) )
                   1433:                *rp = 0;
                   1434:        else {
                   1435:                ptoup((P)ARG0(arg),&p1);
                   1436:                ptoup((P)ARG1(arg),&p2);
                   1437:                ptoup((P)ARG2(arg),&inv);
                   1438:                if ( p1->d >= 2*p2->d ) {
                   1439:                        error("urembymul_precomp : degree of 1st arg is too large");
                   1440: /*                     fprintf(stderr,"urembymul_precomp : degree of 1st arg is too large"); */
                   1441:                        remup(p1,p2,&r);
                   1442:                } else
                   1443:                        hybrid_rembymulup_special(current_ff,p1,p2,inv,&r);
                   1444:                uptop(r,rp);
                   1445:        }
                   1446: }
                   1447:
                   1448: void Puinvmod(arg,rp)
                   1449: NODE arg;
                   1450: P *rp;
                   1451: {
                   1452:        UP p,r;
                   1453:
                   1454:        ptoup((P)ARG0(arg),&p);
                   1455:        invmodup(p,QTOS((Q)ARG1(arg)),&r);
                   1456:        uptop(r,rp);
                   1457: }
                   1458:
                   1459: void Purevinvmod(arg,rp)
                   1460: NODE arg;
                   1461: P *rp;
                   1462: {
                   1463:        UP p,pr,r;
                   1464:
                   1465:        ptoup((P)ARG0(arg),&p);
                   1466:        reverseup(p,p->d,&pr);
                   1467:        invmodup(pr,QTOS((Q)ARG1(arg)),&r);
                   1468:        uptop(r,rp);
                   1469: }
                   1470:
                   1471: void Ppwrmod_ff(arg,rp)
                   1472: NODE arg;
                   1473: P *rp;
                   1474: {
                   1475:        UP p1,p2;
                   1476:
                   1477:        ptoup((P)ARG0(arg),&p1);
                   1478:        switch ( current_ff ) {
                   1479:                case FF_GFP:
                   1480:                        hybrid_powermodup(p1,&p2); break;
                   1481:                case FF_GF2N:
                   1482:                        powermodup_gf2n(p1,&p2); break;
                   1483:                case FF_GFPN:
1.10      noro     1484:                case FF_GFS:
1.15    ! noro     1485:                case FF_GFSN:
1.1       noro     1486:                        powermodup(p1,&p2); break;
                   1487:                default:
                   1488:                        error("pwrmod_ff : current_ff is not set");
                   1489:        }
                   1490:        uptop(p2,rp);
                   1491: }
                   1492:
                   1493: void Pgeneric_pwrmod_ff(arg,rp)
                   1494: NODE arg;
                   1495: P *rp;
                   1496: {
                   1497:        UP g,f,r;
                   1498:
                   1499:        ptoup((P)ARG0(arg),&g);
                   1500:        ptoup((P)ARG1(arg),&f);
                   1501:        switch ( current_ff ) {
                   1502:                case FF_GFP:
                   1503:                        hybrid_generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
                   1504:                case FF_GF2N:
                   1505:                        generic_powermodup_gf2n(g,f,(Q)ARG2(arg),&r); break;
                   1506:                case FF_GFPN:
1.10      noro     1507:                case FF_GFS:
1.15    ! noro     1508:                case FF_GFSN:
1.1       noro     1509:                        generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
                   1510:                default:
                   1511:                        error("generic_pwrmod_ff : current_ff is not set");
                   1512:        }
                   1513:        uptop(r,rp);
                   1514: }
                   1515:
                   1516: void Ppwrtab_ff(arg,rp)
                   1517: NODE arg;
                   1518: VECT *rp;
                   1519: {
                   1520:        UP f,xp;
                   1521:        UP *tab;
                   1522:        VECT r;
                   1523:        int i,d;
                   1524:
                   1525:        ptoup((P)ARG0(arg),&f);
                   1526:        ptoup((P)ARG1(arg),&xp);
                   1527:        d = f->d;
                   1528:
                   1529:        tab = (UP *)ALLOCA(d*sizeof(UP));
                   1530:        switch ( current_ff ) {
                   1531:                case FF_GFP:
                   1532:                        hybrid_powertabup(f,xp,tab); break;
                   1533:                case FF_GF2N:
                   1534:                        powertabup_gf2n(f,xp,tab); break;
                   1535:                case FF_GFPN:
1.10      noro     1536:                case FF_GFS:
1.15    ! noro     1537:                case FF_GFSN:
1.1       noro     1538:                        powertabup(f,xp,tab); break;
                   1539:                default:
                   1540:                        error("pwrtab_ff : current_ff is not set");
                   1541:        }
                   1542:        MKVECT(r,d); *rp = r;
                   1543:        for ( i = 0; i < d; i++ )
                   1544:                uptop(tab[i],(P *)&BDY(r)[i]);
                   1545: }
                   1546:
                   1547: void Pkpwrmod_lm(arg,rp)
                   1548: NODE arg;
                   1549: P *rp;
                   1550: {
                   1551:        UP p1,p2;
                   1552:
                   1553:        ptoup((P)ARG0(arg),&p1);
                   1554:        powermodup(p1,&p2);
                   1555:        uptop(p2,rp);
                   1556: }
                   1557:
                   1558: void Pkgeneric_pwrmod_lm(arg,rp)
                   1559: NODE arg;
                   1560: P *rp;
                   1561: {
                   1562:        UP g,f,r;
                   1563:
                   1564:        ptoup((P)ARG0(arg),&g);
                   1565:        ptoup((P)ARG1(arg),&f);
                   1566:        generic_powermodup(g,f,(Q)ARG2(arg),&r);
                   1567:        uptop(r,rp);
                   1568: }
                   1569:
                   1570: void Pkpwrtab_lm(arg,rp)
                   1571: NODE arg;
                   1572: VECT *rp;
                   1573: {
                   1574:        UP f,xp;
                   1575:        UP *tab;
                   1576:        VECT r;
                   1577:        int i,d;
                   1578:
                   1579:        ptoup((P)ARG0(arg),&f);
                   1580:        ptoup((P)ARG1(arg),&xp);
                   1581:        d = f->d;
                   1582:
                   1583:        tab = (UP *)ALLOCA(d*sizeof(UP));
                   1584:        powertabup(f,xp,tab);
                   1585:        MKVECT(r,d); *rp = r;
                   1586:        for ( i = 0; i < d; i++ )
                   1587:                uptop(tab[i],(P *)&BDY(r)[i]);
                   1588: }
                   1589:
                   1590: void Plazy_lm(arg,rp)
                   1591: NODE arg;
                   1592: Q *rp;
                   1593: {
                   1594:        lm_lazy = QTOS((Q)ARG0(arg));
                   1595:        *rp = 0;
                   1596: }
                   1597:
                   1598: void Pkmul(arg,rp)
                   1599: NODE arg;
                   1600: P *rp;
                   1601: {
                   1602:        P n1,n2;
                   1603:
                   1604:        n1 = (P)ARG0(arg); n2 = (P)ARG1(arg);
                   1605:        asir_assert(n1,O_P,"kmul");
                   1606:        asir_assert(n2,O_P,"kmul");
                   1607:        kmulp(CO,n1,n2,rp);
                   1608: }
                   1609:
                   1610: void Pksquare(arg,rp)
                   1611: NODE arg;
                   1612: P *rp;
                   1613: {
                   1614:        P n1;
                   1615:
                   1616:        n1 = (P)ARG0(arg);
                   1617:        asir_assert(n1,O_P,"ksquare");
                   1618:        ksquarep(CO,n1,rp);
                   1619: }
                   1620:
                   1621: void Pktmul(arg,rp)
                   1622: NODE arg;
                   1623: P *rp;
                   1624: {
                   1625:        UP p1,p2,r;
                   1626:
                   1627:        ptoup((P)ARG0(arg),&p1);
                   1628:        ptoup((P)ARG1(arg),&p2);
                   1629:        tkmulup(p1,p2,QTOS((Q)ARG2(arg))+1,&r);
                   1630:        uptop(r,rp);
                   1631: }
                   1632:
                   1633: void Pumul(arg,rp)
                   1634: NODE arg;
                   1635: P *rp;
                   1636: {
                   1637:        P a1,a2;
                   1638:        UP p1,p2,r;
                   1639:
                   1640:        a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
                   1641:        if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
                   1642:                mulp(CO,a1,a2,rp);
                   1643:        else {
                   1644:                if ( !uzpcheck(a1) || !uzpcheck(a2) || VR(a1) != VR(a2) )
                   1645:                        error("umul : invalid argument");
                   1646:                ptoup(a1,&p1);
                   1647:                ptoup(a2,&p2);
                   1648:                hybrid_mulup(0,p1,p2,&r);
                   1649:                uptop(r,rp);
                   1650:        }
                   1651: }
                   1652:
                   1653: void Pusquare(arg,rp)
                   1654: NODE arg;
                   1655: P *rp;
                   1656: {
                   1657:        UP p1,p2,r;
                   1658:
                   1659:        ptoup((P)ARG0(arg),&p1);
                   1660:        hybrid_squareup(0,p1,&r);
                   1661:        uptop(r,rp);
                   1662: }
                   1663:
                   1664: void Putmul(arg,rp)
                   1665: NODE arg;
                   1666: P *rp;
                   1667: {
                   1668:        UP p1,p2,r;
                   1669:
                   1670:        ptoup((P)ARG0(arg),&p1);
                   1671:        ptoup((P)ARG1(arg),&p2);
                   1672:        hybrid_tmulup(0,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
                   1673:        uptop(r,rp);
                   1674: }
                   1675:
                   1676: void Pumul_ff(arg,rp)
                   1677: NODE arg;
                   1678: Obj *rp;
                   1679: {
                   1680:        P a1,a2;
                   1681:        UP p1,p2,r;
                   1682:        P p;
                   1683:
                   1684:        a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
                   1685:        ptoup(a1,&p1);
                   1686:        ptoup(a2,&p2);
                   1687:        hybrid_mulup(current_ff,p1,p2,&r);
                   1688:        uptop(r,&p);
                   1689:        simp_ff((Obj)p,rp);
                   1690: }
                   1691:
                   1692: void Pusquare_ff(arg,rp)
                   1693: NODE arg;
                   1694: Obj *rp;
                   1695: {
                   1696:        UP p1,p2,r;
                   1697:        P p;
                   1698:
                   1699:        ptoup((P)ARG0(arg),&p1);
                   1700:        hybrid_squareup(current_ff,p1,&r);
                   1701:        uptop(r,&p);
                   1702:        simp_ff((Obj)p,rp);
                   1703: }
                   1704:
                   1705: void Putmul_ff(arg,rp)
                   1706: NODE arg;
                   1707: Obj *rp;
                   1708: {
                   1709:        UP p1,p2,r;
                   1710:        P p;
                   1711:
                   1712:        ptoup((P)ARG0(arg),&p1);
                   1713:        ptoup((P)ARG1(arg),&p2);
                   1714:        hybrid_tmulup(current_ff,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
                   1715:        uptop(r,&p);
                   1716:        simp_ff((Obj)p,rp);
                   1717: }
                   1718:
                   1719: void Phfmul_lm(arg,rp)
                   1720: NODE arg;
                   1721: P *rp;
                   1722: {
                   1723:        UP p1,p2,r;
                   1724:        UP hi,lo,mid,t,s,p10,p11,p20,p21;
                   1725:        unsigned int m,d;
                   1726:        int i;
                   1727:
                   1728:        ptoup((P)ARG0(arg),&p1);
                   1729:        ptoup((P)ARG1(arg),&p2);
                   1730:        d = MAX(p1->d,p2->d);
                   1731:        for ( m = 1; m < d; m <<= 1 );
                   1732:        if ( m > d )
                   1733:                m >>= 1;
                   1734:        if ( d-m < 10000 ) {
                   1735:                decompup(p1,m,&p10,&p11); /* p1 = p11*x^m+p10 */
                   1736:                decompup(p2,m,&p20,&p21); /* p2 = p21*x^m+p20 */
                   1737:                fft_mulup_lm(p10,p20,&lo);
                   1738:                kmulup(p11,p21,&hi);
                   1739:                kmulup(p11,p20,&t); kmulup(p10,p21,&s); addup(t,s,&mid);
                   1740:                r = UPALLOC(2*d);
                   1741:                bzero((char *)COEF(r),(2*d+1)*sizeof(Num));
                   1742:                if ( lo )
                   1743:                        bcopy((char *)COEF(lo),(char *)COEF(r),(DEG(lo)+1)*sizeof(Num));
                   1744:                if ( hi )
                   1745:                        bcopy((char *)COEF(hi),(char *)(COEF(r)+2*m),(DEG(hi)+1)*sizeof(Num));
                   1746:                for ( i = 2*d; i >= 0 && !COEF(r)[i]; i-- );
                   1747:                if ( i < 0 )
                   1748:                        r = 0;
                   1749:                else {
                   1750:                        DEG(r) = i;
                   1751:                        t = UPALLOC(DEG(mid)+m); DEG(t) = DEG(mid)+m;
                   1752:                        bzero((char *)COEF(t),(DEG(mid)+m+1)*sizeof(Num));
                   1753:                        bcopy((char *)COEF(mid),(char *)(COEF(t)+m),(DEG(mid)+1)*sizeof(Num));
                   1754:                        addup(t,r,&s);
                   1755:                        r = s;
                   1756:                }
                   1757:        } else
                   1758:                fft_mulup_lm(p1,p2,&r);
                   1759:        uptop(r,rp);
                   1760: }
                   1761:
                   1762: void Pfmultest(arg,rp)
                   1763: NODE arg;
                   1764: LIST *rp;
                   1765: {
                   1766:        P p1,p2,r;
                   1767:        int d1,d2;
                   1768:        UM w1,w2,wr;
                   1769:        unsigned int *f1,*f2,*fr,*w;
                   1770:        int index,mod,root,d,maxint,i;
                   1771:        int cond;
                   1772:        Q prime;
                   1773:        NODE n0,n1;
                   1774:
                   1775:        p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); index = QTOS((Q)ARG2(arg));
                   1776:        FFT_primes(index,&mod,&root,&d);
                   1777:        maxint = 1<<d;
                   1778:        d1 = UDEG(p1); d2 = UDEG(p2);
                   1779:        if ( maxint < d1+d2+1 )
                   1780:                *rp = 0;
                   1781:        else {
                   1782:                w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
                   1783:                wr = W_UMALLOC(d1+d2);
                   1784:                ptoum(mod,p1,w1); ptoum(mod,p2,w2);
                   1785:                f1 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
                   1786:                f2 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
                   1787:                fr = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
                   1788:                w = (unsigned int *)ALLOCA(12*maxint*sizeof(unsigned int));
                   1789:
                   1790:                for ( i = 0; i <= d1; i++ )
                   1791:                        f1[i] = (unsigned int)w1->c[i];
                   1792:                for ( i = 0; i <= d2; i++ )
                   1793:                        f2[i] = (unsigned int)w2->c[i];
                   1794:
                   1795:                cond = FFT_pol_product(d1,f1,d2,f2,fr,index,w);
                   1796:                if ( cond )
                   1797:                        error("fmultest : ???");
                   1798:                wr->d = d1+d2;
                   1799:                for ( i = 0; i <= d1+d2; i++ )
                   1800:                        wr->c[i] = (unsigned int)fr[i];
                   1801:                umtop(VR(p1),wr,&r);
                   1802:                STOQ(mod,prime);
                   1803:                MKNODE(n1,prime,0);
                   1804:                MKNODE(n0,r,n1);
                   1805:                MKLIST(*rp,n0);
                   1806:        }
                   1807: }
                   1808:
                   1809: void Pkmulum(arg,rp)
                   1810: NODE arg;
                   1811: P *rp;
                   1812: {
                   1813:        P p1,p2;
                   1814:        int d1,d2,mod;
                   1815:        UM w1,w2,wr;
                   1816:
                   1817:        p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); mod = QTOS((Q)ARG2(arg));
                   1818:        d1 = UDEG(p1); d2 = UDEG(p2);
                   1819:        w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
                   1820:        wr = W_UMALLOC(d1+d2);
                   1821:        ptoum(mod,p1,w1); ptoum(mod,p2,w2);
                   1822:        kmulum(mod,w1,w2,wr);
                   1823:        umtop(VR(p1),wr,rp);
                   1824: }
                   1825:
                   1826: void Pksquareum(arg,rp)
                   1827: NODE arg;
                   1828: P *rp;
                   1829: {
                   1830:        P p1;
                   1831:        int d1,mod;
                   1832:        UM w1,wr;
                   1833:
                   1834:        p1 = (P)ARG0(arg); mod = QTOS((Q)ARG1(arg));
                   1835:        d1 = UDEG(p1);
                   1836:        w1 = W_UMALLOC(d1);
                   1837:        wr = W_UMALLOC(2*d1);
                   1838:        ptoum(mod,p1,w1);
                   1839:        kmulum(mod,w1,w1,wr);
                   1840:        umtop(VR(p1),wr,rp);
                   1841: }
                   1842:
                   1843: void Ptracemod_gf2n(arg,rp)
                   1844: NODE arg;
                   1845: P *rp;
                   1846: {
                   1847:        UP g,f,r;
                   1848:
                   1849:        ptoup((P)ARG0(arg),&g);
                   1850:        ptoup((P)ARG1(arg),&f);
                   1851:        tracemodup_gf2n(g,f,(Q)ARG2(arg),&r);
                   1852:        uptop(r,rp);
1.2       noro     1853: }
                   1854:
                   1855: void Pumul_specialmod(arg,rp)
                   1856: NODE arg;
                   1857: P *rp;
                   1858: {
                   1859:        P a1,a2;
                   1860:        UP p1,p2,r;
                   1861:        int i,nmod;
                   1862:        int *modind;
                   1863:        NODE t,n;
                   1864:
                   1865:        a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
                   1866:        if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
                   1867:                mulp(CO,a1,a2,rp);
                   1868:        else {
                   1869:                if ( !uzpcheck(a1) || !uzpcheck(a2) || VR(a1) != VR(a2) )
                   1870:                        error("umul_specialmod : invalid argument");
                   1871:                ptoup(a1,&p1);
                   1872:                ptoup(a2,&p2);
                   1873:                n = BDY((LIST)ARG2(arg));
                   1874:                nmod = length(n);
                   1875:                modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
                   1876:                for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
                   1877:                        modind[i] = QTOS((Q)BDY(t));
                   1878:                fft_mulup_specialmod_main(p1,p2,0,modind,nmod,&r);
                   1879:                uptop(r,rp);
                   1880:        }
                   1881: }
                   1882:
                   1883: void Pusquare_specialmod(arg,rp)
                   1884: NODE arg;
                   1885: P *rp;
                   1886: {
                   1887:        P a1;
                   1888:        UP p1,r;
                   1889:        int i,nmod;
                   1890:        int *modind;
                   1891:        NODE t,n;
                   1892:
                   1893:        a1 = (P)ARG0(arg);
                   1894:        if ( !a1 || NUM(a1) )
                   1895:                mulp(CO,a1,a1,rp);
                   1896:        else {
                   1897:                if ( !uzpcheck(a1) )
                   1898:                        error("usquare_specialmod : invalid argument");
                   1899:                ptoup(a1,&p1);
                   1900:                n = BDY((LIST)ARG1(arg));
                   1901:                nmod = length(n);
                   1902:                modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
                   1903:                for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
                   1904:                        modind[i] = QTOS((Q)BDY(t));
                   1905:                fft_mulup_specialmod_main(p1,p1,0,modind,nmod,&r);
                   1906:                uptop(r,rp);
                   1907:        }
                   1908: }
                   1909:
                   1910: void Putmul_specialmod(arg,rp)
                   1911: NODE arg;
                   1912: P *rp;
                   1913: {
                   1914:        P a1,a2;
                   1915:        UP p1,p2,r;
                   1916:        int i,nmod;
                   1917:        int *modind;
                   1918:        NODE t,n;
                   1919:
                   1920:        a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
                   1921:        if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
                   1922:                mulp(CO,a1,a2,rp);
                   1923:        else {
                   1924:                if ( !uzpcheck(a1) || !uzpcheck(a2) || VR(a1) != VR(a2) )
                   1925:                        error("utmul_specialmod : invalid argument");
                   1926:                ptoup(a1,&p1);
                   1927:                ptoup(a2,&p2);
                   1928:                n = BDY((LIST)ARG3(arg));
                   1929:                nmod = length(n);
                   1930:                modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
                   1931:                for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
                   1932:                        modind[i] = QTOS((Q)BDY(t));
                   1933:                fft_mulup_specialmod_main(p1,p2,QTOS((Q)ARG2(arg))+1,modind,nmod,&r);
                   1934:                uptop(r,rp);
                   1935:        }
1.1       noro     1936: }

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