{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
module Numeric.LAPACK.Matrix.Permutation (
   Permutation,
   size,
   identity,
   Mod.Inversion(NonInverted,Inverted),
   Perm.inversionFromTransposition,
   fromPermutation,
   toPermutation,
   toSquare,
   determinant,
   transpose,
   multiplyVector,
   multiplyFull,
   ) where

import qualified Numeric.LAPACK.Matrix.Array.Private as ArrMatrix
import qualified Numeric.LAPACK.Matrix.Type.Private as Matrix
import qualified Numeric.LAPACK.Matrix.Shape.Omni as Omni
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent
import qualified Numeric.BLAS.Matrix.Modifier as Mod
import qualified Numeric.LAPACK.Permutation.Private as Plain
import qualified Numeric.LAPACK.Permutation as Perm
import Numeric.LAPACK.Matrix.Type.Private (Matrix(Permutation))
import Numeric.LAPACK.Vector (Vector)

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Shape as Shape


type Permutation sh =
      FlexPermutation Layout.Filled Layout.Filled sh
type FlexPermutation lower upper sh =
      Matrix.Quadratic Matrix.Permutation () () lower upper sh

size :: FlexPermutation lower upper sh a -> sh
size :: forall lower upper sh a. FlexPermutation lower upper sh a -> sh
size (Permutation Permutation sh
perm) = Permutation sh -> sh
forall sh. Permutation sh -> sh
Perm.size Permutation sh
perm

identity :: (Shape.C sh) => sh -> FlexPermutation lower upper sh a
identity :: forall sh lower upper a.
C sh =>
sh -> FlexPermutation lower upper sh a
identity = Permutation sh
-> Matrix Permutation () () lower upper Shape Small Small sh sh a
forall height lower upper a.
Permutation height
-> Matrix
     Permutation () () lower upper Shape Small Small height height a
Permutation (Permutation sh
 -> Matrix Permutation () () lower upper Shape Small Small sh sh a)
-> (sh -> Permutation sh)
-> sh
-> Matrix Permutation () () lower upper Shape Small Small sh sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. sh -> Permutation sh
forall sh. C sh => sh -> Permutation sh
Perm.identity

fromPermutation ::
   (Shape.C sh) => Perm.Permutation sh -> Permutation sh a
fromPermutation :: forall sh a. C sh => Permutation sh -> Permutation sh a
fromPermutation = Permutation sh
-> Matrix Permutation () () Filled Filled Shape Small Small sh sh a
forall height lower upper a.
Permutation height
-> Matrix
     Permutation () () lower upper Shape Small Small height height a
Permutation

toPermutation ::
   (Shape.C sh) => FlexPermutation lower upper sh a -> Perm.Permutation sh
toPermutation :: forall sh lower upper a.
C sh =>
FlexPermutation lower upper sh a -> Permutation sh
toPermutation (Permutation Permutation sh
perm) = Permutation sh
perm

determinant ::
   (Shape.C sh, Class.Floating a) => FlexPermutation lower upper sh a -> a
determinant :: forall sh a lower upper.
(C sh, Floating a) =>
FlexPermutation lower upper sh a -> a
determinant (Permutation Permutation sh
perm) = Sign -> a
forall a. Floating a => Sign -> a
Perm.numberFromSign (Sign -> a) -> Sign -> a
forall a b. (a -> b) -> a -> b
$ Permutation sh -> Sign
forall sh. C sh => Permutation sh -> Sign
Perm.determinant Permutation sh
perm


transpose ::
   (Shape.C sh) =>
   FlexPermutation lower upper sh a -> FlexPermutation upper lower sh a
transpose :: forall sh lower upper a.
C sh =>
FlexPermutation lower upper sh a
-> FlexPermutation upper lower sh a
transpose (Permutation Permutation sh
perm) = Permutation sh
-> Matrix Permutation () () upper lower Shape Small Small sh sh a
forall height lower upper a.
Permutation height
-> Matrix
     Permutation () () lower upper Shape Small Small height height a
Permutation (Permutation sh
 -> Matrix Permutation () () upper lower Shape Small Small sh sh a)
-> Permutation sh
-> Matrix Permutation () () upper lower Shape Small Small sh sh a
forall a b. (a -> b) -> a -> b
$ Permutation sh -> Permutation sh
forall sh. C sh => Permutation sh -> Permutation sh
Perm.transpose Permutation sh
perm

toSquare ::
   (Omni.Strip lower, Omni.Strip upper, Shape.C sh, Class.Floating a) =>
   FlexPermutation lower upper sh a ->
   ArrMatrix.Quadratic Layout.Unpacked Omni.Arbitrary lower upper sh a
toSquare :: forall lower upper sh a.
(Strip lower, Strip upper, C sh, Floating a) =>
FlexPermutation lower upper sh a
-> Quadratic Unpacked Arbitrary lower upper sh a
toSquare (Permutation Permutation sh
perm) = FullArray Shape Small Small sh sh a
-> UnpackedMatrix Arbitrary lower upper Shape Small Small sh sh a
forall propertyA lowerA upperA measA vertA horizA heightA widthA a.
(Property propertyA, Strip lowerA, Strip upperA) =>
FullArray measA vertA horizA heightA widthA a
-> UnpackedMatrix
     propertyA lowerA upperA measA vertA horizA heightA widthA a
ArrMatrix.liftUnpacked0 (FullArray Shape Small Small sh sh a
 -> UnpackedMatrix Arbitrary lower upper Shape Small Small sh sh a)
-> FullArray Shape Small Small sh sh a
-> UnpackedMatrix Arbitrary lower upper Shape Small Small sh sh a
forall a b. (a -> b) -> a -> b
$ Permutation sh -> FullArray Shape Small Small sh sh a
forall sh a. (C sh, Floating a) => Permutation sh -> Square sh a
Plain.toMatrix Permutation sh
perm

multiplyVector ::
   (Shape.C size, Eq size, Class.Floating a) =>
   Mod.Inversion -> FlexPermutation lower upper size a ->
   Vector size a -> Vector size a
multiplyVector :: forall size a lower upper.
(C size, Eq size, Floating a) =>
Inversion
-> FlexPermutation lower upper size a
-> Vector size a
-> Vector size a
multiplyVector Inversion
inverted (Permutation Permutation size
perm) =
   Order
-> (General size () a -> General size () a)
-> Vector size a
-> Vector size a
forall height0 a height1 b.
Order
-> (General height0 () a -> General height1 () b)
-> Vector height0 a
-> Vector height1 b
ArrMatrix.unliftColumn Order
Layout.ColumnMajor (Inversion
-> Permutation size -> General size () a -> General size () a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, Eq height, C width,
 Floating a) =>
Inversion
-> Permutation height
-> Full meas vert horiz height width a
-> Full meas vert horiz height width a
Perm.apply Inversion
inverted Permutation size
perm)

multiplyFull ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, Shape.C width, Class.Floating a) =>
   Mod.Inversion -> FlexPermutation lower upper height a ->
   ArrMatrix.Full meas vert horiz height width a ->
   ArrMatrix.Full meas vert horiz height width a
multiplyFull :: forall meas vert horiz height width a lower upper.
(Measure meas, C vert, C horiz, C height, Eq height, C width,
 Floating a) =>
Inversion
-> FlexPermutation lower upper height a
-> Full meas vert horiz height width a
-> Full meas vert horiz height width a
multiplyFull Inversion
inverted (Permutation Permutation height
perm) = Inversion
-> Permutation height
-> Full meas vert horiz height width a
-> Full meas vert horiz height width a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, Eq height, C width,
 Floating a) =>
Inversion
-> Permutation height
-> Full meas vert horiz height width a
-> Full meas vert horiz height width a
Perm.apply Inversion
inverted Permutation height
perm