module ForSyDe.Shallow.Utility.PolyArith(
Poly(..),
addPoly, mulPoly, divPoly, powerPoly,
getCoef, scalePoly, addPolyCoef, subPolyCoef, scalePolyCoef
)
where
data Poly a = Poly [a]
| PolyPair (Poly a, Poly a) deriving (Eq)
mulPoly :: Num a => Poly a -> Poly a -> Poly a
mulPoly (Poly []) _ = Poly []
mulPoly _ (Poly []) = Poly []
mulPoly (Poly xs) (Poly ys) = Poly $ foldr (\y zs ->
let (v:vs) = scalePolyCoef y xs in v :addPolyCoef vs zs) [] ys
mulPoly (PolyPair (a, b)) (PolyPair (c, d)) =
PolyPair (mulPoly a c, mulPoly b d)
mulPoly (PolyPair (a, b)) (Poly c) =
PolyPair (mulPoly a (Poly c), b)
mulPoly (Poly c) (PolyPair (a, b)) =
mulPoly (PolyPair (a, b)) (Poly c)
divPoly :: Num a => Poly a -> Poly a -> Poly a
divPoly (Poly a) (Poly b) = PolyPair (Poly a,Poly b)
divPoly (PolyPair (a, b)) (PolyPair (c, d)) =
mulPoly (PolyPair (a, b)) (PolyPair (d, c))
divPoly (PolyPair (a, b)) (Poly c) =
PolyPair (a, mulPoly b (Poly c))
divPoly (Poly c) (PolyPair (a, b)) =
PolyPair (mulPoly b (Poly c), a)
addPoly :: (Num a, Eq a) => Poly a -> Poly a -> Poly a
addPoly (Poly a) (Poly b) = Poly $ addPolyCoef a b
addPoly (PolyPair (a, b)) (PolyPair (c, d)) =
if b==d then
PolyPair (addPoly a c, d)
else
PolyPair (dividedPoly, divisorPoly)
where
divisorPoly = if b ==d then b else mulPoly b d
dividedPoly = if b == d then addPoly a c
else addPoly (mulPoly a d) (mulPoly b c)
addPoly (Poly a) (PolyPair (c, d) ) =
addPoly (PolyPair (multiPolyHelper, d)) (PolyPair (c,d) )
where
multiPolyHelper = mulPoly (Poly a) d
addPoly abPoly@(PolyPair _) cPoly@(Poly _) = addPoly cPoly abPoly
powerPoly :: Num a => Poly a -> Int -> Poly a
powerPoly p n = powerX' (Poly [1]) p n
where
powerX' :: Num a => Poly a -> Poly a -> Int -> Poly a
powerX' p' _ 0 = p'
powerX' p' p n = powerX' (mulPoly p' p) p (n-1)
getCoef :: Num a => Poly a -> ([a],[a])
getCoef (Poly xs) = (xs,[1])
getCoef (PolyPair (Poly xs,Poly ys)) = (xs,ys)
getCoef _ = error "getCoef: Nested fractions found"
scalePoly :: (Num a) => a -> Poly a -> Poly a
scalePoly s p = mulPoly (Poly [s]) p
addPolyCoef :: Num a => [a] -> [a] -> [a]
addPolyCoef = zipWithExt (0,0) (+)
subPolyCoef :: RealFloat a => [a] -> [a] -> [a]
subPolyCoef = zipWithExt (0,0) (-)
scalePolyCoef :: (Num a) => a -> [a] -> [a]
scalePolyCoef s p = map (s*) p
zipWithExt :: (a,b) -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithExt _ _ [] [] = []
zipWithExt (x0,y0) f (x:xs) [] = f x y0 : (zipWithExt (x0,y0) f xs [])
zipWithExt (x0,y0) f [] (y:ys) = f x0 y : (zipWithExt (x0,y0) f [] ys)
zipWithExt (x0,y0) f (x:xs) (y:ys) = f x y : (zipWithExt (x0,y0) f xs ys)