123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- MODULE VECPOLY;
- % Authors: A. C. Norman and P. M. A. Moore, 1979;
- FLUID '(CURRENT!-MODULUS SAFE!-FLAG);
- %**********************************************************************;
- % Routines for working with modular univariate polynomials
- % stored as vectors. Used to avoid unwarranted storage management
- % in the mod-p factorization process;
- SAFE!-FLAG:=CARCHECK 0;
- SYMBOLIC PROCEDURE COPY!-VECTOR(A,DA,B);
- % Copy A into B;
- << FOR I:=0:DA DO
- PUTV(B,I,GETV(A,I));
- DA >>;
- SYMBOLIC PROCEDURE TIMES!-IN!-VECTOR(A,DA,B,DB,C);
- % Put the product of A and B into C and return its degree.
- % C must not overlap with either A or B;
- BEGIN
- SCALAR DC,IC,W;
- IF DA#<0 OR DB#<0 THEN RETURN MINUS!-ONE;
- DC:=DA#+DB;
- FOR I:=0:DC DO PUTV(C,I,0);
- FOR IA:=0:DA DO <<
- W:=GETV(A,IA);
- FOR IB:=0:DB DO <<
- IC:=IA#+IB;
- PUTV(C,IC,MODULAR!-PLUS(GETV(C,IC),
- MODULAR!-TIMES(W,GETV(B,IB)))) >> >>;
- RETURN DC
- END;
- SYMBOLIC PROCEDURE QUOTFAIL!-IN!-VECTOR(A,DA,B,DB);
- % Overwrite A with (A/B) and return degree of result.
- % The quotient must be exact;
- IF DA#<0 THEN DA
- ELSE IF DB#<0 THEN ERRORF "Attempt to divide by zero"
- ELSE IF DA#<DB THEN ERRORF "Bad degrees in QUOTFAIL-IN-VECTOR"
- ELSE BEGIN
- SCALAR DC;
- DC:=DA#-DB; % Degree of result;
- FOR I:=DC STEP -1 UNTIL 0 DO BEGIN
- SCALAR Q;
- Q:=MODULAR!-QUOTIENT(GETV(A,DB#+I),GETV(B,DB));
- FOR J:=0:DB#-1 DO
- PUTV(A,I#+J,MODULAR!-DIFFERENCE(GETV(A,I#+J),
- MODULAR!-TIMES(Q,GETV(B,J))));
- PUTV(A,DB#+I,Q)
- END;
- FOR I:=0:DB#-1 DO IF GETV(A,I) NEQ 0 THEN
- ERRORF "Quotient not exact in QUOTFAIL!-IN!-VECTOR";
- FOR I:=0:DC DO
- PUTV(A,I,GETV(A,DB#+I));
- RETURN DC
- END;
- SYMBOLIC PROCEDURE REMAINDER!-IN!-VECTOR(A,DA,B,DB);
- % Overwrite the vector A with the remainder when A is
- % divided by B, and return the degree of the result;
- BEGIN
- SCALAR DELTA,DB!-1,RECIP!-LC!-B,W;
- IF DB=0 THEN RETURN MINUS!-ONE
- ELSE IF DB=MINUS!-ONE THEN ERRORF "ATTEMPT TO DIVIDE BY ZERO";
- RECIP!-LC!-B:=MODULAR!-MINUS MODULAR!-RECIPROCAL GETV(B,DB);
- DB!-1:=DB#-1; % Leading coeff of B treated specially, hence this;
- WHILE NOT((DELTA:=DA#-DB) #< 0) DO <<
- W:=MODULAR!-TIMES(RECIP!-LC!-B,GETV(A,DA));
- FOR I:=0:DB!-1 DO
- PUTV(A,I#+DELTA,MODULAR!-PLUS(GETV(A,I#+DELTA),
- MODULAR!-TIMES(GETV(B,I),W)));
- DA:=DA#-1;
- WHILE NOT(DA#<0) AND GETV(A,DA)=0 DO DA:=DA#-1 >>;
- RETURN DA
- END;
- SYMBOLIC PROCEDURE EVALUATE!-IN!-VECTOR(A,DA,N);
- % Evaluate A at N;
- BEGIN
- SCALAR R;
- R:=GETV(A,DA);
- FOR I:=DA#-1 STEP -1 UNTIL 0 DO
- R:=MODULAR!-PLUS(GETV(A,I),
- MODULAR!-TIMES(R,N));
- RETURN R
- END;
- SYMBOLIC PROCEDURE GCD!-IN!-VECTOR(A,DA,B,DB);
- % Overwrite A with the gcd of A and B. On input A and B are
- % vectors of coefficients, representing polynomials
- % of degrees DA and DB. Return DG, the degree of the gcd;
- BEGIN
- SCALAR W;
- IF DA=0 OR DB=0 THEN << PUTV(A,0,1); RETURN 0 >>
- ELSE IF DA#<0 OR DB#<0 THEN ERRORF "GCD WITH ZERO NOT ALLOWED";
- TOP:
- % Reduce the degree of A;
- DA:=REMAINDER!-IN!-VECTOR(A,DA,B,DB);
- IF DA=0 THEN << PUTV(A,0,1); RETURN 0 >>
- ELSE IF DA=MINUS!-ONE THEN <<
- W:=MODULAR!-RECIPROCAL GETV(B,DB);
- FOR I:=0:DB DO PUTV(A,I,MODULAR!-TIMES(GETV(B,I),W));
- RETURN DB >>;
- % Now reduce degree of B;
- DB:=REMAINDER!-IN!-VECTOR(B,DB,A,DA);
- IF DB=0 THEN << PUTV(A,0,1); RETURN 0 >>
- ELSE IF DB=MINUS!-ONE THEN <<
- W:=MODULAR!-RECIPROCAL GETV(A,DA);
- IF NOT (W=1) THEN
- FOR I:=0:DA DO PUTV(A,I,MODULAR!-TIMES(GETV(A,I),W));
- RETURN DA >>;
- GO TO TOP
- END;
- CARCHECK SAFE!-FLAG;
- ENDMODULE;
- END;
|