module Data.Sparse.Common ( module X, svToSM, outerProdSV, (><), toSV, extractCol, extractRow, extractDiagonalDSM, matVec, (#>), vecMat, (<#)) where import Data.Sparse.Utils as X import Data.Sparse.SpMatrix as X import Data.Sparse.SpVector as X import Numeric.Eps as X import Numeric.LinearAlgebra.Data as X import Numeric.LinearAlgebra.Class as X import Numeric.LinearAlgebra.Sparse.IntMap as X import qualified Data.IntMap as IM -- | promote a SV to SM svToSM :: SpVector a -> SpMatrix a svToSM (SV n d) = SM (n, 1) $ IM.singleton 0 d -- ** Outer vector product outerProdSV, (><) :: Num a => SpVector a -> SpVector a -> SpMatrix a outerProdSV v1 v2 = fromListSM (m, n) ixy where m = dim v1 n = dim v2 ixy = [(i,j, x * y) | (i,x) <- toListSV v1 , (j, y) <- toListSV v2] (><) = outerProdSV -- |Demote (n x 1) or (1 x n) SpMatrix to SpVector toSV :: SpMatrix a -> SpVector a toSV (SM (m,n) im) = SV d $ snd . head $ IM.toList im where d | m==1 && n==1 = 1 | m==1 && n>1 = n | n==1 && m>1 = m | otherwise = error $ "toSV : incompatible dimensions " ++ show (m,n) -- |Extract jth column, and place into SpVector extractCol :: SpMatrix a -> IxCol -> SpVector a extractCol m j = toSV $ extractColSM m j -- |Extract ith row, and place into SpVector extractRow :: SpMatrix a -> IxRow -> SpVector a extractRow m i = toSV $ extractRowSM m i -- | Extract the diagonal as a SpVector (with default 0) extractDiagonalDSM :: Num a => SpMatrix a -> SpVector a extractDiagonalDSM mm = fromListDenseSV n $ foldr ins [] ll where ll = [0 .. n - 1] n = nrows mm ins i acc = mm@@(i,i) : acc -- ** Matrix action on a vector {- FIXME : matVec is more general than SpVector's : \m v -> fmap (`dot` v) m :: (Normed f1, Num b, Functor f) => f (f1 b) -> f1 b -> f b -} -- |Matrix-on-vector matVec, (#>) :: Num a => SpMatrix a -> SpVector a -> SpVector a matVec (SM (nr, nc) mdata) (SV n sv) | nc == n = SV nr $ fmap (`dot` sv) mdata | otherwise = error $ "matVec : mismatching dimensions " ++ show (nc, n) (#>) = matVec -- |Vector-on-matrix (FIXME : transposes matrix: more costly than `matVec`, I think) vecMat, (<#) :: Num a => SpVector a -> SpMatrix a -> SpVector a vecMat (SV n sv) (SM (nr, nc) mdata) | n == nr = SV nc $ fmap (`dot` sv) (transposeIM2 mdata) | otherwise = error $ "vecMat : mismatching dimensions " ++ show (n, nr) (<#) = vecMat