module Numeric.LAPACK.Matrix.Full (
   Full,
   Unpacked.Unpacked,
   identity,
   diagonal,
   mapExtent,
   mapHeight,
   mapWidth,
   transpose,
   adjoint,
   multiplyVector,
   multiply,
   ) where

import qualified Numeric.LAPACK.Matrix.Array.Unpacked as Unpacked
import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix
import qualified Numeric.LAPACK.Matrix.Basic as Basic
import qualified Numeric.LAPACK.Matrix.Plain as Plain
import qualified Numeric.LAPACK.Matrix.Extent as Extent
import Numeric.LAPACK.Matrix.Array (Full)
import Numeric.LAPACK.Vector (Vector)

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Shape as Shape


identity ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   (Shape.C sh, Class.Floating a) =>
   sh -> Full meas vert horiz sh sh a
identity :: sh -> Full meas vert horiz sh sh a
identity = Array (Full meas vert horiz sh sh) a
-> Full meas vert horiz sh sh a
forall pack prop lower upper meas vert horiz height width a.
FromPlain pack prop lower upper meas vert horiz height width =>
PlainArray pack prop lower upper meas vert horiz height width a
-> ArrayMatrix pack prop lower upper meas vert horiz height width a
ArrMatrix.lift0 (Array (Full meas vert horiz sh sh) a
 -> Full meas vert horiz sh sh a)
-> (sh -> Array (Full meas vert horiz sh sh) a)
-> sh
-> Full meas vert horiz sh sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. sh -> Array (Full meas vert horiz sh sh) a
forall meas vert horiz sh a.
(Measure meas, C vert, C horiz, C sh, Floating a) =>
sh -> Full meas vert horiz sh sh a
Plain.identity

diagonal ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   (Shape.C sh, Class.Floating a) =>
   Vector sh a -> Full meas vert horiz sh sh a
diagonal :: Vector sh a -> Full meas vert horiz sh sh a
diagonal = Array (Full meas vert horiz sh sh) a
-> Full meas vert horiz sh sh a
forall pack prop lower upper meas vert horiz height width a.
FromPlain pack prop lower upper meas vert horiz height width =>
PlainArray pack prop lower upper meas vert horiz height width a
-> ArrayMatrix pack prop lower upper meas vert horiz height width a
ArrMatrix.lift0 (Array (Full meas vert horiz sh sh) a
 -> Full meas vert horiz sh sh a)
-> (Vector sh a -> Array (Full meas vert horiz sh sh) a)
-> Vector sh a
-> Full meas vert horiz sh sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector sh a -> Array (Full meas vert horiz sh sh) a
forall meas vert horiz sh a.
(Measure meas, C vert, C horiz, C sh, Floating a) =>
Vector sh a -> Full meas vert horiz sh sh a
Plain.diagonal


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
-> Full measA vertA horizA height width a
-> Full measB vertB horizB height width a
forall property lower upper measA vertA horizA measB vertB horizB
       height width a.
(Property property, Strip lower, Strip upper, Measure measA,
 C vertA, C horizA, Measure measB, C vertB, C horizB) =>
Map measA vertA horizA measB vertB horizB height width
-> Unpacked property lower upper measA vertA horizA height width a
-> Unpacked property lower upper measB vertB horizB height width a
Unpacked.mapExtent

{- |
The number of rows must be maintained by the height mapping function.
-}
mapHeight ::
   (Extent.C vert, Extent.C horiz,
    Shape.C heightA, Shape.C heightB, Shape.C width) =>
   (heightA -> heightB) ->
   Full Extent.Size vert horiz heightA width a ->
   Full Extent.Size vert horiz heightB width a
mapHeight :: (heightA -> heightB)
-> Full Size vert horiz heightA width a
-> Full Size vert horiz heightB width a
mapHeight = (Array (Full Size vert horiz heightA width) a
 -> Array (Full Size vert horiz heightB width) a)
-> Full Size vert horiz heightA width a
-> Full Size vert horiz heightB width a
forall packA propA lowerA upperA measA vertA horizA heightA widthA
       packB propB lowerB upperB measB vertB horizB heightB widthB a b.
(ToPlain
   packA propA lowerA upperA measA vertA horizA heightA widthA,
 FromPlain
   packB propB lowerB upperB measB vertB horizB heightB widthB) =>
(PlainArray
   packA propA lowerA upperA measA vertA horizA heightA widthA a
 -> PlainArray
      packB propB lowerB upperB measB vertB horizB heightB widthB b)
-> ArrayMatrix
     packA propA lowerA upperA measA vertA horizA heightA widthA a
-> ArrayMatrix
     packB propB lowerB upperB measB vertB horizB heightB widthB b
ArrMatrix.lift1 ((Array (Full Size vert horiz heightA width) a
  -> Array (Full Size vert horiz heightB width) a)
 -> Full Size vert horiz heightA width a
 -> Full Size vert horiz heightB width a)
-> ((heightA -> heightB)
    -> Array (Full Size vert horiz heightA width) a
    -> Array (Full Size vert horiz heightB width) a)
-> (heightA -> heightB)
-> Full Size vert horiz heightA width a
-> Full Size vert horiz heightB width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (heightA -> heightB)
-> Array (Full Size vert horiz heightA width) a
-> Array (Full Size vert horiz heightB width) a
forall heightA heightB vert horiz width a.
(C heightA, C heightB, C vert, C horiz) =>
(heightA -> heightB)
-> Full Size vert horiz heightA width a
-> Full Size vert horiz heightB width a
Plain.mapHeight

{- |
The number of columns must be maintained by the width mapping function.
-}
mapWidth ::
   (Extent.C vert, Extent.C horiz,
    Shape.C widthA, Shape.C widthB, Shape.C height) =>
   (widthA -> widthB) ->
   Full Extent.Size vert horiz height widthA a ->
   Full Extent.Size vert horiz height widthB a
mapWidth :: (widthA -> widthB)
-> Full Size vert horiz height widthA a
-> Full Size vert horiz height widthB a
mapWidth = (Array (Full Size vert horiz height widthA) a
 -> Array (Full Size vert horiz height widthB) a)
-> Full Size vert horiz height widthA a
-> Full Size vert horiz height widthB a
forall packA propA lowerA upperA measA vertA horizA heightA widthA
       packB propB lowerB upperB measB vertB horizB heightB widthB a b.
(ToPlain
   packA propA lowerA upperA measA vertA horizA heightA widthA,
 FromPlain
   packB propB lowerB upperB measB vertB horizB heightB widthB) =>
(PlainArray
   packA propA lowerA upperA measA vertA horizA heightA widthA a
 -> PlainArray
      packB propB lowerB upperB measB vertB horizB heightB widthB b)
-> ArrayMatrix
     packA propA lowerA upperA measA vertA horizA heightA widthA a
-> ArrayMatrix
     packB propB lowerB upperB measB vertB horizB heightB widthB b
ArrMatrix.lift1 ((Array (Full Size vert horiz height widthA) a
  -> Array (Full Size vert horiz height widthB) a)
 -> Full Size vert horiz height widthA a
 -> Full Size vert horiz height widthB a)
-> ((widthA -> widthB)
    -> Array (Full Size vert horiz height widthA) a
    -> Array (Full Size vert horiz height widthB) a)
-> (widthA -> widthB)
-> Full Size vert horiz height widthA a
-> Full Size vert horiz height widthB a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (widthA -> widthB)
-> Array (Full Size vert horiz height widthA) a
-> Array (Full Size vert horiz height widthB) a
forall widthA widthB vert horiz height a.
(C widthA, C widthB, C vert, C horiz) =>
(widthA -> widthB)
-> Full Size vert horiz height widthA a
-> Full Size vert horiz height widthB a
Plain.mapWidth


transpose ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   Full meas vert horiz height width a -> Full meas horiz vert width height a
transpose :: Full meas vert horiz height width a
-> Full meas horiz vert width height a
transpose = Full meas vert horiz height width a
-> Full meas horiz vert width height a
forall property lower upper meas vert horiz height width a.
(Property property, Strip lower, Strip upper, Measure meas, C vert,
 C horiz) =>
Unpacked property lower upper meas vert horiz height width a
-> Unpacked property upper lower meas horiz vert width height a
Unpacked.transpose

{- |
conjugate transpose

Problem: @adjoint a \<\> a@ is always square,
but how to convince the type checker to choose the Square type?

Anser: Use @Hermitian.toSquare $ Hermitian.gramian a@ instead.
-}
adjoint ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C height, Shape.C width, Class.Floating a) =>
   Full meas vert horiz height width a -> Full meas horiz vert width height a
adjoint :: Full meas vert horiz height width a
-> Full meas horiz vert width height a
adjoint = (PlainArray
   Unpacked Arbitrary Filled Filled meas vert horiz height width a
 -> PlainArray
      Unpacked Arbitrary Filled Filled meas horiz vert width height a)
-> Full meas vert horiz height width a
-> Full meas horiz vert width height a
forall packA propA lowerA upperA measA vertA horizA heightA widthA
       packB propB lowerB upperB measB vertB horizB heightB widthB a b.
(ToPlain
   packA propA lowerA upperA measA vertA horizA heightA widthA,
 FromPlain
   packB propB lowerB upperB measB vertB horizB heightB widthB) =>
(PlainArray
   packA propA lowerA upperA measA vertA horizA heightA widthA a
 -> PlainArray
      packB propB lowerB upperB measB vertB horizB heightB widthB b)
-> ArrayMatrix
     packA propA lowerA upperA measA vertA horizA heightA widthA a
-> ArrayMatrix
     packB propB lowerB upperB measB vertB horizB heightB widthB b
ArrMatrix.lift1 PlainArray
  Unpacked Arbitrary Filled Filled meas vert horiz height width a
-> PlainArray
     Unpacked Arbitrary Filled Filled meas horiz vert width height a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, C width, Floating a) =>
Full meas vert horiz height width a
-> Full meas horiz vert width height a
Basic.adjoint


multiplyVector ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C height, Shape.C width, Eq width, Class.Floating a) =>
   Full meas vert horiz height width a -> Vector width a -> Vector height a
multiplyVector :: Full meas vert horiz height width a
-> Vector width a -> Vector height a
multiplyVector = Full meas vert horiz height width a
-> Vector width a -> Vector height a
forall property lower upper meas vert horiz height width a.
(Property property, Strip lower, Strip upper, Measure meas, C vert,
 C horiz, C height, C width, Eq width, Floating a) =>
Unpacked property lower upper meas vert horiz height width a
-> Vector width a -> Vector height a
Unpacked.multiplyVector

multiply ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C height,
    Shape.C fuse, Eq fuse,
    Shape.C width,
    Class.Floating a) =>
   Full meas vert horiz height fuse a ->
   Full meas vert horiz fuse width a ->
   Full meas vert horiz height width a
multiply :: Full meas vert horiz height fuse a
-> Full meas vert horiz fuse width a
-> Full meas vert horiz height width a
multiply = Full meas vert horiz height fuse a
-> Full meas vert horiz fuse width a
-> Full meas vert horiz height width a
forall propertyA lowerA upperA propertyB lowerB upperB propertyC
       lowerC upperC meas vert horiz height fuse width a.
(Property propertyA, Strip lowerA, Strip upperA,
 Property propertyB, Strip lowerB, Strip upperB, Property propertyC,
 Strip lowerC, Strip upperC, Measure meas, C vert, C horiz,
 C height, C fuse, Eq fuse, C width, Floating a) =>
Unpacked propertyA lowerA upperA meas vert horiz height fuse a
-> Unpacked propertyB upperB lowerB meas vert horiz fuse width a
-> Unpacked propertyC upperC lowerC meas vert horiz height width a
Unpacked.multiply