{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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
R:ExponentNonetypAxlAxuAlowerAupperAmeasAvertAhorizAheightAwidthAtypBxlBxuBlowerBupperBmeasBvertBhorizBheightBwidthBa
  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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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
R:ExponentTransposetypAxlAxuAlowerAupperAmeasAvertAhorizAheightAwidthAtypBxlBxuBlowerBupperBmeasBvertBhorizBheightBwidthBa
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
T = Matrix
  typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB 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
forall xl xu meas vert horiz height width a lower upper.
(TransposeExtra typB xl, TransposeExtra typB xu, Measure meas,
 C vert, C horiz, C height, C width, Floating a) =>
Matrix typB xl xu lower upper meas vert horiz height width a
-> Matrix typB xu xl upper lower meas horiz vert width height a
Matrix.transpose Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
Matrix
  typB xuB xlB upperB lowerB measB horizB vertB widthB heightB 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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
R:ExponentAdjointtypAxlAxuAlowerAupperAmeasAvertAhorizAheightAwidthAtypBxlBxuBlowerBupperBmeasBvertBhorizBheightBwidthBa
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
A = Matrix
  typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB 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
Matrix
  typB xuB xlB upperB lowerB measB horizB vertB widthB heightB 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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
R:ExponentConjugatetypAxlAxuAlowerAupperAmeasAvertAhorizAheightAwidthAtypBxlBxuBlowerBupperBmeasBvertBhorizBheightBwidthBa
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
C = Matrix
  typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB 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
forall xl xu lower upper meas vert horiz height width
       (matrix :: * -> *) a.
(Matrix typA 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
Matrix
  typB xlB xuB lowerB upperB measB vertB horizB heightB widthB 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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
R:ExponentInversetypAxlAxuAlowerAupperAmeasAvertAhorizAheightAwidthAtypBxlBxuBlowerBupperBmeasBvertBhorizBheightBwidthBa
  typA
  xlA
  xuA
  lowerA
  upperA
  measA
  vertA
  horizA
  heightA
  widthA
  typB
  xlB
  xuB
  lowerB
  upperB
  measB
  vertB
  horizB
  heightB
  widthB
  a
Inv = QuadraticMeas typB xlB xuB lowerB upperB measB widthB heightB a
-> QuadraticMeas typB xlB xuB lowerB upperB measB heightB widthB 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
forall xl xu lower upper meas height width a.
(InverseExtra typB xl, InverseExtra typB xu, PowerStrip lower,
 PowerStrip upper, Measure meas, C height, C width, Floating a) =>
QuadraticMeas typB xl xu lower upper meas height width a
-> QuadraticMeas typB xl xu lower upper meas width height a
Matrix.inverse Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
QuadraticMeas typB xlB xuB lowerB upperB measB widthB heightB 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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 RealOf a
rcond = (Int,
 Matrix
   typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a)
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
forall a b. (a, b) -> b
snd ((Int,
  Matrix
    typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a)
 -> Matrix
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a)
-> (Int,
    Matrix
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a)
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
forall a b. (a -> b) -> a -> b
$ RealOf a
-> Full measB horizB vertB widthB heightB a
-> (Int, Full measB vertB horizB heightB widthB 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 measB horizB vertB widthB heightB 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#^ :: forall measA vertA horizA widthA heightA measB vertB horizB widthB
       heightB a typA xlA xuA lowerA upperA typB xlB xuB lowerB upperB.
(Measure measA, C vertA, C horizA, C widthA, C heightA,
 Measure measB, C vertB, C horizB, C widthB, C heightB,
 Floating 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 Integer
n = Integer
-> Quadratic typB xlB xuB lowerB upperB heightB a
-> Quadratic typB xlB xuB lowerB upperB heightB 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
forall xl xu lower upper sh a.
(PowerExtra typB xl, PowerExtra typB xu, PowerStrip lower,
 PowerStrip upper, C sh, Floating a) =>
Integer
-> Quadratic typB xl xu lower upper sh a
-> Quadratic typB xl xu lower upper sh a
Matrix.power Integer
n Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
Quadratic typB xlB xuB lowerB upperB heightB a
a