home *** CD-ROM | disk | FTP | other *** search
-
- (* Copyright 1988 Wolfram Research, Inc. *)
-
- (*:Version: Mathematica 2.0 *)
-
- (*:Name: Algebra`CountRoots` *)
-
- (*:Title: Sturm's Method for Counting Real Roots in an Interval *)
-
- (*:Author:
- Dan Grayson, modified September, 1990 by Bruce Sawhill,
- modified October, 1990 by Hon Wah Tam
- modified December, 1990 by E C Martin
- *)
-
- (*:Keywords:
- Sturm's method, polynomial, real roots, endpoints
- *)
-
- (*:Requirements: none. *)
-
- (*:Warnings: Not working for complex polynomials. *)
-
- (*:Sources:
- The Theory of Equations,
- by W.S. Burnside and A.W. Panton, S. Chand & Co., 1972.
- *)
-
- (*:Summary:
- For a given real polynomial f[x] and a given interval a <= x <= b,
- CountRoots computes the number of roots of f[x] within the given
- interval, using Sturm's method.
- *)
-
- BeginPackage["Algebra`CountRoots`"]
-
- CountRoots::usage = "CountRoots[f,{x,a,b}] uses Sturm's method
- to compute the number of zeros of the real polynomial f
- on the interval x->[a,b]. The endpoints may be
- infinite. Duplicated roots are only counted once."
-
- Begin["Algebra`CountRoots`Private`"]
-
- CountRoots::npoly = "`1` is not a polynomial in `2`."
- CountRoots::llim = "Lower limit `1` is neither a real number nor -Infinity."
- CountRoots::ulim = "Upper limit `1` is neither a real number nor Infinity."
- CountRoots::intv = "Lower limit `1` is not less than upper limit `2`."
-
- CountRoots[ x___] :=
- With[{result = CountRoots0[x]}, result /; result =!= $Failed]
-
-
- OmitZeroes[m_] := Select[m,#!=0&]
-
- CountChanges[m_] :=
- Module[{i,len=Length[m],num=0} ,
- Do[ If[m[[i]] != m[[i+1]], num++], {i,len-1} ]; num
- ]
-
- CountSignChanges[m_] := CountChanges[OmitZeroes[Sign[m]]]
-
- TopCoeff[f_,x_] := Coefficient[f,x,Exponent[f,x]]
-
- SignedTopCoeff[f_,x_] :=
- Module[{d=Exponent[f,x]},
- Coefficient[f,x,d] (-1)^d
- ]
-
- SturmSequence[f_,g_,x_] := Module[ { seq = {f}, p=f, q=g} ,
- While[ If[q!=0,True,False,True] ,
- seq = Append[seq,q];
- {p,q} = {q,Expand[-PolynomialRemainder[p,q,x]]};
- ];
- seq
- ]
-
- SturmSequence[f_,x_] := SturmSequence[f,D[f,x],x]
-
- CountRoots0[f_,{x_,a_,b_}] :=
- Which[ !PolynomialQ[f,x],
- Message[CountRoots::npoly,f,x]; $Failed,
- ( (!NumberQ[a] || SameQ[Head[a],Complex]) &&
- !SameQ[a, -Infinity] ),
- Message[CountRoots::llim,a]; $Failed,
- ( (!NumberQ[b] || SameQ[Head[b],Complex]) &&
- !SameQ[b, Infinity] ),
- Message[CountRoots::ulim,b]; $Failed,
- True, countroots[f,{x,a,b}] ]
-
- CountRoots0[ _] := $Failed
-
- countroots[f_,{x_,a_,b_}] :=
- Module[{seq = SturmSequence[f,x] } ,
- If[ !TrueQ[ a <= b ],
- Message[CountRoots::intv,a,b]; $Failed,
- CountSignChanges[ seq/.x->a ]
- -CountSignChanges[ seq/.x->b ]+
- If[(f/.x->a)==0,1,0] ]
- ] /; NumberQ[a] && NumberQ[b]
-
- countroots[f_,{x_,-Infinity,b_}] :=
- Module[{seq = SturmSequence[f,x]} ,
- If[ !TrueQ[ -Infinity < b ],
- Message[CountRoots::intv,-Infinity,b]; $Failed,
- CountSignChanges[ SignedTopCoeff[#,x]& /@ seq ]
- -CountSignChanges[ seq/.x->b ] ]
- ] /; NumberQ[b]
-
- countroots[f_,{x_,a_,Infinity}] :=
- Module[{seq = SturmSequence[f,x]} ,
- If[ !TrueQ[ a < Infinity ],
- Message[CountRoots::intv,a,Infinity]; $Failed,
- CountSignChanges[ seq/.x->a ]
- -CountSignChanges[ TopCoeff[#,x]& /@ seq ]+
- If[(f/.x->a)==0,1,0] ]
- ] /; NumberQ[a]
-
- countroots[f_,{x_,-Infinity,Infinity}] :=
- Module[{seq = SturmSequence[f,x]} ,
- CountSignChanges[ SignedTopCoeff[#,x]& /@ seq ]
- -CountSignChanges[ TopCoeff[#,x]& /@ seq ]
- ]
-
- End[] (* Algebra`CountRoots`Private` *)
-
- Protect[CountRoots]
-
- EndPackage[] (* Algebra`CountRoots` *)
-
- (*:Limitations: Real intervals only. *)
-
- (*:Examples:
- CountRoots[ x^3 + 4 x^2 - x + 7,{x,-10,10}]
-
- *)
-
-