{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Data.Matrix.Dense.Generic.Mutable
   ( -- * Mutable Matrix
     MMatrix(..)
   , C.dim
   , takeRow
   , C.write
   , C.unsafeWrite
   , C.read
   , C.unsafeRead
   , C.new
   , C.replicate
   ) where

import Prelude hiding (read, replicate)
import Control.Monad (liftM)
import qualified Data.Vector.Generic.Mutable as GM

import qualified Data.Matrix.Generic.Mutable as C

-- | mutable matrix
data MMatrix v s a = MMatrix !Int !Int !Int !Int !(v s a)

instance GM.MVector v a => C.MMatrix MMatrix v a where
    dim (MMatrix r c _ _ _) = (r,c)
    {-# INLINE dim #-}

    unsafeRead (MMatrix _ _ tda offset v) (i,j) = GM.unsafeRead v idx
      where idx = offset + i * tda + j
    {-# INLINE unsafeRead #-}

    unsafeWrite (MMatrix _ _ tda offset v) (i,j) = GM.unsafeWrite v idx
      where idx = offset + i * tda + j
    {-# INLINE unsafeWrite #-}

    new (r,c) = MMatrix r c c 0 `liftM` GM.new (r*c)
    {-# INLINE new #-}

    replicate (r,c) x = MMatrix r c c 0 `liftM` GM.replicate (r*c) x
    {-# INLINE replicate #-}
    
takeRow :: GM.MVector v a => MMatrix v m a -> Int -> v m a
takeRow (MMatrix _ c tda offset vec) i = GM.slice i' c vec
  where
    i' = offset + i * tda
{-# INLINE takeRow #-}