diff options
author | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
commit | ab8cc85adde879fb963c94d15675783f2cf4b183 (patch) | |
tree | c202482327f474583b750b2c45dedfc4e4312b1d /src/algebra/solvefor.spad.pamphlet | |
download | open-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz |
Initial population.
Diffstat (limited to 'src/algebra/solvefor.spad.pamphlet')
-rw-r--r-- | src/algebra/solvefor.spad.pamphlet | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/src/algebra/solvefor.spad.pamphlet b/src/algebra/solvefor.spad.pamphlet new file mode 100644 index 00000000..7095d4e1 --- /dev/null +++ b/src/algebra/solvefor.spad.pamphlet @@ -0,0 +1,327 @@ +\documentclass{article} +\usepackage{axiom} +\begin{document} +\title{\$SPAD/src/algebra solvefor.spad} +\author{Stephen M. Watt, Barry Trager} +\maketitle +\begin{abstract} +\end{abstract} +\eject +\tableofcontents +\eject +\section{package SOLVEFOR PolynomialSolveByFormulas} +<<package SOLVEFOR PolynomialSolveByFormulas>>= +)abbrev package SOLVEFOR PolynomialSolveByFormulas +-- Current fields with "**": (%, RationalNumber) -> % are +-- ComplexFloat, RadicalExtension(K) and RationalRadical +-- SMW June 86, BMT Sept 93 +++ Description: +++ This package factors the formulas out of the general solve code, +++ allowing their recursive use over different domains. +++ Care is taken to introduce few radicals so that radical extension +++ domains can more easily simplify the results. + +PolynomialSolveByFormulas(UP, F): PSFcat == PSFdef where + + UP: UnivariatePolynomialCategory F + F: Field with "**": (%, Fraction Integer) -> % + + L ==> List + + PSFcat == with + solve: UP -> L F + ++ solve(u) \undocumented + particularSolution: UP -> F + ++ particularSolution(u) \undocumented + mapSolve: (UP, F -> F) -> Record(solns: L F, + maps: L Record(arg:F,res:F)) + ++ mapSolve(u,f) \undocumented + + linear: UP -> L F + ++ linear(u) \undocumented + quadratic: UP -> L F + ++ quadratic(u) \undocumented + cubic: UP -> L F + ++ cubic(u) \undocumented + quartic: UP -> L F + ++ quartic(u) \undocumented + + -- Arguments give coefs from high to low degree. + linear: (F, F) -> L F + ++ linear(f,g) \undocumented + quadratic: (F, F, F) -> L F + ++ quadratic(f,g,h) \undocumented + cubic: (F, F, F, F) -> L F + ++ cubic(f,g,h,i) \undocumented + quartic: (F, F, F, F, F) -> L F + ++ quartic(f,g,h,i,j) \undocumented + + aLinear: (F, F) -> F + ++ aLinear(f,g) \undocumented + aQuadratic: (F, F, F) -> F + ++ aQuadratic(f,g,h) \undocumented + aCubic: (F, F, F, F) -> F + ++ aCubic(f,g,h,j) \undocumented + aQuartic: (F, F, F, F, F) -> F + ++ aQuartic(f,g,h,i,k) \undocumented + + PSFdef == add + + ----------------------------------------------------------------- + -- Stuff for mapSolve + ----------------------------------------------------------------- + id ==> (IDENTITY$Lisp) + + maplist: List Record(arg: F, res: F) := [] + mapSolving?: Boolean := false + -- map: F -> F := id #1 replaced with line below + map: Boolean := false + + mapSolve(p, fn) == + -- map := fn #1 replaced with line below + locmap: F -> F := fn #1; map := id locmap + mapSolving? := true; maplist := [] + slist := solve p + mapSolving? := false; + -- map := id #1 replaced with line below + locmap := id #1; map := id locmap + [slist, maplist] + + part(s: F): F == + not mapSolving? => s + -- t := map s replaced with line below + t: F := SPADCALL(s, map)$Lisp + t = s => s + maplist := cons([t, s], maplist) + t + + ----------------------------------------------------------------- + -- Entry points and error handling + ----------------------------------------------------------------- + cc ==> coefficient + + -- local intsolve + intsolve(u:UP):L(F) == + u := (factors squareFree u).1.factor + n := degree u + n=1 => linear (cc(u,1), cc(u,0)) + n=2 => quadratic (cc(u,2), cc(u,1), cc(u,0)) + n=3 => cubic (cc(u,3), cc(u,2), cc(u,1), cc(u,0)) + n=4 => quartic (cc(u,4), cc(u,3), cc(u,2), cc(u,1), cc(u,0)) + error "All sqfr factors of polynomial must be of degree < 5" + + solve u == + ls := nil$L(F) + for f in factors squareFree u repeat + lsf := intsolve f.factor + for i in 1..(f.exponent) repeat ls := [:lsf,:ls] + ls + + particularSolution u == + u := (factors squareFree u).1.factor + n := degree u + n=1 => aLinear (cc(u,1), cc(u,0)) + n=2 => aQuadratic (cc(u,2), cc(u,1), cc(u,0)) + n=3 => aCubic (cc(u,3), cc(u,2), cc(u,1), cc(u,0)) + n=4 => aQuartic (cc(u,4), cc(u,3), cc(u,2), cc(u,1), cc(u,0)) + error "All sqfr factors of polynomial must be of degree < 5" + + needDegree(n: Integer, u: UP): Boolean == + degree u = n => true + error concat("Polynomial must be of degree ", n::String) + + needLcoef(cn: F): Boolean == + cn ^= 0 => true + error "Leading coefficient must not be 0." + + needChar0(): Boolean == + characteristic()$F = 0 => true + error "Formula defined only for fields of characteristic 0." + + linear u == + needDegree(1, u) + linear (coefficient(u,1), coefficient(u,0)) + + quadratic u == + needDegree(2, u) + quadratic (coefficient(u,2), coefficient(u,1), + coefficient(u,0)) + + cubic u == + needDegree(3, u) + cubic (coefficient(u,3), coefficient(u,2), + coefficient(u,1), coefficient(u,0)) + + quartic u == + needDegree(4, u) + quartic (coefficient(u,4),coefficient(u,3), + coefficient(u,2),coefficient(u,1),coefficient(u,0)) + + ----------------------------------------------------------------- + -- The formulas + ----------------------------------------------------------------- + + -- local function for testing equality of radicals. + -- This function is necessary to detect at least some of the + -- situations like sqrt(9)-3 = 0 --> false. + equ(x:F,y:F):Boolean == + ( (recip(x-y)) case "failed" ) => true + false + + linear(c1, c0) == + needLcoef c1 + [- c0/c1 ] + + aLinear(c1, c0) == + first linear(c1,c0) + + quadratic(c2, c1, c0) == + needLcoef c2; needChar0() + (c0 = 0) => [0$F,:linear(c2, c1)] + (c1 = 0) => [(-c0/c2)**(1/2),-(-c0/c2)**(1/2)] + D := part(c1**2 - 4*c2*c0)**(1/2) + [(-c1+D)/(2*c2), (-c1-D)/(2*c2)] + + aQuadratic(c2, c1, c0) == + needLcoef c2; needChar0() + (c0 = 0) => 0$F + (c1 = 0) => (-c0/c2)**(1/2) + D := part(c1**2 - 4*c2*c0)**(1/2) + (-c1+D)/(2*c2) + + w3: F := (-1 + (-3::F)**(1/2)) / 2::F + + cubic(c3, c2, c1, c0) == + needLcoef c3; needChar0() + + -- case one root = 0, not necessary but keeps result small + (c0 = 0) => [0$F,:quadratic(c3, c2, c1)] + a1 := c2/c3; a2 := c1/c3; a3 := c0/c3 + + -- case x**3-a3 = 0, not necessary but keeps result small + (a1 = 0 and a2 = 0) => + [ u*(-a3)**(1/3) for u in [1, w3, w3**2 ] ] + + -- case x**3 + a1*x**2 + a1**2*x/3 + a3 = 0, the general for- + -- mula is not valid in this case, but solution is easy. + P := part(-a1/3::F) + equ(a1**2,3*a2) => + S := part((- a3 + (a1**3)/27::F)**(1/3)) + [ P + S*u for u in [1,w3,w3**2] ] + + -- general case + Q := part((3*a2 - a1**2)/9::F) + R := part((9*a1*a2 - 27*a3 - 2*a1**3)/54::F) + D := part(Q**3 + R**2)**(1/2) + S := part(R + D)**(1/3) + -- S = 0 is done in the previous case + [ P + S*u - Q/(S*u) for u in [1, w3, w3**2] ] + + aCubic(c3, c2, c1, c0) == + needLcoef c3; needChar0() + (c0 = 0) => 0$F + a1 := c2/c3; a2 := c1/c3; a3 := c0/c3 + (a1 = 0 and a2 = 0) => (-a3)**(1/3) + P := part(-a1/3::F) + equ(a1**2,3*a2) => + S := part((- a3 + (a1**3)/27::F)**(1/3)) + P + S + Q := part((3*a2 - a1**2)/9::F) + R := part((9*a1*a2 - 27*a3 - 2*a1**3)/54::F) + D := part(Q**3 + R**2)**(1/2) + S := part(R + D)**(1/3) + P + S - Q/S + + quartic(c4, c3, c2, c1, c0) == + needLcoef c4; needChar0() + + -- case one root = 0, not necessary but keeps result small + (c0 = 0) => [0$F,:cubic(c4, c3, c2, c1)] + -- Make monic: + a1 := c3/c4; a2 := c2/c4; a3 := c1/c4; a4 := c0/c4 + + -- case x**4 + a4 = 0 <=> (x**2-sqrt(-a4))*(x**2+sqrt(-a4)) + -- not necessary but keeps result small. + (a1 = 0 and a2 = 0 and a3 = 0) => + append( quadratic(1, 0, (-a4)**(1/2)),_ + quadratic(1 ,0, -((-a4)**(1/2))) ) + + -- Translate w = x+a1/4 to eliminate a1: w**4+p*w**2+q*w+r + p := part(a2-3*a1*a1/8::F) + q := part(a3-a1*a2/2::F + a1**3/8::F) + r := part(a4-a1*a3/4::F + a1**2*a2/16::F - 3*a1**4/256::F) + -- t0 := the cubic resolvent of x**3-p*x**2-4*r*x+4*p*r-q**2 + -- The roots of the translated polynomial are those of + -- two quadratics. (What about rt=0 ?) + -- rt=0 can be avoided by picking a root ^= p of the cubic + -- polynomial above. This is always possible provided that + -- the input is squarefree. In this case the two other roots + -- are +(-) 2*r**(1/2). + if equ(q,0) -- this means p is a root + then t0 := part(2*(r**(1/2))) + else t0 := aCubic(1, -p, -4*r, 4*p*r - q**2) + rt := part(t0 - p)**(1/2) + slist := append( quadratic( 1, rt, (-q/rt + t0)/2::F ), + quadratic( 1, -rt, ( q/rt + t0)/2::F )) + -- Translate back: + [s - a1/4::F for s in slist] + + aQuartic(c4, c3, c2, c1, c0) == + needLcoef c4; needChar0() + (c0 = 0) => 0$F + a1 := c3/c4; a2 := c2/c4; a3 := c1/c4; a4 := c0/c4 + (a1 = 0 and a2 = 0 and a3 = 0) => (-a4)**(1/4) + p := part(a2-3*a1*a1/8::F) + q := part(a3-a1*a2/2::F + a1**2*a1/8::F) + r := part(a4-a1*a3/4::F + a1**2*a2/16::F - 3*a1**4/256::F) + if equ(q,0) + then t0 := part(2*(r**(1/2))) + else t0 := aCubic(1, -p, -4*r, 4*p*r - q**2) + rt := part(t0 - p)**(1/2) + s := aQuadratic( 1, rt, (-q/rt + t0)/2::F ) + s - a1/4::F + +@ +\section{License} +<<license>>= +--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. +--All rights reserved. +-- +--Redistribution and use in source and binary forms, with or without +--modification, are permitted provided that the following conditions are +--met: +-- +-- - Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- +-- - Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in +-- the documentation and/or other materials provided with the +-- distribution. +-- +-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the +-- names of its contributors may be used to endorse or promote products +-- derived from this software without specific prior written permission. +-- +--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +@ +<<*>>= +<<license>> + +<<package SOLVEFOR PolynomialSolveByFormulas>> +@ +\eject +\begin{thebibliography}{99} +\bibitem{1} nothing +\end{thebibliography} +\end{document} |