{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PatternSynonyms #-}
module Data.Poly.Semiring
( Poly
, VPoly
, UPoly
, unPoly
, leading
, toPoly
, monomial
, scale
, pattern X
, eval
, subst
, deriv
, integral
, denseToSparse
, sparseToDense
, dft
, inverseDft
, dftMult
) where
import Data.Bits
import Data.Euclidean (Field)
import Data.Semiring (Semiring(..))
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed.Sized as SU
import qualified Data.Poly.Internal.Convert as Convert
import Data.Poly.Internal.Dense (Poly(..), VPoly, UPoly, leading)
import qualified Data.Poly.Internal.Dense as Dense
import Data.Poly.Internal.Dense.Field ()
import Data.Poly.Internal.Dense.DFT
import Data.Poly.Internal.Dense.GcdDomain ()
import qualified Data.Poly.Internal.Multi as Sparse
toPoly :: (Eq a, Semiring a, G.Vector v a) => v a -> Poly v a
toPoly = Dense.toPoly'
monomial :: (Eq a, Semiring a, G.Vector v a) => Word -> a -> Poly v a
monomial = Dense.monomial'
scale :: (Eq a, Semiring a, G.Vector v a) => Word -> a -> Poly v a -> Poly v a
scale = Dense.scale'
pattern X :: (Eq a, Semiring a, G.Vector v a) => Poly v a
pattern X = Dense.X'
eval :: (Semiring a, G.Vector v a) => Poly v a -> a -> a
eval = Dense.eval'
subst :: (Eq a, Semiring a, G.Vector v a, G.Vector w a) => Poly v a -> Poly w a -> Poly w a
subst = Dense.subst'
deriv :: (Eq a, Semiring a, G.Vector v a) => Poly v a -> Poly v a
deriv = Dense.deriv'
integral :: (Eq a, Field a, G.Vector v a) => Poly v a -> Poly v a
integral = Dense.integral'
dftMult
:: (Eq a, Field a, G.Vector v a)
=> (Int -> a)
-> Poly v a
-> Poly v a
-> Poly v a
dftMult getPrimRoot (Poly xs) (Poly ys) =
toPoly $ inverseDft primRoot $ G.zipWith times (dft primRoot xs') (dft primRoot ys')
where
nextPowerOf2 :: Int -> Int
nextPowerOf2 0 = 1
nextPowerOf2 1 = 1
nextPowerOf2 x = 1 `unsafeShiftL` (finiteBitSize (0 :: Int) - countLeadingZeros (x - 1))
padTo l vs = G.generate l (\k -> if k < G.length vs then vs G.! k else zero)
zl = nextPowerOf2 (G.length xs + G.length ys)
xs' = padTo zl xs
ys' = padTo zl ys
primRoot = getPrimRoot zl
denseToSparse :: (Eq a, Semiring a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a)) => Dense.Poly v a -> Sparse.Poly v a
denseToSparse = Convert.denseToSparse'
sparseToDense :: (Semiring a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a)) => Sparse.Poly v a -> Dense.Poly v a
sparseToDense = Convert.sparseToDense'