{-# language TypeFamilies, FlexibleInstances, DeriveFunctor #-} module Data.Sparse.Internal.SList where import Data.Sparse.Utils import Numeric.LinearAlgebra.Class -- | Sparse list newtype SList a = SL {unSL :: [(Int, a)]} deriving (Eq, Show, Functor) emptySL :: SList a emptySL = SL [] consSL :: (Int, a) -> SList a -> SList a consSL x (SL xs) = SL (x : xs) headSL :: SList a -> Maybe (Int, a) headSL (SL (x:_)) = Just x headSL (SL []) = Nothing fromList :: [(Int, a)] -> SList a fromList = SL toList :: SList a -> [(Int, a)] toList = unSL {-| NB : unionWith and intersectWith work only if the indices are _sorted_ NB2 : we use the _descending_ order comparison -} -- | Inner product between sparse lists sldot :: (Elt a, Ord i) => [(i, a)] -> [(i, a)] -> a sldot u v = sum $ intersectWithD pf u v where pf x y = conj x * y -- | Vector sum of sparse lists slsum :: (Ord i, Elt a) => [(i, a)] -> [(i, a)] -> [(i, a)] slsum = unionWithD (+) 0 -- | `vector-space` instances instance Elt a => AdditiveGroup (SList a) where zeroV = SL [] negateV = fmap (* (-1)) u ^+^ v = SL $ slsum (unSL u) (unSL v) instance Elt a => VectorSpace (SList a) where type Scalar (SList a) = a a .* v = fmap (* a) v instance (AdditiveGroup a, Elt a) => InnerSpace (SList a) where u <.> v = sldot (unSL u) (unSL v) -- instance InnerSpace (SList Double) where -- u <.> v = inner (unSV u) (unSV v) -- instance InnerSpace (SList (Complex Double)) where -- u <.> v = innerC (unSV u) (unSV v) -- test data l1, l2 :: [(Int, Double)] l1 = [(0, pi), (2, pi), (3, 5.4) ] l2 = [(1, exp 1), (2, 3.4)] -- l1c :: [(Int, Complex Double)] -- l1c = zip ii $ zipWith (:+) [1..3] [3,2,1] where -- ii = [0, 2, 5] -- sl1c = SL l1c -- helpers -- sortIndices :: [(IM.Key, a)] -> [(IM.Key, a)] -- sortIndices = IM.toList . IM.fromList