123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- module sqfrnorm;
- % Author: James H. Davenport.
- fluid '(!*pvar listofallsqrts);
- global '(modevalcount);
- modevalcount:=1;
- exports sqfr!-norm2,res!-sqrt;
- %symbolic procedure resultant(u,v);
- %begin
- % scalar maxdeg,zeroes,ldegu,ldegv,m;
- % % we can have gone makemainvar on u and v;
- % ldegu:=ldeg u;
- % ldegv:=ldeg v;
- % maxdeg:=isub1 max2(ldegu,ldegv);
- % zeroes:=nlist(nil,maxdeg);
- % u:=remake(u,mvar u,ldegu);
- % v:=remake(v,mvar v,ldegv);
- % m:=nil;
- % ldegu:=isub1 ldegu;
- % ldegv:=isub1 ldegv;
- % for i:=0 step 1 until ldegv do
- % m:=append(ncdr(zeroes,maxdeg-ldegv+i),
- % append(u,ncdr(zeroes,maxdeg-i))).m;
- % for i:=0 step 1 until ldegu do
- % m:=append(ncdr(zeroes,maxdeg-ldegu+i),
- % append(v,ncdr(zeroes,maxdeg-i))).m;
- % return detqf m
- % end;
- % symbolic procedure ncdr(l,n);
- % % we can use small integer arithmetic here.
- % if n=0 then l else ncdr(cdr l,isub1 n);
- %symbolic procedure remake(u,v,w);
- %% remakes u into a list of sf's representing its coefficients;
- %if w iequal 0 then list u
- % else if (pairp u) and (mvar u eq v) and (ldeg u iequal w)
- % then (lc u).remake(red u,v,isub1 w)
- % else (nil ).remake( u,v,isub1 w);
- %fluid '(n); %needed for the mapcar;
- %symbolic procedure detqf u;
- % %u is a square matrix standard form.
- %% %value is the determinant of u.
- %% %algorithm is expansion by minors of first row/column;
- % begin integer n;
- % scalar x,y,z;
- % if length u neq length car u then rederr "Non square matrix"
- % else if null cdr u then return caar u;
- % if length u < 3
- % then go to noopt;
- % % try to remove a row with only one non-zero in it;
- % z:=1;
- % x:=u;
- % loop:
- % n:=posnnonnull car x;
- % if n eq t
- % then return nil;
- % % special test for all null;
- % if n then <<
- % y:=nth(car x,n);
- % % next line is equivalent to:
- %% onne of n,z is even;
- % if evenp (n+z-1)
- % then y:=negf y;
- % u:=remove(u,z);
- % return !*multf(y,detqf remove2 u) >>;
- % x:=cdr x;
- % z:=z+1;
- % if x
- % then go to loop;
- % noopt:
- % x := u;
- % n := 1; %number of current row/column;
- % z := nil;
- % if nonnull car u < nonnullcar u
- % then go to row!-expand;
- % u:=mapcar(u,function cdr);
- % a: if null x then return z;
- % y := caar x;
- % if null y then go to b
- % else if evenp n then y := negf y;
- % z := addf(!*multf(y,detqf remove(u,n)),z);
- % b: x := cdr x;
- % n := iadd1 n;
- % go to a;
- % row!-expand:
- % u:=cdr u;
- % x:=car x;
- % aa:
- % if null x then return z;
- % y:=car x;
- % if null y
- % then go to bb
- % else if evenp n then y:=negf y;
- % z:=addf(!*multf(y,detqf remove2 u),z);
- % bb:
- % x:=cdr x;
- % n:=iadd1 n;
- % go to aa
- % end;
- %
- %
- %symbolic procedure remove2 u;
- %mapcar(u,function (lambda x;
- % remove(x,n)));
- %
- %unfluid '(n);
- %
- %symbolic procedure nonnull u;
- %if null u
- % then 0
- % else if null car u
- % then nonnull cdr u
- % else iadd1 (nonnull cdr u);
- %
- %
- %symbolic procedure nonnullcar u;
- %if null u
- % then 0
- % else if null caar u
- % then nonnullcar cdr u
- % else iadd1 (nonnullcar cdr u);
- %
- %
- %
- %symbolic procedure posnnonnull u;
- %% returns t if u has no non-null elements
- %% nil if more than one
- %% else position of the first;
- %begin
- % scalar n,x;
- % n:=1;
- %loop:
- % if null u
- % then return
- % if x
- % then x
- % else t;
- % if car u
- % then if x
- % then return nil
- % else x:=n;
- % n:=iadd1 n;
- % u:=cdr u;
- % go to loop
- % end;
- symbolic procedure res!-sqrt(u,a);
- % Evaluates resultant of u ( as a poly in its mvar) and x**-a.
- begin
- scalar x,n,v,k,l;
- x:=mvar u;
- n:=ldeg u;
- n:=quotient(n,2);
- v:=mkvect n;
- putv(v,0,1);
- for i:=1:n do
- putv(v,i,!*multf(a,getv(v,i-1)));
- % now substitute for x**2 in u leaving k*x+l.
- k:=l:=nil;
- while u do
- if mvar u neq x
- then <<
- l:=addf(l,u);
- u:=nil >>
- else <<
- if evenp ldeg u
- then l:=addf(l,!*multf(lc u,getv(v,(ldeg u)/2)))
- else k:=addf(k,!*multf(lc u,getv(v,(ldeg u -1)/2)));
- u:=red u >>;
- % now have k*x+l,x**2-a, giving l*l-a*k*k.
- return addf(!*multf(l,l),!*multf(negf a,multf(k,k)))
- end;
- symbolic procedure sqfr!-norm2 (f,mvarf,a);
- begin
- scalar u,w,aa,ff,resfn;
- resfn:='resultant;
- if eqcar(a,'sqrt)
- then <<
- resfn:='res!-sqrt;
- aa:=!*q2f simp argof a >>
- else rerror(algint,1,"Norms over transcendental extensions");
- f:=pvarsub(f,a,'! gerbil);
- w:=nil;
- if involvesf(f,'! gerbil) then goto l1;
- increase:
- w:=addf(w,!*p2f mksp(a,1));
- f:=!*q2f algint!-subf(f,list(mvarf . list('plus,mvarf,
- list('minus,'! gerbil))));
- l1:
- u:=apply2(resfn,makemainvar(f,'! gerbil),aa);
- ff:=nsqfrp(u,mvarf);
- if ff
- then go to increase;
- f:=!*q2f algint!-subf(f,list('! gerbil.a));
- % cannot use pvarsub since want to squash higher powers.
- return list(u,w,f)
- end;
- symbolic procedure nsqfrp(u,v);
- begin
- scalar w;
- w:=modeval(u,v);
- if w eq 'failed
- then go to normal;
- if atom w
- then go to normal;
- if ldegvar(w,v) neq ldegvar(u,v)
- then go to normal;
- % printc "Modular image is:";
- % printsf w;
- w:=gcdf(w,partialdiff(w,v));
- % printc "Answer is:";
- % printsf w;
- if w iequal 1
- then return nil;
- normal;
- w:=gcdf(u,partialdiff(u,v));
- if involvesf(w,v)
- then return w
- else return nil
- end;
- symbolic procedure ldegvar(u,v);
- if atom u
- then 0
- else if mvar u eq v
- then ldeg u
- else if ordop(v,mvar u)
- then 0
- else max2(ldegvar(lc u,v),ldegvar(red u,v));
- symbolic procedure modeval(u,v);
- if atom u
- then u
- else if v eq mvar u
- then begin
- scalar w,x;
- w:=modeval(lc u,v);
- if w eq 'failed
- then return w;
- x:=modeval(red u,v);
- if x eq 'failed
- then return x;
- if null w
- then return x
- else return (lpow u .* w) .+ x
- end
- else begin
- scalar w,x;
- x:=mvar u;
- if not atom x
- then if dependsp(x,v)
- then return 'failed;
- x:=modevalvar x;
- if x eq 'failed
- then return x;
- w:=modeval(lc u,v);
- if w eq 'failed
- then return w;
- if x
- then w:=multf(w,exptf(x,ldeg u));
- x:=modeval(red u,v);
- if x eq 'failed
- then return x;
- return addf(w,x)
- end;
- symbolic procedure modevalvar v;
- begin scalar w;
- if atom v
- then <<if (w := get(v,'modvalue)) then return w;
- put(v,'modvalue,modevalcount);
- modevalcount := modevalcount+1;
- return modevalcount-1>>
- else if car v neq 'sqrt
- then <<if !*tra then <<princ "Unexpected algebraic:"; print v>>;
- error1()>>
- else if numberp argof v then return (mksp(v,1) .* 1) .+ nil;
- w := modeval(!*q2f simp argof v,!*pvar);
- w := assoc(w,listofallsqrts);
- % The variable does not matter, since we know it does not depend.
- if w then return cdr w else return 'failed
- end;
- % unglobal '(modevalcount);
- endmodule;
- end;
|