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

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

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