bed-and-breakfast 0.3.2 → 0.4
raw patch · 2 files changed
+114/−131 lines, 2 filesdep +binaryPVP ok
version bump matches the API change (PVP)
Dependencies added: binary
API changes (from Hackage documentation)
+ Numeric.Matrix: instance (MatrixElement e, Binary e) => Binary (Matrix e)
+ Numeric.Matrix: instance Division Int16
+ Numeric.Matrix: instance Division Int32
+ Numeric.Matrix: instance Division Int64
+ Numeric.Matrix: instance Division Int8
+ Numeric.Matrix: instance Division Word16
+ Numeric.Matrix: instance Division Word32
+ Numeric.Matrix: instance Division Word64
+ Numeric.Matrix: instance Division Word8
Files
- bed-and-breakfast.cabal +7/−1
- src/Numeric/Matrix.hs +107/−130
bed-and-breakfast.cabal view
@@ -1,5 +1,5 @@ Name: bed-and-breakfast-Version: 0.3.2+Version: 0.4 Synopsis: Efficient Matrix operations in 100% Haskell. Description: Efficient Matrix operations in 100% Haskell. .@@ -48,6 +48,10 @@ . [@v0.3.2@] Numeric.Matrix.Sugar was not mentioned in the cabal file. Improved test suite. Improved documentation.+ .+ [@v0.4@] Fixed a bug regarding @empty@ and @fromList@.+ Use unsafe operations where it is safe for speed.+ Added RULES. Added an instance for binary. License: MIT@@ -70,6 +74,7 @@ Build-Depends: base >= 4.5 && < 5, deepseq >= 1.3, array >= 0.4,+ binary >= 0.5, template-haskell >= 2.7 Hs-Source-Dirs: src @@ -80,4 +85,5 @@ build-depends: base >= 4.5 && < 5, bed-and-breakfast == 0.3.2, QuickCheck >= 2.4.2+
src/Numeric/Matrix.hs view
@@ -59,26 +59,22 @@ import Control.Monad import Control.Monad.ST ---import Control.Concurrent---import Control.Concurrent.MVar---import qualified Control.Monad.Parallel as MPar- import Data.Function (on) import Data.Ratio import Data.Complex import Data.Maybe---import Data.Foldable (Foldable)---import qualified Data.Foldable as F+import Data.Int+import Data.Word import qualified Data.List as L import Data.Array.IArray import Data.Array.MArray import Data.Array.Unboxed import Data.Array.ST---import Data.Array.IO+import Data.Array.Base (unsafeRead, unsafeWrite) import Data.STRef+import Data.Binary ---import System.IO.Unsafe import qualified Data.Array.Unsafe as U import Data.Typeable@@ -86,6 +82,7 @@ import Prelude hiding (any, all, read, map) import qualified Prelude as P + -- | Matrices are represented by a type which fits best the component type. -- For example a @Matrix Double@ is represented by unboxed arrays, -- @Matrix Integer@ by boxed arrays.@@ -95,9 +92,9 @@ -- example you can not compute the inverse matrix of a @Matrix Int@. -- -- Every matrix (regardless of the component type) has instances for--- 'Show', 'Read', 'Num', 'Fractional', 'Eq', 'Typeable', and 'NFData'.--- This means that you can use arithmetic operations like '+', '*', and--- '/', as well as functions like 'show', 'read', or 'typeOf'.+-- 'Show', 'Read', 'Num', 'Fractional', 'Eq', 'Typeable', 'Binary',+-- and 'NFData'. This means that you can use arithmetic operations like+-- '+', '*', and '/', as well as functions like 'show', 'read', or 'typeOf'. -- -- [@Show (Matrix e)@] -- Note that a Show instance for the component type @e@ must exist.@@ -132,7 +129,11 @@ -- monad (see the @monad-par@ package for details). -- -- [@Typeable (Matrix e)@]--- Allows you to use matrices as 'Data.Dynamic' values.+-- Allows you to use matrices as 'Dynamic' values.+--+-- [@Binary (Matrix e)@]+-- Serialize and unserialize matrices using the @binary@ package.+-- See @encode@ and @decode@. data family Matrix e data instance Matrix Int@@ -191,7 +192,25 @@ instance (MatrixElement e) => NFData (Matrix e) where rnf matrix = matrix `deepseq` () +instance (MatrixElement e, Binary e) => Binary (Matrix e) where+ + put m = do+ let (rows, cols) = dimensions m+ + put rows >> put cols + forM_ [1..rows] $ \i -> do+ forM_ [1..cols] $ \j -> do+ put (m `at` (i,j))++ get = do+ rows <- get :: Get Int+ cols <- get :: Get Int++ forM [1..rows] (const (forM [1..cols] (const get)))+ >>= return . fromList++ (<|>) :: MatrixElement e => Matrix e -> Matrix e -> Matrix e -- ^ Joins two matrices horizontally. --@@ -268,19 +287,22 @@ class Division e where divide :: e -> e -> e -instance Division Int where divide = quot--- instance Division Int8 where divide = quot--- instance Division Int16 where divide = quot--- instance Division Int32 where divide = quot--- instance Division Int64 where divide = quot+instance Division Int where divide = quot+instance Division Int8 where divide = quot+instance Division Int16 where divide = quot+instance Division Int32 where divide = quot+instance Division Int64 where divide = quot+instance Division Word8 where divide = quot+instance Division Word16 where divide = quot+instance Division Word32 where divide = quot+instance Division Word64 where divide = quot instance Division Integer where divide = quot-instance Division Float where divide = (/)-instance Division Double where divide = (/)+instance Division Float where divide = (/)+instance Division Double where divide = (/) instance Integral a => Division (Ratio a) where divide = (/) instance RealFloat a => Division (Complex a) where divide = (/) - class (Eq e, Num e) => MatrixElement e where -- | Creates a matrix of the given size using a generator@@ -366,12 +388,14 @@ -- Returns 0 if the matrix is not a square matrix. det :: Matrix e -> e - -- | Flips rows and columns.+ -- | Flip rows and columns. -- -- > 1 8 9 1 2 3 -- > 2 1 8 --transpose-> 8 1 2 -- > 3 2 1 9 8 1 transpose :: Matrix e -> Matrix e++ -- | Compute the rank of a matrix. rank :: Matrix e -> e trace :: Matrix e -> [e] @@ -380,15 +404,15 @@ adjugate :: MatrixElement e => Matrix e -> Matrix e minorMatrix :: MatrixElement e => Matrix e -> (Int, Int) -> Matrix e - -- | Applies a function on every component in the matrix.+ -- | Apply a function on every component in the matrix. map :: MatrixElement f => (e -> f) -> Matrix e -> Matrix f - -- | Applies a predicate on every component in the matrix- -- and returns True if all components satisfy it.+ -- | Apply a predicate on every component in the matrix+ -- and returns True iff all components satisfy it. all :: (e -> Bool) -> Matrix e -> Bool - -- | Applies a predicate on every component in the matrix- -- and returns True if one or more components satisfy it.+ -- | Apply a predicate on every component in the matrix+ -- and return True if one or more components satisfy it. any :: (e -> Bool) -> Matrix e -> Bool mapWithIndex :: MatrixElement f => ((Int, Int) -> e -> f) -> Matrix e -> Matrix f@@ -551,7 +575,7 @@ => (Int -> Int -> a Int (u Int e) -> matrix e) -> [[e]] -> matrix e _fromList c xs = let lengths = P.map length xs- numCols = foldl1 min lengths+ numCols = if null lengths then 0 else foldl1 min lengths numRows = length lengths in c numRows numCols@@ -602,21 +626,13 @@ => (Int, Int) -> e -> ST s ((STUArray s) Int e) arraySTU = newArray ---arrayIO :: MArray IOArray e IO--- => (Int, Int) -> e -> IO (IOArray Int e)---arrayIO = newArray ---arrayIOU :: MArray IOUArray e IO--- => (Int, Int) -> e -> IO (IOUArray Int e)---arrayIOU = newArray-- tee :: Monad m => (b -> m a) -> b -> m b tee f x = f x >> return x read :: (MArray a1 b m, MArray a (a1 Int b) m) => a Int (a1 Int b) -> Int -> Int -> m b-read a i j = readArray a i >>= flip readArray j+read a i j = unsafeRead a i >>= flip unsafeRead j _inv :: (IArray a e, MArray (u s) e (ST s), Fractional e, Ord e, Show e)@@ -628,15 +644,15 @@ n = 2*m swap a i j = do- tmp <- readArray a i- readArray a j >>= writeArray a i- writeArray a j tmp+ tmp <- unsafeRead a i+ unsafeRead a j >>= unsafeWrite a i+ unsafeWrite a j tmp okay <- newSTRef True a <- augment mkArrayST mat - flip mapM_ [1..m] $ \k -> do+ forM_ [1..m] $ \k -> do iPivot <- zip [k..m] <$> mapM (\i -> abs <$> read a i k) [k..m] >>= return . fst . L.maximumBy (compare `on` snd) @@ -645,38 +661,38 @@ swap a iPivot k - flip mapM_ [k+1..m] $ \i -> do- a_i <- readArray a i- a_k <- readArray a k- flip mapM_ [k+1..n] $ \j -> do- a_ij <- readArray a_i j- a_kj <- readArray a_k j- a_ik <- readArray a_i k- writeArray a_i j (a_ij - a_kj * (a_ik / p))- writeArray a_i k 0+ forM_ [k+1..m] $ \i -> do+ a_i <- unsafeRead a i+ a_k <- unsafeRead a k+ forM_ [k+1..n] $ \j -> do+ a_ij <- unsafeRead a_i j+ a_kj <- unsafeRead a_k j+ a_ik <- unsafeRead a_i k+ unsafeWrite a_i j (a_ij - a_kj * (a_ik / p))+ unsafeWrite a_i k 0 invertible <- readSTRef okay if invertible then do- flip mapM_ [ m - v | v <- [0..m-1] ] $ \i -> do- a_i <- readArray a i- p <- readArray a_i i- writeArray a_i i 1- flip mapM_ [i+1..n] $ \j -> do- readArray a_i j >>= writeArray a_i j . (/ p)+ forM_ [ m - v | v <- [0..m-1] ] $ \i -> do+ a_i <- unsafeRead a i+ p <- unsafeRead a_i i+ unsafeWrite a_i i 1+ forM_ [i+1..n] $ \j -> do+ unsafeRead a_i j >>= unsafeWrite a_i j . (/ p) unless (i == m) $ do- flip mapM_ [i+1..m] $ \k -> do- a_k <- readArray a k- p <- readArray a_i k+ forM_ [i+1..m] $ \k -> do+ a_k <- unsafeRead a k+ p <- unsafeRead a_i k - flip mapM_ [k..n] $ \j -> do- a_ij <- readArray a_i j- a_kj <- readArray a_k j- writeArray a_i j (a_ij - p * a_kj)+ forM_ [k..n] $ \j -> do+ a_ij <- unsafeRead a_i j+ a_kj <- unsafeRead a_k j+ unsafeWrite a_i j (a_ij - p * a_kj) - mapM (\i -> readArray a i >>= getElems+ mapM (\i -> unsafeRead a i >>= getElems >>= return . listArray (1, m) . drop m) [1..m] >>= return . Just . listArray (1, m) @@ -691,16 +707,16 @@ n = snd $ bounds (mat ! 1) swap a i j = do- tmp <- readArray a i- readArray a j >>= writeArray a i- writeArray a j tmp+ tmp <- unsafeRead a i+ unsafeRead a j >>= unsafeWrite a i+ unsafeWrite a j tmp a <- thaws mat >>= arrays ixPivot <- newSTRef 1 prevR <- newSTRef 1 - flip mapM_ [1..n] $ \k -> do+ forM_ [1..n] $ \k -> do pivotRow <- readSTRef ixPivot switchRow <- mapM (\i -> read a i k) [pivotRow .. m]@@ -710,17 +726,17 @@ let ix = fromJust switchRow + pivotRow when (pivotRow /= ix) (swap a pivotRow ix) - a_p <- readArray a k- pivot <- readArray a_p k+ a_p <- unsafeRead a k+ pivot <- unsafeRead a_p k prev <- readSTRef prevR - flip mapM_ [pivotRow+1..m] $ \i -> do- a_i <- readArray a i- flip mapM_ [k+1..n] $ \j -> do- a_ij <- readArray a_i j- a_ik <- readArray a_i k- a_pj <- readArray a_p j- writeArray a_i j ((pivot * a_ij - a_ik * a_pj)+ forM_ [pivotRow+1..m] $ \i -> do+ a_i <- unsafeRead a i+ forM_ [k+1..n] $ \j -> do+ a_ij <- unsafeRead a_i j+ a_ik <- unsafeRead a_i k+ a_pj <- unsafeRead a_p j+ unsafeWrite a_i j ((pivot * a_ij - a_ik * a_pj) `divide` prev) writeSTRef ixPivot (pivotRow + 1)@@ -742,7 +758,7 @@ signR <- newSTRef 1 pivotR <- newSTRef 1 - flip mapM_ [1..size] $ \k -> do+ forM_ [1..size] $ \k -> do sign <- readSTRef signR unless (sign == 0) $ do @@ -750,7 +766,7 @@ pivot <- read a k k >>= tee (writeSTRef pivotR) when (pivot == 0) $ do- s <- flip mapM [(k+1)..size] $ \r -> do+ s <- forM [(k+1)..size] $ \r -> do a_rk <- read a r k if a_rk == 0 then return 0 else return r let sf = filter (>0) s@@ -758,9 +774,9 @@ when (not $ null sf) $ do let sw = head sf - row <- readArray a sw- readArray a k >>= writeArray a sw- writeArray a k row+ row <- unsafeRead a sw+ unsafeRead a k >>= unsafeWrite a sw+ unsafeWrite a k row read a k k >>= writeSTRef pivotR readSTRef signR >>= writeSTRef signR . negate@@ -770,13 +786,13 @@ sign' <- readSTRef signR unless (sign' == 0) $ do pivot' <- readSTRef pivotR- flip mapM_ [(k+1)..size] $ \i -> do- a_i <- readArray a i- flip mapM [(k+1)..size] $ \j -> do- a_ij <- readArray a_i j- a_ik <- readArray a_i k+ forM_ [(k+1)..size] $ \i -> do+ a_i <- unsafeRead a i+ forM [(k+1)..size] $ \j -> do+ a_ij <- unsafeRead a_i j+ a_ik <- unsafeRead a_i k a_kj <- read a k j- writeArray a_i j ((pivot' * a_ij - a_ik * a_kj) `divide` prev)+ unsafeWrite a_i j ((pivot' * a_ij - a_ik * a_kj) `divide` prev) liftM2 (*) (readSTRef pivotR) (readSTRef signR) @@ -787,21 +803,7 @@ colsB = numCols b in matrix (rowsA, colsB) (\(i,j) -> L.foldl' (+) 0 [a `at` (i, k) * b `at` (k, j) | k <- [1..rowsB]]) -{- Old function: TODO benchmark against new one -_matrix_ :: (IArray a (u Int e), IArray u e)- => (Int -> Int -> (a Int (u Int e)) -> matrix e)- -> (Int, Int)- -> ((Int, Int) -> e)- -> matrix e-_matrix_ c (numRows, numCols) generator =- c numRows numCols- $ array (1, numRows)- $ [ (i, array (1, numCols) [(j, generator (i, j))- | j <- [1..numCols]])- | i <- [1..numRows] ]--}- _matrix :: (IArray a1 (u Int e), IArray u e, MArray a2 (u Int e) (ST s), MArray a3 e (ST s), Num e)@@ -813,38 +815,13 @@ -> ST s matrix _matrix c newArray newArrayU (m, n) g = do rows <- newArray (1, m) undefined- flip mapM_ [1..m] $ \i -> do+ forM_ [1..m] $ \i -> do cols <- newArrayU (1, n) 0- flip mapM_ [1..n] $ \j -> do- writeArray cols j (g (i,j))- U.unsafeFreeze cols >>= writeArray rows i+ forM_ [1..n] $ \j -> do+ unsafeWrite cols j (g (i,j))+ U.unsafeFreeze cols >>= unsafeWrite rows i U.unsafeFreeze rows >>= return . c m n -{--_matrixIO c newArray newArrayU (m, n) g = do- rows <- newArray (1, m) undefined-- let half = m `div` 2-- wait <- newEmptyMVar- forkOS $ do- flip mapM_ [1..half] $ \i -> do- cols <- newArrayU (1, n) 0- flip mapM_ [1..n] $ \j -> do- writeArray cols j (g (i,j))- U.unsafeFreeze cols >>= writeArray rows i- putMVar wait ()-- flip mapM_ [half+1..m] $ \i -> do- cols <- newArrayU (1, n) 0- flip mapM_ [1..n] $ \j -> do- writeArray cols j (g (i,j))- U.unsafeFreeze cols >>= writeArray rows i-- takeMVar wait-- U.unsafeFreeze rows >>= return . c m n--} {-# RULES