X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FRoots%2FSimple.hs;h=a5924f4658d5c6ca8d15fbba6b10c24ed446566b;hb=ae914d13235a4582077a5cb2b1edd630d9c6ad62;hp=414b77787262e608ceef4a66981a5dc5ab82cc50;hpb=2f54e89d36e835c58efcc281741632d457859b20;p=numerical-analysis.git diff --git a/src/Roots/Simple.hs b/src/Roots/Simple.hs index 414b777..a5924f4 100644 --- a/src/Roots/Simple.hs +++ b/src/Roots/Simple.hs @@ -8,22 +8,34 @@ -- where f is assumed to be continuous on the interval of interest. -- -module Roots.Simple +module Roots.Simple ( + bisect, + fixed_point, + fixed_point_error_ratios, + fixed_point_iteration_count, + has_root, + newtons_method, + secant_method, + trisect ) where import Data.List (find) +import NumericPrelude hiding ( abs ) +import Algebra.Absolute ( abs ) +import qualified Algebra.Additive as Additive ( C ) +import qualified Algebra.Algebraic as Algebraic ( C ) +import qualified Algebra.Field as Field ( C ) +import qualified Algebra.RealField as RealField ( C ) +import qualified Algebra.RealRing as RealRing ( C ) -import Normed +import Normed ( Normed(..) ) +import qualified Roots.Fast as F ( + bisect, + fixed_point_iterations, + fixed_point_with_iterations, + has_root, + trisect ) -import qualified Roots.Fast as F - -import NumericPrelude hiding (abs) -import Algebra.Absolute (abs) -import qualified Algebra.Additive as Additive -import qualified Algebra.Algebraic as Algebraic -import qualified Algebra.Field as Field -import qualified Algebra.RealField as RealField -import qualified Algebra.RealRing as RealRing -- | Does the (continuous) function @f@ have a root on the interval -- [a,b]? If f(a) <] 0 and f(b) ]> 0, we know that there's a root in @@ -56,7 +68,7 @@ has_root f a b epsilon = -- | We are given a function @f@ and an interval [a,b]. The bisection --- method checks finds a root by splitting [a,b] in half repeatedly. +-- method finds a root by splitting [a,b] in half repeatedly. -- -- If one is found within some prescribed tolerance @epsilon@, it is -- returned. Otherwise, the interval [a,b] is split into two @@ -68,8 +80,12 @@ has_root f a b epsilon = -- -- Examples: -- --- >>> bisect cos 1 2 0.001 --- Just 1.5712890625 +-- >>> let actual = 1.5707963267948966 +-- >>> let Just root = bisect cos 1 2 0.001 +-- >>> root +-- 1.5712890625 +-- >>> abs (root - actual) < 0.001 +-- True -- -- >>> bisect sin (-1) 1 0.001 -- Just 0.0 @@ -84,6 +100,40 @@ bisect f a b epsilon = F.bisect f a b epsilon Nothing Nothing +-- | We are given a function @f@ and an interval [a,b]. The trisection +-- method finds a root by splitting [a,b] into three +-- subintervals repeatedly. +-- +-- If one is found within some prescribed tolerance @epsilon@, it is +-- returned. Otherwise, the interval [a,b] is split into two +-- subintervals [a,c] and [c,b] of equal length which are then both +-- checked via the same process. +-- +-- Returns 'Just' the value x for which f(x) == 0 if one is found, +-- or Nothing if one of the preconditions is violated. +-- +-- Examples: +-- +-- >>> let actual = 1.5707963267948966 +-- >>> let Just root = trisect cos 1 2 0.001 +-- >>> root +-- 1.5713305898491083 +-- >>> abs (root - actual) < 0.001 +-- True +-- +-- >>> trisect sin (-1) 1 0.001 +-- Just 0.0 +-- +trisect :: (RealField.C a, RealRing.C b) + => (a -> b) -- ^ The function @f@ whose root we seek + -> a -- ^ The \"left\" endpoint of the interval, @a@ + -> a -- ^ The \"right\" endpoint of the interval, @b@ + -> a -- ^ The tolerance, @epsilon@ + -> Maybe a +trisect f a b epsilon = + F.trisect f a b epsilon Nothing Nothing + + -- | Find a fixed point of the function @f@ with the search starting -- at x0. We delegate to the version that returns the number of -- iterations and simply discard the number of iterations. @@ -157,8 +207,8 @@ newton_iterations :: (Field.C a) -> (a -> a) -- ^ The derivative of @f@ -> a -- ^ Initial guess, x-naught -> [a] -newton_iterations f f' x0 = - iterate next x0 +newton_iterations f f' = + iterate next where next xn = xn - ( (f xn) / (f' xn) ) @@ -242,8 +292,8 @@ secant_iterations :: (Field.C a) -> a -- ^ Initial guess, x-naught -> a -- ^ Second initial guess, x-one -> [a] -secant_iterations f x0 x1 = - iterate2 g x0 x1 +secant_iterations f = + iterate2 g where g prev2 prev1 = let x_change = prev1 - prev2