{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
module Data.Poly.Internal.Convert
( denseToSparse
, denseToSparse'
, sparseToDense
, sparseToDense'
) where
import Control.Monad.ST
import Data.Semiring (Semiring(..))
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as MG
import qualified Data.Vector.Unboxed.Sized as SU
import qualified Data.Poly.Internal.Dense as Dense
import qualified Data.Poly.Internal.Multi as Sparse
denseToSparse
:: (Eq a, Num a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a))
=> Dense.Poly v a
-> Sparse.Poly v a
denseToSparse = denseToSparseInternal 0
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' = denseToSparseInternal zero
denseToSparseInternal
:: (Eq a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a))
=> a
-> Dense.Poly v a
-> Sparse.Poly v a
denseToSparseInternal z = Sparse.MultiPoly . G.imapMaybe (\i c -> if c == z then Nothing else Just (fromIntegral i, c)) . Dense.unPoly
sparseToDense
:: (Num a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a))
=> Sparse.Poly v a
-> Dense.Poly v a
sparseToDense = sparseToDenseInternal 0
sparseToDense'
:: (Semiring a, G.Vector v a, G.Vector v (SU.Vector 1 Word, a))
=> Sparse.Poly v a
-> Dense.Poly v a
sparseToDense' = sparseToDenseInternal zero
sparseToDenseInternal
:: (G.Vector v a, G.Vector v (SU.Vector 1 Word, a))
=> a
-> Sparse.Poly v a
-> Dense.Poly v a
sparseToDenseInternal z (Sparse.MultiPoly xs)
| G.null xs = Dense.Poly G.empty
| otherwise = runST $ do
let len = fromIntegral (SU.head (fst (G.unsafeLast xs)) + 1)
ys <- MG.unsafeNew len
MG.set ys z
let go xi yi
| xi >= G.length xs = pure ()
| (yi', c) <- G.unsafeIndex xs xi
, yi == fromIntegral (SU.head yi')
= MG.unsafeWrite ys yi c >> go (xi + 1) (yi + 1)
| otherwise = go xi (yi + 1)
go 0 0
Dense.Poly <$> G.unsafeFreeze ys