numeric-prelude-0.3: src/MathObj/PowerSeries/Example.hs
{-# LANGUAGE NoImplicitPrelude #-}
module MathObj.PowerSeries.Example where
import qualified MathObj.PowerSeries.Core as PS
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
-- import qualified Algebra.Additive as Additive
import qualified Algebra.ZeroTestable as ZeroTestable
import qualified Algebra.Transcendental as Transcendental
import Algebra.Additive (zero, subtract, negate)
import Data.List (intersperse, )
import Data.List.HT (sieve, )
import NumericPrelude.Numeric (one, (*), (/),
fromInteger, {-fromRational,-} pi)
import NumericPrelude.Base -- (Bool, const, map, zipWith, id, (&&), (==))
{- * Default implementations. -}
recip :: (Ring.C a) => [a]
recip = recipExpl
exp, sin, cos,
log, asin, atan, sqrt :: (Field.C a) => [a]
acos :: (Transcendental.C a) => [a]
tan :: (ZeroTestable.C a, Field.C a) => [a]
exp = expODE
sin = sinODE
cos = cosODE
tan = tanExplSieve
log = logODE
asin = asinODE
acos = acosODE
atan = atanODE
sinh, cosh, atanh :: (Field.C a) => [a]
sinh = sinhODE
cosh = coshODE
atanh = atanhODE
pow :: (Field.C a) => a -> [a]
pow = powExpl
sqrt = sqrtExpl
{- * Generate Taylor series explicitly. -}
recipExpl :: (Ring.C a) => [a]
recipExpl = cycle [1,-1]
expExpl, sinExpl, cosExpl :: (Field.C a) => [a]
expExpl = scanl (*) one PS.recipProgression
sinExpl = zero : PS.holes2alternate (tail expExpl)
cosExpl = PS.holes2alternate expExpl
tanExpl, tanExplSieve :: (ZeroTestable.C a, Field.C a) => [a]
tanExpl = PS.divide sinExpl cosExpl
-- ignore zero values
tanExplSieve =
concatMap
(\x -> [zero,x])
(PS.divide (sieve 2 (tail sin)) (sieve 2 cos))
logExpl, atanExpl, sqrtExpl :: (Field.C a) => [a]
logExpl = zero : PS.alternate PS.recipProgression
atanExpl = zero : PS.holes2alternate PS.recipProgression
sinhExpl, coshExpl, atanhExpl :: (Field.C a) => [a]
sinhExpl = zero : PS.holes2 (tail expExpl)
coshExpl = PS.holes2 expExpl
atanhExpl = zero : PS.holes2 PS.recipProgression
{- * Power series of (1+x)^expon using the binomial series. -}
powExpl :: (Field.C a) => a -> [a]
powExpl expon =
scanl (*) 1 (zipWith (/)
(iterate (subtract 1) expon) PS.progression)
sqrtExpl = powExpl (1/2)
{- |
Power series of error function (almost).
More precisely @ erf = 2 \/ sqrt pi * integrate (\x -> exp (-x^2)) @,
with @erf 0 = 0@.
-}
erf :: (Field.C a) => [a]
erf = PS.integrate 0 $ intersperse 0 $ PS.alternate exp
{-
integrate (\x -> exp (-x^2/2)) :
erf = PS.integrate 0 $ intersperse 0 $
snd $ mapAccumL (\twoPow c -> (twoPow/(-2), twoPow*c)) 1 exp
-}
{- * Generate Taylor series from differential equations. -}
{-
exp' x == exp x
sin' x == cos x
cos' x == - sin x
tan' x == 1 + tan x ^ 2
== cos x ^ (-2)
-}
expODE, sinODE, cosODE, tanODE, tanODESieve :: (Field.C a) => [a]
expODE = PS.integrate 1 expODE
sinODE = PS.integrate 0 cosODE
cosODE = PS.integrate 1 (PS.negate sinODE)
tanODE = PS.integrate 0 (PS.add [1] (PS.mul tanODE tanODE))
tanODESieve =
-- sieve is too strict here because it wants to detect end of lists
let tan2 = map head (iterate (drop 2) (tail tanODESieve))
in PS.integrate 0 (intersperse zero (1 : PS.mul tan2 tan2))
{-
log' (1+x) == 1/(1+x)
asin' x == acos' x == 1/sqrt(1-x^2)
atan' x == 1/(1+x^2)
-}
logODE, recipCircle, asinODE, atanODE, sqrtODE :: (Field.C a) => [a]
logODE = PS.integrate zero recip
recipCircle = intersperse zero (PS.alternate (powODE (-1/2)))
asinODE = PS.integrate 0 recipCircle
atanODE = PS.integrate zero (cycle [1,0,-1,0])
sqrtODE = powODE (1/2)
acosODE :: (Transcendental.C a) => [a]
acosODE = PS.integrate (pi/2) recipCircle
sinhODE, coshODE, atanhODE :: (Field.C a) => [a]
sinhODE = PS.integrate 0 coshODE
coshODE = PS.integrate 1 sinhODE
atanhODE = PS.integrate zero (cycle [1,0])
{-
Power series for y with
y x = (1+x) ** alpha
by solving the differential equation
alpha * y x = (1+x) * y' x
-}
powODE :: (Field.C a) => a -> [a]
powODE expon =
let y = PS.integrate 1 y'
y' = PS.scale expon (scanl1 subtract y)
in y