module Numeric.LAPACK.Matrix.Private where

import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape
import qualified Numeric.LAPACK.Matrix.Shape.Box as Box
import qualified Numeric.LAPACK.Matrix.Extent as Extent

import qualified Data.Array.Comfort.Storable.Unchecked as Array
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable.Unchecked (Array(Array))

import Foreign.ForeignPtr (ForeignPtr)


type Full vert horiz height width =
         Array (MatrixShape.Full vert horiz height width)

type General height width = Array (MatrixShape.General height width)
type Tall height width = Array (MatrixShape.Tall height width)
type Wide height width = Array (MatrixShape.Wide height width)
type Square sh = Array (MatrixShape.Square sh)


argGeneral ::
   (MatrixShape.Order -> height -> width -> ForeignPtr a -> b) ->
   (General height width a -> b)
argGeneral :: (Order -> height -> width -> ForeignPtr a -> b)
-> General height width a -> b
argGeneral Order -> height -> width -> ForeignPtr a -> b
f (Array (MatrixShape.Full Order
order Extent Big Big height width
extent) ForeignPtr a
a) =
   Order -> height -> width -> ForeignPtr a -> b
f Order
order (Extent Big Big height width -> height
forall vert horiz height width.
(C vert, C horiz) =>
Extent vert horiz height width -> height
Extent.height Extent Big Big height width
extent) (Extent Big Big height width -> width
forall vert horiz height width.
(C vert, C horiz) =>
Extent vert horiz height width -> width
Extent.width Extent Big Big height width
extent) ForeignPtr a
a

argSquare ::
   (MatrixShape.Order -> sh -> ForeignPtr a -> b) -> (Square sh a -> b)
argSquare :: (Order -> sh -> ForeignPtr a -> b) -> Square sh a -> b
argSquare Order -> sh -> ForeignPtr a -> b
f (Array (MatrixShape.Full Order
order Extent Small Small sh sh
extent) ForeignPtr a
a) =
   Order -> sh -> ForeignPtr a -> b
f Order
order (Extent Small Small sh sh -> sh
forall height width. Extent Small Small height width -> height
Extent.squareSize Extent Small Small sh sh
extent) ForeignPtr a
a


type ShapeInt = Shape.ZeroBased Int

shapeInt :: Int -> ShapeInt
shapeInt :: Int -> ShapeInt
shapeInt = Int -> ShapeInt
forall n. n -> ZeroBased n
Shape.ZeroBased


mapExtent ::
   (Extent.C vertA, Extent.C horizA) =>
   (Extent.C vertB, Extent.C horizB) =>
   Extent.Map vertA horizA vertB horizB height width ->
   Full vertA horizA height width a -> Full vertB horizB height width a
mapExtent :: Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map vertA horizA vertB horizB height width
f = (Full vertA horizA height width -> Full vertB horizB height width)
-> Full vertA horizA height width a
-> Full vertB horizB height width a
forall sh0 sh1 a. (sh0 -> sh1) -> Array sh0 a -> Array sh1 a
Array.mapShape ((Full vertA horizA height width -> Full vertB horizB height width)
 -> Full vertA horizA height width a
 -> Full vertB horizB height width a)
-> (Full vertA horizA height width
    -> Full vertB horizB height width)
-> Full vertA horizA height width a
-> Full vertB horizB height width a
forall a b. (a -> b) -> a -> b
$ Map vertA horizA vertB horizB height width
-> Full vertA horizA height width -> Full vertB horizB height width
forall vertA horizA vertB horizB height width.
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width -> Full vertB horizB height width
MatrixShape.fullMapExtent Map vertA horizA vertB horizB height width
f

fromFull ::
   (Extent.C vert, Extent.C horiz) =>
   Full vert horiz height width a -> General height width a
fromFull :: Full vert horiz height width a -> General height width a
fromFull = Map vert horiz Big Big height width
-> Full vert horiz height width a -> General height width a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map vert horiz Big Big height width
forall vert horiz height width.
(C vert, C horiz) =>
Map vert horiz Big Big height width
Extent.toGeneral

generalizeTall ::
   (Extent.C vert, Extent.C horiz) =>
   Full vert Extent.Small height width a -> Full vert horiz height width a
generalizeTall :: Full vert Small height width a -> Full vert horiz height width a
generalizeTall = Map vert Small vert horiz height width
-> Full vert Small height width a -> Full vert horiz height width a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map vert Small vert horiz height width
forall vert horiz height width.
(C vert, C horiz) =>
Map vert Small vert horiz height width
Extent.generalizeTall

generalizeWide ::
   (Extent.C vert, Extent.C horiz) =>
   Full Extent.Small horiz height width a -> Full vert horiz height width a
generalizeWide :: Full Small horiz height width a -> Full vert horiz height width a
generalizeWide = Map Small horiz vert horiz height width
-> Full Small horiz height width a
-> Full vert horiz height width a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map Small horiz vert horiz height width
forall vert horiz height width.
(C vert, C horiz) =>
Map Small horiz vert horiz height width
Extent.generalizeWide


height :: (Box.Box shape) => Array shape a -> Box.HeightOf shape
height :: Array shape a -> HeightOf shape
height = shape -> HeightOf shape
forall shape. Box shape => shape -> HeightOf shape
Box.height (shape -> HeightOf shape)
-> (Array shape a -> shape) -> Array shape a -> HeightOf shape
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array shape a -> shape
forall sh a. Array sh a -> sh
Array.shape

width :: (Box.Box shape) => Array shape a -> Box.WidthOf shape
width :: Array shape a -> WidthOf shape
width = shape -> WidthOf shape
forall shape. Box shape => shape -> WidthOf shape
Box.width (shape -> WidthOf shape)
-> (Array shape a -> shape) -> Array shape a -> WidthOf shape
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array shape a -> shape
forall sh a. Array sh a -> sh
Array.shape


revealOrder ::
   (Extent.C vert, Extent.C horiz) =>
   Full vert horiz height width a ->
   Either (Array (height,width) a) (Array (width,height) a)
revealOrder :: Full vert horiz height width a
-> Either (Array (height, width) a) (Array (width, height) a)
revealOrder (Array (MatrixShape.Full Order
order Extent vert horiz height width
extent) ForeignPtr a
a) =
   let (height
h,width
w) = Extent vert horiz height width -> (height, width)
forall vert horiz height width.
(C vert, C horiz) =>
Extent vert horiz height width -> (height, width)
Extent.dimensions Extent vert horiz height width
extent
   in case Order
order of
         Order
MatrixShape.RowMajor -> Array (height, width) a
-> Either (Array (height, width) a) (Array (width, height) a)
forall a b. a -> Either a b
Left (Array (height, width) a
 -> Either (Array (height, width) a) (Array (width, height) a))
-> Array (height, width) a
-> Either (Array (height, width) a) (Array (width, height) a)
forall a b. (a -> b) -> a -> b
$ (height, width) -> ForeignPtr a -> Array (height, width) a
forall sh a. sh -> ForeignPtr a -> Array sh a
Array (height
h,width
w) ForeignPtr a
a
         Order
MatrixShape.ColumnMajor -> Array (width, height) a
-> Either (Array (height, width) a) (Array (width, height) a)
forall a b. b -> Either a b
Right (Array (width, height) a
 -> Either (Array (height, width) a) (Array (width, height) a))
-> Array (width, height) a
-> Either (Array (height, width) a) (Array (width, height) a)
forall a b. (a -> b) -> a -> b
$ (width, height) -> ForeignPtr a -> Array (width, height) a
forall sh a. sh -> ForeignPtr a -> Array sh a
Array (width
w,height
h) ForeignPtr a
a