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