module Numeric.LAPACK.Matrix.Private where

import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Matrix.Extent.Private 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 meas vert horiz height width =
         Array (Layout.Full meas vert horiz height width)

type General height width = Array (Layout.General height width)
type Tall height width = Array (Layout.Tall height width)
type Wide height width = Array (Layout.Wide height width)
type LiberalSquare height width = Array (Layout.LiberalSquare height width)
type Square sh = Array (Layout.Square sh)
type SquareMeas meas height width = Array (Layout.SquareMeas meas height width)


argGeneral ::
   (Layout.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 (Layout.Full Order
order Extent Size Big Big height width
extent) ForeignPtr a
a) =
   Order -> height -> width -> ForeignPtr a -> b
f Order
order (Extent Size Big Big height width -> height
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Extent meas vert horiz height width -> height
Extent.height Extent Size Big Big height width
extent) (Extent Size Big Big height width -> width
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Extent meas vert horiz height width -> width
Extent.width Extent Size Big Big height width
extent) ForeignPtr a
a

argSquare ::
   (Layout.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 (Layout.Full Order
order Extent Shape Small Small sh sh
extent) ForeignPtr a
a) =
   Order -> sh -> ForeignPtr a -> b
f Order
order (Extent Shape Small Small sh sh -> sh
forall shape. Square shape -> shape
Extent.squareSize Extent Shape 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.Measure measA, Extent.C vertA, Extent.C horizA) =>
   (Extent.Measure measB, Extent.C vertB, Extent.C horizB) =>
   Extent.Map measA vertA horizA measB vertB horizB height width ->
   Full measA vertA horizA height width a ->
   Full measB vertB horizB height width a
mapExtent :: Map measA vertA horizA measB vertB horizB height width
-> Full measA vertA horizA height width a
-> Full measB vertB horizB height width a
mapExtent Map measA vertA horizA measB vertB horizB height width
f = (Full measA vertA horizA height width
 -> Full measB vertB horizB height width)
-> Full measA vertA horizA height width a
-> Full measB vertB horizB height width a
forall sh0 sh1 a. (sh0 -> sh1) -> Array sh0 a -> Array sh1 a
Array.mapShape ((Full measA vertA horizA height width
  -> Full measB vertB horizB height width)
 -> Full measA vertA horizA height width a
 -> Full measB vertB horizB height width a)
-> (Full measA vertA horizA height width
    -> Full measB vertB horizB height width)
-> Full measA vertA horizA height width a
-> Full measB vertB horizB height width a
forall a b. (a -> b) -> a -> b
$ Map measA vertA horizA measB vertB horizB height width
-> Full measA vertA horizA height width
-> Full measB vertB horizB height width
forall measA vertA horizA measB vertB horizB height width.
Map measA vertA horizA measB vertB horizB height width
-> Full measA vertA horizA height width
-> Full measB vertB horizB height width
Layout.fullMapExtent Map measA vertA horizA measB vertB horizB height width
f

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

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

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

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

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


height ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   Full meas vert horiz height width a -> height
height :: Full meas vert horiz height width a -> height
height = Full meas vert horiz height width -> height
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Full meas vert horiz height width -> height
Layout.fullHeight (Full meas vert horiz height width -> height)
-> (Full meas vert horiz height width a
    -> Full meas vert horiz height width)
-> Full meas vert horiz height width a
-> height
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full meas vert horiz height width a
-> Full meas vert horiz height width
forall sh a. Array sh a -> sh
Array.shape

width ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   Full meas vert horiz height width a -> width
width :: Full meas vert horiz height width a -> width
width = Full meas vert horiz height width -> width
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Full meas vert horiz height width -> width
Layout.fullWidth (Full meas vert horiz height width -> width)
-> (Full meas vert horiz height width a
    -> Full meas vert horiz height width)
-> Full meas vert horiz height width a
-> width
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full meas vert horiz height width a
-> Full meas vert horiz height width
forall sh a. Array sh a -> sh
Array.shape


revealOrder ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   Full meas vert horiz height width a ->
   Either (Array (height,width) a) (Array (width,height) a)
revealOrder :: Full meas vert horiz height width a
-> Either (Array (height, width) a) (Array (width, height) a)
revealOrder (Array (Layout.Full Order
order Extent meas vert horiz height width
extent) ForeignPtr a
a) =
   let (height
h,width
w) = Extent meas vert horiz height width -> (height, width)
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Extent meas vert horiz height width -> (height, width)
Extent.dimensions Extent meas vert horiz height width
extent
   in case Order
order of
         Order
Layout.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
Layout.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