packages feed

matrices (empty) → 0.1.0

raw patch · 11 files changed

+420/−0 lines, 11 filesdep +basedep +primitivedep +vectorsetup-changed

Dependencies added: base, primitive, vector

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Kai Zhang++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Kai Zhang nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ matrices.cabal view
@@ -0,0 +1,40 @@+-- Initial matrices.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                matrices+version:             0.1.0+synopsis:            native matrix based on vector+description:         This library provide the APIs for creating, indexing,+                     modifying matrices (2d arrays). The underling data+                     structure is vector. It's not intended to be a linear+                     algebra library.+license:             BSD3+license-file:        LICENSE+author:              Kai Zhang+maintainer:          kai@kzhang.org+copyright:           <c> 2014 Kai Zhang+category:            Data+build-type:          Simple+-- extra-source-files:  +cabal-version:       >=1.10++library+  exposed-modules:+      Data.Matrix+    , Data.Matrix.Mutable+    , Data.Matrix.Generic+    , Data.Matrix.Generic.Mutable+    , Data.Matrix.Generic.Base+    , Data.Matrix.Generic.Types+    , Data.Matrix.Unboxed+    , Data.Matrix.Unboxed.Mutable++  -- other-modules:       ++  build-depends:+      base >=4.0 && <4.8+    , vector >=0.9+    , primitive++  hs-source-dirs:      src+  default-language:    Haskell2010
+ src/Data/Matrix.hs view
@@ -0,0 +1,10 @@+module Data.Matrix+    ( Matrix+    , module Data.Matrix.Generic.Base+    ) where++import qualified Data.Matrix.Generic.Types as MG+import Data.Matrix.Generic.Base+import qualified Data.Vector as V++type Matrix a = MG.Matrix V.Vector a
+ src/Data/Matrix/Generic.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE GADTs #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  $Header$+-- Copyright   :  (c) 2014 Kai Zhang+-- License     :  BSD3++-- Maintainer  :  kai@kzhang.org+-- Stability   :  experimental+-- Portability :  portable++--+--------------------------------------------------------------------------------++module Data.Matrix.Generic+    ( module Data.Matrix.Generic.Base+    , module Data.Matrix.Generic.Types+    ) where++import Data.Matrix.Generic.Base+import Data.Matrix.Generic.Types
+ src/Data/Matrix/Generic/Base.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  $Header$+-- Copyright   :  (c) 2014 Kai Zhang+-- License     :  BSD3++-- Maintainer  :  kai@kzhang.org+-- Stability   :  experimental+-- Portability :  portable++--+--------------------------------------------------------------------------------+module Data.Matrix.Generic.Base+    ( rows+    , cols+    , (!)+    , matrix+    , flatten+    , fromVector+    , toRows+    , toList+    , toLists+    , tr+    , subMatrix+    , ident+    , diag+    , diagRect+    , fromBlocks+    , isSymmetric+    ) where++import Control.Arrow ((***), (&&&))+import Control.Monad+import qualified Data.Foldable as F+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import Data.Matrix.Generic.Types++rows :: G.Vector v a => Matrix v a -> Int+rows (Matrix m _ _ _ _) = m++cols :: G.Vector v a => Matrix v a -> Int+cols (Matrix _ n _ _ _) = n++(!) :: G.Vector v a => Matrix v a -> (Int, Int) -> a+(!) (Matrix _ _ tda offset vec) (i, j) = vec G.! idx+  where+    idx = offset + i * tda + j+{-# INLINE (!) #-}++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+  where+    vec = G.fromList xs+    nrow = n `div` ncol+    n = G.length vec+{-# INLINE matrix #-}++flatten :: Matrix v a -> v a+flatten (Matrix m n tda offset vec)+    | n == tda = G.slice offset (m * n) vec+    | otherwise = G.generate (m * n) f+  where+    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+{-# INLINE fromVector #-}++toList :: G.Vector v a => Matrix v a -> [a]+toList = G.toList . flatten+{-# INLINE toList #-}++toRows :: G.Vector v a => Matrix v a -> [v a]+toRows (Matrix m n tda offset vec) = loop 0+  where+    loop !i | i < m = G.slice (f i) n vec : loop (i+1)+            | otherwise = []+    f i = offset + i * tda+{-# INLINE toRows #-}++toLists :: G.Vector v a => Matrix v a -> [[a]]+toLists = map G.toList . toRows+{-# INLINE toLists #-}++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+  where+    m' = rj - ri + 1+    n' = cj - ci + 1+    offset' = offset + ri * n + ci+{-# 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+  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+{-# 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+  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+         -> t a       -- ^ diagonal+         -> Matrix v a+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+        f !i x = GM.unsafeWrite v (i*(c'+1)) x >> return (i+1)+    n = r * c+{-# INLINE diagRect #-}++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+  where+    go n' xss v = foldM_ f 0 xss >> return v+      where+        f !cr xs = do (r', _) <- foldM g (0, 0) xs+                      return $ cr + r'+          where+            g (!maxR, !cc) x = do+                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)+                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 . map ((maximum *** sum) . unzip . map (rows &&& cols)) $ ms+{-# INLINE fromBlocks #-}++isSymmetric :: (Eq a, G.Vector v a) => Matrix v a -> Bool+isSymmetric m@(Matrix r c _ _ _) | r /= c = False+                                 | otherwise = all f [0 .. r-1]+  where+    f i = all g [i + 1 .. c-1]+      where g j = m ! (i,j) == m ! (j,i)+{-# INLINE isSymmetric #-}
+ src/Data/Matrix/Generic/Mutable.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE GADTs #-}+module Data.Matrix.Generic.Mutable+   ( thaw+   , unsafeThaw+   , freeze+   , unsafeFreeze+   , write+   , unsafeWrite+   , read+   , unsafeRead+   ) where++import Prelude hiding (read)+import Control.Monad+import Data.Matrix.Generic.Types+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import Control.Monad.Primitive++-- to be removed in GHC-7.10+(<$>) :: Monad m => (a -> b) -> m a -> m b+(<$>) = liftM++thaw :: PrimMonad m => Matrix v a -> m (MMatrix (G.Mutable v) (PrimState m) a)+thaw (Matrix r c tda offset v) = MMatrix r c tda offset <$> G.thaw v+{-# INLINE thaw #-}++unsafeThaw :: PrimMonad m => Matrix v a -> m (MMatrix (G.Mutable v) (PrimState m) a)+unsafeThaw (Matrix r c tda offset v) = MMatrix r c tda offset <$> G.unsafeThaw v+{-# INLINE unsafeThaw #-}++freeze :: (PrimMonad m, G.Vector v a) => MMatrix (G.Mutable v) (PrimState m) a -> m (Matrix v a)+freeze (MMatrix r c tda offset v) = Matrix r c tda offset <$> G.freeze v+{-# INLINE freeze #-}++unsafeFreeze :: (PrimMonad m, G.Vector v a) => MMatrix (G.Mutable v) (PrimState m) a -> m (Matrix v a)+unsafeFreeze (MMatrix r c tda offset v) = Matrix r c tda offset <$> G.unsafeFreeze v+{-# INLINE unsafeFreeze #-}++write :: (PrimMonad m, GM.MVector v a)+      => MMatrix v (PrimState m) a -> Int -> Int -> a -> m ()+write (MMatrix _ _ tda offset v) i j = GM.write v idx+  where idx = offset + i * tda + j+{-# INLINE write #-}++unsafeWrite :: (PrimMonad m, GM.MVector v a)+            => MMatrix v (PrimState m) a -> Int -> Int -> a -> m ()+unsafeWrite (MMatrix _ _ tda offset v) i j = GM.unsafeWrite v idx+  where idx = offset + i * tda + j+{-# INLINE unsafeWrite #-}++read :: (PrimMonad m, GM.MVector v a)+     => MMatrix v (PrimState m) a -> Int -> Int -> m a+read (MMatrix _ _ tda offset v) i j = GM.read v idx+  where idx = offset + i * tda + j+{-# INLINE read #-}++unsafeRead :: (PrimMonad m, GM.MVector v a)+           => MMatrix v (PrimState m) a -> Int -> Int -> m a+unsafeRead (MMatrix _ _ tda offset v) i j = GM.unsafeRead v idx+  where idx = offset + i * tda + j+{-# INLINE unsafeRead #-}
+ src/Data/Matrix/Generic/Types.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverlappingInstances #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  $Header$+-- Copyright   :  (c) 2014 Kai Zhang+-- License     :  BSD3++-- Maintainer  :  kai@kzhang.org+-- Stability   :  experimental+-- Portability :  portable++--+--------------------------------------------------------------------------------++module Data.Matrix.Generic.Types+    ( Matrix(..)+    , MMatrix(..)+    ) where++import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM++-- | row-major matrix supporting efficient slice+data Matrix v a where+    Matrix :: G.Vector v a+           => !Int    -- ^ number of rows+           -> !Int    -- ^ number of cols+           -> !Int    -- ^ physical row dimension+           -> !Int    -- ^ offset+           -> !(v a)  -- ^ flat matrix+           -> Matrix v a++-- | mutable matrix+data MMatrix v m a where+    MMatrix :: GM.MVector v a+            => !Int+            -> !Int+            -> !Int+            -> !Int+            -> !(v m a)+            -> MMatrix v m a++instance (G.Vector v a, Show a) => Show (Matrix v a) where+    show mat = unlines . map (unwords . map show) . toLists $ mat++instance G.Vector v Bool => Show (Matrix v Bool) where+    show mat = unlines . map (unwords . map showBool) . toLists $ mat+      where+        showBool x = if x then "1" else "0"++toRows :: G.Vector v a => Matrix v a -> [v a]+toRows (Matrix m n tda offset vec) = loop 0+    where+    loop !i | i < m = G.slice (f i) n vec : loop (i+1)+            | otherwise = []+    f i = offset + i * tda++toLists :: G.Vector v a => Matrix v a -> [[a]]+toLists = map G.toList . toRows
+ src/Data/Matrix/Mutable.hs view
@@ -0,0 +1,10 @@+module Data.Matrix.Mutable+    ( MMatrix+    , module Data.Matrix.Generic.Mutable+    ) where++import qualified Data.Matrix.Generic.Types as MG+import Data.Matrix.Generic.Mutable+import qualified Data.Vector.Mutable as VM++type MMatrix a = MG.MMatrix VM.MVector a
+ src/Data/Matrix/Unboxed.hs view
@@ -0,0 +1,10 @@+module Data.Matrix.Unboxed+    ( Matrix+    , module Data.Matrix.Generic.Base+    ) where++import qualified Data.Matrix.Generic.Types as MG+import Data.Matrix.Generic.Base+import qualified Data.Vector.Unboxed as V++type Matrix a = MG.Matrix V.Vector a
+ src/Data/Matrix/Unboxed/Mutable.hs view
@@ -0,0 +1,10 @@+module Data.Matrix.Unboxed.Mutable+    ( MMatrix+    , module Data.Matrix.Generic.Mutable+    ) where++import qualified Data.Matrix.Generic.Types as MG+import Data.Matrix.Generic.Mutable+import qualified Data.Vector.Unboxed.Mutable as UM++type MMatrix a = MG.MMatrix UM.MVector a