packages feed

matrices 0.2.0 → 0.3.0

raw patch · 3 files changed

+119/−36 lines, 3 files

Files

matrices.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                matrices-version:             0.2.0+version:             0.3.0 synopsis:            native matrix based on vector description:         This library provide the APIs for creating, indexing,                      modifying matrices (2d arrays). The underling data@@ -36,7 +36,7 @@   -- other-modules:           build-depends:-      base >=4.0 && <4.8+      base >=4.0 && <5     , vector >=0.9     , primitive 
src/Data/Matrix/Generic/Base.hs view
@@ -16,8 +16,12 @@ module Data.Matrix.Generic.Base     ( rows     , cols+    , dim     , (!)     , unsafeIndex+    , empty++    -- * Conversions     , matrix     , flatten     , fromVector@@ -28,6 +32,10 @@     , toList     , toLists     , fromLists++    -- * Different matrix types+    , convert+     , tr     , takeRow     , takeColumn@@ -35,10 +43,22 @@     , ident     , diag     , diagRect+    , takeDiag     , fromBlocks     , isSymmetric     , force+    , Data.Matrix.Generic.Base.foldl++    -- * Mapping+    , imap     , Data.Matrix.Generic.Base.map++    -- * Monadic mapping+    , Data.Matrix.Generic.Base.mapM+    , Data.Matrix.Generic.Base.mapM_+    , Data.Matrix.Generic.Base.forM+    , Data.Matrix.Generic.Base.forM_+     ) where  import Control.Arrow ((***), (&&&))@@ -54,6 +74,11 @@ cols :: G.Vector v a => Matrix v a -> Int cols (Matrix _ n _ _ _) = n +dim :: G.Vector v a => Matrix v a -> (Int, Int)+dim (Matrix r c _ _ _) = (r,c)+{-# INLINE dim #-}++-- TODO: better error message (!) :: G.Vector v a => Matrix v a -> (Int, Int) -> a (!) (Matrix _ _ tda offset vec) (i, j) = vec G.! idx   where@@ -66,9 +91,16 @@     idx = offset + i * tda + j {-# INLINE unsafeIndex #-} ++--reshape :: G.Vector v a => Matrix v a -> (Int, Int) -> Matrix v a++empty :: G.Vector v a => Matrix v a+empty = Matrix 0 0 0 0 G.empty+{-# INLINE empty #-}+ matrix :: G.Vector v a => Int -> [a] -> Matrix v a matrix ncol xs | n `mod` ncol /= 0 = error "incorrect length"-               | otherwise = fromVector nrow ncol vec+               | otherwise = fromVector (nrow,ncol) vec   where     vec = G.fromList xs     nrow = n `div` ncol@@ -83,8 +115,8 @@     f i = (G.!) vec $ offset + (i `div` n) * tda + i `mod` n {-# INLINE flatten #-} -fromVector :: G.Vector v a => Int -> Int -> v a -> Matrix v a-fromVector r c = Matrix r c c 0+fromVector :: G.Vector v a => (Int, Int) -> v a -> Matrix v a+fromVector (r,c) = Matrix r c c 0 {-# INLINE fromVector #-}  toList :: G.Vector v a => Matrix v a -> [a]@@ -100,13 +132,13 @@ {-# INLINE toRows #-}  toColumns :: G.Vector v a => Matrix v a -> [v a]-toColumns m = Prelude.map (`takeRow` m) [0 .. c-1]+toColumns m = Prelude.map (takeColumn m) [0 .. c-1]   where c = cols m {-# INLINE toColumns #-}  fromRows :: G.Vector v a => [v a] -> Matrix v a fromRows xs | any (\x -> G.length x /= c) xs = error "inequal length"-            | otherwise = fromVector r c . G.concat $ xs+            | otherwise = fromVector (r,c) . G.concat $ xs   where     r = length xs     c = G.length . head $ xs@@ -122,20 +154,25 @@  -- | doesn't check if the list of list is a valid matrix fromLists :: G.Vector v a => [[a]] -> Matrix v a-fromLists xs = fromVector r c . G.fromList . concat $ xs+fromLists xs = fromVector (r,c) . G.fromList . concat $ xs   where     r = length xs     c = length .head $ xs {-# INLINE fromLists #-} -takeRow :: G.Vector v a => Int -> Matrix v a -> v a-takeRow i (Matrix _ c tda offset vec) = G.slice i' c vec+-- | convert different matrix type+convert :: (G.Vector v a, G.Vector w a) => Matrix v a -> Matrix w a+convert (Matrix r c tda offset vec) = Matrix r c tda offset . G.convert $ vec+{-# INLINE convert #-}++takeRow :: G.Vector v a => Matrix v a -> Int -> v a+takeRow (Matrix _ c tda offset vec) i = G.slice i' c vec   where     i' = offset + i * tda {-# INLINE takeRow #-} -takeColumn :: G.Vector v a => Int -> Matrix v a -> v a-takeColumn j (Matrix r _ tda offset vec) = G.create $ GM.new r >>= go idx vec r 0+takeColumn :: G.Vector v a => Matrix v a -> Int -> v a+takeColumn (Matrix r _ tda offset vec) j = G.create $ GM.new r >>= go idx vec r 0   where     go f vec' r' !i v | i >= r' = return v                       | otherwise = do GM.unsafeWrite v i $ vec' G.! f i@@ -143,41 +180,45 @@     idx i = offset + i * tda + j {-# INLINE takeColumn #-} -subMatrix :: G.Vector v a => (Int, Int) -> (Int, Int) -> Matrix v a -> Matrix v a-subMatrix (ri, rj) (ci, cj) (Matrix _ n tda offset vec) =-    Matrix m' n' tda offset' vec+-- | O(1) extract sub matrix+subMatrix :: G.Vector v a+          => (Int, Int)  -- ^ upper left corner of the submatrix+          -> (Int, Int)  -- ^ bottom right corner of the submatrix+          -> Matrix v a -> Matrix v a+subMatrix (i,j) (i',j') (Matrix _ n tda offset vec)+    | m' <= 0 || n' <= 0 = empty+    | otherwise = Matrix m' n' tda offset' vec   where-    m' = rj - ri + 1-    n' = cj - ci + 1-    offset' = offset + ri * n + ci+    m' = i' - i + 1+    n' = j' - j + 1+    offset' = offset + i * n + j {-# INLINE subMatrix #-}  tr :: G.Vector v a => Matrix v a -> Matrix v a-tr (Matrix r c tda offset vec) = fromVector c r $ G.generate (r*c) f+tr (Matrix r c tda offset vec) = fromVector (c,r) $ G.generate (r*c) f   where     f i = vec G.! (offset + i `mod` r * tda + i `div` r) {-# INLINE tr #-}  ident :: (Num a, G.Vector v a) => Int -> Matrix v a-ident n = diagRect 0 n n $ replicate n 1+ident n = diagRect 0 (n,n) $ replicate n 1 {-# INLINE ident #-}  -- | create a square matrix with given diagonal, other entries default to 0 diag :: (Num a, G.Vector v a, F.Foldable t)      => t a  -- ^ diagonal      -> Matrix v a-diag d = diagRect 0 n n d+diag d = diagRect 0 (n,n) d   where n = length . F.toList $ d {-# INLINE diag #-}  -- | create a rectangular matrix with default values and given diagonal diagRect :: (G.Vector v a, F.Foldable t)          => a         -- ^ default value-         -> Int       -- ^ number of rows-         -> Int       -- ^ number of columns+         -> (Int, Int)          -> t a       -- ^ diagonal          -> Matrix v a-diagRect z0 r c d = fromVector r c $ G.create $ GM.replicate n z0 >>= go d c+diagRect z0 (r,c) d = fromVector (r,c) $ G.create $ GM.replicate n z0 >>= go d c   where     go xs c' v = F.foldlM f 0 xs >> return v       where@@ -185,11 +226,18 @@     n = r * c {-# INLINE diagRect #-} +-- | extracts the diagonal from a rectangular matrix+takeDiag :: G.Vector v a => Matrix v a -> v a+takeDiag mat@(Matrix r c _ _ _) = G.generate n $ \i -> unsafeIndex mat (i,i)+  where+    n = min r c+{-# INLINE takeDiag #-}+ fromBlocks :: G.Vector v a            => a               -- ^ default value            -> [[Matrix v a]]            -> Matrix v a-fromBlocks d ms = fromVector m n $ G.create $ GM.replicate (m*n) d >>= go n ms+fromBlocks d ms = fromVector (m,n) $ G.create $ GM.replicate (m*n) d >>= go n ms   where     go n' xss v = foldM_ f 0 xss >> return v       where@@ -200,12 +248,14 @@                 let c = cols x                     r = rows x                     vec = flatten x-                    step i u = do GM.unsafeWrite v ((cr + i `div` c) * n' + i `mod` c + cc) u-                                  return (i+1)+                    step i u = do+                        GM.unsafeWrite v ((cr + i `div` c) * n' + i `mod` c + cc) u+                        return (i+1)                 G.foldM'_ step (0::Int) vec                 return (max maxR r, cc + c)     -- figure out the dimension of the new matrix-    (m, n) = (sum *** maximum) . unzip . Prelude.map ((maximum *** sum) . unzip . Prelude.map (rows &&& cols)) $ ms+    (m, n) = (sum *** maximum) . unzip . Prelude.map ((maximum *** sum) .+                unzip . Prelude.map (rows &&& cols)) $ ms {-# INLINE fromBlocks #-}  isSymmetric :: (Eq a, G.Vector v a) => Matrix v a -> Bool@@ -217,9 +267,35 @@ {-# INLINE isSymmetric #-}  force :: G.Vector v a => Matrix v a -> Matrix v a-force m@(Matrix r c _ _ _) = fromVector r c . G.force . flatten $ m+force m@(Matrix r c _ _ _) = fromVector (r,c) . G.force . flatten $ m {-# INLINE force #-} +imap :: (G.Vector v a, G.Vector v b) => ((Int, Int) -> a -> b) -> Matrix v a -> Matrix v b+imap f m@(Matrix r c _ _ _) = fromVector (r,c) $ G.imap f' . flatten $ m+  where+    f' i = f (i `div` c, i `mod` c)+{-# INLINE imap #-}+ map :: (G.Vector v a, G.Vector v b) => (a -> b) -> Matrix v a -> Matrix v b-map f m@(Matrix r c _ _ _) = fromVector r c $ G.map f . flatten $ m+map f m@(Matrix r c _ _ _) = fromVector (r,c) $ G.map f . flatten $ m {-# INLINE map #-}++foldl :: G.Vector v b => (a -> b -> a) -> a -> Matrix v b -> a+foldl f acc m = G.foldl f acc . flatten $ m+{-# INLINE foldl #-}++mapM :: (G.Vector v a, G.Vector v b, Monad m) => (a -> m b) -> Matrix v a -> m (Matrix v b)+mapM f m@(Matrix r c _ _ _) = liftM (fromVector (r,c)) . G.mapM f . flatten $ m+{-# INLINE mapM #-}++mapM_ :: (G.Vector v a, Monad m) => (a -> m b) -> Matrix v a -> m ()+mapM_ f = G.mapM_ f . flatten+{-# INLINE mapM_ #-}++forM :: (G.Vector v a, G.Vector v b, Monad m) => Matrix v a -> (a -> m b) -> m (Matrix v b)+forM = flip Data.Matrix.Generic.Base.mapM+{-# INLINE forM #-}++forM_ :: (G.Vector v a, Monad m) => Matrix v a -> (a -> m b) -> m ()+forM_ = flip Data.Matrix.Generic.Base.mapM_+{-# INLINE forM_ #-}
src/Data/Matrix/Generic/Mutable.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE GADTs #-}+{-# LANGUAGE Rank2Types #-} module Data.Matrix.Generic.Mutable    ( fromMVector    , thaw@@ -11,10 +12,12 @@    , unsafeRead    , replicate    , new+   , create    ) where  import Prelude hiding (read, replicate) import Control.Monad+import Control.Monad.ST import Data.Matrix.Generic.Types import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Mutable as GM@@ -24,8 +27,8 @@ (<$>) :: Monad m => (a -> b) -> m a -> m b (<$>) = liftM -fromMVector :: GM.MVector v a => Int -> Int -> v m a -> MMatrix v m a-fromMVector r c = MMatrix r c c 0+fromMVector :: GM.MVector v a => (Int, Int) -> v m a -> MMatrix v m a+fromMVector (r,c) = MMatrix r c c 0 {-# INLINE fromMVector #-}  thaw :: PrimMonad m => Matrix v a -> m (MMatrix (G.Mutable v) (PrimState m) a)@@ -69,11 +72,15 @@ {-# INLINE unsafeRead #-}  replicate :: (PrimMonad m, GM.MVector v a)-          => Int -> Int -> a -> m (MMatrix v (PrimState m) a)-replicate r c x = fromMVector r c <$> GM.replicate (r*c) x+          => (Int, Int) -> a -> m (MMatrix v (PrimState m) a)+replicate (r,c) x = fromMVector (r,c) <$> GM.replicate (r*c) x {-# INLINE replicate #-}  new :: (PrimMonad m, GM.MVector v a)-    => Int -> Int -> m (MMatrix v (PrimState m) a)-new r c = fromMVector r c <$> GM.new (r*c)+    => (Int, Int) -> m (MMatrix v (PrimState m) a)+new (r,c) = fromMVector (r,c) <$> GM.new (r*c) {-# INLINE new #-}++create :: G.Vector v a => (forall s . ST s (MMatrix (G.Mutable v) s a)) -> Matrix v a+create m = runST $ unsafeFreeze =<< m+{-# INLINE create #-}