{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Numeric.Polynomial.Simple
(
Poly
, eval
, degree
, constant
, zero
, monomial
, fromCoefficients
, toCoefficients
, scale
, scaleX
, display
, lineFromTo
, translate
, integrate
, differentiate
, euclidianDivision
, convolve
, compareToZero
, countRoots
, isMonotonicallyIncreasingOn
, root
, squareFreeFactorisation
) where
import Control.DeepSeq
( NFData
, NFData1
)
import GHC.Generics
( Generic
, Generic1
)
import Math.Combinatorics.Exact.Binomial
( choose
)
import qualified Data.Function.Class as Fun
newtype Poly a = Poly [a]
deriving (Int -> Poly a -> ShowS
[Poly a] -> ShowS
Poly a -> String
(Int -> Poly a -> ShowS)
-> (Poly a -> String) -> ([Poly a] -> ShowS) -> Show (Poly a)
forall a. Show a => Int -> Poly a -> ShowS
forall a. Show a => [Poly a] -> ShowS
forall a. Show a => Poly a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Poly a -> ShowS
showsPrec :: Int -> Poly a -> ShowS
$cshow :: forall a. Show a => Poly a -> String
show :: Poly a -> String
$cshowList :: forall a. Show a => [Poly a] -> ShowS
showList :: [Poly a] -> ShowS
Show, (forall x. Poly a -> Rep (Poly a) x)
-> (forall x. Rep (Poly a) x -> Poly a) -> Generic (Poly a)
forall x. Rep (Poly a) x -> Poly a
forall x. Poly a -> Rep (Poly a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Poly a) x -> Poly a
forall a x. Poly a -> Rep (Poly a) x
$cfrom :: forall a x. Poly a -> Rep (Poly a) x
from :: forall x. Poly a -> Rep (Poly a) x
$cto :: forall a x. Rep (Poly a) x -> Poly a
to :: forall x. Rep (Poly a) x -> Poly a
Generic, (forall a. Poly a -> Rep1 Poly a)
-> (forall a. Rep1 Poly a -> Poly a) -> Generic1 Poly
forall a. Rep1 Poly a -> Poly a
forall a. Poly a -> Rep1 Poly a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cfrom1 :: forall a. Poly a -> Rep1 Poly a
from1 :: forall a. Poly a -> Rep1 Poly a
$cto1 :: forall a. Rep1 Poly a -> Poly a
to1 :: forall a. Rep1 Poly a -> Poly a
Generic1)
instance NFData a => NFData (Poly a)
instance NFData1 Poly
instance (Eq a, Num a) => Eq (Poly a) where
Poly a
x == :: Poly a -> Poly a -> Bool
== Poly a
y =
Poly a -> [a]
forall a. Poly a -> [a]
toCoefficients (Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly Poly a
x) [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a -> [a]
forall a. Poly a -> [a]
toCoefficients (Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly Poly a
y)
constant :: a -> Poly a
constant :: forall a. a -> Poly a
constant a
x = [a] -> Poly a
forall a. [a] -> Poly a
Poly [a
x]
zero :: Num a => Poly a
zero :: forall a. Num a => Poly a
zero = a -> Poly a
forall a. a -> Poly a
constant a
0
degree :: (Eq a, Num a) => Poly a -> Int
degree :: forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
x = case Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly Poly a
x of
Poly [a
0] -> -Int
1
Poly [a]
xs -> [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
trimPoly :: (Eq a, Num a) => Poly a -> Poly a
trimPoly :: forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly (Poly [a]
as) = [a] -> Poly a
forall a. [a] -> Poly a
Poly ([a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall {a}. (Eq a, Num a) => [a] -> [a]
goTrim ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall a. [a] -> [a]
reverse [a]
as)
where
goTrim :: [a] -> [a]
goTrim [] = String -> [a]
forall a. HasCallStack => String -> a
error String
"Empty polynomial"
goTrim xss :: [a]
xss@[a
_] = [a]
xss
goTrim xss :: [a]
xss@(a
x : [a]
xs) = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then [a] -> [a]
goTrim [a]
xs else [a]
xss
monomial :: (Eq a, Num a) => Int -> a -> Poly a
monomial :: forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial Int
n a
x = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then Poly a
forall a. Num a => Poly a
zero else [a] -> Poly a
forall a. [a] -> Poly a
Poly ([a] -> [a]
forall a. [a] -> [a]
reverse (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Int -> a -> [a]
forall a. Int -> a -> [a]
replicate Int
n a
0))
fromCoefficients :: (Eq a, Num a) => [a] -> Poly a
fromCoefficients :: forall a. (Eq a, Num a) => [a] -> Poly a
fromCoefficients [] = Poly a
forall a. Num a => Poly a
zero
fromCoefficients [a]
as = Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly (Poly a -> Poly a) -> Poly a -> Poly a
forall a b. (a -> b) -> a -> b
$ [a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
as
toCoefficients :: Poly a -> [a]
toCoefficients :: forall a. Poly a -> [a]
toCoefficients (Poly [a]
as) = [a]
as
scaleX :: (Eq a, Num a) => Poly a -> Poly a
scaleX :: forall a. (Eq a, Num a) => Poly a -> Poly a
scaleX (Poly [a]
xs)
| [a]
xs [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== [a
0] = [a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
xs
| Bool
otherwise = [a] -> Poly a
forall a. [a] -> Poly a
Poly (a
0 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs)
scale :: Num a => a -> Poly a -> Poly a
scale :: forall a. Num a => a -> Poly a -> Poly a
scale a
x (Poly [a]
xs) = [a] -> Poly a
forall a. [a] -> Poly a
Poly ((a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Num a => a -> a -> a
* a
x) [a]
xs)
addPolys :: (Eq a, Num a) => Poly a -> Poly a -> Poly a
addPolys :: forall a. (Eq a, Num a) => Poly a -> Poly a -> Poly a
addPolys (Poly [a]
as) (Poly [a]
bs) = Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly ([a] -> Poly a
forall a. [a] -> Poly a
Poly ([a] -> [a] -> [a]
forall {a}. Num a => [a] -> [a] -> [a]
go [a]
as [a]
bs))
where
go :: [a] -> [a] -> [a]
go [] [a]
ys = [a]
ys
go [a]
xs [] = [a]
xs
go (a
x : [a]
xs) (a
y : [a]
ys) = (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
y) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a] -> [a]
go [a]
xs [a]
ys
mulPolys :: (Eq a, Num a) => Poly a -> Poly a -> Poly a
mulPolys :: forall a. (Eq a, Num a) => Poly a -> Poly a -> Poly a
mulPolys Poly a
as Poly a
bs = [Poly a] -> Poly a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (Poly a -> Poly a -> [Poly a]
forall a. (Eq a, Num a) => Poly a -> Poly a -> [Poly a]
intermediateSums Poly a
as Poly a
bs)
where
intermediateSums :: (Eq a, Num a) => Poly a -> Poly a -> [Poly a]
intermediateSums :: forall a. (Eq a, Num a) => Poly a -> Poly a -> [Poly a]
intermediateSums Poly a
_ (Poly []) = String -> [Poly a]
forall a. HasCallStack => String -> a
error String
"Second polynomial was empty"
intermediateSums (Poly []) Poly a
_ = []
intermediateSums (Poly (a
x : [a]
xs)) Poly a
ys =
a -> Poly a -> Poly a
forall a. Num a => a -> Poly a -> Poly a
scale a
x Poly a
ys Poly a -> [Poly a] -> [Poly a]
forall a. a -> [a] -> [a]
: Poly a -> Poly a -> [Poly a]
forall a. (Eq a, Num a) => Poly a -> Poly a -> [Poly a]
intermediateSums ([a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
xs) (Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
scaleX Poly a
ys)
instance (Eq a, Num a) => Num (Poly a) where
+ :: Poly a -> Poly a -> Poly a
(+) = Poly a -> Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a -> Poly a
addPolys
* :: Poly a -> Poly a -> Poly a
(*) = Poly a -> Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a -> Poly a
mulPolys
negate :: Poly a -> Poly a
negate (Poly [a]
a) = [a] -> Poly a
forall a. [a] -> Poly a
Poly ((a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map a -> a
forall a. Num a => a -> a
negate [a]
a)
abs :: Poly a -> Poly a
abs = Poly a -> Poly a
forall a. HasCallStack => a
undefined
signum :: Poly a -> Poly a
signum = Poly a -> Poly a
forall a. HasCallStack => a
undefined
fromInteger :: Integer -> Poly a
fromInteger Integer
n = [a] -> Poly a
forall a. [a] -> Poly a
Poly [Integer -> a
forall a. Num a => Integer -> a
Prelude.fromInteger Integer
n]
instance Num a => Fun.Function (Poly a) where
type Domain (Poly a) = a
type Codomain (Poly a) = a
eval :: Poly a -> Domain (Poly a) -> Codomain (Poly a)
eval = Poly a -> a -> a
Poly a -> Domain (Poly a) -> Codomain (Poly a)
forall a. Num a => Poly a -> a -> a
eval
eval :: Num a => Poly a -> a -> a
eval :: forall a. Num a => Poly a -> a -> a
eval (Poly [a]
as) a
x = (a -> a -> a) -> a -> [a] -> a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
ai a
result -> a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
result a -> a -> a
forall a. Num a => a -> a -> a
+ a
ai) a
0 [a]
as
display :: (Ord a, Eq a, Num a) => Poly a -> (a, a) -> a -> [(a, a)]
display :: forall a. (Ord a, Eq a, Num a) => Poly a -> (a, a) -> a -> [(a, a)]
display Poly a
p (a
l, a
u) a
s
| a
s a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = (a -> (a, a)) -> [a] -> [(a, a)]
forall a b. (a -> b) -> [a] -> [b]
map a -> (a, a)
evalPoint [a
l, a
u]
| Bool
otherwise = (a -> (a, a)) -> [a] -> [(a, a)]
forall a b. (a -> b) -> [a] -> [b]
map a -> (a, a)
evalPoint (a
l a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a -> [a]
go (a
l a -> a -> a
forall a. Num a => a -> a -> a
+ a
s))
where
evalPoint :: a -> (a, a)
evalPoint a
x = (a
x, Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
x)
go :: a -> [a]
go a
x
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
u = [a
u]
| Bool
otherwise = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a -> [a]
go (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
s)
lineFromTo :: (Eq a, Fractional a) => (a, a) -> (a, a) -> Poly a
lineFromTo :: forall a. (Eq a, Fractional a) => (a, a) -> (a, a) -> Poly a
lineFromTo (a
x1, a
y1) (a
x2, a
y2)
| a
x1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x2 = a -> Poly a
forall a. a -> Poly a
constant a
y1
| a
slope a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Poly a
forall a. a -> Poly a
constant a
y1
| Bool
otherwise = [a] -> Poly a
forall a. (Eq a, Num a) => [a] -> Poly a
fromCoefficients [a
shift, a
slope]
where
slope :: a
slope = (a
y2 a -> a -> a
forall a. Num a => a -> a -> a
- a
y1) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
x2 a -> a -> a
forall a. Num a => a -> a -> a
- a
x1)
shift :: a
shift = a
y1 a -> a -> a
forall a. Num a => a -> a -> a
- a
x1 a -> a -> a
forall a. Num a => a -> a -> a
* a
slope
integrate :: (Eq a, Fractional a) => Poly a -> Poly a
integrate :: forall a. (Eq a, Fractional a) => Poly a -> Poly a
integrate (Poly [a]
as) =
Poly a -> Poly a
forall a. (Eq a, Num a) => Poly a -> Poly a
trimPoly ([a] -> Poly a
forall a. [a] -> Poly a
Poly (a
0 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: (a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> a
forall a. Fractional a => a -> a -> a
(/) [a]
as ((a -> a) -> a -> [a]
forall a. (a -> a) -> a -> [a]
iterate (a -> a -> a
forall a. Num a => a -> a -> a
+ a
1) a
1)))
differentiate :: Num a => Poly a -> Poly a
differentiate :: forall a. Num a => Poly a -> Poly a
differentiate (Poly []) = String -> Poly a
forall a. HasCallStack => String -> a
error String
"Polynomial was empty"
differentiate (Poly [a
_]) = Poly a
forall a. Num a => Poly a
zero
differentiate (Poly (a
_ : [a]
as)) =
[a] -> Poly a
forall a. [a] -> Poly a
Poly ((a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> a
forall a. Num a => a -> a -> a
(*) [a]
as ((a -> a) -> a -> [a]
forall a. (a -> a) -> a -> [a]
iterate (a -> a -> a
forall a. Num a => a -> a -> a
+ a
1) a
1))
convolve
:: (Fractional a, Eq a, Ord a) => (a, a, Poly a) -> (a, a, Poly a) -> [(a, Poly a)]
convolve :: forall a.
(Fractional a, Eq a, Ord a) =>
(a, a, Poly a) -> (a, a, Poly a) -> [(a, Poly a)]
convolve (a
lf, a
uf, Poly [a]
fs) (a
lg, a
ug, Poly [a]
gs)
| (a
lf a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0) Bool -> Bool -> Bool
|| (a
lg a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0) = String -> [(a, Poly a)]
forall a. HasCallStack => String -> a
error String
"Interval bounds cannot be negative"
| (a
lf a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
uf) Bool -> Bool -> Bool
|| (a
lg a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
ug) = String -> [(a, Poly a)]
forall a. HasCallStack => String -> a
error String
"Invalid interval"
| (a
ug a -> a -> a
forall a. Num a => a -> a -> a
- a
lg) a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> (a
uf a -> a -> a
forall a. Num a => a -> a -> a
- a
lf) = (a, a, Poly a) -> (a, a, Poly a) -> [(a, Poly a)]
forall a.
(Fractional a, Eq a, Ord a) =>
(a, a, Poly a) -> (a, a, Poly a) -> [(a, Poly a)]
convolve (a
lg, a
ug, [a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
gs) (a
lf, a
uf, [a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
fs)
| Bool
otherwise
=
let
sumSeries :: t -> (t -> a) -> (t -> Poly a) -> Poly a
sumSeries t
k t -> a
mulFactor t -> Poly a
poly = [Poly a] -> Poly a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [t -> a
mulFactor t
n a -> Poly a -> Poly a
forall a. Num a => a -> Poly a -> Poly a
`scale` t -> Poly a
poly t
n | t
n <- [t
0 .. t
k]]
innerSum :: Int -> Int -> (Int -> a) -> Int -> Poly a
innerSum Int
m Int
n Int -> a
term Int
k = Int -> (Int -> a) -> (Int -> Poly a) -> Poly a
forall {a} {t}.
(Eq a, Num a, Num t, Enum t) =>
t -> (t -> a) -> (t -> Poly a) -> Poly a
sumSeries (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> a
innerMult (\Int
j -> Int -> a -> Poly a
forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
j) (Int -> a
term Int
j))
where
innerMult :: Int -> a
innerMult Int
j =
Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral
(if Int -> Bool
forall a. Integral a => a -> Bool
even Int
j then (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`choose` Int
j else Int -> Int
forall a. Num a => a -> a
negate ((Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`choose` Int
j))
convolveMonomials :: t -> t -> (t -> t -> t -> Poly a) -> Poly a
convolveMonomials t
m t
n t -> t -> t -> Poly a
innerTerm = t -> (t -> a) -> (t -> Poly a) -> Poly a
forall {a} {t}.
(Eq a, Num a, Num t, Enum t) =>
t -> (t -> a) -> (t -> Poly a) -> Poly a
sumSeries t
n (t -> t -> t -> a
forall {a} {a}. (Fractional a, Integral a) => a -> a -> a -> a
multiplier t
m t
n) (t -> t -> t -> Poly a
innerTerm t
m t
n)
where
multiplier :: a -> a -> a -> a
multiplier a
p a
q a
k =
a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (if a -> Bool
forall a. Integral a => a -> Bool
even a
k then a
q a -> a -> a
forall a. Integral a => a -> a -> a
`choose` a
k else a -> a
forall a. Num a => a -> a
negate (a
q a -> a -> a
forall a. Integral a => a -> a -> a
`choose` a
k))
a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
p a -> a -> a
forall a. Num a => a -> a -> a
+ a
k a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)
makeTerm :: (Int -> Int -> Int -> Poly a) -> Poly a
makeTerm Int -> Int -> Int -> Poly a
f =
[Poly a] -> Poly a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum
[ (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b) a -> Poly a -> Poly a
forall a. Num a => a -> Poly a -> Poly a
`scale` Int -> Int -> (Int -> Int -> Int -> Poly a) -> Poly a
forall {a} {t}.
(Fractional a, Integral t, Eq a) =>
t -> t -> (t -> t -> t -> Poly a) -> Poly a
convolveMonomials Int
m Int
n Int -> Int -> Int -> Poly a
f
| (Int
m, a
a) <- [Int] -> [a] -> [(Int, a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 ..] [a]
fs
, (Int
n, a
b) <- [Int] -> [a] -> [(Int, a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 ..] [a]
gs
]
firstTerm :: Poly a
firstTerm =
(Int -> Int -> Int -> Poly a) -> Poly a
makeTerm (\Int
m Int
n Int
k -> Int -> Int -> (Int -> a) -> Int -> Poly a
forall {a}.
(Eq a, Num a) =>
Int -> Int -> (Int -> a) -> Int -> Poly a
innerSum Int
m Int
n (a
lg a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^) Int
k Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- Int -> a -> Poly a
forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) (a
lf a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)))
secondTerm :: Poly a
secondTerm = (Int -> Int -> Int -> Poly a) -> Poly a
makeTerm (\Int
m Int
n -> Int -> Int -> (Int -> a) -> Int -> Poly a
forall {a}.
(Eq a, Num a) =>
Int -> Int -> (Int -> a) -> Int -> Poly a
innerSum Int
m Int
n (\Int
k -> a
lg a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
k a -> a -> a
forall a. Num a => a -> a -> a
- a
ug a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
k))
thirdTerm :: Poly a
thirdTerm =
(Int -> Int -> Int -> Poly a) -> Poly a
makeTerm (\Int
m Int
n Int
k -> Int -> a -> Poly a
forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) (a
uf a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- Int -> Int -> (Int -> a) -> Int -> Poly a
forall {a}.
(Eq a, Num a) =>
Int -> Int -> (Int -> a) -> Int -> Poly a
innerSum Int
m Int
n (a
ug a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^) Int
k)
in
if a
lf a -> a -> a
forall a. Num a => a -> a -> a
+ a
ug a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
uf a -> a -> a
forall a. Num a => a -> a -> a
+ a
lg
then [(a
lf a -> a -> a
forall a. Num a => a -> a -> a
+ a
lg, Poly a
firstTerm), (a
uf a -> a -> a
forall a. Num a => a -> a -> a
+ a
lg, Poly a
thirdTerm), (a
uf a -> a -> a
forall a. Num a => a -> a -> a
+ a
ug, Poly a
forall a. Num a => Poly a
zero)]
else
[ (a
lf a -> a -> a
forall a. Num a => a -> a -> a
+ a
lg, Poly a
firstTerm)
, (a
lf a -> a -> a
forall a. Num a => a -> a -> a
+ a
ug, Poly a
secondTerm)
, (a
uf a -> a -> a
forall a. Num a => a -> a -> a
+ a
lg, Poly a
thirdTerm)
, (a
uf a -> a -> a
forall a. Num a => a -> a -> a
+ a
ug, Poly a
forall a. Num a => Poly a
zero)
]
translate :: forall a. (Fractional a, Eq a, Num a) => a -> Poly a -> Poly a
translate :: forall a. (Fractional a, Eq a, Num a) => a -> Poly a -> Poly a
translate a
y (Poly [a]
ps) =
[Poly a] -> Poly a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum
[ a
b a -> Poly a -> Poly a
forall a. Num a => a -> Poly a -> Poly a
`scale` Integer -> Poly a
binomialExpansion Integer
n
| (Integer
n, a
b) <- [Integer] -> [a] -> [(Integer, a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Integer
0 ..] [a]
ps
]
where
binomialTerm :: Integer -> Integer -> a
binomialTerm :: Integer -> Integer -> a
binomialTerm Integer
n Integer
k = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer
n Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`choose` Integer
k) a -> a -> a
forall a. Num a => a -> a -> a
* (-a
y) a -> Integer -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
k)
binomialExpansion :: Integer -> Poly a
binomialExpansion :: Integer -> Poly a
binomialExpansion Integer
n = [a] -> Poly a
forall a. [a] -> Poly a
Poly ((Integer -> a) -> [Integer] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Integer -> Integer -> a
binomialTerm Integer
n) [Integer
0 .. Integer
n])
euclidianDivision
:: forall a. (Fractional a, Eq a, Ord a)
=> Poly a -> Poly a -> (Poly a, Poly a)
euclidianDivision :: forall a.
(Fractional a, Eq a, Ord a) =>
Poly a -> Poly a -> (Poly a, Poly a)
euclidianDivision Poly a
pa Poly a
pb
| Poly a
pb Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a
forall a. Num a => Poly a
zero = String -> (Poly a, Poly a)
forall a. HasCallStack => String -> a
error String
"Division by zero polynomial"
| Bool
otherwise = (Poly a, Poly a) -> (Poly a, Poly a)
goDivide (Poly a
forall a. Num a => Poly a
zero, Poly a
pa)
where
degB :: Int
degB = Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
pb
leadingCoefficient :: Poly a -> a
leadingCoefficient :: Poly a -> a
leadingCoefficient (Poly [a]
x) = [a] -> a
forall a. HasCallStack => [a] -> a
last [a]
x
lcB :: a
lcB = Poly a -> a
leadingCoefficient Poly a
pb
goDivide :: (Poly a, Poly a) -> (Poly a, Poly a)
goDivide :: (Poly a, Poly a) -> (Poly a, Poly a)
goDivide (Poly a
q, Poly a
r)
| Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
degB = (Poly a
q, Poly a
r)
| Bool
otherwise = (Poly a, Poly a) -> (Poly a, Poly a)
goDivide (Poly a
q Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
+ Poly a
s, Poly a
r Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- Poly a
s Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
* Poly a
pb)
where
s :: Poly a
s = Int -> a -> Poly a
forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial (Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
degB) (Poly a -> a
leadingCoefficient Poly a
r a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
lcB)
countRoots :: (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots :: forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
l, a
r, Poly a
p) =
Poly a -> Int
countRoots' (Poly a -> Int) -> Poly a -> Int
forall a b. (a -> b) -> a -> b
$ (Poly a
p Poly a -> a -> Poly a
forall a. (Fractional a, Ord a) => Poly a -> a -> Poly a
`factorOutRoot` a
l) Poly a -> a -> Poly a
forall a. (Fractional a, Ord a) => Poly a -> a -> Poly a
`factorOutRoot` a
r
where
countRoots' :: Poly a -> Int
countRoots' Poly a
q = case Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
q of
-1 -> Int
0
Int
0 -> Int
0
Int
1 -> if Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
q a
l a -> a -> a
forall a. Num a => a -> a -> a
* Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
q a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 then Int
1 else Int
0
Int
_ -> (a, a, Poly a) -> Int
forall a. (Fractional a, Eq a, Ord a) => (a, a, Poly a) -> Int
countRootsSturm (a
l, a
r, Poly a
q)
factorOutRoot :: (Fractional a, Ord a) => Poly a -> a -> Poly a
factorOutRoot :: forall a. (Fractional a, Ord a) => Poly a -> a -> Poly a
factorOutRoot Poly a
p0 a
x0
| Poly a
p0 Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a
forall a. Num a => Poly a
zero = Poly a
forall a. Num a => Poly a
zero
| Bool
otherwise = Poly a -> Poly a
go Poly a
p0
where
go :: Poly a -> Poly a
go Poly a
p
| Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
x0 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Poly a -> a -> Poly a
forall a. (Fractional a, Ord a) => Poly a -> a -> Poly a
factorOutRoot Poly a
pDividedByXMinusX0 a
x0
| Bool
otherwise = Poly a
p
where
xMinusX0 :: Poly a
xMinusX0 = Int -> a -> Poly a
forall a. (Eq a, Num a) => Int -> a -> Poly a
monomial Int
1 a
1 Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- a -> Poly a
forall a. a -> Poly a
constant a
x0
(Poly a
pDividedByXMinusX0, Poly a
_) = Poly a
p Poly a -> Poly a -> (Poly a, Poly a)
forall a.
(Fractional a, Eq a, Ord a) =>
Poly a -> Poly a -> (Poly a, Poly a)
`euclidianDivision` Poly a
xMinusX0
countRootsSturm :: (Fractional a, Eq a, Ord a) => (a, a, Poly a) -> Int
countRootsSturm :: forall a. (Fractional a, Eq a, Ord a) => (a, a, Poly a) -> Int
countRootsSturm (a
l, a
r, Poly a
p) =
[a] -> Int
forall a. (Fractional a, Ord a) => [a] -> Int
signVariations [a]
psl Int -> Int -> Int
forall a. Num a => a -> a -> a
- [a] -> Int
forall a. (Fractional a, Ord a) => [a] -> Int
signVariations [a]
psr
where
ps :: [Poly a]
ps = Poly a -> [Poly a]
forall a. (Fractional a, Ord a) => Poly a -> [Poly a]
reversedSturmSequence Poly a
p
psl :: [a]
psl = (Poly a -> a) -> [Poly a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map ((Poly a -> a -> a) -> a -> Poly a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval a
l) [Poly a]
ps
psr :: [a]
psr = (Poly a -> a) -> [Poly a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map ((Poly a -> a -> a) -> a -> Poly a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval a
r) [Poly a]
ps
signVariations :: (Fractional a, Ord a) => [a] -> Int
signVariations :: forall a. (Fractional a, Ord a) => [a] -> Int
signVariations [a]
xs =
[a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0) [a]
pairsMultiplied)
where
zeroesRemoved :: [a]
zeroesRemoved = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0) [a]
xs
pairsMultiplied :: [a]
pairsMultiplied = (a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> a
forall a. Num a => a -> a -> a
(*) [a]
zeroesRemoved (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
1 [a]
zeroesRemoved)
reversedSturmSequence :: (Fractional a, Ord a) => Poly a -> [Poly a]
reversedSturmSequence :: forall a. (Fractional a, Ord a) => Poly a -> [Poly a]
reversedSturmSequence Poly a
p =
[Poly a] -> [Poly a]
forall {a}. (Fractional a, Ord a) => [Poly a] -> [Poly a]
go [Poly a -> Poly a
forall a. Num a => Poly a -> Poly a
differentiate Poly a
p, Poly a
p]
where
go :: [Poly a] -> [Poly a]
go ps :: [Poly a]
ps@(Poly a
pI : Poly a
pIminusOne : [Poly a]
_)
| Poly a
remainder Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a
forall a. Num a => Poly a
zero = [Poly a]
ps
| Bool
otherwise = [Poly a] -> [Poly a]
go (Poly a -> Poly a
forall a. Num a => a -> a
negate Poly a
remainder Poly a -> [Poly a] -> [Poly a]
forall a. a -> [a] -> [a]
: [Poly a]
ps)
where
remainder :: Poly a
remainder = (Poly a, Poly a) -> Poly a
forall a b. (a, b) -> b
snd ((Poly a, Poly a) -> Poly a) -> (Poly a, Poly a) -> Poly a
forall a b. (a -> b) -> a -> b
$ Poly a -> Poly a -> (Poly a, Poly a)
forall a.
(Fractional a, Eq a, Ord a) =>
Poly a -> Poly a -> (Poly a, Poly a)
euclidianDivision Poly a
pIminusOne Poly a
pI
go [Poly a]
_ = String -> [Poly a]
forall a. HasCallStack => String -> a
error String
"reversedSturmSequence: impossible"
isMonotonicallyIncreasingOn
:: (Fractional a, Eq a, Ord a) => Poly a -> (a, a) -> Bool
isMonotonicallyIncreasingOn :: forall a. (Fractional a, Eq a, Ord a) => Poly a -> (a, a) -> Bool
isMonotonicallyIncreasingOn Poly a
p (a
x1, a
x2) =
Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
x1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
x2
Bool -> Bool -> Bool
&& (a, a, Poly a) -> Int
forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
x1, a
x2, Poly a -> Poly a
forall a. Num a => Poly a -> Poly a
differentiate Poly a
p) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
compareToZero :: (Fractional a, Eq a, Ord a) => (a, a, Poly a) -> Maybe Ordering
compareToZero :: forall a.
(Fractional a, Eq a, Ord a) =>
(a, a, Poly a) -> Maybe Ordering
compareToZero (a
l, a
u, Poly a
p)
| a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
u = String -> Maybe Ordering
forall a. HasCallStack => String -> a
error String
"Invalid interval"
| Poly a
p Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a
forall a. Num a => Poly a
zero = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
EQ
| a
lower a -> a -> a
forall a. Num a => a -> a -> a
* a
upper a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = Maybe Ordering
forall a. Maybe a
Nothing
| (a, a, Poly a) -> Int
forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
l, a
u, Poly a
p) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Maybe Ordering
forall a. Maybe a
Nothing
| a
lower a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just (a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
upper a
lower)
| a
upper a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just (a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
lower a
upper)
| a
lower a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
GT
| Bool
otherwise = Ordering -> Maybe Ordering
forall a. a -> Maybe a
Just Ordering
LT
where
lower :: a
lower = Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
l
upper :: a
upper = Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
u
findRoot
:: forall a. (Fractional a, Eq a, Num a, Ord a) => a -> (a, a) -> Poly a -> Maybe a
findRoot :: forall a.
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> Poly a -> Maybe a
findRoot a
precision (a
lower, a
upper) Poly a
poly =
if [Poly a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Poly a]
rootFactors
then Maybe a
forall a. Maybe a
Nothing
else a -> (a, a) -> Poly a -> Maybe a
getRoot a
precision (a
lower, a
upper) ([Poly a] -> Poly a
forall a. HasCallStack => [a] -> a
head [Poly a]
rootFactors)
where
rootFactors :: [Poly a]
rootFactors =
(Poly a -> Bool) -> [Poly a] -> [Poly a]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Poly a
x -> (a, a, Poly a) -> Int
forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
lower, a
upper, Poly a
x) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) (Poly a -> [Poly a]
forall a. (Fractional a, Eq a, Num a, Ord a) => Poly a -> [Poly a]
squareFreeFactorisation Poly a
poly)
getRoot :: a -> (a, a) -> Poly a -> Maybe a
getRoot a
eps (a
l, a
u) Poly a
p
| Int
degp Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = a -> Maybe a
forall a. a -> Maybe a
Just a
l
| Int
degp Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Maybe a
forall a. Maybe a
Nothing
| Int
degp Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = a -> Maybe a
forall a. a -> Maybe a
Just (-([a] -> a
forall a. HasCallStack => [a] -> a
head [a]
ps a -> a -> a
forall a. Fractional a => a -> a -> a
/ [a] -> a
forall a. HasCallStack => [a] -> a
last [a]
ps))
| a
eps a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 = String -> Maybe a
forall a. HasCallStack => String -> a
error String
"Invalid precision value"
| Bool
otherwise = a -> (a, a) -> (a, a) -> Poly a -> Maybe a
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
eps (a
l, a
u) (Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
l, Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p a
u) Poly a
p
where
ps :: [a]
ps = Poly a -> [a]
forall a. Poly a -> [a]
toCoefficients Poly a
p
degp :: Int
degp = Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
p
bisect
:: (Fractional a, Eq a, Num a, Ord a) => a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect :: (Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
e (a
x, a
y) (a
px, a
py) Poly a
p'
| a
px a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Maybe a
forall a. a -> Maybe a
Just a
x
| a
py a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Maybe a
forall a. a -> Maybe a
Just a
y
| a
pmid a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Maybe a
forall a. a -> Maybe a
Just a
mid
| a
width a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
e = a -> Maybe a
forall a. a -> Maybe a
Just a
mid
| a -> a
forall a. Num a => a -> a
signum a
px a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a -> a
forall a. Num a => a -> a
signum a
pmid = a -> (a, a) -> (a, a) -> Poly a -> Maybe a
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
e (a
x, a
mid) (a
px, a
pmid) Poly a
p'
| a -> a
forall a. Num a => a -> a
signum a
py a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a -> a
forall a. Num a => a -> a
signum a
pmid = a -> (a, a) -> (a, a) -> Poly a -> Maybe a
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
e (a
mid, a
y) (a
pmid, a
py) Poly a
p'
| (a, a, Poly a) -> Int
forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
x, a
mid, Poly a
p') Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = a -> (a, a) -> (a, a) -> Poly a -> Maybe a
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
e (a
x, a
mid) (a
px, a
pmid) Poly a
p'
| (a, a, Poly a) -> Int
forall a. (Fractional a, Ord a) => (a, a, Poly a) -> Int
countRoots (a
mid, a
y, Poly a
p') Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = a -> (a, a) -> (a, a) -> Poly a -> Maybe a
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> (a, a) -> Poly a -> Maybe a
bisect a
e (a
mid, a
y) (a
pmid, a
py) Poly a
p'
| Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
where
width :: a
width = a
y a -> a -> a
forall a. Num a => a -> a -> a
- a
x
mid :: a
mid = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
width a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2
pmid :: a
pmid = Poly a -> a -> a
forall a. Num a => Poly a -> a -> a
eval Poly a
p' a
mid
root
:: (Ord a, Num a, Eq a, Fractional a)
=> a
-> a
-> (a, a)
-> Poly a
-> Maybe a
root :: forall a.
(Ord a, Num a, Eq a, Fractional a) =>
a -> a -> (a, a) -> Poly a -> Maybe a
root a
e a
x (a
l, a
u) Poly a
p = a -> (a, a) -> Poly a -> Maybe a
forall a.
(Fractional a, Eq a, Num a, Ord a) =>
a -> (a, a) -> Poly a -> Maybe a
findRoot a
e (a
l, a
u) (Poly a
p Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- a -> Poly a
forall a. a -> Poly a
constant a
x)
gcdPoly
:: forall a. (Fractional a, Eq a, Num a, Ord a) => Poly a -> Poly a -> Poly a
gcdPoly :: forall a.
(Fractional a, Eq a, Num a, Ord a) =>
Poly a -> Poly a -> Poly a
gcdPoly Poly a
a Poly a
b = if Poly a
b Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== Poly a
forall a. Num a => Poly a
zero then Poly a
a else Poly a -> Poly a
makeMonic (Poly a -> Poly a -> Poly a
forall a.
(Fractional a, Eq a, Num a, Ord a) =>
Poly a -> Poly a -> Poly a
gcdPoly Poly a
b (Poly a -> Poly a -> Poly a
polyRemainder Poly a
a Poly a
b))
where
makeMonic :: Poly a -> Poly a
makeMonic :: Poly a -> Poly a
makeMonic (Poly [a]
as) = a -> Poly a -> Poly a
forall a. Num a => a -> Poly a -> Poly a
scale (a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ [a] -> a
forall a. HasCallStack => [a] -> a
last [a]
as) ([a] -> Poly a
forall a. [a] -> Poly a
Poly [a]
as)
polyRemainder :: Poly a -> Poly a -> Poly a
polyRemainder :: Poly a -> Poly a -> Poly a
polyRemainder Poly a
x Poly a
y = (Poly a, Poly a) -> Poly a
forall a b. (a, b) -> b
snd (Poly a -> Poly a -> (Poly a, Poly a)
forall a.
(Fractional a, Eq a, Ord a) =>
Poly a -> Poly a -> (Poly a, Poly a)
euclidianDivision Poly a
x Poly a
y)
squareFreeFactorisation
:: (Fractional a, Eq a, Num a, Ord a) => Poly a -> [Poly a]
squareFreeFactorisation :: forall a. (Fractional a, Eq a, Num a, Ord a) => Poly a -> [Poly a]
squareFreeFactorisation Poly a
p =
if Poly a -> Int
forall a. (Eq a, Num a) => Poly a -> Int
degree Poly a
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 then [Poly a
p] else Poly a -> Poly a -> [Poly a]
forall {a}. (Fractional a, Ord a) => Poly a -> Poly a -> [Poly a]
go Poly a
c1 Poly a
d1
where
diffP :: Poly a
diffP = Poly a -> Poly a
forall a. Num a => Poly a -> Poly a
differentiate Poly a
p
g0 :: Poly a
g0 = Poly a -> Poly a -> Poly a
forall a.
(Fractional a, Eq a, Num a, Ord a) =>
Poly a -> Poly a -> Poly a
gcdPoly Poly a
p Poly a
diffP
c1 :: Poly a
c1 = Poly a
p Poly a -> Poly a -> Poly a
forall {a}. (Fractional a, Ord a) => Poly a -> Poly a -> Poly a
`divide` Poly a
g0
d1 :: Poly a
d1 = (Poly a
diffP Poly a -> Poly a -> Poly a
forall {a}. (Fractional a, Ord a) => Poly a -> Poly a -> Poly a
`divide` Poly a
g0) Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- Poly a -> Poly a
forall a. Num a => Poly a -> Poly a
differentiate Poly a
c1
divide :: Poly a -> Poly a -> Poly a
divide Poly a
x Poly a
y = (Poly a, Poly a) -> Poly a
forall a b. (a, b) -> a
fst (Poly a -> Poly a -> (Poly a, Poly a)
forall a.
(Fractional a, Eq a, Ord a) =>
Poly a -> Poly a -> (Poly a, Poly a)
euclidianDivision Poly a
x Poly a
y)
go :: Poly a -> Poly a -> [Poly a]
go Poly a
c Poly a
d
| Poly a
c Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Poly a
forall a. a -> Poly a
constant a
1 = []
| Poly a
a' Poly a -> Poly a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Poly a
forall a. a -> Poly a
constant a
1 = Poly a -> Poly a -> [Poly a]
go Poly a
c' Poly a
d'
| Bool
otherwise = Poly a
a' Poly a -> [Poly a] -> [Poly a]
forall a. a -> [a] -> [a]
: Poly a -> Poly a -> [Poly a]
go Poly a
c' Poly a
d'
where
a' :: Poly a
a' = Poly a -> Poly a -> Poly a
forall a.
(Fractional a, Eq a, Num a, Ord a) =>
Poly a -> Poly a -> Poly a
gcdPoly Poly a
c Poly a
d
c' :: Poly a
c' = Poly a
c Poly a -> Poly a -> Poly a
forall {a}. (Fractional a, Ord a) => Poly a -> Poly a -> Poly a
`divide` Poly a
a'
d' :: Poly a
d' = (Poly a
d Poly a -> Poly a -> Poly a
forall {a}. (Fractional a, Ord a) => Poly a -> Poly a -> Poly a
`divide` Poly a
a') Poly a -> Poly a -> Poly a
forall a. Num a => a -> a -> a
- Poly a -> Poly a
forall a. Num a => Poly a -> Poly a
differentiate Poly a
c'