Commits

Sergey Astanin committed 438a3f9

toArray and toArrayM, convert 'Matrix a' to IArray and MArray respectively.

Comments (0)

Files changed (2)

matrix-market-pure.cabal

   -- Packages needed in order to build this package.
   Build-depends:
      base >= 3 && < 5
+     , array >= 0.3
+     , containers >= 0.3
 
   -- Modules not exported by this package.
   -- Other-modules:

src/Data/MatrixMarket.hs

   , mm'rows, mm'cols, mm'shape
   , toList
   , toCompleteList
+  , toArray
+  , toArrayM
   , at
     -- * Re-exports
   , Complex(..)
   )
   where
 
+import Data.Array.IArray (IArray, array)
+import Data.Array.MArray (MArray, newArray, writeArray)
 import Data.Char (toLower)
 import Data.Complex (Complex(..), conjugate)
+import qualified Data.Map as Map
 import Data.Maybe (listToMaybe)
 import Control.Applicative ((<$>), (<*>))
-import Control.Monad (join)
+import Control.Monad (join, forM_)
 
 -- | Matrix Market format representation.
 data (MValue a) => Matrix a
       (CoordinateM cm) -> cm'cols cm
       (ArrayM am) -> am'cols am
 
--- | Dimensions of the matrix.
+-- | Dimensions of the matrix: (number of rows, number of columns).
 mm'shape :: MValue a => Matrix a -> (Int, Int)
 mm'shape m = (mm'rows m, mm'cols m)
 
   | NoParse
   deriving (Show, Eq)
 
--- | Make a list of non-zero entries (without symmetric entries).
+-- | Construct a list of non-zero entries (without symmetric entries).
 toList :: (MValue a) => Matrix a -> [((Int, Int), a)]
 toList (MM (CoordinateM cm) _ _ _) = cm'values cm
 toList (MM (ArrayM am) _ _ _) =
         ncs = am'cols am
     in  zip [ (r,c) | c<-[1..ncs], r<-[1..nrs] ] $ am'values am
 
--- | Make a list of all non-zero entries (including symmetric entries).
+-- | Construct a list of all non-zero entries (including symmetric entries).
 toCompleteList :: (MValue a) => Matrix a -> [((Int, Int), a)]
 toCompleteList m@(MM _ _ General _) = toList m
 toCompleteList m@(MM _ _ Symmetric _) = concatMap (insertSymmetric) (toList m)
 toCompleteList m@(MM _ _ SkewSymmetric _) = concatMap (insertSkew) (toList m)
 toCompleteList m@(MM _ _ Hermitian _) = concatMap (insertHermitian) (toList m)
 
+-- | Convert to an immutable dense array.
+toArray :: (IArray arr a, MValue a)
+        => Int      -- ^ array starting index, usually 0 or 1
+        -> Matrix a -- ^ matrix to convert
+        -> arr (Int,Int) a
+toArray idx0 m =
+  let rows = mm'rows m
+      cols = mm'cols m
+      nonzeros = map (\((i,j),v) -> ((idx0+i-1,idx0+j-1),v)) $ toCompleteList m
+      mat = Map.fromList nonzeros
+  in  array ((idx0,idx0), (rows-1+idx0,cols-1+idx0)) $
+            [ ((i,j), Map.findWithDefault 0 (i,j) mat) |
+              i<-[idx0..(rows-1+idx0)], j<-[idx0..(cols-1+idx0)] ]
+
+-- | Convert to a mutable dense array.
+toArrayM :: (MArray arr a m, MValue a)
+         => Int       -- ^ array starting index, usually 0 or 1
+         -> Matrix a  -- ^ matrix to convert
+         -> m (arr (Int,Int) a)
+toArrayM idx0 mat =
+  let rows = mm'rows mat
+      cols = mm'cols mat
+      rng = ((idx0, idx0), (rows-1+idx0, cols-1+idx0))
+      nonzeros = map (\((i,j),v) -> ((idx0+i-1,idx0+j-1),v))$toCompleteList mat
+  in  do
+      newarr <- newArray rng 0
+      forM_ nonzeros $ \(ij,v) -> writeArray newarr ij v
+      return newarr
+
 insertSymmetric p@((i,j),v)
     | i /= j     = [p, ((j,i),v)]
     | otherwise  = [p]
     | otherwise  = [p]
 
 -- | Get an element of the matrix at the specified position.
--- Warning: This operation is slow.
+-- Warning: This operation is slow, use 'toArray' or 'toArrayM'
+-- to convert to an array first.
 at :: MValue a => Matrix a -> (Int, Int) -> a
 m `at` ij = maybe 0 id $ lookup ij $ toCompleteList m