{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE EmptyDataDecls #-}
{- |
This module provides an infix operator and some data constructors
that shall resemble mathematical notation.
E.g. you can write @a#^T@ for @Matrix.transpose a@.
It is clearly abuse of the type system
because I suspect you will never write algorithms
that are generic in the superscript type.
-}
module Numeric.LAPACK.Matrix.Superscript where

import qualified Numeric.LAPACK.Singular as Singular
import qualified Numeric.LAPACK.Matrix.Shape.Omni as Omni
import qualified Numeric.LAPACK.Matrix.Layout as Layout
import qualified Numeric.LAPACK.Matrix.Extent as Extent
import qualified Numeric.LAPACK.Matrix.Array.Private as ArrMatrix
import qualified Numeric.LAPACK.Matrix as Matrix
import Numeric.LAPACK.Matrix.Layout.Private (Filled)
import Numeric.LAPACK.Matrix.Extent (Shape, Small)
import Numeric.LAPACK.Matrix (Matrix)

import qualified Data.Array.Comfort.Shape as Shape

import qualified Numeric.Netlib.Class as Class


{- |
left associative in contrast to ^, ^^ etc.
because there is no law analogous to power law @(x^a)^b = x^(a*b)@.
-}
infixl 8 #^

class Superscript sup where
   data Exponent sup
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
   (#^) ::
      (Extent.Measure measA, Extent.C vertA, Extent.C horizA) =>
      (Shape.C widthA, Shape.C heightA) =>
      (Extent.Measure measB, Extent.C vertB, Extent.C horizB) =>
      (Shape.C widthB, Shape.C heightB) =>
      (Class.Floating a) =>
      Matrix typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a ->
      Exponent sup
         typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
         typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a ->
      Matrix typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a


data None
instance Superscript None where
   data Exponent None
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         N ::
            Exponent None
               typ xl xu lower upper meas vert horiz height width
               typ xl xu lower upper meas vert horiz height width a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     None
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exponent
  None
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
N = Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
Matrix
  typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
a


data Transpose
instance Superscript Transpose where
   data Exponent Transpose
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         T ::
            (Matrix.Transpose typ,
             Matrix.TransposeExtra typ xl, Matrix.TransposeExtra typ xu) =>
            Exponent Transpose
               typ xl xu lower upper meas vert horiz height width
               typ xu xl upper lower meas horiz vert width height a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     Transpose
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exponent
  Transpose
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
T = Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Matrix
     typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
forall typ xl xu meas vert horiz height width a lower upper.
(Transpose typ, TransposeExtra typ xl, TransposeExtra typ xu,
 Measure meas, C vert, C horiz, C height, C width, Floating a) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xu xl upper lower meas horiz vert width height a
Matrix.transpose Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a


data Adjoint
instance Superscript Adjoint where
   data Exponent Adjoint
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         A ::
            (Matrix.Transpose typ, Matrix.Complex typ,
             Matrix.TransposeExtra typ xl, Matrix.TransposeExtra typ xu) =>
            Exponent Adjoint
               typ xl xu lower upper meas vert horiz height width
               typ xu xl upper lower meas horiz vert width height a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     Adjoint
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exponent
  Adjoint
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
A = Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Matrix
     typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
forall typ xl xu meas vert horiz height width a lower upper.
(Transpose typ, Complex typ, TransposeExtra typ xl,
 TransposeExtra typ xu, Measure meas, C vert, C horiz, C height,
 C width, Floating a) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xu xl upper lower meas horiz vert width height a
Matrix.adjoint Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a


data Conjugate
instance Superscript Conjugate where
   data Exponent Conjugate
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         C ::
            (Matrix.Complex typ) =>
            Exponent Conjugate
               typ xl xu lower upper meas vert horiz height width
               typ xl xu lower upper meas vert horiz height width a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     Conjugate
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exponent
  Conjugate
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
C = Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Matrix
     typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
forall typ xl xu lower upper meas vert horiz height width
       (matrix :: * -> *) a.
(Complex typ,
 Matrix typ xl xu lower upper meas vert horiz height width ~ matrix,
 Measure meas, C vert, C horiz, C height, C width, Floating a) =>
matrix a -> matrix a
Matrix.conjugate Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a


data Inverse
instance Superscript Inverse where
   data Exponent Inverse
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         -- We could relax lowerB and upperB using Filled type function
         Inv ::
            (Matrix.Inverse typ,
             Matrix.InverseExtra typ xl, Matrix.InverseExtra typ xu,
             Omni.PowerStrip lower, Omni.PowerStrip upper) =>
            Exponent Inverse
               typ xl xu lower upper meas Small Small height width
               typ xl xu lower upper meas Small Small width height a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     Inverse
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exponent
  Inverse
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
Inv = QuadraticMeas typA xlA xuA lowerA upperA measA heightA widthA a
-> QuadraticMeas typA xlA xuA lowerA upperA measA widthA heightA a
forall typ xl xu lower upper meas height width a.
(Inverse typ, InverseExtra typ xl, InverseExtra typ xu,
 PowerStrip lower, PowerStrip upper, Measure meas, C height,
 C width, Floating a) =>
QuadraticMeas typ xl xu lower upper meas height width a
-> QuadraticMeas typ xl xu lower upper meas width height a
Matrix.inverse Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
QuadraticMeas typA xlA xuA lowerA upperA measA heightA widthA a
a


data PseudoInverse
instance Superscript PseudoInverse where
   data Exponent PseudoInverse
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         Pseudo ::
            (typ ~ ArrMatrix.Array Layout.Unpacked Omni.Arbitrary) =>
            Matrix.RealOf a ->
            Exponent PseudoInverse
               typ () () Filled Filled Shape Small Small sh sh
               typ () () Filled Filled Shape Small Small sh sh a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     PseudoInverse
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Pseudo rcond = (Int, Full measA horizA vertA widthA heightA a)
-> Full measA horizA vertA widthA heightA a
forall a b. (a, b) -> b
snd ((Int, Full measA horizA vertA widthA heightA a)
 -> Full measA horizA vertA widthA heightA a)
-> (Int, Full measA horizA vertA widthA heightA a)
-> Full measA horizA vertA widthA heightA a
forall a b. (a -> b) -> a -> b
$ RealOf a
-> Full measA vertA horizA heightA widthA a
-> (Int, Full measA horizA vertA widthA heightA a)
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, C width, Floating a) =>
RealOf a
-> Full meas vert horiz height width a
-> (Int, Full meas horiz vert width height a)
Singular.pseudoInverseRCond RealOf a
rcond Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
Full measA vertA horizA heightA widthA a
a


data Power
instance Superscript Power where
   data Exponent Power
      typA xlA xuA lowerA upperA measA vertA horizA heightA widthA
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a where
         -- We could relax lowerB and upperB using Filled type function
         Exp ::
            (Matrix.Power typ,
             Matrix.PowerExtra typ xl, Matrix.PowerExtra typ xu,
             Omni.PowerStrip lower, Omni.PowerStrip upper) =>
            Integer ->
            Exponent Power
               typ xl xu lower upper Shape Small Small sh sh
               typ xl xu lower upper Shape Small Small sh sh a
   Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a#^ :: Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> Exponent
     Power
     typA
     xlA
     xuA
     lowerA
     upperA
     measA
     vertA
     horizA
     heightA
     widthA
     typB
     xlB
     xuB
     lowerB
     upperB
     measB
     vertB
     horizB
     heightB
     widthB
     a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
#^Exp n = Integer
-> Quadratic typA xlA xuA lowerA upperA heightA a
-> Quadratic typA xlA xuA lowerA upperA heightA a
forall typ xl xu lower upper sh a.
(Power typ, PowerExtra typ xl, PowerExtra typ xu, PowerStrip lower,
 PowerStrip upper, C sh, Floating a) =>
Integer
-> Quadratic typ xl xu lower upper sh a
-> Quadratic typ xl xu lower upper sh a
Matrix.power Integer
n Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
Quadratic typA xlA xuA lowerA upperA heightA a
a