module Data.VectorSpace.Free.FiniteSupportedSequence (
FinSuppSeq (..)
, SparseSuppSeq (..)
, SemisparseSuppSeq (..)
) where
import Data.AffineSpace
import Data.VectorSpace
import Data.VectorSpace.Free.Class
import Data.Basis
import qualified Data.Foldable as Foldable
import qualified Data.Vector.Generic as Arr
import qualified Data.Vector.Unboxed as UArr
import qualified Data.Vector.Generic.Mutable as MArr
import GHC.Exts (IsList(..))
import Control.Arrow (first, second)
import Control.Monad (forM_)
newtype FinSuppSeq n = FinSuppSeq { getFiniteSeq :: UArr.Vector n }
liftU2FSS :: UArr.Unbox n => (n -> n -> n) -> FinSuppSeq n -> FinSuppSeq n -> FinSuppSeq n
liftU2FSS f (FinSuppSeq u) (FinSuppSeq v) = FinSuppSeq $ case compare lu lv of
LT | lu == 0 -> v
| otherwise -> UArr.modify
(\ w -> Foldable.forM_ [0..lu1] $
\i -> MArr.unsafeWrite w i $ f (UArr.unsafeIndex u i)
(UArr.unsafeIndex v i)) v
EQ -> UArr.zipWith f u v
GT | lv == 0 -> u
| otherwise -> UArr.modify
(\ w -> Foldable.forM_ [0..lv1] $
\i -> MArr.unsafeWrite w i $ f (UArr.unsafeIndex u i)
(UArr.unsafeIndex v i)) u
where lu = UArr.length u
lv = UArr.length v
instance (Num n, UArr.Unbox n) => AffineSpace (FinSuppSeq n) where
type Diff (FinSuppSeq n) = FinSuppSeq n
(.-.) = (^-^)
(.+^) = (^+^)
instance (Num n, UArr.Unbox n) => AdditiveGroup (FinSuppSeq n) where
zeroV = FinSuppSeq $ UArr.empty
(^+^) = liftU2FSS (+)
negateV (FinSuppSeq v) = FinSuppSeq $ UArr.map negate v
instance (Num n, UArr.Unbox n) => VectorSpace (FinSuppSeq n) where
type Scalar (FinSuppSeq n) = n
μ*^FinSuppSeq v = FinSuppSeq $ UArr.map (μ*) v
instance (Num n, AdditiveGroup n, UArr.Unbox n) => FreeVectorSpace (FinSuppSeq n) where
FinSuppSeq v^*^FinSuppSeq w = FinSuppSeq (UArr.zipWith (*) v w)
vmap f (FinSuppSeq v) = FinSuppSeq $ UArr.map f v
instance (Num n, AdditiveGroup n, UArr.Unbox n) => InnerSpace (FinSuppSeq n) where
FinSuppSeq v<.>FinSuppSeq w = UArr.sum (UArr.zipWith (*) v w)
instance (Num n, UArr.Unbox n) => HasBasis (FinSuppSeq n) where
type Basis (FinSuppSeq n) = Int
basisValue i = FinSuppSeq $ UArr.replicate i 0 `UArr.snoc` 1
decompose = zip [0..] . toList
decompose' (FinSuppSeq v) i = maybe 0 id $ v UArr.!? i
instance UArr.Unbox n => IsList (FinSuppSeq n) where
type Item (FinSuppSeq n) = n
fromListN l = FinSuppSeq . fromListN l
fromList = FinSuppSeq . fromList
toList = toList . getFiniteSeq
instance (UArr.Unbox n, Show n) => Show (FinSuppSeq n) where
show = ("fromList "++) . show . toList
data SparseSuppSeq n = SparseSuppSeq {
sparseNonzeroes :: UArr.Vector (Int,n)
}
instance (Num n, UArr.Unbox n) => AffineSpace (SparseSuppSeq n) where
type Diff (SparseSuppSeq n) = SparseSuppSeq n
(.-.) = (^-^)
(.+^) = (^+^)
instance (Num n, UArr.Unbox n) => AdditiveGroup (SparseSuppSeq n) where
zeroV = SparseSuppSeq $ UArr.empty
SparseSuppSeq u ^+^ SparseSuppSeq v = SparseSuppSeq w
where w = Arr.unfoldrN (Arr.length u + Arr.length v) seekws (0,0)
seekws (pu,pv) = case (u Arr.!? pu, v Arr.!? pv) of
(Just (ju,uj), Just (jv,vj))
-> if | ju>jv -> Just ((jv, vj), (pu, pv+1))
| ju<jv -> Just ((ju, uj), (pu+1, pv))
| otherwise -> Just ((ju, uj+vj), (pu+1, pv+1))
(Just (ju,uj), Nothing)
-> Just ((ju, uj), (pu+1, pv))
(Nothing, Just (jv,vj))
-> Just ((jv, vj), (pu, pv+1))
(Nothing, Nothing) -> Nothing
negateV (SparseSuppSeq v) = SparseSuppSeq $ Arr.map (second negate) v
instance (Num n, UArr.Unbox n) => VectorSpace (SparseSuppSeq n) where
type Scalar (SparseSuppSeq n) = n
μ *^ SparseSuppSeq v = SparseSuppSeq $ Arr.map (second (*μ)) v
instance (Num n, UArr.Unbox n) => FreeVectorSpace (SparseSuppSeq n) where
SparseSuppSeq u ^*^ SparseSuppSeq v = SparseSuppSeq w
where w = Arr.unfoldrN (Arr.length u `min` Arr.length v) seekws (0,0)
seekws (pu,pv) = case (u Arr.!? pu, v Arr.!? pv) of
(Just (ju,uj), Just (jv,vj))
-> if | ju>jv -> seekws (pu, pv+1)
| ju<jv -> seekws (pu+1, pv)
| otherwise -> Just ((ju, uj*vj), (pu+1, pv+1))
_ -> Nothing
vmap f (SparseSuppSeq v) = SparseSuppSeq $ Arr.map (second f) v
instance (Num n, AdditiveGroup n, UArr.Unbox n) => InnerSpace (SparseSuppSeq n) where
v <.> w = case v ^*^ w of SparseSuppSeq vw -> Arr.foldl' (\acc (_,q) -> acc+q) 0 vw
instance (Num n, UArr.Unbox n) => HasBasis (SparseSuppSeq n) where
type Basis (SparseSuppSeq n) = Int
basisValue i = SparseSuppSeq $ UArr.singleton (i,1)
decompose (SparseSuppSeq v) = UArr.toList v
decompose' (SparseSuppSeq v) i = goBisect 0 (Arr.length v)
where goBisect jb jt
| jb==jt = 0
| otherwise = case first (`compare`i) $ v Arr.! jm of
(LT,_) -> goBisect (jm+1) jt
(EQ,q) -> q
(GT,_) -> goBisect jb jm
where jm = (jb+jt)`div`2
instance (UArr.Unbox n, Eq n, Num n) => IsList (SparseSuppSeq n) where
type Item (SparseSuppSeq n) = n
fromListN n xs = SparseSuppSeq $ Arr.unfoldrN n go (0,xs)
where go (_,[]) = Nothing
go (j,0:xs) = go (j+1,xs)
go (j,x:xs) = Just ((j,x), (j+1,xs))
fromList l = fromListN (length l) l
toList (SparseSuppSeq xs) = go 0 0
where go i j = case xs Arr.!? j of
Just (i',x) | i==i' -> x : go (i+1) (j+1)
Nothing -> []
_ -> 0 : go (i+1) j
data SemisparseSuppSeq n = SemisparseSuppSeq {
chunkSparseNonzeroes :: UArr.Vector n
, sparseNonzeroLocation :: UArr.Vector (Int, Int)
}
asSemisparse :: UArr.Unbox n => SparseSuppSeq n -> SemisparseSuppSeq n
asSemisparse (SparseSuppSeq v) = SemisparseSuppSeq (Arr.map snd v)
$ Arr.unfoldrN (Arr.length v) mkIndex 0
where mkIndex :: Int -> Maybe ((Int, Int), Int)
mkIndex i
| Just (j,_) <- v Arr.!? i = case mkIndex $ i+1 of
Just ((j',l),n) | j'==j+1 -> Just ((j,l+1), n)
_ -> Just ((j,1), i+1)
| otherwise = Nothing
fromSemisparse :: ∀ n . UArr.Unbox n => SemisparseSuppSeq n -> SparseSuppSeq n
fromSemisparse (SemisparseSuppSeq v ssIx) = SparseSuppSeq . (`Arr.zip`v) $ Arr.create (do
ix <- MArr.new $ Arr.length v
Arr.foldM_ (\i (j,l) -> do
forM_ [0..l1]
$ \k -> MArr.write ix (i+k) (j+k)
return $ i+l
) 0 ssIx
return ix
)
instance (Num n, UArr.Unbox n) => AffineSpace (SemisparseSuppSeq n) where
type Diff (SemisparseSuppSeq n) = SemisparseSuppSeq n
(.-.) = (^-^)
(.+^) = (^+^)
instance (Num n, UArr.Unbox n) => AdditiveGroup (SemisparseSuppSeq n) where
zeroV = SemisparseSuppSeq UArr.empty UArr.empty
u ^+^ v =
asSemisparse $ fromSemisparse u ^+^ fromSemisparse v
negateV (SemisparseSuppSeq v vis) = SemisparseSuppSeq (Arr.map negate v) vis
instance (Num n, UArr.Unbox n) => VectorSpace (SemisparseSuppSeq n) where
type Scalar (SemisparseSuppSeq n) = n
μ *^ SemisparseSuppSeq v ix = SemisparseSuppSeq (Arr.map (μ*) v) ix
instance (Num n, UArr.Unbox n) => FreeVectorSpace (SemisparseSuppSeq n) where
u ^*^ v =
asSemisparse $ fromSemisparse u ^*^ fromSemisparse v
vmap f (SemisparseSuppSeq v ix) = SemisparseSuppSeq (Arr.map f v) ix
instance (Num n, AdditiveGroup n, UArr.Unbox n) => InnerSpace (SemisparseSuppSeq n) where
v <.> w = fromSemisparse v <.> fromSemisparse w
instance (Num n, UArr.Unbox n) => HasBasis (SemisparseSuppSeq n) where
type Basis (SemisparseSuppSeq n) = Int
basisValue i = SemisparseSuppSeq (UArr.singleton 1) (UArr.singleton (i,1))
decompose = decompose . fromSemisparse
decompose' v = decompose' $ fromSemisparse v
instance (UArr.Unbox n, Eq n, Num n) => IsList (SemisparseSuppSeq n) where
type Item (SemisparseSuppSeq n) = n
fromListN n = asSemisparse . fromListN n
fromList = asSemisparse . fromList
toList = toList . fromSemisparse