Skip to content

Instantly share code, notes, and snippets.

@scravy
Created April 5, 2013 07:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scravy/5317395 to your computer and use it in GitHub Desktop.
Save scravy/5317395 to your computer and use it in GitHub Desktop.
{-# LANGUAGE Haskell2010
, FlexibleContexts
#-}
{-# OPTIONS -Wall #-}
module Main where
import Control.Monad
import Control.Monad.ST
import Data.List
import Data.Array.IArray
import Data.Array.Unboxed
import Data.Array.MArray
import Data.Array.ST
import Data.STRef
import Data.Int
import Data.Word
import Prelude hiding (read)
newtype Matrix e = Matrix (Array Int (UArray Int e))
{- -- excluded, requires FlexibleInstances and UndecidableInstances
instance (Show e, IArray UArray e) => Show (Matrix e) where
show = show . rows
rows, cols :: IArray UArray e => Matrix e -> [[e]]
rows (Matrix arr) = map elems $ elems arr
cols = transpose . rows
-}
matrix :: (IArray UArray e) => [[e]] -> Matrix e
matrix xs =
let lengths = map length xs
numCols = foldl1 min lengths
numRows = length lengths
in Matrix $ array (1, numRows)
$ zip [1..numRows]
$ map (array (1, numCols) . zip [1..numCols]) xs
thaws :: (IArray UArray e, MArray (STUArray s) e (ST s))
=> Array Int (UArray Int e) -> ST s [STUArray s Int e]
thaws = mapM thaw . elems
arrays :: [STUArray s Int e] -> ST s (STArray s Int (STUArray s Int e))
arrays list = newListArray (1, length list) list
detST :: (IArray UArray e, MArray (STUArray s) e (ST s),
Num e, Eq e, Division e)
=> Array Int (UArray Int e) -> ST s e
detST mat = do
let size = snd $ bounds mat
tee f x = f x >> return x
read a i j = readArray a i >>= flip readArray j
a <- thaws mat >>= arrays
signR <- newSTRef 1
pivotR <- newSTRef 1
flip mapM_ [1..size] $ \k -> do
prev <- readSTRef pivotR
pivot <- read a k k >>= tee (writeSTRef pivotR)
when (pivot == 0) $ do
s <- flip mapM [(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
when (not $ null sf) $ do
let sw = head sf
row <- readArray a sw
readArray a k >>= writeArray a sw
writeArray a k row
read a k k >>= writeSTRef pivotR
readSTRef signR >>= writeSTRef signR . negate
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
a_kj <- read a k j
writeArray a_i j ((pivot' * a_ij - a_ik * a_kj) `divide` prev)
liftM2 (*) (readSTRef pivotR) (readSTRef signR)
{- -- can't get this one to work
det :: (IArray UArray e, MArray (STUArray s) e (ST s),
Num e) => Matrix e -> e
det (Matrix arr) = runST (detST arr)
-}
main :: IO ()
main = do
let (Matrix x) = matrix [ [1,-2,3,234]
, [5,2,3,-3]
, [7,18,3,40]
, [2,9,71,0] ]
d = runST (detST x) :: Int
print d
class Division e where
divide :: e -> e -> e
instance Division Int where divide = quot
instance Division Int32 where divide = quot
instance Division Int64 where divide = quot
instance Division Word32 where divide = quot
instance Division Word64 where divide = quot
instance Division Float where divide = (/)
instance Division Double where divide = (/)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment