123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- MODULE GCDCHK; % Check for a unit gcd using modular arithmetic.
- % Author: Arthur C. Norman and Mary Ann Moore.
- % Modifications by: Anthony C. Hearn.
- FLUID '(!*BACKTRACE LIST!-OF!-LARGE!-PRIMES MODULAR!-VALUES);
- % LIST!-OF!-LARGE!-PRIMES is a list of the largest pair of adjacent
- % primes that can fit in the inum range of the implementation.
- % This should be set here in an implementation dependent manner.
- % For the time begin, a maximum inum value of 2^23 is assumed.
- LIST!-OF!-LARGE!-PRIMES := '(8388449 8388451);
- SYMBOLIC PROCEDURE MONIC!-MOD!-P A;
- IF NULL A THEN NIL
- ELSE IF DOMAINP A THEN 1
- ELSE IF LC A = 1 THEN A
- ELSE MULTIPLY!-BY!-CONSTANT!-MOD!-P(A,MODULAR!-RECIPROCAL LC A);
-
- SMACRO PROCEDURE BEFORE!-IN!-ORDER(A,B);
- %Predicate taking the value true if the polynomial
- %a has a leading term which comes strictly before that
- %of b in canonical order;
- NULL DOMAINP A AND (DOMAINP B OR LDEG A>LDEG B);
-
- SYMBOLIC PROCEDURE UNI!-PLUS!-MOD!-P(A,B);
- % Form the sum of the two univariate polynomials a and b
- % working over the ground domain defined by the routines
- % modular!-plus, modular!-times etc. The inputs to this
- % routine are assumed to have coefficients already
- % in the required domain;
- IF NULL A THEN B
- ELSE IF NULL B THEN A
- ELSE IF BEFORE!-IN!-ORDER(A,B)
- THEN (LT A) .+ UNI!-PLUS!-MOD!-P(RED A,B)
- ELSE IF BEFORE!-IN!-ORDER(B,A)
- THEN (LT B) .+ UNI!-PLUS!-MOD!-P(A,RED B)
- ELSE IF DOMAINP A
- THEN <<A:=MODULAR!-PLUS(A,B); IF A=0 THEN NIL ELSE A>>
- ELSE BEGIN SCALAR W;
- W:=UNI!-PLUS!-MOD!-P(RED A,RED B);
- B:=MODULAR!-PLUS(LC A,LC B);
- IF B=0 THEN RETURN W;
- RETURN (LPOW A .* B) .+ W
- END;
-
- %symbolic procedure uni!-times!-mod!-p(a,b);
- % if (null a) or (null b) then nil
- % else if domainp a then multiply!-by!-constant!-mod!-p(b,a)
- % else if domainp b then multiply!-by!-constant!-mod!-p(a,b)
- % else uni!-plus!-mod!-p(
- % uni!-plus!-mod!-p(uni!-times!-mod!-p(red a,red b),
- % uni!-times!-term!-mod!-p(lt a,b)),
- % uni!-times!-term!-mod!-p(lt b,red a));
-
- SYMBOLIC PROCEDURE UNI!-TIMES!-TERM!-MOD!-P(TERM,B);
- %Multiply the given polynomial by the given term;
- IF NULL B THEN NIL
- ELSE IF DOMAINP B THEN <<
- B:=MODULAR!-TIMES(TC TERM,B);
- IF B=0 THEN NIL
- ELSE (TPOW TERM .* B) .+ NIL >>
- ELSE BEGIN SCALAR W;
- W:=MODULAR!-TIMES(TC TERM,LC B);
- IF W=0 THEN RETURN UNI!-TIMES!-TERM!-MOD!-P(TERM,RED B);
- W:= (TVAR TERM TO (TDEG TERM+LDEG B)) .* W;
- RETURN W .+ UNI!-TIMES!-TERM!-MOD!-P(TERM,RED B)
- END;
-
- SYMBOLIC PROCEDURE UNI!-REMAINDER!-MOD!-P(A,B);
- % Remainder when a is divided by b;
- IF NULL B THEN REDERR "B=0 IN REMAINDER-MOD-P"
- ELSE IF DOMAINP B THEN NIL
- ELSE XUNI!-REMAINDER!-MOD!-P(A,B);
-
- SYMBOLIC PROCEDURE XUNI!-REMAINDER!-MOD!-P(A,B);
- % Remainder when the univariate modular polynomial a is
- % divided by b, given that b is non degenerate;
- IF DOMAINP A OR LDEG A < LDEG B THEN A
- ELSE BEGIN
- SCALAR Q,W;
- Q:=MODULAR!-QUOTIENT(MODULAR!-MINUS LC A,LC B);
- % compute -lc of quotient;
- W:= LDEG A - LDEG B; %ldeg of quotient;
- IF W=0 THEN A:=UNI!-PLUS!-MOD!-P(RED A,
- MULTIPLY!-BY!-CONSTANT!-MOD!-P(RED B,Q))
- ELSE
- A:=UNI!-PLUS!-MOD!-P(RED A,UNI!-TIMES!-TERM!-MOD!-P(
- (MVAR B TO W) .* Q,RED B));
- % the above lines of code use red a and red b because
- % by construction the leading terms of the required
- % answers will cancel out;
- RETURN XUNI!-REMAINDER!-MOD!-P(A,B)
- END;
-
- SYMBOLIC PROCEDURE MULTIPLY!-BY!-CONSTANT!-MOD!-P(A,N);
- % Multiply the polynomial a by the constant n
- % assumes that a is univariate, and that n is coprime with
- % the current modulus so that modular!-times(xxx,n) neq 0
- % for all xxx;
- IF NULL A THEN NIL
- ELSE IF N=1 THEN A
- ELSE IF DOMAINP A THEN MODULAR!-TIMES(A,N)
- ELSE (LPOW A .* MODULAR!-TIMES(LC A,N)) .+
- MULTIPLY!-BY!-CONSTANT!-MOD!-P(RED A,N);
-
- SYMBOLIC PROCEDURE UNI!-GCD!-MOD!-P(A,B);
- %Return the monic gcd of the two modular univariate
- %polynomials a and b;
- IF NULL A THEN MONIC!-MOD!-P B
- ELSE IF NULL B THEN MONIC!-MOD!-P A
- ELSE IF DOMAINP A THEN 1
- ELSE IF DOMAINP B THEN 1
- ELSE IF LDEG A > LDEG B THEN
- ORDERED!-UNI!-GCD!-MOD!-P(A,B)
- ELSE ORDERED!-UNI!-GCD!-MOD!-P(B,A);
-
- SYMBOLIC PROCEDURE ORDERED!-UNI!-GCD!-MOD!-P(A,B);
- % As above, but degr a > degr b;
- IF NULL B THEN MONIC!-MOD!-P A
- ELSE ORDERED!-UNI!-GCD!-MOD!-P(B,UNI!-REMAINDER!-MOD!-P(A,B));
-
- SYMBOLIC MACRO PROCEDURE MYERR U;
- LIST('ERRORSET,
- 'LIST .
- MKQUOTE CAADR U .
- FOR EACH J IN CDADR U COLLECT LIST('MKQUOTE,J),
- T,'!*BACKTRACE);
- SYMBOLIC PROCEDURE MODULAR!-MULTICHECK(U,V,VAR);
- IF ERRORP (U := MYERR MODULAR!-MULTICHECK1(U,V,VAR)) THEN NIL
- ELSE CAR U;
- SYMBOLIC PROCEDURE MODULAR!-MULTICHECK1(U,V,VAR);
- % TRUE if a modular check tells me that U and V are coprime;
- BEGIN
- SCALAR OLDP,P,MODULAR!-VALUES,UMODP,VMODP;
- P:=LIST!-OF!-LARGE!-PRIMES;
- OLDP:=SETMOD NIL;
- TRY!-NEXT!-PRIME:
- MODULAR!-VALUES:=NIL;
- IF NULL P THEN GOTO UNCERTAIN;
- SETMOD CAR P;
- P:=CDR P;
- IF NULL MODULAR!-IMAGE(LC U,VAR) OR NULL MODULAR!-IMAGE(LC V,VAR)
- THEN GO TO TRY!-NEXT!-PRIME;
- UMODP:=MODULAR!-IMAGE(U,VAR);
- VMODP:=MODULAR!-IMAGE(V,VAR);
- P := DOMAINP UNI!-GCD!-MOD!-P(UMODP,VMODP);
- UNCERTAIN:
- SETMOD OLDP;
- RETURN P
- END;
- SYMBOLIC PROCEDURE MODULAR!-IMAGE(P,VAR);
- IF DOMAINP P
- THEN IF NULL P THEN NIL
- ELSE IF NOT ATOM P THEN ERROR1()
- ELSE <<P := MODULAR!-NUMBER P; IF P=0 THEN NIL ELSE P>>
- ELSE BEGIN
- SCALAR V,X,W;
- V:=MVAR P;
- IF V=VAR THEN <<
- X:=MODULAR!-IMAGE(LC P,VAR);
- IF NULL X THEN RETURN MODULAR!-IMAGE(RED P,VAR)
- ELSE RETURN (LPOW P .* X) .+ MODULAR!-IMAGE(RED P,VAR) >>;
- X:=ATSOC(V,MODULAR!-VALUES);
- IF NULL X THEN <<
- X:=MODULAR!-NUMBER RANDOM CAR LIST!-OF!-LARGE!-PRIMES;
- MODULAR!-VALUES:=(V . X) . MODULAR!-VALUES >>
- ELSE X:=CDR X;
- X:=MODULAR!-EXPT(X,LDEG P);
- W:=MODULAR!-IMAGE(RED P,VAR);
- V:=MODULAR!-IMAGE(LC P,VAR);
- IF NULL V THEN X:=NIL
- ELSE X:=MODULAR!-TIMES(V,X);
- IF W THEN X:=MODULAR!-PLUS(X,W);
- RETURN IF X=0 THEN NIL ELSE X
- END;
- ENDMODULE;
- END;
|