{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
module Numeric.LAPACK.Matrix.Type where

import qualified Numeric.LAPACK.Matrix.Plain.Format as ArrFormat
import qualified Numeric.LAPACK.Output as Output
import qualified Numeric.LAPACK.Permutation.Private as Perm
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape
import qualified Numeric.LAPACK.Matrix.Shape.Omni as Omni
import qualified Numeric.LAPACK.Matrix.Extent.Strict as ExtentStrict
import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent
import Numeric.LAPACK.Matrix.Layout.Private (Empty, Filled)
import Numeric.LAPACK.Matrix.Extent.Private (Extent, Shape, Small)
import Numeric.LAPACK.Output (Output)

import qualified Numeric.Netlib.Class as Class

import qualified Hyper

import qualified Control.DeepSeq as DeepSeq

import qualified Data.Array.Comfort.Shape as Shape

import Data.Function.HT (Id)
import Data.Monoid (Monoid, mempty, mappend)
import Data.Semigroup (Semigroup, (<>))



data family
   Matrix typ extraLower extraUpper lower upper meas vert horiz height width a

type Quadratic typ extraLower extraUpper lower upper sh =
      QuadraticMeas typ extraLower extraUpper lower upper Shape sh sh
type QuadraticMeas typ extraLower extraUpper lower upper meas =
      Matrix typ extraLower extraUpper lower upper meas Small Small


asQuadratic ::
   Id (QuadraticMeas typ extraLower extraUpper lower upper meas height width a)
asQuadratic :: Id
  (QuadraticMeas
     typ extraLower extraUpper lower upper meas height width a)
asQuadratic = Id
  (QuadraticMeas
     typ extraLower extraUpper lower upper meas height width a)
forall a. a -> a
id


data Product fuse
data instance
   Matrix (Product fuse) xl xu lower upper meas vert horiz height width a where
      Product ::
         (Omni.MultipliedBands lowerA lowerB ~ lowerC,
          Omni.MultipliedBands lowerB lowerA ~ lowerC,
          Omni.MultipliedBands upperA upperB ~ upperC,
          Omni.MultipliedBands upperB upperA ~ upperC) =>
         Matrix typA xlA xuA lowerA upperA meas vert horiz height fuse a ->
         Matrix typB xlB xuB lowerB upperB meas vert horiz fuse width a ->
         Matrix (Product fuse)
            (typA,lowerA,lowerB,xlA,xlB) (typB,upperB,upperA,xuB,xuA)
            lowerC upperC meas vert horiz height width a


data Scale
data instance
   Matrix Scale xl xu lower upper meas vert horiz height width a where
      Scale :: sh -> a -> Quadratic Scale () () Empty Empty sh a

deriving instance
   (Shape.C height, Show height, Show a) =>
   Show (Matrix Scale xl xu lower upper meas vert horiz height width a)


data Identity
data instance
   Matrix Identity xl xu lower upper meas vert horiz height width a where
      Identity ::
         (Extent.Measure meas) =>
         Extent meas Small Small height width ->
         QuadraticMeas Identity () () Empty Empty meas height width a


data Permutation
data instance
   Matrix Permutation xl xu lower upper meas vert horiz height width a where
   Permutation ::
      Perm.Permutation sh -> Quadratic Permutation () () lower upper sh a

deriving instance
   (Shape.C height, Show height) =>
   Show (Matrix Permutation xl xu lower upper meas vert horiz height width a)

deriving instance
   (Shape.C height, Eq height) =>
   Eq (Matrix Permutation xl xu lower upper meas vert horiz height width a)


instance
   (NFData typ,
    Extent.Measure meas, Extent.C vert, Extent.C horiz,
    DeepSeq.NFData height, DeepSeq.NFData width, DeepSeq.NFData a) =>
   DeepSeq.NFData (Matrix typ xl xu lower upper meas vert horiz height width a)
      where
   rnf :: Matrix typ xl xu lower upper meas vert horiz height width a -> ()
rnf = Matrix typ xl xu lower upper meas vert horiz height width a -> ()
forall typ meas vert horiz height width a xl xu lower upper.
(NFData typ, Measure meas, C vert, C horiz, NFData height,
 NFData width, NFData a) =>
Matrix typ xl xu lower upper meas vert horiz height width a -> ()
rnf

class NFData typ where
   rnf ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz,
       DeepSeq.NFData height, DeepSeq.NFData width, DeepSeq.NFData a) =>
      Matrix typ xl xu lower upper meas vert horiz height width a -> ()



instance
   (FormatMatrix typ, Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C width, Shape.C height, Class.Floating a) =>
      Hyper.Display
         (Matrix typ xl xu lower upper meas vert horiz height width a) where
   display :: Matrix typ xl xu lower upper meas vert horiz height width a
-> Graphic
display = Html -> Graphic
Output.hyper (Html -> Graphic)
-> (Matrix typ xl xu lower upper meas vert horiz height width a
    -> Html)
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Graphic
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Html
forall typ meas vert horiz width height a out xl xu lower upper.
(FormatMatrix typ, Measure meas, C vert, C horiz, C width,
 C height, Floating a, Output out) =>
String
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> out
formatMatrix String
ArrFormat.deflt


class FormatMatrix typ where
   {-
   We use constraint @(Class.Floating a)@ and not @(Format a)@
   because it allows us to align the components of complex numbers.
   -}
   formatMatrix ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz,
       Shape.C width, Shape.C height, Class.Floating a, Output out) =>
      String ->
      Matrix typ xl xu lower upper meas vert horiz height width a ->
      out

instance FormatMatrix Scale where
   formatMatrix :: String
-> Matrix Scale xl xu lower upper meas vert horiz height width a
-> out
formatMatrix String
fmt (Scale shape a) =
      String -> Order -> height -> [a] -> out
forall size a out.
(C size, Floating a, Output out) =>
String -> Order -> size -> [a] -> out
ArrFormat.formatDiagonal String
fmt Order
Layout.RowMajor height
shape ([a] -> out) -> [a] -> out
forall a b. (a -> b) -> a -> b
$
      Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (height -> Int
forall sh. C sh => sh -> Int
Shape.size height
shape) a
a

instance FormatMatrix Permutation where
   formatMatrix :: String
-> Matrix
     Permutation xl xu lower upper meas vert horiz height width a
-> out
formatMatrix String
_fmt (Permutation perm) = Permutation height -> out
forall sh out. (C sh, Output out) => Permutation sh -> out
Perm.format Permutation height
perm



instance
   (MultiplySame typ xl xu, MatrixShape.PowerStrip lower, MatrixShape.PowerStrip upper,
    Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, height ~ width, Class.Floating a) =>
      Semigroup (Matrix typ xl xu lower upper meas vert horiz height width a)
         where
   <> :: Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
(<>) = Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
forall typ xl xu matrix lower upper meas vert horiz sh a.
(MultiplySame typ xl xu,
 matrix ~ Matrix typ xl xu lower upper meas vert horiz sh sh a,
 PowerStrip lower, PowerStrip upper, Measure meas, C vert, C horiz,
 C sh, Eq sh, Floating a) =>
matrix -> matrix -> matrix
multiplySame

class (Box typ) => MultiplySame typ xl xu where
   multiplySame ::
      (matrix ~ Matrix typ xl xu lower upper meas vert horiz sh sh a,
       MatrixShape.PowerStrip lower, MatrixShape.PowerStrip upper,
       Extent.Measure meas, Extent.C vert, Extent.C horiz,
       Shape.C sh, Eq sh, Class.Floating a) =>
      matrix -> matrix -> matrix

instance (xl ~ (), xu ~ ()) => MultiplySame Scale xl xu where
   multiplySame :: matrix -> matrix -> matrix
multiplySame =
      String
-> (Matrix Scale () () lower upper meas vert horiz sh sh a -> sh)
-> (a
    -> Matrix Scale () () lower upper meas vert horiz sh sh a
    -> matrix)
-> Matrix Scale () () lower upper meas vert horiz sh sh a
-> Matrix Scale () () lower upper meas vert horiz sh sh a
-> matrix
forall shape b a c xl xu lower upper meas vert horiz.
Eq shape =>
String
-> (b -> shape)
-> (a -> b -> c)
-> Matrix Scale xl xu lower upper meas vert horiz shape shape a
-> b
-> c
scaleWithCheck String
"Scale.multiplySame" Matrix Scale () () lower upper meas vert horiz sh sh a -> sh
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> height
height
         (\a
a (Scale shape b) -> sh -> a -> Quadratic Scale () () Empty Empty sh a
forall sh a. sh -> a -> Quadratic Scale () () Empty Empty sh a
Scale sh
shape (a -> Quadratic Scale () () Empty Empty sh a)
-> a -> Quadratic Scale () () Empty Empty sh a
forall a b. (a -> b) -> a -> b
$ a
aa -> a -> a
forall a. Num a => a -> a -> a
*a
b)

instance (xl ~ (), xu ~ ()) => MultiplySame Permutation xl xu where
   multiplySame :: matrix -> matrix -> matrix
multiplySame (Permutation a) (Permutation b) =
      Permutation sh -> Quadratic Permutation () () lower upper sh a
forall sh lower upper a.
Permutation sh -> Quadratic Permutation () () lower upper sh a
Permutation (Permutation sh -> Quadratic Permutation () () lower upper sh a)
-> Permutation sh -> Quadratic Permutation () () lower upper sh a
forall a b. (a -> b) -> a -> b
$ Permutation sh -> Permutation sh -> Permutation sh
forall sh.
(C sh, Eq sh) =>
Permutation sh -> Permutation sh -> Permutation sh
Perm.multiply Permutation sh
b Permutation sh
a


instance
   (MultiplySame typ xl xu, StaticIdentity typ xl xu lower upper,
    MatrixShape.PowerStrip lower, MatrixShape.PowerStrip upper,
    meas ~ Shape, vert ~ Small, horiz ~ Small,
    Shape.Static height, Eq height, height ~ width, Class.Floating a) =>
      Monoid (Matrix typ xl xu lower upper meas vert horiz height width a) where
   mappend :: Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
mappend = Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xl xu lower upper meas vert horiz height width a
forall a. Semigroup a => a -> a -> a
(<>)
   mempty :: Matrix typ xl xu lower upper meas vert horiz height width a
mempty = Matrix typ xl xu lower upper meas vert horiz height width a
forall typ xl xu lower upper sh a.
(StaticIdentity typ xl xu lower upper, Static sh, Floating a) =>
Quadratic typ xl xu lower upper sh a
staticIdentity

class StaticIdentity typ xl xu lower upper where
   staticIdentity ::
      (Shape.Static sh, Class.Floating a) =>
      Quadratic typ xl xu lower upper sh a

instance
   (xl ~ (), xu ~ (), lower ~ Empty, upper ~ Empty) =>
      StaticIdentity Scale xl xu lower upper where
   staticIdentity :: Quadratic Scale xl xu lower upper sh a
staticIdentity = sh -> a -> Quadratic Scale () () Empty Empty sh a
forall sh a. sh -> a -> Quadratic Scale () () Empty Empty sh a
Scale sh
forall sh. Static sh => sh
Shape.static a
1

instance
   (xl ~ (), xu ~ (), lower ~ Filled, upper ~ Filled) =>
      StaticIdentity Permutation xl xu lower upper where
   staticIdentity :: Quadratic Permutation xl xu lower upper sh a
staticIdentity = Permutation sh -> Quadratic Permutation () () lower upper sh a
forall sh lower upper a.
Permutation sh -> Quadratic Permutation () () lower upper sh a
Permutation (Permutation sh -> Quadratic Permutation () () lower upper sh a)
-> Permutation sh -> Quadratic Permutation () () lower upper sh a
forall a b. (a -> b) -> a -> b
$ sh -> Permutation sh
forall sh. C sh => sh -> Permutation sh
Perm.identity sh
forall sh. Static sh => sh
Shape.static


scaleWithCheck :: (Eq shape) =>
   String -> (b -> shape) ->
   (a -> b -> c) ->
   Matrix Scale xl xu lower upper meas vert horiz shape shape a ->
   b -> c
scaleWithCheck :: String
-> (b -> shape)
-> (a -> b -> c)
-> Matrix Scale xl xu lower upper meas vert horiz shape shape a
-> b
-> c
scaleWithCheck String
name b -> shape
getSize a -> b -> c
f (Scale shape a) b
b =
   if shape
shape shape -> shape -> Bool
forall a. Eq a => a -> a -> Bool
== b -> shape
getSize b
b
      then a -> b -> c
f a
a b
b
      else String -> c
forall a. HasCallStack => String -> a
error (String -> c) -> String -> c
forall a b. (a -> b) -> a -> b
$ String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": dimensions mismatch"


class Box typ where
   extent ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
      Matrix typ xl xu lower upper meas vert horiz height width a ->
      Extent.Extent meas vert horiz height width
   height ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
      Matrix typ xl xu lower upper meas vert horiz height width a -> height
   height = Extent meas vert horiz 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 meas vert horiz height width -> height)
-> (Matrix typ xl xu lower upper meas vert horiz height width a
    -> Extent meas vert horiz height width)
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> height
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix typ xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
extent
   width ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
      Matrix typ xl xu lower upper meas vert horiz height width a -> width
   width = Extent meas vert horiz 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 meas vert horiz height width -> width)
-> (Matrix typ xl xu lower upper meas vert horiz height width a
    -> Extent meas vert horiz height width)
-> Matrix typ xl xu lower upper meas vert horiz height width a
-> width
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix typ xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
extent

instance Box Scale where
   extent :: Matrix Scale xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
extent (Scale shape _) = height -> Square height
forall sh. sh -> Square sh
Extent.square height
shape
   height :: Matrix Scale xl xu lower upper meas vert horiz height width a
-> height
height (Scale shape _) = height
shape
   width :: Matrix Scale xl xu lower upper meas vert horiz height width a
-> width
width (Scale shape _) = height
width
shape

instance Box Identity where
   extent :: Matrix Identity xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
extent (Identity extent_) = Extent meas vert horiz height width
Extent meas Small Small height width
extent_

instance Box Permutation where
   extent :: Matrix Permutation xl xu lower upper meas vert horiz height width a
-> Extent meas vert horiz height width
extent (Permutation perm) = height -> Square height
forall sh. sh -> Square sh
Extent.square (height -> Square height) -> height -> Square height
forall a b. (a -> b) -> a -> b
$ Permutation height -> height
forall sh. Permutation sh -> sh
Perm.size Permutation height
perm
   height :: Matrix Permutation xl xu lower upper meas vert horiz height width a
-> height
height (Permutation perm) = Permutation height -> height
forall sh. Permutation sh -> sh
Perm.size Permutation height
perm
   width :: Matrix Permutation xl xu lower upper meas vert horiz height width a
-> width
width (Permutation perm) = Permutation height -> height
forall sh. Permutation sh -> sh
Perm.size Permutation height
perm

{- ToDo: requires parameters xl and xu for Box class

instance (Eq fuse) => Box (Product fuse) where
   extent (Product a b) =
      fromMaybe (error "Matrix.Product: shapes mismatch") $
      Extent.fuse (extent a) (extent b)
-}

squareSize :: (Box typ) => Quadratic typ xl xu lower upper sh a -> sh
squareSize :: Quadratic typ xl xu lower upper sh a -> sh
squareSize = Quadratic typ xl xu lower upper sh a -> sh
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> height
height

indices ::
   (Box typ, Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
   (Shape.Indexed height, Shape.Indexed width) =>
   Matrix typ xl xu lower upper meas vert horiz height width a ->
   [(Shape.Index height, Shape.Index width)]
indices :: Matrix typ xl xu lower upper meas vert horiz height width a
-> [(Index height, Index width)]
indices Matrix typ xl xu lower upper meas vert horiz height width a
sh = (height, width) -> [Index (height, width)]
forall sh. Indexed sh => sh -> [Index sh]
Shape.indices (Matrix typ xl xu lower upper meas vert horiz height width a
-> height
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> height
height Matrix typ xl xu lower upper meas vert horiz height width a
sh, Matrix typ xl xu lower upper meas vert horiz height width a
-> width
forall typ meas vert horiz xl xu lower upper height width a.
(Box typ, Measure meas, C vert, C horiz) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> width
width Matrix typ xl xu lower upper meas vert horiz height width a
sh)


class (Box typ) => ToQuadratic typ where
   heightToQuadratic ::
      (Extent.Measure meas) =>
      QuadraticMeas typ xl xu lower upper meas height width a ->
      Quadratic typ xl xu lower upper height a
   widthToQuadratic ::
      (Extent.Measure meas) =>
      QuadraticMeas typ xl xu lower upper meas height width a ->
      Quadratic typ xl xu lower upper width a

instance ToQuadratic Scale where
   heightToQuadratic :: QuadraticMeas Scale xl xu lower upper meas height width a
-> Quadratic Scale xl xu lower upper height a
heightToQuadratic (Scale shape a) = height -> a -> Quadratic Scale () () Empty Empty height a
forall sh a. sh -> a -> Quadratic Scale () () Empty Empty sh a
Scale height
shape a
a
   widthToQuadratic :: QuadraticMeas Scale xl xu lower upper meas height width a
-> Quadratic Scale xl xu lower upper width a
widthToQuadratic (Scale shape a) = height -> a -> Quadratic Scale () () Empty Empty height a
forall sh a. sh -> a -> Quadratic Scale () () Empty Empty sh a
Scale height
shape a
a

instance ToQuadratic Identity where
   heightToQuadratic :: QuadraticMeas Identity xl xu lower upper meas height width a
-> Quadratic Identity xl xu lower upper height a
heightToQuadratic (Identity extent_) =
      Extent Shape Small Small height height
-> QuadraticMeas Identity () () Empty Empty Shape height height a
forall meas height width a.
Measure meas =>
Extent meas Small Small height width
-> QuadraticMeas Identity () () Empty Empty meas height width a
Identity (Extent Shape Small Small height height
 -> QuadraticMeas Identity () () Empty Empty Shape height height a)
-> Extent Shape Small Small height height
-> QuadraticMeas Identity () () Empty Empty Shape height height a
forall a b. (a -> b) -> a -> b
$ height -> Extent Shape Small Small height height
forall sh. sh -> Square sh
Extent.square (height -> Extent Shape Small Small height height)
-> height -> Extent Shape Small Small height height
forall a b. (a -> b) -> a -> b
$ Extent meas Small Small 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 meas Small Small height width
extent_
   widthToQuadratic :: QuadraticMeas Identity xl xu lower upper meas height width a
-> Quadratic Identity xl xu lower upper width a
widthToQuadratic (Identity extent_) =
      Extent Shape Small Small width width
-> QuadraticMeas Identity () () Empty Empty Shape width width a
forall meas height width a.
Measure meas =>
Extent meas Small Small height width
-> QuadraticMeas Identity () () Empty Empty meas height width a
Identity (Extent Shape Small Small width width
 -> QuadraticMeas Identity () () Empty Empty Shape width width a)
-> Extent Shape Small Small width width
-> QuadraticMeas Identity () () Empty Empty Shape width width a
forall a b. (a -> b) -> a -> b
$ width -> Extent Shape Small Small width width
forall sh. sh -> Square sh
Extent.square (width -> Extent Shape Small Small width width)
-> width -> Extent Shape Small Small width width
forall a b. (a -> b) -> a -> b
$ Extent meas Small Small 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 meas Small Small height width
extent_

instance ToQuadratic Permutation where
   heightToQuadratic :: QuadraticMeas Permutation xl xu lower upper meas height width a
-> Quadratic Permutation xl xu lower upper height a
heightToQuadratic (Permutation perm) = Permutation height
-> Quadratic Permutation () () lower upper height a
forall sh lower upper a.
Permutation sh -> Quadratic Permutation () () lower upper sh a
Permutation Permutation height
perm
   widthToQuadratic :: QuadraticMeas Permutation xl xu lower upper meas height width a
-> Quadratic Permutation xl xu lower upper width a
widthToQuadratic (Permutation perm) = Permutation height
-> Quadratic Permutation () () lower upper height a
forall sh lower upper a.
Permutation sh -> Quadratic Permutation () () lower upper sh a
Permutation Permutation height
perm


class (Box typ) => MapExtent typ xl xu lower upper where
   mapExtent ::
      (Extent.Measure measA, Extent.C vertA, Extent.C horizA) =>
      (Extent.Measure measB, Extent.C vertB, Extent.C horizB) =>
      ExtentStrict.Map measA vertA horizA measB vertB horizB height width ->
      Matrix typ xl xu lower upper measA vertA horizA height width a ->
      Matrix typ xl xu lower upper measB vertB horizB height width a


class (Box typ) => Transpose typ where
   transpose ::
      (Extent.Measure meas, Extent.C vert, Extent.C horiz) =>
      (Shape.C width, Shape.C height, Class.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

instance Transpose Scale where
   transpose :: Matrix Scale xl xu lower upper meas vert horiz height width a
-> Matrix Scale xu xl upper lower meas horiz vert width height a
transpose (Scale shape a) = height -> a -> Quadratic Scale () () Empty Empty height a
forall sh a. sh -> a -> Quadratic Scale () () Empty Empty sh a
Scale height
shape a
a

instance Transpose Identity where
   transpose :: Matrix Identity xl xu lower upper meas vert horiz height width a
-> Matrix Identity xu xl upper lower meas horiz vert width height a
transpose (Identity extent_) = Extent meas Small Small width height
-> QuadraticMeas Identity () () Empty Empty meas width height a
forall meas height width a.
Measure meas =>
Extent meas Small Small height width
-> QuadraticMeas Identity () () Empty Empty meas height width a
Identity (Extent meas Small Small width height
 -> QuadraticMeas Identity () () Empty Empty meas width height a)
-> Extent meas Small Small width height
-> QuadraticMeas Identity () () Empty Empty meas width height a
forall a b. (a -> b) -> a -> b
$ Extent meas Small Small height width
-> Extent meas Small Small width height
forall meas vert horiz height width.
(Measure meas, C vert, C horiz) =>
Extent meas vert horiz height width
-> Extent meas horiz vert width height
Extent.transpose Extent meas Small Small height width
extent_

instance Transpose Permutation where
   transpose :: Matrix Permutation xl xu lower upper meas vert horiz height width a
-> Matrix
     Permutation xu xl upper lower meas horiz vert width height a
transpose (Permutation perm) = Permutation height
-> Quadratic Permutation () () upper lower height a
forall sh lower upper a.
Permutation sh -> Quadratic Permutation () () lower upper sh a
Permutation (Permutation height
 -> Quadratic Permutation () () upper lower height a)
-> Permutation height
-> Quadratic Permutation () () upper lower height a
forall a b. (a -> b) -> a -> b
$ Permutation height -> Permutation height
forall sh. C sh => Permutation sh -> Permutation sh
Perm.transpose Permutation height
perm

{-
instance (Shape.C fuse, Eq fuse) => Transpose (Product fuse) where
   transpose (Product a b) = Product (transpose b) (transpose a)
-}


swapMultiply ::
   (Transpose typA, Transpose typB) =>
   (Extent.Measure measA, Extent.C vertA, Extent.C horizA) =>
   (Extent.Measure measB, Extent.C vertB, Extent.C horizB) =>
   (Shape.C heightA, Shape.C widthA) =>
   (Shape.C heightB, Shape.C widthB) =>
   (Class.Floating a) =>
   (matrix ->
    Matrix typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a ->
    Matrix typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a) ->
   Matrix typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a ->
   matrix ->
   Matrix typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
swapMultiply :: (matrix
 -> Matrix
      typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
 -> Matrix
      typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a)
-> Matrix
     typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
-> matrix
-> Matrix
     typB xlB xuB lowerB upperB measB vertB horizB heightB widthB a
swapMultiply matrix
-> Matrix
     typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
-> Matrix
     typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
multiplyTrans Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a matrix
b =
   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 meas vert horiz width height a xl xu lower upper.
(Transpose typ, Measure meas, C vert, C horiz, C width, C height,
 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
transpose (Matrix
   typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
 -> Matrix
      typB xlB xuB lowerB upperB measB vertB horizB heightB widthB 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 a b. (a -> b) -> a -> b
$ matrix
-> Matrix
     typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
-> Matrix
     typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
multiplyTrans matrix
b (Matrix
   typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
 -> Matrix
      typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a)
-> Matrix
     typA xuA xlA upperA lowerA measA horizA vertA widthA heightA a
-> Matrix
     typB xuB xlB upperB lowerB measB horizB vertB widthB heightB a
forall a b. (a -> b) -> a -> b
$ 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 meas vert horiz width height a xl xu lower upper.
(Transpose typ, Measure meas, C vert, C horiz, C width, C height,
 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
transpose Matrix
  typA xlA xuA lowerA upperA measA vertA horizA heightA widthA a
a

powerStrips ::
   (MatrixShape.PowerStrip lower, MatrixShape.PowerStrip upper) =>
   Matrix typ xl xu lower upper meas vert horiz height width a ->
   (MatrixShape.PowerStripSingleton lower, MatrixShape.PowerStripSingleton upper)
powerStrips :: Matrix typ xl xu lower upper meas vert horiz height width a
-> (PowerStripSingleton lower, PowerStripSingleton upper)
powerStrips Matrix typ xl xu lower upper meas vert horiz height width a
_ = (PowerStripSingleton lower
forall c. PowerStrip c => PowerStripSingleton c
MatrixShape.powerStripSingleton, PowerStripSingleton upper
forall c. PowerStrip c => PowerStripSingleton c
MatrixShape.powerStripSingleton)

strips ::
   (MatrixShape.Strip lower, MatrixShape.Strip upper) =>
   Matrix typ xl xu lower upper meas vert horiz height width a ->
   (MatrixShape.StripSingleton lower, MatrixShape.StripSingleton upper)
strips :: Matrix typ xl xu lower upper meas vert horiz height width a
-> (StripSingleton lower, StripSingleton upper)
strips Matrix typ xl xu lower upper meas vert horiz height width a
_ = (StripSingleton lower
forall c. Strip c => StripSingleton c
MatrixShape.stripSingleton, StripSingleton upper
forall c. Strip c => StripSingleton c
MatrixShape.stripSingleton)