[BACK]Return to sp CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2018 / lib

Annotation of OpenXM_contrib2/asir2018/lib/sp, Revision 1.1

1.1     ! 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
        !            26:  * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
        !            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:  *
        !            48:  * $OpenXM$
        !            49: */
        !            50: /*
        !            51:        sp : functions related to algebraic number fields
        !            52:
        !            53:        Revision History:
        !            54:
        !            55:        2001/10/12    noro    if USE_PARI_FACTOR is nonzero, pari factor is called
        !            56:        2000/03/10    noro    fixed several bugs around gathering algebraic numbers
        !            57:        1999/08/24    noro    modified for 1999 release version
        !            58: */
        !            59:
        !            60: #include "defs.h"
        !            61:
        !            62: extern ASCENT,GCDTIME,UFTIME,RESTIME,SQTIME,PRINT$
        !            63: extern SpOrd$
        !            64: extern USE_PARI_FACTOR$
        !            65:
        !            66: /* gen_sp can handle non-monic poly */
        !            67:
        !            68: def gen_sp(P)
        !            69: {
        !            70:        P = ptozp(P);
        !            71:        V = var(P);
        !            72:        D = deg(P,V);
        !            73:        LC = coef(P,D,V);
        !            74:        F = LC^(D-1)*subst(P,V,V/LC);
        !            75:        /* F must be monic */
        !            76:        L = sp(F);
        !            77:        return cons(map(subst,car(L),V,LC*V),cdr(L));
        !            78: }
        !            79:
        !            80: def sp(P)
        !            81: {
        !            82:        RESTIME=UFTIME=GCDTIME=SQTIME=0;
        !            83:        L = flatmf(fctr(P)); X = var(P);
        !            84:        AL = []; ADL = [];
        !            85:        while ( 1 ) {
        !            86:                L = sort_by_deg(L);
        !            87:                for ( T = L, H = []; T != []; H = cons(car(T),H), T = cdr(T) )
        !            88:                        if ( deg(car(T),X) > 1 )
        !            89:                                break;
        !            90:                if ( T == [] ) {
        !            91:                        if ( dp_gr_print() ) {
        !            92:                                print(["GCDTIME = ",GCDTIME]);
        !            93:                                print(["UFTIME = ",UFTIME]);
        !            94:                                print(["RESTIME = ",RESTIME]);
        !            95:                        }
        !            96:                        return [L,ADL];
        !            97:                } else {
        !            98:                        A = newalg(car(T));
        !            99:                        R = pdiva(car(T),X-A);
        !           100:                        AL = cons(A,AL);
        !           101:                        ADL = cons([A,defpoly(A)],ADL);
        !           102:                        L = aflist(append(H,append([X-A,R],cdr(T))),AL);
        !           103:                }
        !           104:        }
        !           105: }
        !           106:
        !           107: /*
        !           108:        Input:
        !           109:                F=F(x,a1,...,an)
        !           110:                DL = [[an,dn(an,...,a1)],...,[a2,d2(a2,a1)],[a1,d1(a1)]]
        !           111:                'ai' denotes a root of di(t).
        !           112:        Output:
        !           113:                irreducible factorization of F over Q(a1,...,an)
        !           114:                [[F1(x,a1,...,an),e1],...,[Fk(x,a1,...,an),ek]]
        !           115:                'ej' denotes the multiplicity of Fj.
        !           116: */
        !           117:
        !           118: def af_noalg(F,DL)
        !           119: {
        !           120:        DL = reverse(DL);
        !           121:        N = length(DL);
        !           122:        Tab = newvect(N);
        !           123:        /* Tab = [[a1,r1],...]; ri is a root of di(t,r(i-1),...,r1). */
        !           124:        AL = [];
        !           125:        for ( I = 0; I < N; I++ ) {
        !           126:                T = DL[I];
        !           127:                for ( J = 0, DP = T[1]; J < I; J++ )
        !           128:                        DP = subst(DP,Tab[J][0],Tab[J][1]);
        !           129:                B = newalg(DP);
        !           130:                Tab[I] = [T[0],B];
        !           131:                F = subst(F,T[0],B);
        !           132:                AL = cons(B,AL);
        !           133:        }
        !           134:        FL = af(F,AL);
        !           135:        for ( T = FL, R = []; T != []; T = cdr(T) )
        !           136:                R = cons([conv_noalg(T[0][0],Tab),T[0][1]],R);
        !           137:        return reverse(R);
        !           138: }
        !           139:
        !           140: /*
        !           141:        Input:
        !           142:                F=F(x) univariate polynomial over the rationals
        !           143:        Output:
        !           144:                [FL,DL]
        !           145:                DL = [[an,dn(an,...,a1)],...,[a2,d2(a2,a1)],[a1,d1(a1)]]
        !           146:                'ai' denotes a root of di(t).
        !           147:                FL = [F1,F2,...]
        !           148:                irreducible factors of F over Q(a1,...,an)
        !           149: */
        !           150:
        !           151: def sp_noalg(F)
        !           152: {
        !           153:        L = sp(F);
        !           154:        FL = map(algptorat,L[0]);
        !           155:        for ( T = L[1], DL = []; T != []; T = cdr(T) )
        !           156:                DL = cons([algtorat(T[0][0]),T[0][1]],DL);
        !           157:        return [FL,reverse(DL)];
        !           158: }
        !           159:
        !           160: def conv_noalg(F,Tab)
        !           161: {
        !           162:        N = size(Tab)[0];
        !           163:        F = algptorat(F);
        !           164:        for ( I = N-1; I >= 0; I-- )
        !           165:                F = subst(F,algtorat(Tab[I][1]),Tab[I][0]);
        !           166:        return F;
        !           167: }
        !           168:
        !           169: def aflist(L,AL)
        !           170: {
        !           171:        for ( DC = []; L != []; L = cdr(L) ) {
        !           172:                T = af_sp(car(L),AL,1);
        !           173:                DC = append(DC,T);
        !           174:        }
        !           175:        return DC;
        !           176: }
        !           177:
        !           178: def sort_by_deg(F)
        !           179: {
        !           180:        for ( T = F, S = []; T != []; T = cdr(T) )
        !           181:                if ( type(car(T)) != NUM )
        !           182:                        S = cons(car(T),S);
        !           183:        N = length(S); W = newvect(N);
        !           184:        for ( I = 0; I < N; I++ )
        !           185:                W[I] = S[I];
        !           186:        V = var(W[0]);
        !           187:        for ( I = 0; I < N; I++ ) {
        !           188:                for ( J = I + 1, J0 = I; J < N; J++ )
        !           189:                        if ( deg(W[J0],V) > deg(W[J],V) )
        !           190:                                J0 = J;
        !           191:                if ( J0 != I ) {
        !           192:                        T = W[I]; W[I] = W[J0]; W[J0] = T;
        !           193:                }
        !           194:        }
        !           195:        if ( ASCENT )
        !           196:                for ( I = N-1, S = []; I >= 0; I-- )
        !           197:                        S = cons(W[I],S);
        !           198:        else
        !           199:                for ( I = 0, S = []; I < N; I++ )
        !           200:                        S = cons(W[I],S);
        !           201:        return S;
        !           202: }
        !           203:
        !           204: def flatmf(L) {
        !           205:        for ( S = []; L != []; L = cdr(L) )
        !           206:                if ( type(F=car(car(L))) != NUM )
        !           207:                        S = append(S,[F]);
        !           208:        return S;
        !           209: }
        !           210:
        !           211: def af(P,AL)
        !           212: {
        !           213:        RESTIME=UFTIME=GCDTIME=SQTIME=0;
        !           214:     V = var(P);
        !           215:     LC = coef(P,deg(P,V),V);
        !           216:     if ( ntype(LC) != 1 )
        !           217:       P = simpalg(1/LC*P);
        !           218:        S = reverse(asq(P));
        !           219:        for ( L = []; S != []; S = cdr(S) ) {
        !           220:                FM = car(S); F = FM[0]; M = FM[1];
        !           221:                G = af_sp(F,AL,1);
        !           222:                for ( ; G != []; G = cdr(G) )
        !           223:                        L = cons([car(G),M],L);
        !           224:        }
        !           225:        if ( dp_gr_print() )
        !           226:                print(["GCDTIME = ",GCDTIME,"UFTIME = ",UFTIME,"RESTIME = ",RESTIME,"SQTIME=",SQTIME]);
        !           227:        return L;
        !           228: }
        !           229:
        !           230: def af_sp(P,AL,HINT)
        !           231: {
        !           232:        if ( !P || type(P) == NUM )
        !           233:                return [P];
        !           234:     V = var(P);
        !           235:     LC = coef(P,deg(P,V),V);
        !           236:     if ( ntype(LC) != 1 )
        !           237:       P = simpalg(1/LC*P);
        !           238:        P1 = simpcoef(simpalg(P));
        !           239:        return af_spmain(P1,AL,1,HINT,P1,[]);
        !           240: }
        !           241:
        !           242: def af_spmain(P,AL,INIT,HINT,PP,SHIFT)
        !           243: {
        !           244:        if ( !P || type(P) == NUM )
        !           245:                return [P];
        !           246:        P = simpcoef(simpalg(P));
        !           247:        if ( DEG(P) == 1 )
        !           248:                return [simpalg(P)];
        !           249:        if ( AL == [] ) {
        !           250:                TTT = time()[0];
        !           251:                F = flatmf(ufctrhint_heuristic(P,HINT,PP,SHIFT));
        !           252:                UFTIME+=time()[0]-TTT;
        !           253:                return F;
        !           254:        }
        !           255:        A0 = car(AL); P0 = defpoly(A0);
        !           256:        V = var(P); V0 = var(P0);
        !           257:        P = simpcoef(P);
        !           258:        TTT = time()[0];
        !           259:        N = simpcoef(sp_norm(A0,V,subst(P,V,V-INIT*A0),AL));
        !           260:        RESTIME+=time()[0]-TTT;
        !           261:        TTT = time()[0];
        !           262:        DCSQ = sortfs(asq(N));
        !           263:        SQTIME+=time()[0]-TTT;
        !           264:        for ( G = P, A = V+INIT*A0, DCR = []; DCSQ != []; DCSQ = cdr(DCSQ) ) {
        !           265:                C = TT(DCSQ); D = TS(DCSQ);
        !           266:                if ( !var(C) )
        !           267:                        continue;
        !           268:                if ( D == 1 )
        !           269:                        DCT = af_spmain(C,cdr(AL),1,HINT*deg(P0,V0),PP,cons([A0,INIT],SHIFT));
        !           270:                else
        !           271:                        DCT = af_spmain(C,cdr(AL),1,1,C,[]);
        !           272:                for ( ; DCT != []; DCT = cdr(DCT) ) {
        !           273:                        if ( !var(car(DCT)) )
        !           274:                                continue;
        !           275:                        if ( length(DCSQ) == 1 && length(DCT) == 1 )
        !           276:                                U = simpcoef(G);
        !           277:                        else {
        !           278:                                S = subst(car(DCT),V,A);
        !           279:                                if ( pra(G,S,AL) )
        !           280:                                        U = cr_gcda(S,G);
        !           281:                                else
        !           282:                                        U = S;
        !           283:                        }
        !           284:                        if ( var(U) == V ) {
        !           285:                                G = pdiva(G,U);
        !           286:                                if ( D == 1 )
        !           287:                                        DCR = cons(simpcoef(U),DCR);
        !           288:                                else {
        !           289:                                        T = af_spmain(U,AL,sp_next(INIT),HINT,PP,SHIFT);
        !           290:                                        DCR = append(DCR,T);
        !           291:                                }
        !           292:                        }
        !           293:                }
        !           294:        }
        !           295:        return DCR;
        !           296: }
        !           297:
        !           298: def sp_next(I)
        !           299: {
        !           300:        if ( I > 0 )
        !           301:                return -I;
        !           302:        else
        !           303:                return -I+1;
        !           304: }
        !           305:
        !           306: extern USE_RES;
        !           307:
        !           308: def sp_norm(A,V,P,AL)
        !           309: {
        !           310:        P = simpcoef(simpalg(P));
        !           311:        if (USE_RES)
        !           312:                return sp_norm_res(A,V,P,AL);
        !           313:        else
        !           314:                return sp_norm_ch(A,V,P,AL);
        !           315: }
        !           316:
        !           317: def sp_norm_ch(A,V,P,AL)
        !           318: {
        !           319:        Len = length(AL);
        !           320:        P0 = defpoly(A); V0 = var(P0);
        !           321:        PR = algptorat(P);
        !           322:        if ( nmono(P0) == 2 )
        !           323:                R = res(V0,PR,P0);
        !           324:        else if ( Len == 1 || Len == 3 )
        !           325:                R = res_ch1(V0,V,PR,P0);
        !           326:        else if ( Len == 2 ) {
        !           327:                P1 = defpoly(AL[1]);
        !           328:                R = norm_ch1(V0,V,PR,P0,P1);
        !           329:        } else
        !           330:                R = res(V0,PR,P0);
        !           331:        return rattoalgp(R,cdr(AL));
        !           332: }
        !           333:
        !           334: def sp_norm_res(A,V,P,AL)
        !           335: {
        !           336:        Len = length(AL);
        !           337:        P0 = defpoly(A); V0 = var(P0);
        !           338:        PR = algptorat(P);
        !           339:        R = res(V0,PR,P0);
        !           340:        return rattoalgp(R,cdr(AL));
        !           341: }
        !           342:
        !           343: def simpalg(P) {
        !           344:        if ( !P )
        !           345:                return 0;
        !           346:        else if ( type(P) == NUM )
        !           347:                return ntype(P) <= 1 ? P : simpalgn(P);
        !           348:        else if ( type(P) == POLY )
        !           349:                return simpalgp(P);
        !           350:        else if ( type(P) == RAT )
        !           351:                return simpalg(nm(P))/simpalg(dn(P));
        !           352: }
        !           353:
        !           354: def simpalgp(P) {
        !           355:        for ( V = var(P), I = deg(P,V), T = 0; I >= 0; I-- )
        !           356:                if ( C = coef(P,I) )
        !           357:                        T += simpalg(C)*V^I;
        !           358:        return T;
        !           359: }
        !           360:
        !           361: def simpalgn(A) {
        !           362:        if ( ntype(A) <= 1 )
        !           363:                return A;
        !           364:        else if ( type(R=algtorat(A)) == POLY )
        !           365:                return simpalgb(A);
        !           366:        else
        !           367:                return simpalgb(
        !           368:                        invalgp(simpalgb(rattoalg(dn(R))))
        !           369:                        *simpalgb(rattoalg(nm(R)))
        !           370:                );
        !           371: }
        !           372:
        !           373: def simpalgb(P) {
        !           374:        if ( ntype(P) <= 1 )
        !           375:                return P;
        !           376:        else {
        !           377:                A0 = getalg(P);
        !           378:                Used = [];
        !           379:                while ( A0 != [] ) {
        !           380:                        S = algtorat(P);
        !           381:                        for ( A = A0; A != []; A = cdr(A) )
        !           382:                                S = srem(S,defpoly(car(A)));
        !           383:                        P = rattoalg(S);
        !           384:                        Used = append(Used,[car(A0)]);
        !           385:                        A0 = setminus(getalg(P),Used);
        !           386:                }
        !           387:                return P;
        !           388:        }
        !           389: }
        !           390:
        !           391: def setminus(A,B) {
        !           392:        for ( T = reverse(A), R = []; T != []; T = cdr(T) ) {
        !           393:                for ( S = B, M = car(T); S != []; S = cdr(S) )
        !           394:                        if ( car(S) == M )
        !           395:                                break;
        !           396:                if ( S == [] )
        !           397:                        R = cons(M,R);
        !           398:        }
        !           399:        return R;
        !           400: }
        !           401:
        !           402: def getalgp(P) {
        !           403:        if ( type(P) <= 1 )
        !           404:                return getalg(P);
        !           405:        else {
        !           406:                for ( V = var(P), I = deg(P,V), T = []; I >= 0; I-- )
        !           407:                        if ( C = coef(P,I) )
        !           408:                                T = union_sort(T,getalgp(C));
        !           409:                return T;
        !           410:        }
        !           411: }
        !           412:
        !           413: def getalgtreep(P) {
        !           414:        if ( type(P) <= 1 )
        !           415:                return getalgtree(P);
        !           416:        else {
        !           417:                for ( V = var(P), I = deg(P,V), T = []; I >= 0; I-- )
        !           418:                        if ( C = coef(P,I) )
        !           419:                                T = union_sort(T,getalgtreep(C));
        !           420:                return T;
        !           421:        }
        !           422: }
        !           423:
        !           424: /* C = union of A and B; A and B is sorted. C should also be sorted. */
        !           425:
        !           426: def union_sort(A,B)
        !           427: {
        !           428:        if ( A == [] )
        !           429:                return B;
        !           430:        else if ( B == [] )
        !           431:                return A;
        !           432:        else {
        !           433:                A0 = car(A);
        !           434:                B0 = car(B);
        !           435:                if ( A0 == B0 )
        !           436:                        return cons(A0,union_sort(cdr(A),cdr(B)));
        !           437:                else if ( A0 > B0 )
        !           438:                        return cons(A0,union_sort(cdr(A),B));
        !           439:                else
        !           440:                        return cons(B0,union_sort(A,cdr(B)));
        !           441:        }
        !           442: }
        !           443:
        !           444: def invalgp(A)
        !           445: {
        !           446:        if ( ntype(A) <= 1 )
        !           447:                return 1/A;
        !           448:        P0 = defpoly(mainalg(A)); P = algtorat(A);
        !           449:        V = var(P0); G1 = P0;
        !           450:        G2 = DEG(P)>=DEG(P0)?srem(P,P0):P;
        !           451:        for ( H = 1, X = 1, U1 = 0, U2 = 1; deg(G2,V); ) {
        !           452:                D = DEG(G1)-DEG(G2); T = LCOEF(G2)^(D+1);
        !           453:                L = sqr(G1*T,G2); Q = car(L); R = car(cdr(L));
        !           454:                S = U1*T-U2*Q;
        !           455:                M = H^D; M1 = M*X;
        !           456:                G1 = G2; G2 = sdiv(R,M1);
        !           457:                U1 = U2; U2 = sdiv(S,M1);
        !           458:                X = LCOEF(G1); H = sdiv(X^D*H,M);
        !           459:        }
        !           460:        C = invalgp(rattoalg(srem(P*U2,P0)));
        !           461:        return C*rattoalg(U2);
        !           462: }
        !           463:
        !           464: def algptorat(P) {
        !           465:        if ( type(P) <= 1 )
        !           466:                return algtorat(P);
        !           467:        else {
        !           468:                for ( V = var(P), I = deg(P,V), T = 0; I >= 0; I-- )
        !           469:                        if ( C = coef(P,I) )
        !           470:                                T += algptorat(C)*V^I;
        !           471:                return T;
        !           472:        }
        !           473: }
        !           474:
        !           475: def rattoalgp(P,M) {
        !           476:        for ( T = M, S = P; T != []; T = cdr(T) )
        !           477:                S = subst(S,algtorat(FIRST(T)),FIRST(T));
        !           478:        return S;
        !           479: }
        !           480: def sortfs(L)
        !           481: {
        !           482: #define Factor(a) car(a)
        !           483: #define Mult(a) car(cdr(a))
        !           484:        if ( type(TT(L)) == NUM )
        !           485:                L = cdr(L);
        !           486:        for ( N = 0, T = L; T != []; T = cdr(T), N++ );
        !           487:        P = newvect(N); P1 = newvect(N);
        !           488:        for ( I = 0, T = L, R = []; T != []; T = cdr(T) )
        !           489:                if ( Mult(car(T)) == 1 ) {
        !           490:                        R = cons(car(T),R); N--;
        !           491:                } else {
        !           492:                        P[I] = car(T); I++;
        !           493:                }
        !           494:        for ( J = 0, V = var(Factor(P[0])); J < N; J++ ) {
        !           495:                for ( K0 = K = J, D = deg(Factor(P[J]),V); K < N; K++ )
        !           496:                        if ( deg(Factor(P[K]),V) < D ) {
        !           497:                                K0 = K;
        !           498:                                D = deg(Factor(P[K]),V);
        !           499:                        }
        !           500:                        P1[J] = P[K0];
        !           501:                        if ( J != K0 )
        !           502:                                P[K0] = P[J];
        !           503:        }
        !           504:        for ( I = N - 1; I >= 0; I-- )
        !           505:                R = cons(P1[I],R);
        !           506:        return R;
        !           507: }
        !           508:
        !           509: def pdiva(P1,P2)
        !           510: {
        !           511:        A = union_sort(getalgp(P1),getalgp(P2));
        !           512:        P1 = algptorat(P1); P2 = algptorat(P2);
        !           513:        return simpalg(rattoalgp(sdiv(P1*LCOEF(P2)^(DEG(P1)-DEG(P2)+1),P2),A));
        !           514: }
        !           515:
        !           516: def pqra(P1,P2)
        !           517: {
        !           518:        if ( type(P2) != POLY )
        !           519:                return [P1,0];
        !           520:        else if ( (type(P1) != POLY) || (deg(P1,var(P1)) < deg(P2,var(P1))) )
        !           521:                return [0,P1];
        !           522:        else {
        !           523:                A = union_sort(getalgp(P1),getalgp(P2));
        !           524:                P1 = algptorat(P1); P2 = algptorat(P2);
        !           525:                L = sqr(P1*LCOEF(P2)^(DEG(P1)-DEG(P2)+1),P2);
        !           526:                return [simpalg(rattoalgp(L[0],A)),simpalg(rattoalgp(L[1],A))];
        !           527:        }
        !           528: }
        !           529:
        !           530: def pra(P1,P2,AL)
        !           531: {
        !           532:        if ( type(P2) != POLY )
        !           533:                return 0;
        !           534:        else if ( (type(P1) != POLY) || (deg(P1,var(P1)) < deg(P2,var(P1))) )
        !           535:                return P1;
        !           536:        else {
        !           537:                F1 = algptorat(P1); F2 = algptorat(P2); ML = map(defpoly,AL);
        !           538:                B = append(reverse(ML),[F2]);
        !           539:                V0 = var(P1);
        !           540:                V = cons(V0,map(algtorat,AL));
        !           541:                G = srem_by_nf(F1,B,V,2);
        !           542:                return simpalg(rattoalgp(G[0]/G[1],AL));
        !           543:        }
        !           544: }
        !           545:
        !           546: def sort_alg(VL)
        !           547: {
        !           548:        N = length(VL); W = newvect(N,VL);
        !           549:        for ( I = 0; I < N; I++ ) {
        !           550:                for ( M = I, J = I + 1; J < N; J++ )
        !           551:                        if ( W[J] > W[M] )
        !           552:                                M = J;
        !           553:                if ( I != M ) {
        !           554:                        T = W[I]; W[I] = W[M]; W[M] = T;
        !           555:                }
        !           556:        }
        !           557:        for ( I = N-1, L = []; I >= 0; I-- )
        !           558:                L = cons(W[I],L);
        !           559:        return L;
        !           560: }
        !           561:
        !           562: def asq(P)
        !           563: {
        !           564:        P = simpalg(P);
        !           565:        if ( type(P) == NUM )
        !           566:                return [[1,1]];
        !           567:        else if ( getalgp(P) == [] )
        !           568:                return sqfr(P);
        !           569:        else {
        !           570:                V = var(P); N = DEG(P); A = newvect(N+1); B = newvect(N+1);
        !           571:                for ( I = 0, F = P; ;I++ ) {
        !           572:                        if ( type(F) == NUM )
        !           573:                                break;
        !           574:                        F1 = diff(F,V);
        !           575:                        GCD = cr_gcda(F,F1);
        !           576:                        FLAT = pdiva(F,GCD);
        !           577:                        if ( type(GCD) == NUM ) {
        !           578:                                A[I] = F; B[I] = 1;
        !           579:                                break;
        !           580:                        }
        !           581:                        for ( J = 1, F = GCD; ; J++ ) {
        !           582:                                L = pqra(F,FLAT); Q = L[0]; R = L[1];
        !           583:                                if ( R )
        !           584:                                        break;
        !           585:                                else
        !           586:                                        F = Q;
        !           587:                        }
        !           588:                        A[I] = FLAT; B[I] = J;
        !           589:                }
        !           590:                for ( I = 0, J = 0, L = []; A[I]; I++ ) {
        !           591:                        J += B[I];
        !           592:                        if ( A[I+1] )
        !           593:                                C = pdiva(A[I],A[I+1]);
        !           594:                        else
        !           595:                                C = A[I];
        !           596:                        L = cons([C,J],L);
        !           597:                }
        !           598:                return L;
        !           599:        }
        !           600: }
        !           601:
        !           602: def ufctrhint1(P,HINT)
        !           603: {
        !           604:        if ( deg(P,var(P)) == 168 ) {
        !           605:                SQ = sqfr(P);
        !           606:                if ( length(SQ) == 2 && SQ[1][1] == 1 )
        !           607:                        return [[1,1],[P,1]];
        !           608:                else
        !           609:                        return ufctrhint(P,HINT);
        !           610:        } else
        !           611:                return ufctrhint(P,HINT);
        !           612: }
        !           613:
        !           614: def simpcoef(P) {
        !           615:        return rattoalgp(ptozp(algptorat(P)),getalgp(P));
        !           616: }
        !           617:
        !           618: def ufctrhint_heuristic(P,HINT,PP,SHIFT) {
        !           619:        if ( USE_PARI_FACTOR )
        !           620:                return pari_ufctr(P);
        !           621:        else
        !           622:                return asir_ufctrhint_heuristic(P,HINT,PP,SHIFT);
        !           623: }
        !           624:
        !           625: def pari_ufctr(P) {
        !           626:        F = pari(factpol,P);
        !           627:        S = size(F);
        !           628:        for ( I = S[0]-1, R = []; I >= 0; I-- )
        !           629:                R = cons(vtol(F[I]),R);
        !           630:        return cons([1,1],R);
        !           631: }
        !           632:
        !           633: def asir_ufctrhint_heuristic(P,HINT,PP,SHIFT) {
        !           634:        V = var(P); D = deg(P,V);
        !           635:        if ( D == HINT )
        !           636:                return [[P,1]];
        !           637:        for ( S = 0, L = SHIFT, AL = [], K = 1; L != []; L = cdr(L) ) {
        !           638:                A = car(L)[0]; S += A*car(L)[1]; AL = cons(A,AL);
        !           639:                K *= deg(defpoly(A),algtorat(A));
        !           640:        }
        !           641:        PPP = simpcoef(simpalg(subst(PP,V,V-S)));
        !           642:        for ( T = P-coef(P,D)*V^D, G = D; T; T -= coef(T,DT)*V^DT )
        !           643:                G = igcd(G,DT=deg(T,V));
        !           644:        if ( G == 1 ) {
        !           645:                if ( K*deg(PPP,V) != deg(P,V) )
        !           646:                        PPP = cr_gcda(PPP,P);
        !           647:                return ufctrhint2(P,HINT,PPP,AL);
        !           648:        } else {
        !           649:                for ( S = 0, T = P; T; T -= coef(T,DT)*V^DT ) {
        !           650:                        DT = deg(T,V);
        !           651:                        S += coef(T,DT)*V^(DT/G);
        !           652:                }
        !           653:                L = fctr(S);
        !           654:                for ( DC = [car(L)], L = cdr(L); L != []; L = cdr(L) ) {
        !           655:                        H = subst(car(car(L)),V,V^G);
        !           656:                        HH = cr_gcda(PPP,H);
        !           657:                        T = ufctrhint2(H,HINT,HH,AL);
        !           658:                        DC = append(DC,T);
        !           659:                }
        !           660:                return DC;
        !           661:        }
        !           662: }
        !           663:
        !           664: def ufctrhint2(P,HINT,PP,AL)
        !           665: {
        !           666:        if ( deg(P,var(P)) == HINT )
        !           667:                return [[P,1]];
        !           668:        if ( AL == [] )
        !           669:                return ufctrhint(P,HINT);
        !           670:
        !           671:        /* if P != norm(PP) then call the generic ufctrhint() */
        !           672:        for ( T = AL, E = 1; T != []; T = cdr(T) ) {
        !           673:                D = defpoly(car(T)); E *= deg(D,var(D));
        !           674:        }
        !           675:        if ( E*deg(PP,var(PP)) != deg(P,var(P)) )
        !           676:                return ufctrhint(P,HINT);
        !           677:
        !           678:        /* P = norm(PP) */
        !           679:        L = resfctr(algptorat(PP),map(defpoly,AL),map(algtorat,AL),P);
        !           680:        for ( T = reverse(L[1]), DL = []; T != []; T = cdr(T) )
        !           681:                DL = cons(deg(car(car(T)),a_),DL);
        !           682:        return resfmain(P,L[2],L[0],DL);
        !           683: }
        !           684:
        !           685: def res_det(V,P1,P2)
        !           686: {
        !           687:        D1 = deg(P1,V); D2 = deg(P2,V);
        !           688:        M = newmat(D1+D2,D1+D2);
        !           689:        for ( J = 0; J <= D2; J++ )
        !           690:                M[0][J] = coef(P2,D2-J,V);
        !           691:        for ( I = 1; I < D1; I++ )
        !           692:                for ( J = 0; J <= D2; J++ )
        !           693:                M[I][I+J] = M[0][J];
        !           694:        for ( J = 0; J <= D1; J++ )
        !           695:                M[D1][J] = coef(P1,D1-J,V);
        !           696:        for ( I = 1; I < D2; I++ )
        !           697:                for ( J = 0; J <= D1; J++ )
        !           698:                M[D1+I][I+J] = M[D1][J];
        !           699:        return det(M);
        !           700: }
        !           701:
        !           702: def norm_ch1(V0,VM,P,P0,PR) {
        !           703:        D = deg(P,V0); D0 = deg(P0,V0); DM = deg(P,VM); N = DM*D0;
        !           704:        X = newvect(N+1); V = newvect(N+1); U = newvect(N+1);
        !           705:        Min = -idiv(N,2);
        !           706:        C = coef(P,D,V0);
        !           707:        for ( I = J = 0; I <= N; J++ ) {
        !           708:                if ( PRINT )
        !           709:                        print([J,N]);
        !           710:                T=J+Min;
        !           711:                if ( subst(C,VM,T) ) {
        !           712:                        U[I] = srem(res(V0,subst(P,VM,T),P0),PR);
        !           713:                        X[I++] = T;
        !           714:                }
        !           715:        }
        !           716:        for ( I = 1, M = 1, S = V[0] = U[0]; I <= N; I++ ) {
        !           717:                for ( J = 0, T = U[I]; J < I; J++ )
        !           718:                        T = sdiv(T-V[J],X[I]-X[J]);
        !           719:                V[I] = T;
        !           720:                M *= (VM-X[I-1]);
        !           721:                S += T*M;
        !           722:        }
        !           723:        return S;
        !           724: }
        !           725:
        !           726: def norm_ch2(V0,VM,P,P0,PR) {
        !           727:        D = deg(P,V0); D0 = deg(P0,V0); DM = deg(P,VM); N = DM*D0;
        !           728:        X = newvect(N+1); V = newvect(N+1); U = newvect(N+1);
        !           729:        Min = -idiv(N,2);
        !           730:        C = coef(P,D,V0);
        !           731:        for ( I = J = 0; I <= N; J++ ) {
        !           732:                T=J+Min;
        !           733:                if ( subst(C,VM,T) ) {
        !           734:                        U[I] = srem(res_det(V0,subst(P,VM,T),P0),PR);
        !           735:                        X[I++] = T;
        !           736:                }
        !           737:        }
        !           738:        for ( I = 1, M = 1, S = V[0] = U[0]; I <= N; I++ ) {
        !           739:                for ( J = 0, T = U[I]; J < I; J++ )
        !           740:                        T = sdiv(T-V[J],X[I]-X[J]);
        !           741:                V[I] = T;
        !           742:                M *= (VM-X[I-1]);
        !           743:                S += T*M;
        !           744:        }
        !           745:        return S;
        !           746: }
        !           747:
        !           748: def res_ch1(V0,VM,P,P0) {
        !           749:        D = deg(P,V0); D0 = deg(P0,V0); N = deg(P,VM)*D0+deg(P0,VM)*D;
        !           750:        X = newvect(N+1); V = newvect(N+1); U = newvect(N+1);
        !           751:        Min = -idiv(N,2);
        !           752:        C = coef(P,D,V0); C0 = coef(P0,D0,V0);
        !           753:        for ( I = J = 0; I <= N; J++ ) {
        !           754:                if ( PRINT )
        !           755:                        print([J,N]);
        !           756:                T=J+Min;
        !           757:                if ( subst(C,VM,T) && subst(C0,VM,T) ) {
        !           758:                        U[I] = res(V0,subst(P,VM,T),subst(P0,VM,T));
        !           759:                        X[I++] = T;
        !           760:                }
        !           761:        }
        !           762:        for ( I = 1, M = 1, S = V[0] = U[0]; I <= N; I++ ) {
        !           763:                for ( J = 0, T = U[I]; J < I; J++ )
        !           764:                        T = sdiv(T-V[J],X[I]-X[J]);
        !           765:                V[I] = T;
        !           766:                M *= (VM-X[I-1]);
        !           767:                S += T*M;
        !           768:        }
        !           769:        return S;
        !           770: }
        !           771:
        !           772: def res_ch(V0,VM,P,P0) {
        !           773:        D = deg(P,V0); D0 = deg(P0,V0); N = deg(P,VM)*D0+deg(P0,VM)*D;
        !           774:        X = newvect(N+1); V = newvect(N+1); U = newvect(N+1);
        !           775:        Min = -idiv(N,2);
        !           776:        C = coef(P,D,V0); C0 = coef(P0,D0,V0);
        !           777:        for ( I = J = 0; I <= N; J++ ) {
        !           778:                T=J+Min;
        !           779:                if ( subst(C,VM,T) && subst(C0,VM,T) ) {
        !           780:                        U[I] = res_det(V0,subst(P,VM,T),subst(P0,VM,T));
        !           781:                        X[I++] = T;
        !           782:                }
        !           783:        }
        !           784:        for ( I = 1, M = 1, S = V[0] = U[0]; I <= N; I++ ) {
        !           785:                for ( J = 0, T = U[I]; J < I; J++ )
        !           786:                        T = sdiv(T-V[J],X[I]-X[J]);
        !           787:                V[I] = T;
        !           788:                M *= (VM-X[I-1]);
        !           789:                S += T*M;
        !           790:        }
        !           791:        return S;
        !           792: }
        !           793:
        !           794: def norm_ch2_lag(V,VM,P,P0,PR) {
        !           795:        D0 = deg(P0,V); DM = deg(P,VM); N = DM*D0;
        !           796:        Min = -idiv(N,2);
        !           797:        for ( A = 1, I = 0; I <= N; I++ )
        !           798:                A *= (VM-I-Min);
        !           799:        for ( I = 0, S = 0; I <= N; I++ ) {
        !           800:                R = res_det(V,subst(P,VM,I+Min),P0);
        !           801:                R = srem(R,PR);
        !           802:                T = sdiv(A,VM-I-Min);
        !           803:                S += R*T/subst(T,VM,I+Min);
        !           804:        }
        !           805:        return S;
        !           806: }
        !           807:
        !           808: def norm_ch_lag(V,VM,P,P0) {
        !           809:        D0 = deg(P0,V); DM = deg(P,VM); N = DM*D0;
        !           810:        Min = -idiv(N,2);
        !           811:        for ( A = 1, I = 0; I <= N; I++ )
        !           812:                A *= (VM-I-Min);
        !           813:        for ( I = 0, S = 0; I <= N; I++ ) {
        !           814:                R = res_det(V,subst(P,VM,I+Min),P0);
        !           815:                T = sdiv(A,VM-I-Min);
        !           816:                S += R*T/subst(T,VM,I+Min);
        !           817:        }
        !           818:        return S;
        !           819: }
        !           820:
        !           821: def cr_gcda(P1,P2)
        !           822: {
        !           823:        if ( !P1 )
        !           824:                return P2;
        !           825:        if ( !P2 )
        !           826:                return P1;
        !           827:        if ( !var(P1) || !var(P2) )
        !           828:                return 1;
        !           829:        V = var(P1);
        !           830:        EXT = union_sort(getalgtreep(P1),getalgtreep(P2));
        !           831:        if ( EXT == [] )
        !           832:                return gcd(P1,P2);
        !           833:        NEXT = length(EXT);
        !           834:        if ( deg(P1,V) < deg(P2,V) ) {
        !           835:                T = P1; P1 = P2; P2 = T;
        !           836:        }
        !           837:        G1 = ptozp(algptorat(P1)); G2 = ptozp(algptorat(P2));
        !           838:        for ( ML = VL = [], T = reverse(EXT); T != []; T = cdr(T) ) {
        !           839:                ML = cons(defpoly(car(T)),ML);
        !           840:                VL = cons(algptorat(car(T)),VL);
        !           841:        }
        !           842:        DL = [coef(G1,deg(G1,V),V),coef(G2,deg(G2,V),V)];
        !           843:        for ( T = EXT; T != []; T = cdr(T) ) {
        !           844:                DL = cons(discr(sp_minipoly(car(T),EXT)),DL);
        !           845:                C = LCOEF(defpoly(car(T)));
        !           846:                if ( C != 1 && C != -1 )
        !           847:                        DL = cons(C,DL);
        !           848:        }
        !           849:        TIME = time()[0];
        !           850:        for ( D = deg(P1,V)+1, I = 0; ; I++ ) {
        !           851:                MOD = lprime(I);
        !           852:                for ( J = 0; J < length(DL); J++ )
        !           853:                        if ( !(DL[J] % MOD) )
        !           854:                                break;
        !           855:                if ( J != length(DL) )
        !           856:                        continue;
        !           857:                SpOrd = 2; NOSUGAR = 1;
        !           858:                T = ag_mod(G1 % MOD,G2 % MOD,ML,VL,MOD);
        !           859:                if ( dp_gr_print() )
        !           860:                        print(".");
        !           861:                if ( !T )
        !           862:                        continue;
        !           863:                T = (T*inv(coef(T,deg(T,V),V),MOD))%MOD;
        !           864:                if ( deg(T,V) > D )
        !           865:                        continue;
        !           866:                else if ( deg(T,V) < D ) {
        !           867:                        IMAGE = T; M = MOD; D = deg(T,V);
        !           868:                } else {
        !           869:                        L = cr(IMAGE,M,T,MOD); IMAGE = L[0]; M = L[1];
        !           870:                }
        !           871:                F = intptoratp(IMAGE,M,calcb(M));
        !           872:                if ( F != [] ) {
        !           873:                        F = ptozp(F);
        !           874:                        DIV = rattoalgp(F,EXT);
        !           875:                        if ( type(DIV) == 1 )
        !           876:                                return 1;
        !           877: /*
        !           878:                        if ( srem_simp(G1,F,V,ML) )
        !           879:                                continue;
        !           880:                        if ( srem_simp(G2,F,V,ML) )
        !           881:                                continue;
        !           882: */
        !           883:                        if ( srem_by_nf(G1,reverse(cons(F,ML)),cons(V,VL),2)[0] )
        !           884:                                continue;
        !           885:                        if ( srem_by_nf(G2,reverse(cons(F,ML)),cons(V,VL),2)[0] )
        !           886:                                continue;
        !           887:                        TIME = time()[0]-TIME;
        !           888:                        if ( dp_gr_print() )
        !           889:                                print([TIME]);
        !           890:                        GCDTIME += TIME;
        !           891:                        return DIV;
        !           892:                }
        !           893:        }
        !           894: }
        !           895:
        !           896: def srem_simp(F1,F2,V,D)
        !           897: {
        !           898:        D2 = deg(F2,V); C = coef(F2,D2);
        !           899:        while ( (D1 = deg(F1,V)) >= D2 ) {
        !           900:                F1 -= coef(F1,D1)/C*V^(D1-D2)*F2;
        !           901:                F1 = simp_by_dp(F1,D);
        !           902:        }
        !           903:        return F1;
        !           904: }
        !           905:
        !           906: def member(E,L)
        !           907: {
        !           908:        for ( ; L != []; L = cdr(L) )
        !           909:                if ( E == car(L) )
        !           910:                        return 1;
        !           911:        return 0;
        !           912: }
        !           913:
        !           914: def discr(P) {
        !           915:        V = var(P);
        !           916:        return res(V,P,diff(P,V));
        !           917: }
        !           918:
        !           919: def sp_minipoly(A,EXT)
        !           920: {
        !           921:        while ( car(EXT) != A )
        !           922:                EXT = cdr(EXT);
        !           923:        for ( M = x-A; EXT != []; EXT = cdr(EXT) )
        !           924:                M = sp_norm(car(EXT),x,M,EXT);
        !           925:        F = sqfr(M);
        !           926:        return F[1][0];
        !           927: }
        !           928:
        !           929: def cr(F1,M1,F2,M2)
        !           930: {
        !           931:        K = inv(M1 % M2,M2);
        !           932:        M3 = M1*M2;
        !           933:        F3 = (F1 + (F2-(F1%M2))*K*M1) % M3;
        !           934:        return [F3,M3];
        !           935: }
        !           936:
        !           937: #define ABS(a) ((a)>=0?(a):(-a))
        !           938:
        !           939: #if 0
        !           940: def calcb(M) {
        !           941:        setprec(800);
        !           942:        return pari(floor,eval((M/2)^(1/2)));
        !           943: }
        !           944: #endif
        !           945:
        !           946: def calcb(M) {
        !           947:        N = 2*M;
        !           948:        T = sp_sqrt(N);
        !           949:        if ( T^2 <= N && N < (T+1)^2 )
        !           950:                return idiv(T,2);
        !           951:        else
        !           952:                error("afo");
        !           953: }
        !           954:
        !           955: def sp_sqrt(A) {
        !           956:        for ( J = 0, T = A; T >= 2^27; J++ ) {
        !           957:                T = idiv(T,2^27)+1;
        !           958:        }
        !           959:        for ( I = 0; T >= 2; I++ ) {
        !           960:                S = idiv(T,2);
        !           961:                if ( T = S+S )
        !           962:                        T = S;
        !           963:                else
        !           964:                        T = S+1;
        !           965:        }
        !           966:        X = (2^27)^idiv(J,2)*2^idiv(I,2);
        !           967:        while ( 1 ) {
        !           968:                if ( (Y=X^2) < A )
        !           969:                        X += X;
        !           970:                else if ( Y == A )
        !           971:                        return X;
        !           972:                else
        !           973:                        break;
        !           974:        }
        !           975:        while ( 1 )
        !           976:                if ( (Y = X^2) <= A )
        !           977:                        return X;
        !           978:                else
        !           979:                        X = idiv(A + Y,2*X);
        !           980: }
        !           981:
        !           982: def intptoratp(P,M,B) {
        !           983:        if ( type(P) == 1 ) {
        !           984:                L = inttorat(P,M,B);
        !           985:                if ( L == 0 )
        !           986:                        return [];
        !           987:                else
        !           988:                        return L[0]/L[1];
        !           989:        } else {
        !           990:                V = var(P);
        !           991:                S = 0;
        !           992:                while ( P ) {
        !           993:                        D = deg(P,V);
        !           994:                        C = coef(P,D,V);
        !           995:                        T = intptoratp(C,M,B);
        !           996:                        if ( T == [] )
        !           997:                                return [];
        !           998:                        S += T*V^D;
        !           999:                        P -= C*V^D;
        !          1000:                }
        !          1001:                return S;
        !          1002:        }
        !          1003: }
        !          1004:
        !          1005: def ltoalg(L) {
        !          1006:        F = L[0]; V = reverse(L[1]);
        !          1007:        N = length(V)-1;
        !          1008:        for ( I = 0, G = F; I < N; I++ ) {
        !          1009:                D = car(G);
        !          1010:                A = newalg(D); V = var(D);
        !          1011:                for ( G = reverse(cdr(G)), T = []; G != []; G = cdr(G) )
        !          1012:                        T = cons(subst(car(G),V,A),T);
        !          1013:                G = T;
        !          1014:        }
        !          1015:        return G;
        !          1016: }
        !          1017:
        !          1018: /*
        !          1019: def ag_mod(F1,F2,D,MOD)
        !          1020: {
        !          1021:        if ( length(D) == 1 )
        !          1022:                return ag_mod_single(F1,F2,D,MOD);
        !          1023:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1024:        if ( D1 < D2 ) {
        !          1025:                T = F1; F1 = F2; F2 = T;
        !          1026:                T = D1; D1 = D2; D2 = T;
        !          1027:        }
        !          1028:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1029:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1030:        for ( T = reverse(D), S = []; T != []; T = cdr(T) ) {
        !          1031:                U = car(T);
        !          1032:                S = cons((inv(LCOEF(U),MOD)*U) % MOD,S);
        !          1033:        }
        !          1034:        D = S;
        !          1035:     while ( 1 ) {
        !          1036:                F = srem_simp_mod(F1,F2,V,D,MOD);
        !          1037:                if ( !F )
        !          1038:                        return F2;
        !          1039:                if ( !deg(F,V) )
        !          1040:                        return 1;
        !          1041:                C = LCOEF(F);
        !          1042:                INV = inverse_by_gr_mod(C,D,MOD);
        !          1043:                if ( !INV )
        !          1044:                        return 0;
        !          1045:                F = simp_by_dp_mod(F*INV,D,MOD);
        !          1046:                F = (inv(LCOEF(F),MOD)*F) % MOD;
        !          1047:                F1 = F2; F2 = F;
        !          1048:        }
        !          1049: }
        !          1050: */
        !          1051:
        !          1052: def ag_mod(F1,F2,D,VL,MOD)
        !          1053: {
        !          1054:        if ( length(D) == 1 )
        !          1055:                return ag_mod_single6(F1,F2,D,MOD);
        !          1056:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1057:        if ( D1 < D2 ) {
        !          1058:                T = F1; F1 = F2; F2 = T;
        !          1059:                T = D1; D1 = D2; D2 = T;
        !          1060:        }
        !          1061:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1062:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1063:        for ( T = reverse(D), S = []; T != []; T = cdr(T) ) {
        !          1064:                U = car(T);
        !          1065:                S = cons((inv(LCOEF(U),MOD)*U) % MOD,S);
        !          1066:        }
        !          1067:        D = S;
        !          1068:        VL = cons(V,VL); B = append([F1,F2],D); N = length(VL);
        !          1069:     while ( 1 ) {
        !          1070:                FLAGS = dp_gr_flags(); dp_gr_flags(["Reverse",1,"NoSugar",1]);
        !          1071:                G = dp_gr_mod_main(B,VL,0,MOD,SpOrd);
        !          1072:                dp_gr_flags(FLAGS);
        !          1073:                if ( length(G) == 1 )
        !          1074:                        return 1;
        !          1075:                if ( length(G) == N ) {
        !          1076:                        for ( T = G; T != []; T = cdr(T) )
        !          1077:                                if ( member(V,vars(car(T))) )
        !          1078:                                        return car(T);
        !          1079:                }
        !          1080:        }
        !          1081: }
        !          1082:
        !          1083: def srem_simp_mod(F1,F2,V,D,MOD)
        !          1084: {
        !          1085:        D2 = deg(F2,V); C = coef(F2,D2);
        !          1086:        while ( (D1 = deg(F1,V)) >= D2 ) {
        !          1087:                F1 -= coef(F1,D1)/C*V^(D1-D2)*F2;
        !          1088:                F1 = simp_by_dp_mod(F1,D,MOD);
        !          1089:        }
        !          1090:        return F1;
        !          1091: }
        !          1092:
        !          1093: def ag_mod_single(F1,F2,D,MOD)
        !          1094: {
        !          1095:        TD = TI = TM = 0;
        !          1096:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1097:        if ( D1 < D2 ) {
        !          1098:                T = F1; F1 = F2; F2 = T;
        !          1099:                T = D1; D1 = D2; D2 = T;
        !          1100:        }
        !          1101:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1102:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1103:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1104:        FLAGS = dp_gr_flags(); dp_gr_flags(["Reverse",1,"NoSugar",1]);
        !          1105:        G = dp_gr_mod_main([F1,F2,D],[V,var(D)],0,MOD,2);
        !          1106:        dp_gr_flags(FLAGS);
        !          1107:        if ( length(G) == 1 )
        !          1108:                return 1;
        !          1109:        if ( length(G) != 2 )
        !          1110:                return 0;
        !          1111:        if ( vars(G[0]) == [var(D)] )
        !          1112:                return G[1];
        !          1113:        else
        !          1114:                return G[0];
        !          1115: }
        !          1116:
        !          1117: def ag_mod_single2(F1,F2,D,MOD)
        !          1118: {
        !          1119:        TD = TI = TM = 0;
        !          1120:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1121:        if ( D1 < D2 ) {
        !          1122:                T = F1; F1 = F2; F2 = T;
        !          1123:                T = D1; D1 = D2; D2 = T;
        !          1124:        }
        !          1125:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1126:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1127:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1128:     while ( 1 ) {
        !          1129:                T0 = time()[0];
        !          1130:                F = srem((srem(F1,F2) % MOD),D) % MOD;
        !          1131:                TD += time()[0] - T0;
        !          1132:                if ( !F ) {
        !          1133:                        if ( dp_gr_print() )
        !          1134:                                print(["TD",TD,"TM",TM,"TI",TI]);
        !          1135:                        return F2;
        !          1136:                }
        !          1137:                if ( !deg(F,V) ) {
        !          1138:                        if ( dp_gr_print() )
        !          1139:                                print(["TD",TD,"TM",TM,"TI",TI]);
        !          1140:                        return 1;
        !          1141:                }
        !          1142:                C = LCOEF(F);
        !          1143:                T0 = time()[0];
        !          1144:                INV = inva_mod(D,MOD,C);
        !          1145:                TI += time()[0] - T0;
        !          1146:                if ( !INV )
        !          1147:                        return 0;
        !          1148:                T0 = time()[0];
        !          1149:                F = remc_mod((INV*F) % MOD,D,MOD);
        !          1150:                TM += time()[0] - T0;
        !          1151:                F1 = F2; F2 = F;
        !          1152:        }
        !          1153: }
        !          1154:
        !          1155: def ag_mod_single3(F1,F2,D,MOD)
        !          1156: {
        !          1157:        TD = TI = TM = 0;
        !          1158:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1159:        if ( D1 < D2 ) {
        !          1160:                T = F1; F1 = F2; F2 = T;
        !          1161:                T = D1; D1 = D2; D2 = T;
        !          1162:        }
        !          1163:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1164:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1165:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1166:     while ( 1 ) {
        !          1167:                if ( !D2 )
        !          1168:                        return 1;
        !          1169:                while ( D1 >= D2 ) {
        !          1170:                        F = srem((coef(F2,D2,V)*F1-coef(F1,D1,V)*F2*V^(D1-D2))%MOD,D)%MOD;
        !          1171:                        F1 = F; D1 = deg(F1,V);
        !          1172:                }
        !          1173:                if ( !F1 ) {
        !          1174:                        INV = inva_mod(D,MOD,coef(F2,D2,V));
        !          1175:                        if ( dp_gr_print() )
        !          1176:                                print(".");
        !          1177:                        return srem((INV*F2) % MOD,D)%MOD;
        !          1178:                } else {
        !          1179:                        T = F1; F1 = F2; F2 = T;
        !          1180:                        T = D1; D1 = D2; D2 = T;
        !          1181:                }
        !          1182:        }
        !          1183: }
        !          1184:
        !          1185: def ag_mod_single4(F1,F2,D,MOD)
        !          1186: {
        !          1187:        if ( !F1 )
        !          1188:                return F2;
        !          1189:        if ( !F2 )
        !          1190:                return F1;
        !          1191:        TD = TI = TM = TR = 0;
        !          1192:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1193:        if ( D1 < D2 ) {
        !          1194:                T = F1; F1 = F2; F2 = T;
        !          1195:                T = D1; D1 = D2; D2 = T;
        !          1196:        }
        !          1197:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1198:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1199:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1200:     while ( 1 ) {
        !          1201:                T0 = time()[0]; R = srem(F1,F2); TR += time()[0] - T0;
        !          1202:                T0 = time()[0]; F = srem(R % MOD,D) % MOD; TD += time()[0] - T0;
        !          1203:                if ( !F ) {
        !          1204:                        if ( dp_gr_print() )
        !          1205:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1206:                        return F2;
        !          1207:                }
        !          1208:                if ( !deg(F,V) ) {
        !          1209:                        if ( dp_gr_print() )
        !          1210:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1211:                        return 1;
        !          1212:                }
        !          1213:                C = LCOEF(F);
        !          1214:                T0 = time()[0]; INV = inva_mod(D,MOD,C); TI += time()[0] - T0;
        !          1215:                if ( !INV )
        !          1216:                        return 0;
        !          1217:                T0 = time()[0]; F = srem((INV*F) % MOD,D) % MOD; TM += time()[0] - T0;
        !          1218:                F1 = F2; F2 = F;
        !          1219:        }
        !          1220: }
        !          1221:
        !          1222: def ag_mod_single5(F1,F2,D,MOD)
        !          1223: {
        !          1224:        TD = TI = TM = TR = 0;
        !          1225:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1226:        if ( D1 < D2 ) {
        !          1227:                T = F1; F1 = F2; F2 = T;
        !          1228:                T = D1; D1 = D2; D2 = T;
        !          1229:        }
        !          1230:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1231:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1232:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1233:     while ( 1 ) {
        !          1234:                T0 = time()[0];
        !          1235:                D1 = deg(F1,V); D2 = deg(F2,V); F = F1;
        !          1236:                while ( D1 >= D2 ) {
        !          1237:                        R = (F-coef(F,D1,V)*F2*V^(D1-D2))%MOD;
        !          1238:                        D1 = deg(R,V); HC = coef(R,D1,V);
        !          1239:                        F = (R - HC*V^D1) + (srem(HC,D)%MOD)*V^D1;
        !          1240:                }
        !          1241:                TR += time()[0] - T0;
        !          1242:                T0 = time()[0]; F = srem(R % MOD,D) % MOD; TD += time()[0] - T0;
        !          1243:                if ( !F ) {
        !          1244:                        if ( dp_gr_print() )
        !          1245:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1246:                        return F2;
        !          1247:                }
        !          1248:                if ( !deg(F,V) ) {
        !          1249:                        if ( dp_gr_print() )
        !          1250:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1251:                        return 1;
        !          1252:                }
        !          1253:                C = LCOEF(F);
        !          1254:                T0 = time()[0]; INV = inva_mod(D,MOD,C); TI += time()[0] - T0;
        !          1255:                if ( !INV )
        !          1256:                        return 0;
        !          1257:                T0 = time()[0]; F = srem((INV*F) % MOD,D) % MOD; TM += time()[0] - T0;
        !          1258:                F1 = F2; F2 = F;
        !          1259:        }
        !          1260: }
        !          1261:
        !          1262: def ag_mod_single6(F1,F2,D,MOD)
        !          1263: {
        !          1264:        TD = TI = TM = TR = 0;
        !          1265:        V = var(F1); D1 = deg(F1,V); D2 = deg(F2,V);
        !          1266:        if ( D1 < D2 ) {
        !          1267:                T = F1; F1 = F2; F2 = T;
        !          1268:                T = D1; D1 = D2; D2 = T;
        !          1269:        }
        !          1270:        F1 = (inv(LCOEF(F1),MOD)*F1) % MOD;
        !          1271:        F2 = (inv(LCOEF(F2),MOD)*F2) % MOD;
        !          1272:        D = (inv(LCOEF(car(D)),MOD)*car(D)) % MOD;
        !          1273:     while ( 1 ) {
        !          1274:                T0 = time()[0];
        !          1275:                D1 = deg(F1,V); D2 = deg(F2,V); F = F1;
        !          1276:                while ( D1 >= D2 ) {
        !          1277:                        R = (F-coef(F,D1,V)*F2*V^(D1-D2))%MOD;
        !          1278:                        D1 = deg(R,V); HC = coef(R,D1,V);
        !          1279: /*                     F = (R - HC*V^D1) + (srem_mod(HC,D,MOD))*V^D1; */
        !          1280:                        F = remc_mod(R,D,MOD);
        !          1281:                }
        !          1282:                TR += time()[0] - T0;
        !          1283:                T0 = time()[0]; F = remc_mod(R%MOD,D,MOD); TD += time()[0] - T0;
        !          1284:                if ( !F ) {
        !          1285:                        if ( dp_gr_print() )
        !          1286:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1287:                        return F2;
        !          1288:                }
        !          1289:                if ( !deg(F,V) ) {
        !          1290:                        if ( dp_gr_print() )
        !          1291:                                print(["TD",TD,"TM",TM,"TI",TI,"TR",TR]);
        !          1292:                        return 1;
        !          1293:                }
        !          1294:                C = LCOEF(F);
        !          1295:                T0 = time()[0]; INV = inva_mod(D,MOD,C); TI += time()[0] - T0;
        !          1296:                if ( !INV )
        !          1297:                        return 0;
        !          1298:                T0 = time()[0]; F = remc_mod((INV*F)%MOD,D,MOD); TM += time()[0] - T0;
        !          1299:                F1 = F2; F2 = F;
        !          1300:        }
        !          1301: }
        !          1302:
        !          1303: def inverse_by_gr_mod(C,D,MOD)
        !          1304: {
        !          1305:        SpOrd = 2;
        !          1306:        dp_gr_flags(["NoSugar",1]);
        !          1307:        G = dp_gr_mod_main(cons(x*C-1,D),cons(x,vars(D)),0,MOD,SpOrd);
        !          1308:        dp_gr_flags(["NoSugar",0]);
        !          1309:        if ( length(G) == 1 )
        !          1310:                return 1;
        !          1311:        else if ( length(G) == length(D)+1 ) {
        !          1312:                for ( T = G; T != []; T = cdr(T) )
        !          1313:                        if ( member(x,vars(car(G))) )
        !          1314:                                break;
        !          1315:                T = car(G);
        !          1316:                if ( type(coef(T,1,x)) != NUM )
        !          1317:                        return 0;
        !          1318:                else
        !          1319:                        return coef(T,0,x);
        !          1320:        } else
        !          1321:                return 0;
        !          1322: }
        !          1323:
        !          1324: def simp_by_dp(F,D)
        !          1325: {
        !          1326:        for ( T = D; T != []; T = cdr(T) )
        !          1327:                F = srem(F,car(T));
        !          1328:        return F;
        !          1329: }
        !          1330:
        !          1331: def simp_by_dp_mod(F,D,MOD)
        !          1332: {
        !          1333:        F %= MOD;
        !          1334:        for ( T = D; T != []; T = cdr(T) )
        !          1335:                F = srem(F,car(T)) % MOD;
        !          1336:        return F;
        !          1337: }
        !          1338:
        !          1339: def remc_mod(P,D,M)
        !          1340: {
        !          1341:        V = var(P);
        !          1342:        if ( !V || V == var(D) )
        !          1343:                return srem_mod(P,D,M);
        !          1344:        for ( I = deg(P,V), S = 0; I >= 0; I-- )
        !          1345:                if ( C = coef(P,I,V) )
        !          1346:                        S += srem_mod(C,D,M)*V^I;
        !          1347:        return S;
        !          1348: }
        !          1349:
        !          1350: def rem_mod(C,D,M)
        !          1351: {
        !          1352:        V = var(D);
        !          1353:        D2 = deg(D,V);
        !          1354:        while ( (D1 = deg(C,V)) >= D2 ) {
        !          1355:                C -= (D*V^(D1-D2)*coef(C,D1,V))%M;
        !          1356:                C %= M;
        !          1357:        }
        !          1358:        return C;
        !          1359: }
        !          1360:
        !          1361: def resfctr(F,L,V,N)
        !          1362: {
        !          1363:        N = ptozp(N);
        !          1364:        V0 = var(N);
        !          1365:        DN = diff(N,V0);
        !          1366:        LC = coef(N,deg(N,V0),V0);
        !          1367:        LCD = coef(DN,deg(DN,V0),V0);
        !          1368:   J = 2;
        !          1369:   while ( 1 ) {
        !          1370:     Len = deg(N,V0)+1;
        !          1371:          for ( I = 0; I < 5; J++ ) {
        !          1372:                  M = prime(J);
        !          1373:                  if ( !(LC%M) || !(LCD%M))
        !          1374:                          continue;
        !          1375:                  G = gcd(N,DN,M);
        !          1376:                  if ( !deg(G,V0) ) {
        !          1377:                          I++;
        !          1378:                          T = nfctr_mod(N,M);
        !          1379:                          if ( T < Len ) {
        !          1380:                                  Len = T; M0 = M;
        !          1381:                          }
        !          1382:                  }
        !          1383:          }
        !          1384:          S = spm(L,V,M0);
        !          1385:     if ( S ) break;
        !          1386:   }
        !          1387:        T = resfctr_mod(F,S,M0);
        !          1388:        return [T,S,M0];
        !          1389: }
        !          1390:
        !          1391: def resfctr_mod(F,L,M)
        !          1392: {
        !          1393:        for ( T = L, R = []; T != []; T = cdr(T) ) {
        !          1394:                U = car(T); MP = U[0]; W = U[1];
        !          1395:                for ( A = W, B = F; A != []; A = cdr(cdr(A)) )
        !          1396:                        B = sremm(subst(B,A[0],A[1]),MP,M);
        !          1397:                C = res(var(MP),B,MP) % M;
        !          1398:                R = cons(flatten(cdr(modfctr(C,M))),R);
        !          1399:        }
        !          1400:        return reverse(R);
        !          1401: }
        !          1402:
        !          1403: def flatten(L)
        !          1404: {
        !          1405:        for ( T = L, R = []; T != []; T = cdr(T) )
        !          1406:                R = cons(car(car(T)),R);
        !          1407:        return R;
        !          1408: }
        !          1409:
        !          1410: def spm(L,V,M)
        !          1411: {
        !          1412:        if ( length(V) == 1 ) {
        !          1413:                U = modfctr(car(L),M);
        !          1414:                for ( T = cdr(U), R = []; T != []; T = cdr(T) ) {
        !          1415:                        S = car(T);
        !          1416:       if ( S[1] > 1 ) return 0;
        !          1417:                        R = cons([subst(S[0],var(S[0]),a_),[var(S[0]),a_]],R);
        !          1418:                }
        !          1419:                return R;
        !          1420:        }
        !          1421:        L1 = spm(cdr(L),cdr(V),M);
        !          1422:   if ( !L1 ) return 0;
        !          1423:        F0 = car(L); V0 = car(V); VR = cdr(V);
        !          1424:        for ( T = L1, R = []; T != []; T = cdr(T) ) {
        !          1425:                S = car(T);
        !          1426:                F1 = subst(F0,S[1]);
        !          1427:                U = fctr_mod(F1,V0,S[0],M);
        !          1428:                VS = var(S[0]);
        !          1429:                for ( W = U; W != []; W = cdr(W) ) {
        !          1430:       if ( car(W)[1] > 1 ) return 0;
        !          1431:                        A = car(car(W));
        !          1432:                        if ( deg(A,V0) == 1 ) {
        !          1433:                                A = monic_mod(A,V0,S[0],M);
        !          1434:                                R = cons([S[0],append([V0,-coef(A,0,V0)],S[1])],R);
        !          1435:                        } else {
        !          1436:                                B = pe_mod(A,S[0],M);
        !          1437:                                MP = B[0]; VMP = var(MP); NV = B[1];
        !          1438:                                for ( C = S[1], D = []; C != []; C = cdr(cdr(C)) ) {
        !          1439:                                        G = subst(sremm(subst(C[1],VS,NV[1]),MP,M),VMP,VS);
        !          1440:                                        D = append([C[0],G],D);
        !          1441:                                }
        !          1442:                                R = cons([subst(MP,VMP,VS),
        !          1443:                                        append([B[2][0],subst(B[2][1],VMP,VS)],D)],R);
        !          1444:                        }
        !          1445:                }
        !          1446:        }
        !          1447:        return R;
        !          1448: }
        !          1449:
        !          1450: def pe_mod(F,G,M)
        !          1451: {
        !          1452:        V = var(G); W = car(setminus(vars(F),[V]));
        !          1453:        NG = deg(G,V); NF = deg(F,W); N = NG*NF;
        !          1454:        X = prim;
        !          1455:        while ( 1 ) {
        !          1456:                D = mrandompoly(N,X,M);
        !          1457:                if ( irred_check(D,M) )
        !          1458:                        break;
        !          1459:        }
        !          1460:        L = fctr_mod(G,V,D,M);
        !          1461:        for ( T = L; T != []; T = cdr(T) ) {
        !          1462:                U = car(car(T));
        !          1463:                if ( deg(U,V) == 1 )
        !          1464:                        break;
        !          1465:        }
        !          1466:        U = monic_mod(U,V,D,M); RV = -coef(U,0,V);
        !          1467:        L = fctr_mod(sremm(subst(F,V,RV),D,M),W,D,M);
        !          1468:        for ( T = L; T != []; T = cdr(T) ) {
        !          1469:                U = car(car(T));
        !          1470:                if ( deg(U,W) == 1 )
        !          1471:                        break;
        !          1472:        }
        !          1473:        U = monic_mod(U,W,D,M); RW = -coef(U,0,W);
        !          1474:        return [D,[V,RV],[W,RW]];
        !          1475: }
        !          1476:
        !          1477: def fctr_mod(F,V,D,M)
        !          1478: {
        !          1479:        if ( V != x ) {
        !          1480:                F = subst(F,V,x); V0 = V; V = x;
        !          1481:        } else
        !          1482:                V0 = x;
        !          1483:        F = monic_mod(F,V,D,M);
        !          1484:        L = sqfr_mod(F,V,D,M);
        !          1485:        for ( R = [], T = L; T != []; T = cdr(T) ) {
        !          1486:                S = car(T); A = S[0]; E = S[1];
        !          1487:                B = ddd_mod(A,V,D,M);
        !          1488:                R = append(append_mult(B,E),R);
        !          1489:        }
        !          1490:        if ( V0 != x ) {
        !          1491:                for ( R = reverse(R), T = []; R != []; R = cdr(R) )
        !          1492:                        T = cons([subst(car(R)[0],x,V0),car(R)[1]],T);
        !          1493:                R = T;
        !          1494:        }
        !          1495:        return R;
        !          1496: }
        !          1497:
        !          1498: def append_mult(L,E)
        !          1499: {
        !          1500:        for ( T = L, R = []; T != []; T = cdr(T) )
        !          1501:                R = cons([car(T),E],R);
        !          1502:        return R;
        !          1503: }
        !          1504:
        !          1505: def sqfr_mod(F,V,D,M)
        !          1506: {
        !          1507:        setmod(M);
        !          1508:        F = sremm(F,D,M);
        !          1509:        F1 = sremm(diff(F,V),D,M);
        !          1510:        F1 = sremm(F1*inva_mod(D,M,LCOEF(F1)),D,M);
        !          1511:        if ( F1 ) {
        !          1512:                F2 = ag_mod_single4(F,F1,[D],M);
        !          1513:                FLAT = sremm(sdivm(F,F2,M,V),D,M);
        !          1514:                I = 0; L = [];
        !          1515:                while ( deg(FLAT,V) ) {
        !          1516:                        while ( 1 ) {
        !          1517:                                QR = sqrm(F,FLAT,M,V);
        !          1518:                                if ( !sremm(QR[1],D,M) ) {
        !          1519:                                        F = sremm(QR[0],D,M); I++;
        !          1520:                                } else
        !          1521:                                        break;
        !          1522:                        }
        !          1523:                        if ( !deg(F,V) )
        !          1524:                                FLAT1 = 1;
        !          1525:                        else
        !          1526:                                FLAT1 = ag_mod_single4(F,FLAT,[D],M);
        !          1527:                        G = sremm(sdivm(FLAT,FLAT1,M,V),D,M);
        !          1528:                        FLAT = FLAT1;
        !          1529:                        L = cons([G,I],L);
        !          1530:                }
        !          1531:        }
        !          1532:        if ( deg(F,V) ) {
        !          1533:                T = sqfr_mod(pthroot_p_mod(F,V,D,M),V,D,M);
        !          1534:                for ( R = []; T != []; T = cdr(T) ) {
        !          1535:                        H = car(T); R = cons([H[0],M*H[1]],R);
        !          1536:                }
        !          1537:        } else
        !          1538:                R = [];
        !          1539:        return append(L,R);
        !          1540: }
        !          1541:
        !          1542: def pthroot_p_mod(F,V,D,M)
        !          1543: {
        !          1544:        for ( T = F, R = 0; T; ) {
        !          1545:                D1 = deg(T,V); C = coef(T,D1,V); T -= C*V^D1;
        !          1546:                R += pthroot_n_mod(C,D,M)*V^idiv(D1,M);
        !          1547:        }
        !          1548:        return R;
        !          1549: }
        !          1550:
        !          1551: def pthroot_n_mod(C,D,M)
        !          1552: {
        !          1553:        pwr_n_mod(C,D,M,deg(D,var(D))-1);
        !          1554: }
        !          1555:
        !          1556: def pwr_n_mod(C,D,M,N)
        !          1557: {
        !          1558:        if ( N == 0 )
        !          1559:                return 1;
        !          1560:        else if ( N == 1 )
        !          1561:                return C;
        !          1562:        else {
        !          1563:                QR = iqr(N,2);
        !          1564:                T = pwr_n_mod(C,D,M,QR[0]);
        !          1565:                S = sremm(T^2,D,M);
        !          1566:                if ( QR[1] )
        !          1567:                        return sremm(S*C,D,M);
        !          1568:                else
        !          1569:                        return S;
        !          1570:        }
        !          1571: }
        !          1572:
        !          1573: def pwr_p_mod(P,A,V,D,M,N)
        !          1574: {
        !          1575:        if ( N == 0 )
        !          1576:                return 1;
        !          1577:        else if ( N == 1 )
        !          1578:                return P;
        !          1579:        else {
        !          1580:                QR = iqr(N,2);
        !          1581:                T = pwr_p_mod(P,A,V,D,M,QR[0]);
        !          1582:                S = sremm(sremm(sremm(T^2,D,M),A,M,V),D,M);
        !          1583:                if ( QR[1] )
        !          1584:                        return sremm(sremm(sremm(S*P,D,M),A,M,V),D,M);
        !          1585:                else
        !          1586:                        return S;
        !          1587:        }
        !          1588: }
        !          1589:
        !          1590: def qmat_mod(F,V,D,M)
        !          1591: {
        !          1592:        R = tab_mod(F,V,D,M);
        !          1593:        Q = newmat(N,N);
        !          1594:        for ( J = 0; J < N; J++ )
        !          1595:                for ( I = 0, T = R[J]; I < N; I++ ) {
        !          1596:                        Q[I][J] = coef(T,I);
        !          1597:                }
        !          1598:        for ( I = 0; I < N; I++ )
        !          1599:                Q[I][I] = (Q[I][I]+(M-1))%M;
        !          1600:        return Q;
        !          1601: }
        !          1602:
        !          1603: def tab_mod(F,V,D,M)
        !          1604: {
        !          1605:        MD = M^deg(D,var(D));
        !          1606:        N = deg(F,V);
        !          1607:        F = sremm(F*inva_mod(D,M,coef(F,N,V)),D,M);
        !          1608:        R = newvect(N); R[0] = 1;
        !          1609:        R[1] = pwr_mod(V,F,V,D,M,MD);
        !          1610:        for ( I = 2; I < N; I++ )
        !          1611:                R[I] = sremm(sremm(R[1]*R[I-1],F,M),D,M);
        !          1612:        return R;
        !          1613: }
        !          1614:
        !          1615: def ddd_mod(F,V,D,M)
        !          1616: {
        !          1617:        if ( deg(F,V) == 1 )
        !          1618:                return [F];
        !          1619:        TAB = tab_mod(F,V,D,M);
        !          1620:        for ( I = 1, W = V, L = []; 2*I <= deg(F,V); I++ ) {
        !          1621:                for ( T = 0, K = 0; K <= deg(W,V); K++ )
        !          1622:                        if ( C = coef(W,K,V) )
        !          1623:                                T = sremm(T+TAB[K]*C,D,M);
        !          1624:                W = T;
        !          1625:                GCD = ag_mod_single4(F,monic_mod(W-V,V,D,M),[D],M);
        !          1626:                if ( deg(GCD,V) ) {
        !          1627:                        L = append(berlekamp(GCD,V,I,TAB,D,M),L);
        !          1628:                        F = sremm(sdivm(F,GCD,M,V),D,M);
        !          1629:                        W = sremm(sremm(W,F,M,V),D,M);
        !          1630:                }
        !          1631:        }
        !          1632:        if ( deg(F,V) )
        !          1633:                return cons(F,L);
        !          1634:        else
        !          1635:                return L;
        !          1636: }
        !          1637:
        !          1638: def monic_mod(F,V,D,M) {
        !          1639:        if ( !F || !deg(F,V) )
        !          1640:                return F;
        !          1641:        return sremm(F*inva_mod(D,M,coef(F,deg(F,V),V)),D,M);
        !          1642: }
        !          1643:
        !          1644: def berlekamp(F,V,E,TAB,D,M)
        !          1645: {
        !          1646:        N = deg(F,V);
        !          1647:        Q = newmat(N,N);
        !          1648:        for ( J = 0; J < N; J++ ) {
        !          1649:                T = sremm(sremm(TAB[J],F,M,V),D,M);
        !          1650:                for ( I = 0; I < N; I++ ) {
        !          1651:                        Q[I][J] = coef(T,I);
        !          1652:                }
        !          1653:        }
        !          1654:        for ( I = 0; I < N; I++ )
        !          1655:                Q[I][I] = (Q[I][I]+(M-1))%M;
        !          1656:        L = nullspace(Q,D,M); MT = L[0]; IND = L[1];
        !          1657:        NF0 = N/E;
        !          1658:        PS = null_to_poly(MT,IND,V,M);
        !          1659:        R = newvect(NF0); R[0] = monic_mod(F,V,D,M);
        !          1660:        for ( I = 1, NF = 1; NF < NF0 && I < NF0; I++ ) {
        !          1661:                PSI = PS[I];
        !          1662:                MP = minipoly_mod(PSI,F,V,D,M);
        !          1663:                ROOT = find_root(MP,V,D,M); NR = length(ROOT);
        !          1664:                for ( J = 0; J < NF; J++ ) {
        !          1665:                        if ( deg(R[J],V) == E )
        !          1666:                                continue;
        !          1667:                        for ( K = 0; K < NR; K++ ) {
        !          1668:                                GCD = ag_mod_single4(R[J],PSI-ROOT[K],[D],M);
        !          1669:                                if ( deg(GCD,V) > 0 && deg(GCD,V) < deg(R[J],V) ) {
        !          1670:                                        Q = sremm(sdivm(R[J],GCD,M,V),D,M);
        !          1671:                                        R[J] = Q; R[NF++] = GCD;
        !          1672:                                }
        !          1673:                        }
        !          1674:                }
        !          1675:        }
        !          1676:        return vtol(R);
        !          1677: }
        !          1678:
        !          1679: def null_to_poly(MT,IND,V,M)
        !          1680: {
        !          1681:        N = size(MT)[0];
        !          1682:        for ( I = 0, J = 0; I < N; I++ )
        !          1683:                if ( IND[I] )
        !          1684:                        J++;
        !          1685:        R = newvect(J);
        !          1686:        for ( I = 0, L = 0; I < N; I++ ) {
        !          1687:                if ( !IND[I] )
        !          1688:                        continue;
        !          1689:                for ( J = K = 0, T = 0; J < N; J++ )
        !          1690:                        if ( !IND[J] )
        !          1691:                                T += MT[K++][I]*V^J;
        !          1692:                        else if ( J == I )
        !          1693:                                T += (M-1)*V^I;
        !          1694:                R[L++] = T;
        !          1695:        }
        !          1696:        return R;
        !          1697: }
        !          1698:
        !          1699: def minipoly_mod(P,F,V,D,M)
        !          1700: {
        !          1701:        L = [[1,1]]; P0 = P1 = 1;
        !          1702:        while ( 1 ) {
        !          1703:                P0 *= V;
        !          1704:                P1 = sremm(sremm(P*P1,F,M,V),D,M);
        !          1705:                L1 = lnf_mod(P0,P1,L,V,D,M); NP0 = L1[0]; NP1 = L1[1];
        !          1706:                if ( !NP1 )
        !          1707:                        return NP0;
        !          1708:                else
        !          1709:                        L = lnf_insert([NP0,NP1],L,V);
        !          1710:        }
        !          1711: }
        !          1712:
        !          1713: def lnf_mod(P0,P1,L,V,D,M)
        !          1714: {
        !          1715:        NP0 = P0; NP1 = P1;
        !          1716:        for ( T = L; T != []; T = cdr(T) ) {
        !          1717:                Q = car(T);
        !          1718:                D1 = deg(NP1,V);
        !          1719:                if ( D1 == deg(Q[1],V) ) {
        !          1720:                        C = coef(Q[1],D1,V);
        !          1721:                        INV = inva_mod(D,M,M-C); H = sremm(coef(NP1,D1,V)*INV,D,M);
        !          1722:                        NP0 = sremm(NP0+Q[0]*H,D,M);
        !          1723:                        NP1 = sremm(NP1+Q[1]*H,D,M);
        !          1724:                }
        !          1725:        }
        !          1726:        return [NP0,NP1];
        !          1727: }
        !          1728:
        !          1729: def lnf_insert(P,L,V)
        !          1730: {
        !          1731:        if ( L == [] )
        !          1732:                return [P];
        !          1733:        else {
        !          1734:                P0 = car(L);
        !          1735:                if ( deg(P0[1],V) > deg(P[1],V) )
        !          1736:                        return cons(P0,lnf_insert(P,cdr(L),V));
        !          1737:                else
        !          1738:                        return cons(P,L);
        !          1739:        }
        !          1740: }
        !          1741:
        !          1742: def find_root(P,V,D,M)
        !          1743: {
        !          1744:        L = c_z(P,V,1,D,M);
        !          1745:        for ( T = L, U = []; T != []; T = cdr(T) ) {
        !          1746:                S = monic_mod(car(T),V,D,M); U = cons(-coef(S,0,V),U);
        !          1747:        }
        !          1748:        return U;
        !          1749: }
        !          1750:
        !          1751: def c_z(F,V,E,D,M)
        !          1752: {
        !          1753:        N = deg(F,V);
        !          1754:        if ( N == E )
        !          1755:                return [F];
        !          1756:        Q = M^deg(D,var(D));
        !          1757:        K = idiv(N,E);
        !          1758:        L = [F];
        !          1759:        while ( 1 ) {
        !          1760:                W = mrandomgfpoly(2*E,V,D,M);
        !          1761:                if ( M == 2 ) {
        !          1762:                        W = monic_mod(tr_mod(W,F,V,D,M,N-1),V,D,M);
        !          1763:                } else {
        !          1764: /*                     W = monic_mod(pwr_p_mod(W,F,V,D,M,idiv(Q^E-1,2))-1,V,D,M); */
        !          1765:                /*      T = pwr_p_mod(W,F,V,D,M,idiv(Q^E-1,2)); */
        !          1766:                        T = pwr_mod(W,F,V,D,M,idiv(Q^E-1,2));
        !          1767:                        W = monic_mod(T-1,V,D,M);
        !          1768:                }
        !          1769:                if ( !W )
        !          1770:                        continue;
        !          1771:                G = ag_mod_single4(F,W,[D],M);
        !          1772:                if ( deg(G,V) && deg(G,V) < N ) {
        !          1773:                        L1 = c_z(G,V,E,D,M);
        !          1774:                        L2 = c_z(sremm(sdivm(F,G,M,V),D,M),V,E,D,M);
        !          1775:                        return append(L1,L2);
        !          1776:                }
        !          1777:        }
        !          1778: }
        !          1779:
        !          1780: def tr_mod(P,F,V,D,M,N)
        !          1781: {
        !          1782:        for ( I = 1, S = P, W = P; I <= N; I++ ) {
        !          1783:                W = sremm(sremm(W^2,F,M,V),D,M);
        !          1784:                S = sremm(S+W,D,M);
        !          1785:        }
        !          1786:        return S;
        !          1787: }
        !          1788:
        !          1789: def mrandomgfpoly(N,V,D,M)
        !          1790: {
        !          1791:        W = var(D); ND = deg(D,W);
        !          1792:        for ( I = N-2, S = V^(N-1); I >= 0; I-- )
        !          1793:                S += randompoly(ND,W,M)*V^I;
        !          1794:        return S;
        !          1795: }
        !          1796:
        !          1797: def randompoly(N,V,M)
        !          1798: {
        !          1799:        for ( I = 0, S = 0; I < N; I++ )
        !          1800:                S += (random()%M)*V^I;
        !          1801:        return S;
        !          1802: }
        !          1803:
        !          1804: def mrandompoly(N,V,M)
        !          1805: {
        !          1806:        for ( I = N-1, S = V^N; I >=0; I-- )
        !          1807:                S += (random()%M)*V^I;
        !          1808:        return S;
        !          1809: }
        !          1810:
        !          1811: def srem_by_nf(P,B,V,O) {
        !          1812:        dp_ord(O); DP = dp_ptod(P,V);
        !          1813:        N = length(B); DB = newvect(N);
        !          1814:        for ( I = N-1, IL = []; I >= 0; I-- ) {
        !          1815:                DB[I] = dp_ptod(B[I],V);
        !          1816:                IL = cons(I,IL);
        !          1817:        }
        !          1818:        L = dp_true_nf(IL,DP,DB,1);
        !          1819:        return [dp_dtop(L[0],V),L[1]];
        !          1820: }
        !          1821: end$

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