lapack-0.1: src/Numeric/LAPACK/Matrix/Multiply.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Numeric.LAPACK.Matrix.Multiply where
import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape
import qualified Numeric.LAPACK.Matrix.Triangular as Triangular
import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian
import qualified Numeric.LAPACK.Matrix.Square as Square
import qualified Numeric.LAPACK.Vector as Vector
import qualified Numeric.LAPACK.Private as Private
import Numeric.LAPACK.Matrix.Shape.Private
(HeightOf, WidthOf, Order(ColumnMajor), transposeFromOrder)
import Numeric.LAPACK.Matrix.Triangular (Triangular)
import Numeric.LAPACK.Matrix.Private (General)
import Numeric.LAPACK.Vector (Vector)
import Numeric.LAPACK.Private (zero, one)
import qualified Numeric.BLAS.FFI.Generic as BlasGen
import qualified Numeric.Netlib.Utility as Call
import qualified Numeric.Netlib.Class as Class
import qualified Data.Array.Comfort.Storable.Internal as Array
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable.Internal (Array(Array))
import Foreign.ForeignPtr (withForeignPtr)
import Control.Monad.Trans.Cont (ContT(ContT), evalContT)
import Control.Monad.IO.Class (liftIO)
transpose :: General height width a -> General width height a
transpose = Array.mapShape MatrixShape.transpose
multiplyVector ::
(Shape.C height, Shape.C width, Eq width, Class.Floating a) =>
General height width a -> Vector width a -> Vector height a
multiplyVector a x =
let MatrixShape.General _order _height width = Array.shape a
in if width == Array.shape x
then multiplyVectorUnchecked a x
else error "multiplyVector: width shapes mismatch"
multiplyVectorUnchecked ::
(Shape.C height, Shape.C width, Class.Floating a) =>
General height width a -> Vector width a -> Vector height a
multiplyVectorUnchecked
(Array shape@(MatrixShape.General order height _width) a) (Array _ x) =
Array.unsafeCreate height $ \yPtr -> do
let (m,n) = MatrixShape.dimensions shape
let lda = m
evalContT $ do
transPtr <- Call.char $ transposeFromOrder order
mPtr <- Call.cint m
nPtr <- Call.cint n
alphaPtr <- Call.number one
aPtr <- ContT $ withForeignPtr a
ldaPtr <- Call.cint lda
xPtr <- ContT $ withForeignPtr x
incxPtr <- Call.cint 1
betaPtr <- Call.number zero
incyPtr <- Call.cint 1
liftIO $
BlasGen.gemv
transPtr mPtr nPtr alphaPtr aPtr ldaPtr
xPtr incxPtr betaPtr yPtr incyPtr
multiply ::
(Shape.C height,
Shape.C fuse, Eq fuse,
Shape.C width,
Class.Floating a) =>
General height fuse a -> General fuse width a -> General height width a
multiply
(Array (MatrixShape.General orderA height fuseA) a)
(Array (MatrixShape.General orderB fuseB width) b) =
Array.unsafeCreate (MatrixShape.General ColumnMajor height width) $
\cPtr -> do
Call.assert "multiply: fuse shapes mismatch" (fuseA == fuseB)
let m = Shape.size height
let n = Shape.size width
let k = Shape.size fuseA
Private.multiplyMatrix orderA orderB m k n a b cPtr
infixl 7 <#, <#>
infixr 7 #>
class MultiplyRight shape where
(#>) ::
(Class.Floating a) =>
Array shape a -> Array (WidthOf shape) a -> Array (HeightOf shape) a
class MultiplyLeft shape where
(<#) ::
(Class.Floating a) =>
Array (HeightOf shape) a -> Array shape a -> Array (WidthOf shape) a
class Multiply shapeA shapeB where
type Multiplied shapeA shapeB
(<#>) ::
(Class.Floating a) =>
Array shapeA a -> Array shapeB a -> Array (Multiplied shapeA shapeB) a
instance
(Eq width, Shape.C width, Shape.C height) =>
MultiplyRight (MatrixShape.General height width) where
(#>) = multiplyVector
instance
(Eq height, Shape.C width, Shape.C height) =>
MultiplyLeft (MatrixShape.General height width) where
v <# m = multiplyVector (transpose m) v
instance
(Eq shape, Shape.C shape) =>
MultiplyRight (MatrixShape.Square shape) where
m #> v = multiplyVector (Square.toGeneral m) v
instance
(Eq shape, Shape.C shape) =>
MultiplyLeft (MatrixShape.Square shape) where
v <# m = multiplyVector (transpose $ Square.toGeneral m) v
instance
(Eq shape, Shape.C shape) =>
MultiplyRight (MatrixShape.Hermitian shape) where
m #> v = Hermitian.multiplyVector m v
instance
(Eq shape, Shape.C shape) =>
MultiplyLeft (MatrixShape.Hermitian shape) where
v <# m = Hermitian.multiplyVector (Vector.conjugate m) v
instance
(MatrixShape.Uplo uplo, Eq shape, Shape.C shape) =>
MultiplyRight (MatrixShape.Triangular uplo shape) where
m #> v = Triangular.multiplyVectorRight m v
instance
(MatrixShape.Uplo uplo, Eq shape, Shape.C shape) =>
MultiplyLeft (MatrixShape.Triangular uplo shape) where
v <# m = Triangular.multiplyVectorLeft m v
instance
(Shape.C heightA, Shape.C widthA, Shape.C widthB,
widthA ~ heightB, Eq heightB) =>
Multiply
(MatrixShape.General heightA widthA)
(MatrixShape.General heightB widthB) where
type Multiplied
(MatrixShape.General heightA widthA)
(MatrixShape.General heightB widthB) =
MatrixShape.General heightA widthB
(<#>) = multiply
instance
(Shape.C shapeA, Shape.C widthB, shapeA ~ heightB, Eq heightB) =>
Multiply
(MatrixShape.Square shapeA)
(MatrixShape.General heightB widthB) where
type Multiplied
(MatrixShape.Square shapeA)
(MatrixShape.General heightB widthB) =
MatrixShape.General heightB widthB
a <#> b = multiply (Square.toGeneral a) b
instance
(Shape.C heightA, Shape.C widthA, widthA ~ shapeB, Eq shapeB) =>
Multiply
(MatrixShape.General heightA widthA)
(MatrixShape.Square shapeB) where
type Multiplied
(MatrixShape.General heightA widthA)
(MatrixShape.Square shapeB) =
MatrixShape.General heightA widthA
a <#> b = multiply a (Square.toGeneral b)
instance
(Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Square shapeA) (MatrixShape.Square shapeB) where
type Multiplied (MatrixShape.Square shapeA) (MatrixShape.Square shapeB) =
MatrixShape.Square shapeA
(<#>) = Square.multiply
instance
(Shape.C shapeA, shapeA ~ width, Eq width, Shape.C height) =>
Multiply
(MatrixShape.General height width)
(MatrixShape.Hermitian shapeA)
where
type Multiplied
(MatrixShape.General height width) (MatrixShape.Hermitian shapeA) =
MatrixShape.General height width
(<#>) = Hermitian.multiplyGeneralLeft
instance
(Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Square shapeB) (MatrixShape.Hermitian shapeA)
where
type Multiplied
(MatrixShape.Square shapeB) (MatrixShape.Hermitian shapeA) =
MatrixShape.Square shapeA
(<#>) = Hermitian.multiplySquareLeft
instance
(Shape.C shapeA, shapeA ~ height, Eq height, Shape.C width) =>
Multiply
(MatrixShape.Hermitian shapeA)
(MatrixShape.General height width)
where
type Multiplied
(MatrixShape.Hermitian shapeA) (MatrixShape.General height width) =
MatrixShape.General height width
(<#>) = Hermitian.multiplyGeneralRight
instance
(Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Square shapeB)
where
type Multiplied
(MatrixShape.Hermitian shapeA) (MatrixShape.Square shapeB) =
MatrixShape.Square shapeA
(<#>) = Hermitian.multiplySquareRight
instance
(Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB)
where
type Multiplied
(MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB) =
MatrixShape.Square shapeA
a <#> b = Hermitian.multiplySquareRight a (Hermitian.toSquare b)
instance
(MatrixShape.Uplo uplo,
Shape.C shapeA, shapeA ~ width, Eq width, Shape.C height) =>
Multiply
(MatrixShape.General height width)
(MatrixShape.Triangular uplo shapeA)
where
type Multiplied
(MatrixShape.General height width)
(MatrixShape.Triangular uplo shapeA) =
MatrixShape.General height width
(<#>) = Triangular.multiplyGeneralLeft
instance
(MatrixShape.Uplo uplo, Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Square shapeB) (MatrixShape.Triangular uplo shapeA)
where
type Multiplied
(MatrixShape.Square shapeB) (MatrixShape.Triangular uplo shapeA) =
MatrixShape.Square shapeA
(<#>) = Triangular.multiplySquareLeft
instance
(MatrixShape.Uplo uplo,
Shape.C shapeA, shapeA ~ height, Eq height, Shape.C width) =>
Multiply
(MatrixShape.Triangular uplo shapeA)
(MatrixShape.General height width)
where
type Multiplied
(MatrixShape.Triangular uplo shapeA)
(MatrixShape.General height width) =
MatrixShape.General height width
(<#>) = Triangular.multiplyGeneralRight
instance
(MatrixShape.Uplo uplo, Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
Multiply (MatrixShape.Triangular uplo shapeA) (MatrixShape.Square shapeB)
where
type Multiplied
(MatrixShape.Triangular uplo shapeA) (MatrixShape.Square shapeB) =
MatrixShape.Square shapeA
(<#>) = Triangular.multiplySquareRight
instance
(Shape.C shapeA, shapeA ~ shapeB, Eq shapeB,
MultiplyTriangular uploA uploB) =>
Multiply
(MatrixShape.Triangular uploA shapeA)
(MatrixShape.Triangular uploB shapeB) where
type Multiplied
(MatrixShape.Triangular uploA shapeA)
(MatrixShape.Triangular uploB shapeB) =
MultipliedTriangular uploA uploB shapeB
(<#>) = multiplyTriangular
class MultiplyTriangular uploA uploB where
type MultipliedTriangular uploA uploB :: * -> *
multiplyTriangular ::
(Class.Floating a, Shape.C shape, Eq shape) =>
Triangular uploA shape a ->
Triangular uploB shape a ->
Array (MultipliedTriangular uploA uploB shape) a
instance MultiplyTriangular MatrixShape.Lower MatrixShape.Lower where
type MultipliedTriangular MatrixShape.Lower MatrixShape.Lower =
MatrixShape.Triangular MatrixShape.Lower
multiplyTriangular = Triangular.multiply
instance MultiplyTriangular MatrixShape.Upper MatrixShape.Upper where
type MultipliedTriangular MatrixShape.Upper MatrixShape.Upper =
MatrixShape.Triangular MatrixShape.Upper
multiplyTriangular = Triangular.multiply
instance MultiplyTriangular MatrixShape.Lower MatrixShape.Upper where
type MultipliedTriangular MatrixShape.Lower MatrixShape.Upper =
MatrixShape.Square
multiplyTriangular a b =
Square.multiply (Triangular.toSquare a) (Triangular.toSquare b)
instance MultiplyTriangular MatrixShape.Upper MatrixShape.Lower where
type MultipliedTriangular MatrixShape.Upper MatrixShape.Lower =
MatrixShape.Square
multiplyTriangular a b =
Square.multiply (Triangular.toSquare a) (Triangular.toSquare b)