packages feed

free-vector-spaces 0.1.2.0 → 0.1.4.0

raw patch · 4 files changed

+296/−5 lines, 4 filesdep ~vector-spacePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: vector-space

API changes (from Hackage documentation)

+ Data.VectorSpace.Free: (^*^) :: FreeVectorSpace v => v -> v -> v
+ Data.VectorSpace.Free: class (VectorSpace v, Num (Scalar v)) => FreeVectorSpace v
+ Data.VectorSpace.Free: instance (Data.VectorSpace.Free.FiniteFreeSpace (f p), Data.VectorSpace.Free.FiniteFreeSpace (g p), Data.VectorSpace.Scalar (f p) ~ Data.VectorSpace.Scalar (g p)) => Data.VectorSpace.Free.FiniteFreeSpace ((GHC.Generics.:*:) f g p)
+ Data.VectorSpace.Free: instance Data.VectorSpace.Free.FiniteFreeSpace (f p) => Data.VectorSpace.Free.FiniteFreeSpace (GHC.Generics.M1 i c f p)
+ Data.VectorSpace.Free: instance Data.VectorSpace.Free.FiniteFreeSpace a => Data.VectorSpace.Free.FiniteFreeSpace (GHC.Generics.Rec0 a s)
+ Data.VectorSpace.Free: instance Data.VectorSpace.Free.OneDimensional (f p) => Data.VectorSpace.Free.OneDimensional (GHC.Generics.M1 i c f p)
+ Data.VectorSpace.Free: instance Data.VectorSpace.Free.OneDimensional a => Data.VectorSpace.Free.OneDimensional (GHC.Generics.Rec0 a s)
+ Data.VectorSpace.Free: instance GHC.Num.Num s => Data.Cross.HasCross2 (Linear.V2.V2 s)
+ Data.VectorSpace.Free: instance GHC.Num.Num s => Data.Cross.HasCross3 (Linear.V3.V3 s)
+ Data.VectorSpace.Free: vmap :: FreeVectorSpace v => (Scalar v -> Scalar v) -> v -> v
+ Data.VectorSpace.Free.FiniteSupportedSequence: SemisparseSuppSeq :: Vector n -> Vector (Int, Int) -> SemisparseSuppSeq n
+ Data.VectorSpace.Free.FiniteSupportedSequence: SparseSuppSeq :: Vector (Int, n) -> SparseSuppSeq n
+ Data.VectorSpace.Free.FiniteSupportedSequence: [chunkSparseNonzeroes] :: SemisparseSuppSeq n -> Vector n
+ Data.VectorSpace.Free.FiniteSupportedSequence: [sparseNonzeroLocation] :: SemisparseSuppSeq n -> Vector (Int, Int)
+ Data.VectorSpace.Free.FiniteSupportedSequence: [sparseNonzeroes] :: SparseSuppSeq n -> Vector (Int, n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: data SemisparseSuppSeq n
+ Data.VectorSpace.Free.FiniteSupportedSequence: data SparseSuppSeq n
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (Data.Vector.Unboxed.Base.Unbox n, GHC.Classes.Eq n, GHC.Num.Num n) => GHC.Exts.IsList (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (Data.Vector.Unboxed.Base.Unbox n, GHC.Classes.Eq n, GHC.Num.Num n) => GHC.Exts.IsList (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.AdditiveGroup.AdditiveGroup n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.Free.Class.FreeVectorSpace (Data.VectorSpace.Free.FiniteSupportedSequence.FinSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.AdditiveGroup.AdditiveGroup n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.InnerSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.AdditiveGroup.AdditiveGroup n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.InnerSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.AdditiveGroup.AdditiveGroup (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.AdditiveGroup.AdditiveGroup (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.AffineSpace.AffineSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.AffineSpace.AffineSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.Basis.HasBasis (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.Basis.HasBasis (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.Free.Class.FreeVectorSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.Free.Class.FreeVectorSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.VectorSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SemisparseSuppSeq n)
+ Data.VectorSpace.Free.FiniteSupportedSequence: instance (GHC.Num.Num n, Data.Vector.Unboxed.Base.Unbox n) => Data.VectorSpace.VectorSpace (Data.VectorSpace.Free.FiniteSupportedSequence.SparseSuppSeq n)
- Data.VectorSpace.Free: class (VectorSpace v, Num (Scalar v)) => FiniteFreeSpace v where fromUnboxVect v = result where result = case length v of { 0 -> zeroV n | n < d -> unsafeFromFullUnboxVect $ v ++ replicate (d - n) 0 } d = freeDimension [result]
+ Data.VectorSpace.Free: class (VectorSpace v, Num (Scalar v)) => FiniteFreeSpace v where freeDimension _ = freeDimension ([] :: [VRep v]) toFullUnboxVect v = toFullUnboxVect (from v :: VRep v) unsafeFromFullUnboxVect v = to (unsafeFromFullUnboxVect v :: VRep v) fromUnboxVect v = result where result = case length v of { 0 -> zeroV n | n < d -> unsafeFromFullUnboxVect $ v ++ replicate (d - n) 0 } d = freeDimension [result]
- Data.VectorSpace.Free: class (VectorSpace v, Fractional (Scalar v)) => OneDimensional v where v ^/! w = case v ^/^ w of { Just μ -> μ Nothing -> 1 / 0 }
+ Data.VectorSpace.Free: class (VectorSpace v, Fractional (Scalar v)) => OneDimensional v where v ^/^ w = (from v :: VRep v) ^/^ from w v ^/! w = case v ^/^ w of { Just μ -> μ Nothing -> 1 / 0 }

Files

Data/VectorSpace/Free.hs view
@@ -8,10 +8,13 @@ -- Portability : portable --  {-# LANGUAGE TypeFamilies            #-}+{-# LANGUAGE TypeOperators           #-} {-# LANGUAGE FlexibleInstances       #-} {-# LANGUAGE FlexibleContexts        #-} {-# LANGUAGE CPP                     #-} {-# LANGUAGE ConstrainedClassMethods #-}+{-# LANGUAGE DefaultSignatures       #-}+{-# LANGUAGE ScopedTypeVariables     #-}  module Data.VectorSpace.Free (                              -- * Supported types@@ -32,16 +35,20 @@                              -- ** Small                              , OneDimensional(..)                              -- ** Free+                             , FreeVectorSpace(..)                              , FiniteFreeSpace(..)                              ) where  import Data.AffineSpace import Data.VectorSpace+import Data.Cross+import Data.VectorSpace.Free.Class import Data.VectorSpace.Free.FiniteSupportedSequence (FinSuppSeq) import Data.VectorSpace.Free.Sequence (Sequence) import Data.Basis  import Data.MemoTrie+import Data.Void  import qualified Linear as L import Linear.V0@@ -62,6 +69,8 @@ import Foreign.C.Types (CFloat, CDouble)  import GHC.Exts (IsList(..))+import qualified GHC.Generics as Gnrx+import GHC.Generics (Generic, (:*:)(..))  vDecomp :: FoldableWithIndex (L.E v) v => v s -> [(L.E v, s)] vDecomp = ifoldr (\b s l -> (b,s):l) []@@ -101,7 +110,15 @@ portFinDP(V0) portFinDP(V1) portFinDP(V2)+instance Num s => HasCross2 (V2 s) where+  cross2 (V2 x y) = V2 (-y) x+ portFinDP(V3)+instance Num s => HasCross3 (V3 s) where+  V3 ax ay az `cross3` V3 bx by bz = V3 (ay * bz - az * by)+                                        (az * bx - ax * bz)+                                        (ax * by - ay * bx)+ portFinDP(V4)  @@ -137,6 +154,10 @@ class (VectorSpace v, Fractional (Scalar v)) => OneDimensional v where   -- | Compare the (directed) length of two vectors.   (^/^) :: v -> v -> Maybe (Scalar v)+  default (^/^) :: ( Generic v, OneDimensional (VRep v)+                   , Scalar (VRep v) ~ Scalar v )+                     => v -> v -> Maybe (Scalar v)+  v ^/^ w = (Gnrx.from v :: VRep v) ^/^ Gnrx.from w   -- | Unsafe version of '^/^'.   (^/!) :: v -> v -> Scalar v   v^/!w = case v^/^w of@@ -171,10 +192,24 @@   class (VectorSpace v, Num (Scalar v)) => FiniteFreeSpace v where-  {-# MINIMAL freeDimension, toFullUnboxVect, unsafeFromFullUnboxVect #-}   freeDimension :: Functor p => p v -> Int+  default freeDimension :: (Generic v, FiniteFreeSpace (VRep v))+                        => p v -> Int+  freeDimension _ = freeDimension ([]::[VRep v])   toFullUnboxVect :: UArr.Unbox (Scalar v) => v -> UArr.Vector (Scalar v)+  default toFullUnboxVect+        :: ( Generic v, FiniteFreeSpace (VRep v)+           , UArr.Unbox (Scalar v)+           , Scalar (VRep v) ~ Scalar v )+                           => v -> UArr.Vector (Scalar v)+  toFullUnboxVect v = toFullUnboxVect (Gnrx.from v :: VRep v)   unsafeFromFullUnboxVect :: UArr.Unbox (Scalar v) => UArr.Vector (Scalar v) -> v+  default unsafeFromFullUnboxVect+        :: ( Generic v, FiniteFreeSpace (VRep v)+           , UArr.Unbox (Scalar v)+           , Scalar (VRep v) ~ Scalar v )+                           => UArr.Vector (Scalar v) -> v+  unsafeFromFullUnboxVect v = Gnrx.to (unsafeFromFullUnboxVect v :: VRep v)   fromUnboxVect :: UArr.Unbox (Scalar v) => UArr.Vector (Scalar v) -> v   fromUnboxVect v = result    where result = case UArr.length v of@@ -235,3 +270,36 @@   ++instance FiniteFreeSpace a => FiniteFreeSpace (Gnrx.Rec0 a s) where+  freeDimension = freeDimension . fmap Gnrx.unK1+  toFullUnboxVect = toFullUnboxVect . Gnrx.unK1+  unsafeFromFullUnboxVect = Gnrx.K1 . unsafeFromFullUnboxVect+  fromUnboxVect = Gnrx.K1 . fromUnboxVect+instance FiniteFreeSpace (f p) => FiniteFreeSpace (Gnrx.M1 i c f p) where+  freeDimension = freeDimension . fmap Gnrx.unM1+  toFullUnboxVect = toFullUnboxVect . Gnrx.unM1+  unsafeFromFullUnboxVect = Gnrx.M1 . unsafeFromFullUnboxVect+  fromUnboxVect = Gnrx.M1 . fromUnboxVect+instance (FiniteFreeSpace (f p), FiniteFreeSpace (g p), Scalar (f p) ~ Scalar (g p))+              => FiniteFreeSpace ((f :*: g) p) where+  freeDimension p = freeDimension (fmap (\(x:*:_)->x) p)+                   + freeDimension (fmap (\(_:*:y)->y) p)+  toFullUnboxVect (u:*:v) = toFullUnboxVect u UArr.++ toFullUnboxVect v+  unsafeFromFullUnboxVect uv = u:*:v+   where u = unsafeFromFullUnboxVect uv+         v = unsafeFromFullUnboxVect $ UArr.drop du uv+         du = freeDimension [u]+++++instance OneDimensional a => OneDimensional (Gnrx.Rec0 a s) where+  Gnrx.K1 v ^/^ Gnrx.K1 w = v ^/^ w+  Gnrx.K1 v ^/! Gnrx.K1 w = v ^/! w+instance OneDimensional (f p) => OneDimensional (Gnrx.M1 i c f p) where+  Gnrx.M1 v ^/^ Gnrx.M1 w = v ^/^ w+  Gnrx.M1 v ^/! Gnrx.M1 w = v ^/! w+++type VRep v = Gnrx.Rep v Void
+ Data/VectorSpace/Free/Class.hs view
@@ -0,0 +1,58 @@+-- |+-- Module      : Data.VectorSpace.Free.Class+-- Copyright   : (c) Justus Sagemüller 2016+-- License     : GPL v3+-- +-- Maintainer  : (@) sagemueller $ geo.uni-koeln.de+-- Stability   : experimental+-- Portability : portable+-- +{-# LANGUAGE TypeFamilies            #-}+{-# LANGUAGE FlexibleContexts        #-}++module Data.VectorSpace.Free.Class ( FreeVectorSpace(..) ) where++import Data.VectorSpace+import Data.Ratio++import Foreign.C.Types (CFloat, CDouble, CSChar, CShort, CInt, CLong, CLLong, CIntMax)+++-- | Vector spaces that are spanned by a specific, canonical set of basis vectors.+class (VectorSpace v, Num (Scalar v)) => FreeVectorSpace v where+  -- | Element-wise multiplication, equivalent to Matlab's @.*@ operator or+  --   @'L.liftI2' (*)@.+  (^*^) :: v -> v -> v+  -- | Like a monomorphic 'fmap'. Only guaranteed to act on the nonzero entries;+  --   whether the function is also applied on zeroes is instance-specific.+  vmap :: (Scalar v -> Scalar v) -> v -> v++instance FreeVectorSpace Float where {(^*^) = (*); vmap = id}+instance FreeVectorSpace Double where {(^*^) = (*); vmap = id}+instance FreeVectorSpace Int where {(^*^) = (*); vmap = id}+instance FreeVectorSpace Integer where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CSChar where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CShort where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CInt where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CLong where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CLLong where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CFloat where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CDouble where {(^*^) = (*); vmap = id}+instance FreeVectorSpace CIntMax where {(^*^) = (*); vmap = id}+instance Integral a => FreeVectorSpace (Ratio a) where {(^*^) = (*); vmap = id}++instance (FreeVectorSpace v, FreeVectorSpace w, Scalar v ~ Scalar w)+               => FreeVectorSpace (v,w) where+  (v,w)^*^(v',w') = (v^*^v', w^*^w')+  vmap f (v,w) = (vmap f v, vmap f w)+instance ( FreeVectorSpace u, FreeVectorSpace v, FreeVectorSpace w+         , Scalar v ~ Scalar u, Scalar v ~ Scalar w )+               => FreeVectorSpace (u,v,w) where+  (u,v,w)^*^(u',v',w') = (u^*^u', v^*^v', w^*^w')+  vmap f (u,v,w) = (vmap f u, vmap f v, vmap f w)+instance ( FreeVectorSpace u, FreeVectorSpace v, FreeVectorSpace w, FreeVectorSpace x+         , Scalar x ~ Scalar v, Scalar v ~ Scalar u, Scalar v ~ Scalar w )+               => FreeVectorSpace (u,v,w,x) where+  (u,v,w,x)^*^(u',v',w',x') = (u^*^u', v^*^v', w^*^w', x^*^x')+  vmap f (u,v,w,x) = (vmap f u, vmap f v, vmap f w, vmap f x)+
Data/VectorSpace/Free/FiniteSupportedSequence.hs view
@@ -12,22 +12,31 @@ {-# LANGUAGE FlexibleContexts        #-} {-# LANGUAGE CPP                     #-} {-# LANGUAGE ConstrainedClassMethods #-}+{-# LANGUAGE MultiWayIf              #-}+{-# LANGUAGE ScopedTypeVariables     #-}+{-# LANGUAGE UnicodeSyntax           #-}  module Data.VectorSpace.Free.FiniteSupportedSequence (-                             FinSuppSeq (..)+                               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_)   @@ -89,6 +98,10 @@   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) @@ -106,3 +119,155 @@  instance (UArr.Unbox n, Show n) => Show (FinSuppSeq n) where   show = ("fromList "++) . show . toList++++++-- | Sparsely supported sequences (what other languages would call /sparse vectors/)+--   are sequences consisting of lots of zeroes, with finitely many+--   nonzeroes scattered around. Only these nonzero elements are stored.+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+++++-- | Like 'SparseSuppSeq', this type of number-sequence ignores zeroes and only stores+--   nonzero elements with positional information, but it does this not for every single+--   entry separately: only the first position of each contiguous /chunk/ of nonzeroes+--   is tracked. It is thus more suited for vectors that are in some places dense+--   but still have lots of zeroes.+-- +--   The drawback is that random access (i.e. 'decompose'') has complexity 𝓞(𝑛)+--    – instead of 𝓞(1) for 'FinSuppSeq', or 𝓞(log 𝑛) for 'SparseSuppSeq' –+--   so this type should only be used for “abstract vector operations”.+data SemisparseSuppSeq n = SemisparseSuppSeq {+       chunkSparseNonzeroes :: UArr.Vector n+     , sparseNonzeroLocation :: UArr.Vector (Int, Int)+                                        -- ^ Start index of block,+                                        --        size of block of consecutive nonzeroes+     }+     ++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..l-1] -- TODO: faster loop and unsafeWrite+                         $ \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 =  -- TODO: faster, direct implementation+     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 =  -- TODO: faster, direct implementation+      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
free-vector-spaces.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                free-vector-spaces-version:             0.1.2.0+version:             0.1.4.0 synopsis:            Instantiate the classes from the vector-space package with types from linear description:         The <http://hackage.haskell.org/package/linear/ linear> package offers efficient                      vector types — where vector means /element of a free vector space/, i.e.@@ -50,10 +50,10 @@   exposed-modules:     Data.VectorSpace.Free                        , Data.VectorSpace.Free.FiniteSupportedSequence                        , Data.VectorSpace.Free.Sequence-  -- other-modules:       +  other-modules:       Data.VectorSpace.Free.Class   -- other-extensions:       build-depends:       base >=4.6 && <5.1,-                       vector-space >=0.8 && <0.13,+                       vector-space >=0.11 && <0.13,                        MemoTrie,                        linear >=1.18 && <1.23,                        lens >= 4 && < 5,