HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulenumeric-prelude-0.4.4Haskell98

MathObj.PowerSeries.Core

  • 40 values
Example22 expressions
import qualified MathObj.PowerSeries.Core as PSimport qualified MathObj.PowerSeries.Example as PSEimport Test.NumericPrelude.Utility (equalTrunc, (/\))import qualified Test.QuickCheck as QCimport NumericPrelude.Numeric as NPimport NumericPrelude.Base as Pimport Prelude ()import Control.Applicative (liftA3)checkHoles ::   Int -> ([Rational] -> [Rational]) ->   Rational -> [Rational] -> QC.PropertycheckHoles trunc f x xs =   QC.choose (1,10) /\ \expon ->   equalTrunc trunc      (f (PS.insertHoles expon (x:xs)) ++ repeat zero)      (PS.insertHoles expon (f (x:xs)) ++ repeat zero)genInvertible :: QC.Gen [Rational]genInvertible =   liftA3 (\x0 x1 xs -> x0:x1:xs)      QC.arbitrary (fmap QC.getNonZero QC.arbitrary) QC.arbitrary

Simple series manipulation

4 declarations
valuealternate :: C a => [a] -> [a]
#

For the series of a real function f compute the series for x -> f (-x)

valueholes2 :: C a => [a] -> [a]
#

For the series of a real function f compute the series for x -> (f x + f (-x)) / 2

valueholes2alternate :: C a => [a] -> [a]
#

For the series of a real function f compute the real series for x -> (f (i*x) + f (-i*x)) / 2

valueinsertHoles :: C a => Int -> [a] -> [a]
#

For power series of f x, compute the power series of f(x^n).

Property
QC.choose (1,10) /\ \m -> QC.choose (1,10) /\ \n xs -> equalTrunc 100 (PS.insertHoles m $ PS.insertHoles n xs) (PS.insertHoles (m*n) xs)

Series arithmetic

30 declarations
valueadd :: C a => [a] -> [a] -> [a]
#
valuesub :: C a => [a] -> [a] -> [a]
#
valuescale :: C a => a -> [a] -> [a]
#
valuemul :: C a => [a] -> [a] -> [a]
#
valuedivMod :: (C a, C a) => [a] -> [a] -> ([a], [a])
#
valuedivide :: C a => [a] -> [a] -> [a]
#

Divide two series where the absolute term of the divisor is non-zero. That is, power series with leading non-zero terms are the units in the ring of power series.

Knuth: Seminumerical algorithms

valuedivideStripZero :: (C a, C a) => [a] -> [a] -> [a]
#

Divide two series also if the divisor has leading zeros.

valuesqrt :: C a => (a -> a) -> [a] -> [a]
#

We need to compute the square root only of the first term. That is, if the first term is rational, then all terms of the series are rational.

Property
equalTrunc 50 PSE.sqrtExpl (PS.sqrt (\1 -> 1) [1,1])
Property
equalTrunc 500 (1:1:repeat 0) (PS.sqrt (\1 -> 1) (PS.mul [1,1] [1,1]))
Property
checkHoles 50 (PS.sqrt (\1 -> 1)) 1
valuepow :: C a => (a -> a) -> a -> [a] -> [a]
#

Input series must start with a non-zero term, even better with a positive one.

Property
equalTrunc 100 (PSE.powExpl (-1/3)) (PS.pow (\1 -> 1) (-1/3) [1,1])
Property
equalTrunc 50 (PSE.powExpl (-1/3)) (PS.exp (\0 -> 1) (PS.scale (-1/3) PSE.log))
Property
checkHoles 30 (PS.pow (\1 -> 1) (1/3)) 1
Property
checkHoles 30 (PS.pow (\1 -> 1) (2/5)) 1
valueexp :: C a => (a -> a) -> [a] -> [a]
#

The first term needs a transcendent computation but the others do not. That's why we accept a function which computes the first term.

(exp . x)' =   (exp . x) * x'
(sin . x)' =   (cos . x) * x'
(cos . x)' = - (sin . x) * x'
Property
equalTrunc 500 PSE.expExpl (PS.exp (\0 -> 1) [0,1])
Property
equalTrunc 100 (1:1:repeat 0) (PS.exp (\0 -> 1) PSE.log)
Property
checkHoles 30 (PS.exp (\0 -> 1)) 0
valuesinCos :: C a => (a -> (a, a)) -> [a] -> ([a], [a])
#
valuesin :: C a => (a -> (a, a)) -> [a] -> [a]
#
Property
equalTrunc 500 PSE.sinExpl (PS.sin (\0 -> (0,1)) [0,1])
Property
equalTrunc 50 (0:1:repeat 0) (PS.sin (\0 -> (0,1)) PSE.asin)
Property
checkHoles 20 (PS.sin (\0 -> (0,1))) 0
valuecos :: C a => (a -> (a, a)) -> [a] -> [a]
#
Property
equalTrunc 500 PSE.cosExpl (PS.cos (\0 -> (0,1)) [0,1])
Property
checkHoles 20 (PS.cos (\0 -> (0,1))) 0
valuetan :: C a => (a -> (a, a)) -> [a] -> [a]
#
Property
equalTrunc 50 PSE.tanExpl (PS.tan (\0 -> (0,1)) [0,1])
Property
equalTrunc 50 (0:1:repeat 0) (PS.tan (\0 -> (0,1)) PSE.atan)
Property
checkHoles 20 (PS.tan (\0 -> (0,1))) 0
valuelog :: C a => (a -> a) -> [a] -> [a]
#

Input series must start with non-zero term.

Property
equalTrunc 500 PSE.logExpl (PS.log (\1 -> 0) [1,1])
Property
equalTrunc 100 (0:1:repeat 0) (PS.log (\1 -> 0) PSE.exp)
Property
checkHoles 30 (PS.log (\1 -> 0)) 1
valuederivedLog :: C a => [a] -> [a]
#

Computes (log x)', that is x'/x

valueatan :: C a => (a -> a) -> [a] -> [a]
#
Property
equalTrunc 500 PSE.atan (PS.atan (\0 -> 0) [0,1])
Property
equalTrunc 50 (0:1:repeat 0) (PS.atan (\0 -> 0) PSE.tan)
Property
checkHoles 20 (PS.atan (\0 -> 0)) 0
valueasin :: C a => (a -> a) -> (a -> a) -> [a] -> [a]
#
Property
equalTrunc 100 (0:1:repeat 0) (PS.asin (\1 -> 1) (\0 -> 0) PSE.sin)
Property
equalTrunc 50 PSE.asin (PS.asin (\1 -> 1) (\0 -> 0) [0,1])
Property
checkHoles 30 (PS.asin (\1 -> 1) (\0 -> 0)) 0
valueacos :: C a => (a -> a) -> (a -> a) -> [a] -> [a]
#

Would be a nice test, but we cannot compute exactly with pi:

equalTrunc 50 PSE.acos (PS.acos (\1 -> 1) (\0 -> pi/2) [0,1])
valuecompose :: C a => [a] -> [a] -> [a]
#

Since the inner series must start with a zero, the first term is omitted in y.

valuecomposeTaylor :: C a => (a -> [a]) -> [a] -> [a]
#

Compose two power series where the outer series can be developed for any expansion point. To be more precise: The outer series must be expanded with respect to the leading term of the inner series.

valueinv :: (Eq a, C a) => [a] -> (a, [a])
#

This function returns the series of the inverse function in the form: (point of the expansion, power series).

That is, say we have the equation:

y = a + f(x)

where function f is given by a power series with f(0) = 0. We want to solve for x:

x = f^-1(y-a)

If you pass the power series of a+f(x) to inv, you get (a, f^-1) as answer, where f^-1 is a power series.

The linear term of f (the coefficient of x) must be non-zero.

This needs cubic run-time and thus is exceptionally slow. Computing inverse series for special power series might be faster.

Property
genInvertible /\ \xs -> let (y,ys) = PS.inv xs; (z,zs) = PS.invDiff xs in y==z && equalTrunc 15 ys zs