Artifact 49d8fe69d2d02a40982d5cb55cfd92de82732b16b8589c80d5fb9121d499d129:
- Executable file
r37/packages/solve/ppsoln.red
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 4695) [annotate] [blame] [check-ins using] [more...]
module ppsoln; % Solve surd eqns, mainly by principle of powers method. % Authors: Anthony C. Hearn and Stanley L. Kameny. fluid '(!*complex !*msg !*numval !*ppsoln); global '(bfone!*); !*ppsoln := t; % Keep this as internal switch. symbolic procedure solve!-fractional!-power(u,x,var,mu); % Attempts solution of equation car u**cadr u=x with respect to % kernel var and with multiplicity mu, where cadr u is a rational % number. begin scalar v,w,z; v := simp!* car u; w := simp!* cadr u; z := solvesq(subs2 subtrsq(exptsq(v,numr w),exptsq(x,denr w)), var,mu); w := subtrsq(simp('expt . u),x); z := check!-solns(z,numr w,var); % return if z eq 'unsolved then list list(list w,nil,mu) else z return if z eq 'unsolved then mkrootsof(w,var,mu) else z end; symbolic procedure principle!-of!-powers!-soln(ex,x1,var,mu); % Finds solutions of ex=0 by the principle of powers method. Return % 'unsolved if solutions can't be found. begin scalar z; a: if null x1 then return 'unsolved else if suitable!-expt car x1 and not((z := pr!-pow!-soln1(ex,car x1,var,mu)) eq 'unsolved) then return z; x1 := cdr x1; go to a end; symbolic procedure pr!-pow!-soln1(ex,y,var,mu); begin scalar oldkord,z; oldkord := updkorder y; z := reorder ex; setkorder oldkord; if ldeg z neq 1 then return 'unsolved; z := coeflis z; if length z neq 2 or caar z neq 0 then errach list("solve confused",ex,z); z := exptsq(quotsq(negsq(cdar z ./ 1),cdadr z ./ 1), caddr caddr y); z := solvesq(subs2 addsq(simp!* cadr y,negsq z),var,mu); z := check!-solns(z,ex,var); return z end; symbolic procedure check!-solns(z,ex,var); begin scalar x,y,fv,sx,vs; fv := freevarl(ex,var); for each z1 in z do fv := union(fv,union(freevarl(numr caar z1,var), freevarl(denr caar z1,var))); fv := delete('i,fv); % this does only one random setting!! if fv then for each v in fv do if not flagp(v,'constant) then vs := (v . list('quotient,1+random 999,1000)) . vs; sx := if vs then numr subf(ex,vs) else ex; while z do if null cadar z then <<z := nil; x := 'unsolved>> else if <<y := numr subf(ex,list(caadar z . mk!*sq caaar z)); null y % to do multiple random tests, the vs, sx setting and testing % would be moved here and done in a loop. or fv and null(y := numr subf(sx,list(caadar z . mk!*sq subsq(caaar z,vs)))) or null numvalue y>> then <<x := car z . x; z := cdr z>> else z := cdr z; return if null x then 'unsolved else x end; symbolic procedure suitable!-expt u; eqcar(u,'expt) and eqcar(caddr u,'quotient) and cadr caddr u = 1 and fixp caddr caddr u; symbolic procedure freevarl(ex,var); <<for each k in allkern list(ex ./ 1) do l := union(l,varsift(k,var)); delete(var,l)>> where l=if var then list var else nil; symbolic procedure varsift(a,var); if atom a then if not(null a or numberp a or a eq var) then list a else nil else if get(car a,'dname) then nil else if car a eq '!*sq then varsift(prepsq cadr a,var) % else if car a memq '(arbint arbcomplex) then list a else if car a memq '(arbint arbcomplex) or (get(car a,'simpfn) eq 'simpiden and not smember(var,a)) then list a else for each c in cdr a join varsift(c,var); symbolic procedure numvalue u; % Find floating point value of sf u. begin scalar !*numval,x,c,cp,p,m; m := !*msg; !*msg := nil; !*numval := t; c := ('i memq freevarl(u,nil)); if (cp := !*complex) then off complex; x := setdmode('rounded,t); p := precision 10; if x eq '!:rd!: then x := 'rounded; % <==== to avoid error later if c then on complex; !*msg := m; u := numr simp prepf u; !*msg := nil; if c then off complex; if x then setdmode(x,t) else setdmode('rounded,nil); if cp then on complex; precision p; !*msg := m; return if eqcar(u,'!:rd!:) and (numvchk(100,z) where z=round!* u) or eqcar(u,'!:cr!:) and (numvchk(10,z) where z=retag crrl u) and (numvchk(10,z) where z=retag crim u) then nil else u end; symbolic procedure numvchk(fact,z); if atom z then fact*abs z<1 else lessp!:(timbf(bfloat fact,abs!: z),bfone!*); endmodule; end;