{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
module Numeric.LAPACK.Matrix.Plain.Multiply where

import qualified Numeric.LAPACK.Matrix.Plain.Class as Plain
import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape
import qualified Numeric.LAPACK.Matrix.Shape.Box as Box
import qualified Numeric.LAPACK.Matrix.Extent.Private as ExtentPriv
import qualified Numeric.LAPACK.Matrix.Extent as Extent
import qualified Numeric.LAPACK.Matrix.BandedHermitian.Basic as BandedHermitian
import qualified Numeric.LAPACK.Matrix.Banded.Basic as Banded
import qualified Numeric.LAPACK.Matrix.Triangular.Basic as Triangular
import qualified Numeric.LAPACK.Matrix.Hermitian.Basic as Hermitian
import qualified Numeric.LAPACK.Matrix.Square.Basic as Square
import qualified Numeric.LAPACK.Matrix.Basic as Basic
import qualified Numeric.LAPACK.Vector as Vector
import Numeric.LAPACK.Matrix.Shape.Private (Empty, Filled, Unit, NonUnit)
import Numeric.LAPACK.Matrix.Extent.Private (Small)
import Numeric.LAPACK.Matrix.Triangular.Basic (Triangular)
import Numeric.LAPACK.Matrix.Basic (swapMultiply, transpose)
import Numeric.LAPACK.Matrix.Modifier (Transposition(NonTransposed, Transposed))
import Numeric.LAPACK.Matrix.Private (Square, Full, mapExtent)
import Numeric.LAPACK.Vector (Vector)

import qualified Numeric.Netlib.Class as Class

import qualified Type.Data.Num.Unary as Unary
import Type.Data.Num.Unary ((:+:))

import qualified Data.Array.Comfort.Storable.Unchecked as Array
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable.Unchecked (Array)



class (Box.Box shape) => Scale shape where
   scale :: (Class.Floating a) => a -> Array shape a -> Array shape a
   scale = a -> Array shape a -> Array shape a
forall sh a. (C sh, Floating a) => a -> Vector sh a -> Vector sh a
Vector.scale

instance
   (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>
      Scale (MatrixShape.Full vert horiz height width) where

instance
   (MatrixShape.Content lo, MatrixShape.Content up,
    diag ~ NonUnit, Shape.C size) =>
      Scale (MatrixShape.Triangular lo diag up size) where

instance
   (Unary.Natural sub, Unary.Natural super, Extent.C vert, Extent.C horiz,
    Shape.C height, Shape.C width) =>
      Scale (MatrixShape.Banded sub super vert horiz height width) where


class (Box.Box shape) => MultiplyVector shape where
   matrixVector ::
      (Box.WidthOf shape ~ width, Eq width, Class.Floating a) =>
      Array shape a -> Vector width a -> Vector (Box.HeightOf shape) a
   vectorMatrix ::
      (Box.HeightOf shape ~ height, Eq height, Class.Floating a) =>
      Vector height a -> Array shape a -> Vector (Box.WidthOf shape) a


instance
   (Extent.C vert, Extent.C horiz, Shape.C width, Shape.C height) =>
      MultiplyVector (MatrixShape.Full vert horiz height width) where
   matrixVector :: Array (Full vert horiz height width) a
-> Vector width a
-> Vector (HeightOf (Full vert horiz height width)) a
matrixVector = Array (Full vert horiz height width) a
-> Vector width a
-> Vector (HeightOf (Full vert horiz height width)) a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Eq width, Floating a) =>
Full vert horiz height width a -> Vector width a -> Vector height a
Basic.multiplyVector
   vectorMatrix :: Vector height a
-> Array (Full vert horiz height width) a
-> Vector (WidthOf (Full vert horiz height width)) a
vectorMatrix Vector height a
v Array (Full vert horiz height width) a
m = Full horiz vert width height a -> Vector height a -> Vector width a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Eq width, Floating a) =>
Full vert horiz height width a -> Vector width a -> Vector height a
Basic.multiplyVector (Array (Full vert horiz height width) a
-> Full horiz vert width height a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz height width a -> Full horiz vert width height a
transpose Array (Full vert horiz height width) a
m) Vector height a
Vector height a
v


instance (Shape.C shape) => MultiplyVector (MatrixShape.Hermitian shape) where
   matrixVector :: Array (Hermitian shape) a
-> Vector width a -> Vector (HeightOf (Hermitian shape)) a
matrixVector = Transposition
-> Hermitian width a -> Vector width a -> Vector width a
forall sh a.
(C sh, Eq sh, Floating a) =>
Transposition -> Hermitian sh a -> Vector sh a -> Vector sh a
Hermitian.multiplyVector Transposition
NonTransposed
   vectorMatrix :: Vector height a
-> Array (Hermitian shape) a
-> Vector (WidthOf (Hermitian shape)) a
vectorMatrix = (Array (Hermitian shape) a -> Vector shape a -> Vector shape a)
-> Vector shape a -> Array (Hermitian shape) a -> Vector shape a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Array (Hermitian shape) a -> Vector shape a -> Vector shape a)
 -> Vector shape a -> Array (Hermitian shape) a -> Vector shape a)
-> (Array (Hermitian shape) a -> Vector shape a -> Vector shape a)
-> Vector shape a
-> Array (Hermitian shape) a
-> Vector shape a
forall a b. (a -> b) -> a -> b
$ Transposition
-> Array (Hermitian shape) a -> Vector shape a -> Vector shape a
forall sh a.
(C sh, Eq sh, Floating a) =>
Transposition -> Hermitian sh a -> Vector sh a -> Vector sh a
Hermitian.multiplyVector Transposition
Transposed


instance
   (MatrixShape.Content lo, MatrixShape.Content up,
    MatrixShape.TriDiag diag, Shape.C shape) =>
      MultiplyVector (MatrixShape.Triangular lo diag up shape) where
   matrixVector :: Array (Triangular lo diag up shape) a
-> Vector width a
-> Vector (HeightOf (Triangular lo diag up shape)) a
matrixVector Array (Triangular lo diag up shape) a
m Vector width a
v = Array (Triangular lo diag up shape) a
-> Vector shape a -> Vector shape a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag, C sh, Eq sh, Floating a) =>
Triangular lo diag up sh a -> Vector sh a -> Vector sh a
Triangular.multiplyVector Array (Triangular lo diag up shape) a
m Vector shape a
Vector width a
v
   vectorMatrix :: Vector height a
-> Array (Triangular lo diag up shape) a
-> Vector (WidthOf (Triangular lo diag up shape)) a
vectorMatrix Vector height a
v Array (Triangular lo diag up shape) a
m = Triangular up diag lo shape a -> Vector shape a -> Vector shape a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag, C sh, Eq sh, Floating a) =>
Triangular lo diag up sh a -> Vector sh a -> Vector sh a
Triangular.multiplyVector (Array (Triangular lo diag up shape) a
-> Triangular up diag lo shape a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag) =>
Triangular lo diag up sh a -> Triangular up diag lo sh a
Triangular.transpose Array (Triangular lo diag up shape) a
m) Vector shape a
Vector height a
v


instance
   (Unary.Natural sub, Unary.Natural super,
    Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>
      MultiplyVector (MatrixShape.Banded sub super vert horiz height width) where
   matrixVector :: Array (Banded sub super vert horiz height width) a
-> Vector width a
-> Vector (HeightOf (Banded sub super vert horiz height width)) a
matrixVector Array (Banded sub super vert horiz height width) a
m Vector width a
v = Array (Banded sub super vert horiz height width) a
-> Vector width a -> Vector height a
forall sub super vert horiz height width a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 Eq width, Floating a) =>
Banded sub super vert horiz height width a
-> Vector width a -> Vector height a
Banded.multiplyVector Array (Banded sub super vert horiz height width) a
m Vector width a
Vector width a
v
   vectorMatrix :: Vector height a
-> Array (Banded sub super vert horiz height width) a
-> Vector (WidthOf (Banded sub super vert horiz height width)) a
vectorMatrix Vector height a
v Array (Banded sub super vert horiz height width) a
m = Banded super sub horiz vert width height a
-> Vector height a -> Vector width a
forall sub super vert horiz height width a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 Eq width, Floating a) =>
Banded sub super vert horiz height width a
-> Vector width a -> Vector height a
Banded.multiplyVector (Array (Banded sub super vert horiz height width) a
-> Banded super sub horiz vert width height a
forall vert horiz sub super height width a.
(C vert, C horiz) =>
Banded sub super vert horiz height width a
-> Banded super sub horiz vert width height a
Banded.transpose Array (Banded sub super vert horiz height width) a
m) Vector height a
Vector height a
v


instance
   (Unary.Natural offDiag, Shape.C size) =>
      MultiplyVector (MatrixShape.BandedHermitian offDiag size) where
   matrixVector :: Array (BandedHermitian offDiag size) a
-> Vector width a
-> Vector (HeightOf (BandedHermitian offDiag size)) a
matrixVector = Transposition
-> BandedHermitian offDiag width a
-> Vector width a
-> Vector width a
forall offDiag size a.
(Natural offDiag, C size, Eq size, Floating a) =>
Transposition
-> BandedHermitian offDiag size a -> Vector size a -> Vector size a
BandedHermitian.multiplyVector Transposition
NonTransposed
   vectorMatrix :: Vector height a
-> Array (BandedHermitian offDiag size) a
-> Vector (WidthOf (BandedHermitian offDiag size)) a
vectorMatrix = (Array (BandedHermitian offDiag size) a
 -> Vector size a -> Vector size a)
-> Vector size a
-> Array (BandedHermitian offDiag size) a
-> Vector size a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Array (BandedHermitian offDiag size) a
  -> Vector size a -> Vector size a)
 -> Vector size a
 -> Array (BandedHermitian offDiag size) a
 -> Vector size a)
-> (Array (BandedHermitian offDiag size) a
    -> Vector size a -> Vector size a)
-> Vector size a
-> Array (BandedHermitian offDiag size) a
-> Vector size a
forall a b. (a -> b) -> a -> b
$ Transposition
-> Array (BandedHermitian offDiag size) a
-> Vector size a
-> Vector size a
forall offDiag size a.
(Natural offDiag, C size, Eq size, Floating a) =>
Transposition
-> BandedHermitian offDiag size a -> Vector size a -> Vector size a
BandedHermitian.multiplyVector Transposition
Transposed



class (Plain.SquareShape shape) => MultiplySquare shape where
   {-# MINIMAL transposableSquare | fullSquare,squareFull #-}
   transposableSquare ::
      (Box.HeightOf shape ~ height, Eq height, Shape.C width,
       Extent.C vert, Extent.C horiz, Class.Floating a) =>
      Transposition -> Array shape a ->
      Full vert horiz height width a -> Full vert horiz height width a
   transposableSquare Transposition
NonTransposed Array shape a
a Full vert horiz height width a
b = Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull Array shape a
a Full vert horiz height width a
b
   transposableSquare Transposition
Transposed Array shape a
a Full vert horiz height width a
b = Full horiz vert width height a -> Full vert horiz height width a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz height width a -> Full horiz vert width height a
transpose (Full horiz vert width height a -> Full vert horiz height width a)
-> Full horiz vert width height a -> Full vert horiz height width a
forall a b. (a -> b) -> a -> b
$ Full horiz vert width height a
-> Array shape a -> Full horiz vert width height a
forall shape width height vert horiz a.
(MultiplySquare shape, WidthOf shape ~ width, Eq width, C height,
 C vert, C horiz, Floating a) =>
Full vert horiz height width a
-> Array shape a -> Full vert horiz height width a
fullSquare (Full vert horiz height width a -> Full horiz vert width height a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz height width a -> Full horiz vert width height a
transpose Full vert horiz height width a
b) Array shape a
a

   squareFull ::
      (Box.HeightOf shape ~ height, Eq height, Shape.C width,
       Extent.C vert, Extent.C horiz, Class.Floating a) =>
      Array shape a ->
      Full vert horiz height width a -> Full vert horiz height width a
   squareFull = Transposition
-> Array shape a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Transposition
-> Array shape a
-> Full vert horiz height width a
-> Full vert horiz height width a
transposableSquare Transposition
NonTransposed

   fullSquare ::
      (Box.WidthOf shape ~ width, Eq width, Shape.C height,
       Extent.C vert, Extent.C horiz, Class.Floating a) =>
      Full vert horiz height width a ->
      Array shape a -> Full vert horiz height width a
   fullSquare = (Array shape a
 -> Full horiz vert width height a
 -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Array shape a
-> Full vert horiz height width a
forall vertA vertB horizA horizB matrix widthA heightA a widthB
       heightB.
(C vertA, C vertB, C horizA, C horizB) =>
(matrix
 -> Full horizA vertA widthA heightA a
 -> Full horizB vertB widthB heightB a)
-> Full vertA horizA heightA widthA a
-> matrix
-> Full vertB horizB heightB widthB a
swapMultiply ((Array shape a
  -> Full horiz vert width height a
  -> Full horiz vert width height a)
 -> Full vert horiz height width a
 -> Array shape a
 -> Full vert horiz height width a)
-> (Array shape a
    -> Full horiz vert width height a
    -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Array shape a
-> Full vert horiz height width a
forall a b. (a -> b) -> a -> b
$ Transposition
-> Array shape a
-> Full horiz vert width height a
-> Full horiz vert width height a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Transposition
-> Array shape a
-> Full vert horiz height width a
-> Full vert horiz height width a
transposableSquare Transposition
Transposed

instance
   (vert ~ Small, horiz ~ Small, Shape.C height, height ~ width) =>
      MultiplySquare (MatrixShape.Full vert horiz height width) where
   transposableSquare :: Transposition
-> Array (Full vert horiz height width) a
-> Full vert horiz height width a
-> Full vert horiz height width a
transposableSquare Transposition
NonTransposed = Array (Full vert horiz height width) a
-> Full vert horiz height width a -> Full vert horiz height width a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull
   transposableSquare Transposition
Transposed = Array (Full horiz vert width height) a
-> Full vert horiz height width a -> Full vert horiz height width a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull (Array (Full horiz vert width height) a
 -> Full vert horiz height width a
 -> Full vert horiz height width a)
-> (Array (Full vert horiz height width) a
    -> Array (Full horiz vert width height) a)
-> Array (Full vert horiz height width) a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array (Full vert horiz height width) a
-> Array (Full horiz vert width height) a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz height width a -> Full horiz vert width height a
transpose
   squareFull :: Array (Full vert horiz height width) a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull Array (Full vert horiz height width) a
a Full vert horiz height width a
b = Full vert horiz height height a
-> Full vert horiz height width a -> Full vert horiz height width a
forall vert horiz height fuse width a.
(C vert, C horiz, C height, C fuse, Eq fuse, C width,
 Floating a) =>
Full vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Basic.multiply (Map Small Small vert horiz height height
-> Full Small Small height height a
-> Full vert horiz height height a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map Small Small vert horiz height height
forall vert horiz size.
(C vert, C horiz) =>
Map Small Small vert horiz size size
Extent.fromSquare Array (Full vert horiz height width) a
Full Small Small height height a
a) Full vert horiz height width a
Full vert horiz height width a
b

instance (Shape.C shape) => MultiplySquare (MatrixShape.Hermitian shape) where
   transposableSquare :: Transposition
-> Array (Hermitian shape) a
-> Full vert horiz height width a
-> Full vert horiz height width a
transposableSquare = Transposition
-> Array (Hermitian shape) a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall vert horiz height width a.
(C vert, C horiz, C height, Eq height, C width, Floating a) =>
Transposition
-> Hermitian height a
-> Full vert horiz height width a
-> Full vert horiz height width a
Hermitian.multiplyFull

instance
   (MatrixShape.Content lo, MatrixShape.Content up,
    MatrixShape.TriDiag diag, Shape.C shape) =>
      MultiplySquare (MatrixShape.Triangular lo diag up shape) where
   squareFull :: Array (Triangular lo diag up shape) a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull = Array (Triangular lo diag up shape) a
-> Full vert horiz height width a -> Full vert horiz height width a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull
   fullSquare :: Full vert horiz height width a
-> Array (Triangular lo diag up shape) a
-> Full vert horiz height width a
fullSquare =
      (Triangular lo diag up width a
 -> Full horiz vert width height a
 -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Triangular lo diag up width a
-> Full vert horiz height width a
forall vertA vertB horizA horizB matrix widthA heightA a widthB
       heightB.
(C vertA, C vertB, C horizA, C horizB) =>
(matrix
 -> Full horizA vertA widthA heightA a
 -> Full horizB vertB widthB heightB a)
-> Full vertA horizA heightA widthA a
-> matrix
-> Full vertB horizB heightB widthB a
swapMultiply ((Triangular lo diag up width a
  -> Full horiz vert width height a
  -> Full horiz vert width height a)
 -> Full vert horiz height width a
 -> Triangular lo diag up width a
 -> Full vert horiz height width a)
-> (Triangular lo diag up width a
    -> Full horiz vert width height a
    -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Triangular lo diag up width a
-> Full vert horiz height width a
forall a b. (a -> b) -> a -> b
$ Triangular up diag lo width a
-> Full horiz vert width height a -> Full horiz vert width height a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull (Triangular up diag lo width a
 -> Full horiz vert width height a
 -> Full horiz vert width height a)
-> (Triangular lo diag up width a -> Triangular up diag lo width a)
-> Triangular lo diag up width a
-> Full horiz vert width height a
-> Full horiz vert width height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular lo diag up width a -> Triangular up diag lo width a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag) =>
Triangular lo diag up sh a -> Triangular up diag lo sh a
Triangular.transpose

instance
   (Unary.Natural sub, Unary.Natural super,
    vert ~ Small, horiz ~ Small, Shape.C height, height ~ width) =>
      MultiplySquare
         (MatrixShape.Banded sub super vert horiz height width) where
   squareFull :: Array (Banded sub super vert horiz height width) a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull = Banded sub super vert horiz height height a
-> Full vert horiz height width a -> Full vert horiz height width a
forall sub super vert horiz height width fuse a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 C fuse, Eq fuse, Floating a) =>
Banded sub super vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Banded.multiplyFull (Banded sub super vert horiz height height a
 -> Full vert horiz height width a
 -> Full vert horiz height width a)
-> (Square sub super height a
    -> Banded sub super vert horiz height height a)
-> Square sub super height a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square sub super height a
-> Banded sub super vert horiz height height a
forall vert horiz sub super size a.
(C vert, C horiz) =>
Square sub super size a -> Banded sub super vert horiz size size a
bandedGenSquare
   fullSquare :: Full vert horiz height width a
-> Array (Banded sub super vert horiz height width) a
-> Full vert horiz height width a
fullSquare =
      (Banded sub super Small Small width width a
 -> Full horiz vert width height a
 -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Banded sub super Small Small width width a
-> Full vert horiz height width a
forall vertA vertB horizA horizB matrix widthA heightA a widthB
       heightB.
(C vertA, C vertB, C horizA, C horizB) =>
(matrix
 -> Full horizA vertA widthA heightA a
 -> Full horizB vertB widthB heightB a)
-> Full vertA horizA heightA widthA a
-> matrix
-> Full vertB horizB heightB widthB a
swapMultiply ((Banded sub super Small Small width width a
  -> Full horiz vert width height a
  -> Full horiz vert width height a)
 -> Full vert horiz height width a
 -> Banded sub super Small Small width width a
 -> Full vert horiz height width a)
-> (Banded sub super Small Small width width a
    -> Full horiz vert width height a
    -> Full horiz vert width height a)
-> Full vert horiz height width a
-> Banded sub super Small Small width width a
-> Full vert horiz height width a
forall a b. (a -> b) -> a -> b
$ Banded super sub horiz vert width width a
-> Full horiz vert width height a -> Full horiz vert width height a
forall sub super vert horiz height width fuse a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 C fuse, Eq fuse, Floating a) =>
Banded sub super vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Banded.multiplyFull (Banded super sub horiz vert width width a
 -> Full horiz vert width height a
 -> Full horiz vert width height a)
-> (Banded sub super Small Small width width a
    -> Banded super sub horiz vert width width a)
-> Banded sub super Small Small width width a
-> Full horiz vert width height a
-> Full horiz vert width height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square super sub width a
-> Banded super sub horiz vert width width a
forall vert horiz sub super size a.
(C vert, C horiz) =>
Square sub super size a -> Banded sub super vert horiz size size a
bandedGenSquare (Square super sub width a
 -> Banded super sub horiz vert width width a)
-> (Banded sub super Small Small width width a
    -> Square super sub width a)
-> Banded sub super Small Small width width a
-> Banded super sub horiz vert width width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Banded sub super Small Small width width a
-> Square super sub width a
forall vert horiz sub super height width a.
(C vert, C horiz) =>
Banded sub super vert horiz height width a
-> Banded super sub horiz vert width height a
Banded.transpose

bandedGenSquare ::
   (Extent.C vert, Extent.C horiz) =>
   Banded.Square sub super size a ->
   Banded.Banded sub super vert horiz size size a
bandedGenSquare :: Square sub super size a -> Banded sub super vert horiz size size a
bandedGenSquare = Map Small Small vert horiz size size
-> Square sub super size a
-> Banded sub super vert horiz size size a
forall vertA horizA vertB horizB height width super sub a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Banded super sub vertA horizA height width a
-> Banded super sub vertB horizB height width a
Banded.mapExtent Map Small Small vert horiz size size
forall vert horiz size.
(C vert, C horiz) =>
Map Small Small vert horiz size size
Extent.fromSquare

instance
   (Unary.Natural offDiag, Shape.C size) =>
      MultiplySquare (MatrixShape.BandedHermitian offDiag size) where
   transposableSquare :: Transposition
-> Array (BandedHermitian offDiag size) a
-> Full vert horiz height width a
-> Full vert horiz height width a
transposableSquare = Transposition
-> Array (BandedHermitian offDiag size) a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall offDiag vert horiz height width a.
(Natural offDiag, C vert, C horiz, C height, Eq height, C width,
 Floating a) =>
Transposition
-> BandedHermitian offDiag height a
-> Full vert horiz height width a
-> Full vert horiz height width a
BandedHermitian.multiplyFull


class (Plain.SquareShape shape) => Power shape where
   square :: (Class.Floating a) => Array shape a -> Array shape a
   power :: (Class.Floating a) => Int -> Array shape a -> Array shape a

instance
   (Extent.Small ~ vert, Extent.Small ~ horiz,
    Shape.C height, height ~ width) =>
      Power (MatrixShape.Full vert horiz height width) where
   square :: Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
square = Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
forall sh a. (C sh, Floating a) => Square sh a -> Square sh a
Square.square
   power :: Int
-> Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
power = Integer -> Square height a -> Square height a
forall sh a.
(C sh, Floating a) =>
Integer -> Square sh a -> Square sh a
Square.power (Integer -> Square height a -> Square height a)
-> (Int -> Integer) -> Int -> Square height a -> Square height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral

instance (Shape.C size) => Power (MatrixShape.Hermitian size) where
   square :: Array (Hermitian size) a -> Array (Hermitian size) a
square = Array (Hermitian size) a -> Array (Hermitian size) a
forall sh a. (C sh, Floating a) => Hermitian sh a -> Hermitian sh a
Hermitian.square
   power :: Int -> Array (Hermitian size) a -> Array (Hermitian size) a
power = Integer -> Array (Hermitian size) a -> Array (Hermitian size) a
forall sh a.
(C sh, Floating a) =>
Integer -> Hermitian sh a -> Hermitian sh a
Hermitian.power (Integer -> Array (Hermitian size) a -> Array (Hermitian size) a)
-> (Int -> Integer)
-> Int
-> Array (Hermitian size) a
-> Array (Hermitian size) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral

instance
   (Triangular.PowerContentDiag lo diag up, Shape.C size) =>
      Power (MatrixShape.Triangular lo diag up size) where
   square :: Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
square = Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag, C sh, Floating a) =>
Triangular lo diag up sh a
-> Triangular lo (PowerDiag lo up diag) up sh a
Triangular.square
   power :: Int
-> Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
power = Int
-> Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
forall lo up diag sh a.
(Content lo, Content up, TriDiag diag, C sh, Floating a) =>
Int
-> Triangular lo diag up sh a
-> Triangular lo (PowerDiag lo up diag) up sh a
Triangular.power


class (Box.Box shape) => MultiplySame shape where
   same ::
      (Class.Floating a) => Array shape a -> Array shape a -> Array shape a

instance
   (Extent.C vert, Extent.C horiz, Shape.C height, Eq height, height ~ width) =>
      MultiplySame (MatrixShape.Full vert horiz height width) where
   same :: Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
same = Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
forall vert horiz height fuse width a.
(C vert, C horiz, C height, C fuse, Eq fuse, C width,
 Floating a) =>
Full vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Basic.multiply

instance
   (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,
    Shape.C size, Eq size) =>
      MultiplySame (MatrixShape.Triangular lo diag up size) where
   same :: Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
same = Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
-> Array (Triangular lo diag up size) a
forall lo up diag sh a.
(DiagUpLo lo up, TriDiag diag, C sh, Eq sh, Floating a) =>
Triangular lo diag up sh a
-> Triangular lo diag up sh a -> Triangular lo diag up sh a
Triangular.multiply


{- |
This class allows to Basic.multiply two matrices of arbitrary special features
and returns the most special matrix type possible.
At the first glance, this is handy.
At the second glance, this has some problems.
First of all, we may refine the types in future
and then multiplication may return a different, more special type than before.
Second, if you write code with polymorphic matrix types,
then 'matrixMatrix' may leave you with constraints like
@ExtentPriv.Multiply vert vert ~ vert@.
That constraint is always fulfilled but the compiler cannot infer that.
Because of these problems
you may instead consider using specialised 'Basic.multiply' functions
from the various modules for production use.
Btw. 'MultiplyVector' and 'MultiplySquare'
are much less problematic,
because the input and output are always dense vectors or dense matrices.
-}
class (Shape.C shapeA, Shape.C shapeB) => Multiply shapeA shapeB where
   type Multiplied shapeA shapeB
   matrixMatrix ::
      (Class.Floating a) =>
      Array shapeA a -> Array shapeB a -> Array (Multiplied shapeA shapeB) a

instance
   (Shape.C heightA, Shape.C widthA, Shape.C widthB,
    widthA ~ heightB, Eq heightB,
    Extent.C vertA, Extent.C horizA, Extent.C vertB, Extent.C horizB) =>
      Multiply
         (MatrixShape.Full vertA horizA heightA widthA)
         (MatrixShape.Full vertB horizB heightB widthB) where
   type Multiplied
         (MatrixShape.Full vertA horizA heightA widthA)
         (MatrixShape.Full vertB horizB heightB widthB) =
            MatrixShape.Full
               (ExtentPriv.Multiply vertA vertB)
               (ExtentPriv.Multiply horizA horizB)
               heightA widthB
   matrixMatrix :: Array (Full vertA horizA heightA widthA) a
-> Array (Full vertB horizB heightB widthB) a
-> Array
     (Multiplied
        (Full vertA horizA heightA widthA)
        (Full vertB horizB heightB widthB))
     a
matrixMatrix Array (Full vertA horizA heightA widthA) a
a Array (Full vertB horizB heightB widthB) a
b =
      case Extent vertA horizA heightA widthA
-> Extent vertB horizB widthA widthB
-> ((TagFact (Multiply vertA vertB),
     TagFact (Multiply horizA horizB)),
    (Map
       vertA
       horizA
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       heightA
       widthA,
     Map
       vertB
       horizB
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       widthA
       widthB))
forall vertA horizA vertB horizB vertC horizC height fuse width.
(C vertA, C horizA, C vertB, C horizB,
 Multiply vertA vertB ~ vertC, Multiply horizA horizB ~ horizC) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> ((TagFact vertC, TagFact horizC),
    (Map vertA horizA vertC horizC height fuse,
     Map vertB horizB vertC horizC fuse width))
unifyFactors (Array (Full vertA horizA heightA widthA) a
-> Extent vertA horizA heightA widthA
forall vert horiz height width a.
Full vert horiz height width a -> Extent vert horiz height width
fullExtent Array (Full vertA horizA heightA widthA) a
a) (Array (Full vertB horizB heightB widthB) a
-> Extent vertB horizB heightB widthB
forall vert horiz height width a.
Full vert horiz height width a -> Extent vert horiz height width
fullExtent Array (Full vertB horizB heightB widthB) a
b) of
         ((TagFact (Multiply vertA vertB)
ExtentPriv.TagFact, TagFact (Multiply horizA horizB)
ExtentPriv.TagFact), (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft, Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight)) ->
            Full
  (Multiply vertA vertB) (Multiply horizA horizB) heightA widthA a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) widthA widthB a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthB a
forall vert horiz height fuse width a.
(C vert, C horiz, C height, C fuse, Eq fuse, C width,
 Floating a) =>
Full vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Basic.multiply
               (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
-> Array (Full vertA horizA heightA widthA) a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthA a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft Array (Full vertA horizA heightA widthA) a
a)
               (Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
-> Full vertB horizB widthA widthB a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) widthA widthB a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight Full vertB horizB widthA widthB a
Array (Full vertB horizB heightB widthB) a
b)

fullExtent ::
   Full vert horiz height width a ->
   Extent.Extent vert horiz height width
fullExtent :: Full vert horiz height width a -> Extent vert horiz height width
fullExtent = Full vert horiz height width -> Extent vert horiz height width
forall vert horiz height width.
Full vert horiz height width -> Extent vert horiz height width
MatrixShape.fullExtent (Full vert horiz height width -> Extent vert horiz height width)
-> (Full vert horiz height width a -> Full vert horiz height width)
-> Full vert horiz height width a
-> Extent vert horiz height width
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full vert horiz height width a -> Full vert horiz height width
forall sh a. Array sh a -> sh
Array.shape

unifyFactors ::
   (Extent.C vertA, Extent.C horizA, Extent.C vertB, Extent.C horizB) =>
   (ExtentPriv.Multiply vertA vertB ~ vertC) =>
   (ExtentPriv.Multiply horizA horizB ~ horizC) =>
   Extent.Extent vertA horizA height fuse ->
   Extent.Extent vertB horizB fuse width ->
   ((ExtentPriv.TagFact vertC, ExtentPriv.TagFact horizC),
    (Extent.Map vertA horizA vertC horizC height fuse,
     Extent.Map vertB horizB vertC horizC fuse width))
unifyFactors :: Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> ((TagFact vertC, TagFact horizC),
    (Map vertA horizA vertC horizC height fuse,
     Map vertB horizB vertC horizC fuse width))
unifyFactors Extent vertA horizA height fuse
a Extent vertB horizB fuse width
b =
   ((TagFact vertA -> TagFact vertB -> TagFact (Multiply vertA vertB)
forall a b. TagFact a -> TagFact b -> TagFact (Multiply a b)
ExtentPriv.multiplyTagLaw
         (Extent vertA horizA height fuse -> TagFact vertA
forall vert horiz height width.
C vert =>
Extent vert horiz height width -> TagFact vert
ExtentPriv.heightFact Extent vertA horizA height fuse
a) (Extent vertB horizB fuse width -> TagFact vertB
forall vert horiz height width.
C vert =>
Extent vert horiz height width -> TagFact vert
ExtentPriv.heightFact Extent vertB horizB fuse width
b),
     TagFact horizA
-> TagFact horizB -> TagFact (Multiply horizA horizB)
forall a b. TagFact a -> TagFact b -> TagFact (Multiply a b)
ExtentPriv.multiplyTagLaw
         (Extent vertA horizA height fuse -> TagFact horizA
forall horiz vert height width.
C horiz =>
Extent vert horiz height width -> TagFact horiz
ExtentPriv.widthFact Extent vertA horizA height fuse
a) (Extent vertB horizB fuse width -> TagFact horizB
forall horiz vert height width.
C horiz =>
Extent vert horiz height width -> TagFact horiz
ExtentPriv.widthFact Extent vertB horizB fuse width
b)),
    ((Extent vertA horizA height fuse
 -> Extent vertC horizC height fuse)
-> Map vertA horizA vertC horizC height fuse
forall vertA horizA vertB horizB height width.
(Extent vertA horizA height width
 -> Extent vertB horizB height width)
-> Map vertA horizA vertB horizB height width
ExtentPriv.Map ((Extent vertA horizA height fuse
  -> Extent vertC horizC height fuse)
 -> Map vertA horizA vertC horizC height fuse)
-> (Extent vertA horizA height fuse
    -> Extent vertC horizC height fuse)
-> Map vertA horizA vertC horizC height fuse
forall a b. (a -> b) -> a -> b
$ (Extent vertA horizA height fuse
 -> Extent vertB horizB fuse width
 -> Extent vertC horizC height fuse)
-> Extent vertB horizB fuse width
-> Extent vertA horizA height fuse
-> Extent vertC horizC height fuse
forall a b c. (a -> b -> c) -> b -> a -> c
flip Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> Extent vertC horizC height fuse
forall vertA horizA vertB horizB height fuse width.
(C vertA, C horizA, C vertB, C horizB) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> Extent
     (Multiply vertA vertB) (Multiply horizA horizB) height fuse
ExtentPriv.unifyLeft Extent vertB horizB fuse width
b,
     (Extent vertB horizB fuse width -> Extent vertC horizC fuse width)
-> Map vertB horizB vertC horizC fuse width
forall vertA horizA vertB horizB height width.
(Extent vertA horizA height width
 -> Extent vertB horizB height width)
-> Map vertA horizA vertB horizB height width
ExtentPriv.Map ((Extent vertB horizB fuse width -> Extent vertC horizC fuse width)
 -> Map vertB horizB vertC horizC fuse width)
-> (Extent vertB horizB fuse width
    -> Extent vertC horizC fuse width)
-> Map vertB horizB vertC horizC fuse width
forall a b. (a -> b) -> a -> b
$ Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> Extent
     (Multiply vertA vertB) (Multiply horizA horizB) fuse width
forall vertA horizA vertB horizB height fuse width.
(C vertA, C horizA, C vertB, C horizB) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> Extent
     (Multiply vertA vertB) (Multiply horizA horizB) fuse width
ExtentPriv.unifyRight Extent vertA horizA height fuse
a))


instance
   (Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ width, Eq width, Shape.C height) =>
      Multiply
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.Hermitian size)
            where
   type Multiplied
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.Hermitian size) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (Full vert horiz height width) a
-> Array (Hermitian size) a
-> Array
     (Multiplied (Full vert horiz height width) (Hermitian size)) a
matrixMatrix = Array (Full vert horiz height width) a
-> Array (Hermitian size) a
-> Array
     (Multiplied (Full vert horiz height width) (Hermitian size)) a
forall shape width height vert horiz a.
(MultiplySquare shape, WidthOf shape ~ width, Eq width, C height,
 C vert, C horiz, Floating a) =>
Full vert horiz height width a
-> Array shape a -> Full vert horiz height width a
fullSquare

instance
   (Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ height, Eq height, Shape.C width) =>
      Multiply
         (MatrixShape.Hermitian size)
         (MatrixShape.Full vert horiz height width)
            where
   type Multiplied
         (MatrixShape.Hermitian size)
         (MatrixShape.Full vert horiz height width) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (Hermitian size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied (Hermitian size) (Full vert horiz height width)) a
matrixMatrix = Array (Hermitian size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied (Hermitian size) (Full vert horiz height width)) a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull

instance
   (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>
      Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB)
         where
   type Multiplied
         (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB) =
            MatrixShape.Square shapeA
   matrixMatrix :: Array (Hermitian shapeA) a
-> Array (Hermitian shapeB) a
-> Array (Multiplied (Hermitian shapeA) (Hermitian shapeB)) a
matrixMatrix Array (Hermitian shapeA) a
a = Array (Hermitian shapeA) a
-> Full Small Small shapeB shapeB a
-> Full Small Small shapeB shapeB a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull Array (Hermitian shapeA) a
a (Full Small Small shapeB shapeB a
 -> Full Small Small shapeB shapeB a)
-> (Array (Hermitian shapeB) a -> Full Small Small shapeB shapeB a)
-> Array (Hermitian shapeB) a
-> Full Small Small shapeB shapeB a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array (Hermitian shapeB) a -> Full Small Small shapeB shapeB a
forall sh a. (C sh, Floating a) => Hermitian sh a -> Square sh a
Hermitian.toSquare


instance
   (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,
    Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ width, Eq width, Shape.C height) =>
      Multiply
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.Triangular lo diag up size)
            where
   type Multiplied
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.Triangular lo diag up size) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (Full vert horiz height width) a
-> Array (Triangular lo diag up size) a
-> Array
     (Multiplied
        (Full vert horiz height width) (Triangular lo diag up size))
     a
matrixMatrix = Array (Full vert horiz height width) a
-> Array (Triangular lo diag up size) a
-> Array
     (Multiplied
        (Full vert horiz height width) (Triangular lo diag up size))
     a
forall shape width height vert horiz a.
(MultiplySquare shape, WidthOf shape ~ width, Eq width, C height,
 C vert, C horiz, Floating a) =>
Full vert horiz height width a
-> Array shape a -> Full vert horiz height width a
fullSquare

instance
   (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,
    Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ height, Eq height, Shape.C width) =>
      Multiply
         (MatrixShape.Triangular lo diag up size)
         (MatrixShape.Full vert horiz height width)
            where
   type Multiplied
         (MatrixShape.Triangular lo diag up size)
         (MatrixShape.Full vert horiz height width) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (Triangular lo diag up size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied
        (Triangular lo diag up size) (Full vert horiz height width))
     a
matrixMatrix = Array (Triangular lo diag up size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied
        (Triangular lo diag up size) (Full vert horiz height width))
     a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull

instance
   (Shape.C sizeA, sizeA ~ sizeB, Eq sizeB,
    MultiplyTriangular loA upA loB upB,
    MatrixShape.TriDiag diagA, MatrixShape.TriDiag diagB) =>
      Multiply
         (MatrixShape.Triangular loA diagA upA sizeA)
         (MatrixShape.Triangular loB diagB upB sizeB) where
   type Multiplied
         (MatrixShape.Triangular loA diagA upA sizeA)
         (MatrixShape.Triangular loB diagB upB sizeB) =
            -- requires UndecidableInstances
            MultipliedTriangular loA diagA upA loB diagB upB sizeB
   matrixMatrix :: Array (Triangular loA diagA upA sizeA) a
-> Array (Triangular loB diagB upB sizeB) a
-> Array
     (Multiplied
        (Triangular loA diagA upA sizeA) (Triangular loB diagB upB sizeB))
     a
matrixMatrix = Array (Triangular loA diagA upA sizeA) a
-> Array (Triangular loB diagB upB sizeB) a
-> Array
     (Multiplied
        (Triangular loA diagA upA sizeA) (Triangular loB diagB upB sizeB))
     a
forall loA upA loB upB a size diagA diagB.
(MultiplyTriangular loA upA loB upB, Floating a, C size, Eq size,
 TriDiag diagA, TriDiag diagB) =>
Triangular loA diagA upA size a
-> Triangular loB diagB upB size a
-> Array (MultipliedTriangular loA diagA upA loB diagB upB size) a
triangularTriangular

class
   (MatrixShape.Content loA, MatrixShape.Content upA,
    MatrixShape.Content loB, MatrixShape.Content upB) =>
      MultiplyTriangular loA upA loB upB where
   triangularTriangular ::
      (Class.Floating a, Shape.C size, Eq size,
       MatrixShape.TriDiag diagA, MatrixShape.TriDiag diagB) =>
      Triangular loA diagA upA size a ->
      Triangular loB diagB upB size a ->
      Array (MultipliedTriangular loA diagA upA loB diagB upB size) a


type MultipliedTriangular loA diagA upA loB diagB upB size =
   ComposedTriangular
      (MultipliedPart loA loB)
      (MultipliedDiag diagA diagB)
      (MultipliedPart upA upB)
      size

type family MultipliedPart a b :: *
type instance MultipliedPart Empty b = b
type instance MultipliedPart Filled b = Filled

type family MultipliedDiag a b :: *
type instance MultipliedDiag Unit b = b
type instance MultipliedDiag NonUnit b = NonUnit

type family ComposedTriangular lo diag up size :: *
type instance ComposedTriangular Empty diag up size =
         MatrixShape.Triangular Empty diag up size
type instance ComposedTriangular Filled diag Empty size =
         MatrixShape.LowerTriangular diag size
type instance ComposedTriangular Filled diag Filled size =
         MatrixShape.Square size


instance MultiplyTriangular Empty Empty Empty Empty where
   triangularTriangular :: Triangular Empty diagA Empty size a
-> Triangular Empty diagB Empty size a
-> Array
     (MultipliedTriangular Empty diagA Empty Empty diagB Empty size) a
triangularTriangular = Triangular Empty diagA Empty size a
-> Triangular Empty diagB Empty size a
-> Array
     (MultipliedTriangular Empty diagA Empty Empty diagB Empty size) a
forall size a lo up diagA diagB diagC.
(C size, Eq size, Floating a, DiagUpLo lo up, TriDiag diagA,
 TriDiag diagB, MultipliedDiag diagA diagB ~ diagC) =>
Triangular lo diagA up size a
-> Triangular lo diagB up size a -> Triangular lo diagC up size a
triangularTriangularConform

instance MultiplyTriangular Empty Empty Filled Filled where
   triangularTriangular :: Triangular Empty diagA Empty size a
-> Triangular Filled diagB Filled size a
-> Array
     (MultipliedTriangular Empty diagA Empty Filled diagB Filled size) a
triangularTriangular Triangular Empty diagA Empty size a
a = Triangular Empty diagA Empty size a
-> Full Small Small size size a -> Full Small Small size size a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull Triangular Empty diagA Empty size a
a (Full Small Small size size a -> Full Small Small size size a)
-> (Triangular Filled diagB Filled size a
    -> Full Small Small size size a)
-> Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare

instance MultiplyTriangular Empty Filled Filled Filled where
   triangularTriangular :: Triangular Empty diagA Filled size a
-> Triangular Filled diagB Filled size a
-> Array
     (MultipliedTriangular Empty diagA Filled Filled diagB Filled size)
     a
triangularTriangular Triangular Empty diagA Filled size a
a = Triangular Empty diagA Filled size a
-> Full Small Small size size a -> Full Small Small size size a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull Triangular Empty diagA Filled size a
a (Full Small Small size size a -> Full Small Small size size a)
-> (Triangular Filled diagB Filled size a
    -> Full Small Small size size a)
-> Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare

instance MultiplyTriangular Filled Empty Filled Filled where
   triangularTriangular :: Triangular Filled diagA Empty size a
-> Triangular Filled diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Empty Filled diagB Filled size)
     a
triangularTriangular Triangular Filled diagA Empty size a
a = Triangular Filled diagA Empty size a
-> Full Small Small size size a -> Full Small Small size size a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull Triangular Filled diagA Empty size a
a (Full Small Small size size a -> Full Small Small size size a)
-> (Triangular Filled diagB Filled size a
    -> Full Small Small size size a)
-> Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular Filled diagB Filled size a
-> Full Small Small size size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare

instance MultiplyTriangular Empty Filled Empty Filled where
   triangularTriangular :: Triangular Empty diagA Filled size a
-> Triangular Empty diagB Filled size a
-> Array
     (MultipliedTriangular Empty diagA Filled Empty diagB Filled size) a
triangularTriangular = Triangular Empty diagA Filled size a
-> Triangular Empty diagB Filled size a
-> Array
     (MultipliedTriangular Empty diagA Filled Empty diagB Filled size) a
forall size a lo up diagA diagB diagC.
(C size, Eq size, Floating a, DiagUpLo lo up, TriDiag diagA,
 TriDiag diagB, MultipliedDiag diagA diagB ~ diagC) =>
Triangular lo diagA up size a
-> Triangular lo diagB up size a -> Triangular lo diagC up size a
triangularTriangularConform

instance MultiplyTriangular Filled Empty Filled Empty where
   triangularTriangular :: Triangular Filled diagA Empty size a
-> Triangular Filled diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Empty Filled diagB Empty size) a
triangularTriangular = Triangular Filled diagA Empty size a
-> Triangular Filled diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Empty Filled diagB Empty size) a
forall size a lo up diagA diagB diagC.
(C size, Eq size, Floating a, DiagUpLo lo up, TriDiag diagA,
 TriDiag diagB, MultipliedDiag diagA diagB ~ diagC) =>
Triangular lo diagA up size a
-> Triangular lo diagB up size a -> Triangular lo diagC up size a
triangularTriangularConform

instance MultiplyTriangular Filled Empty Empty Filled where
   triangularTriangular :: Triangular Filled diagA Empty size a
-> Triangular Empty diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Empty Empty diagB Filled size) a
triangularTriangular Triangular Filled diagA Empty size a
a = Triangular Filled diagA Empty size a
-> Full Small Small size size a -> Full Small Small size size a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull Triangular Filled diagA Empty size a
a (Full Small Small size size a -> Full Small Small size size a)
-> (Triangular Empty diagB Filled size a
    -> Full Small Small size size a)
-> Triangular Empty diagB Filled size a
-> Full Small Small size size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular Empty diagB Filled size a
-> Full Small Small size size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare

instance MultiplyTriangular Empty Filled Filled Empty where
   triangularTriangular :: Triangular Empty diagA Filled size a
-> Triangular Filled diagB Empty size a
-> Array
     (MultipliedTriangular Empty diagA Filled Filled diagB Empty size) a
triangularTriangular Triangular Empty diagA Filled size a
a = Triangular Empty diagA Filled size a
-> Full Small Small size size a -> Full Small Small size size a
forall lo up diag vert horiz height width a.
(Content lo, Content up, TriDiag diag, C vert, C horiz, C height,
 Eq height, C width, Floating a) =>
Triangular lo diag up height a
-> Full vert horiz height width a -> Full vert horiz height width a
Triangular.multiplyFull Triangular Empty diagA Filled size a
a (Full Small Small size size a -> Full Small Small size size a)
-> (Triangular Filled diagB Empty size a
    -> Full Small Small size size a)
-> Triangular Filled diagB Empty size a
-> Full Small Small size size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular Filled diagB Empty size a
-> Full Small Small size size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare

instance MultiplyTriangular Filled Filled Empty Empty where
   triangularTriangular :: Triangular Filled diagA Filled size a
-> Triangular Empty diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Filled Empty diagB Empty size) a
triangularTriangular = Triangular Filled diagA Filled size a
-> Triangular Empty diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Filled Empty diagB Empty size) a
forall loA upA diagA loB upB diagB size a.
(Content loA, Content upA, TriDiag diagA, Content loB, Content upB,
 TriDiag diagB, C size, Eq size, Floating a) =>
Triangular loA diagA upA size a
-> Triangular loB diagB upB size a -> Square size a
triangularTriangularToSquare

instance MultiplyTriangular Filled Filled Empty Filled where
   triangularTriangular :: Triangular Filled diagA Filled size a
-> Triangular Empty diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Filled Empty diagB Filled size)
     a
triangularTriangular = Triangular Filled diagA Filled size a
-> Triangular Empty diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Filled Empty diagB Filled size)
     a
forall loA upA diagA loB upB diagB size a.
(Content loA, Content upA, TriDiag diagA, Content loB, Content upB,
 TriDiag diagB, C size, Eq size, Floating a) =>
Triangular loA diagA upA size a
-> Triangular loB diagB upB size a -> Square size a
triangularTriangularToSquare

instance MultiplyTriangular Filled Filled Filled Empty where
   triangularTriangular :: Triangular Filled diagA Filled size a
-> Triangular Filled diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Filled Filled diagB Empty size)
     a
triangularTriangular = Triangular Filled diagA Filled size a
-> Triangular Filled diagB Empty size a
-> Array
     (MultipliedTriangular Filled diagA Filled Filled diagB Empty size)
     a
forall loA upA diagA loB upB diagB size a.
(Content loA, Content upA, TriDiag diagA, Content loB, Content upB,
 TriDiag diagB, C size, Eq size, Floating a) =>
Triangular loA diagA upA size a
-> Triangular loB diagB upB size a -> Square size a
triangularTriangularToSquare

instance MultiplyTriangular Filled Filled Filled Filled where
   triangularTriangular :: Triangular Filled diagA Filled size a
-> Triangular Filled diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Filled Filled diagB Filled size)
     a
triangularTriangular = Triangular Filled diagA Filled size a
-> Triangular Filled diagB Filled size a
-> Array
     (MultipliedTriangular Filled diagA Filled Filled diagB Filled size)
     a
forall loA upA diagA loB upB diagB size a.
(Content loA, Content upA, TriDiag diagA, Content loB, Content upB,
 TriDiag diagB, C size, Eq size, Floating a) =>
Triangular loA diagA upA size a
-> Triangular loB diagB upB size a -> Square size a
triangularTriangularToSquare

triangularTriangularToSquare ::
   (MatrixShape.Content loA, MatrixShape.Content upA, MatrixShape.TriDiag diagA,
    MatrixShape.Content loB, MatrixShape.Content upB, MatrixShape.TriDiag diagB,
    Shape.C size, Eq size, Class.Floating a) =>
   Triangular loA diagA upA size a ->
   Triangular loB diagB upB size a ->
   Square size a
triangularTriangularToSquare :: Triangular loA diagA upA size a
-> Triangular loB diagB upB size a -> Square size a
triangularTriangularToSquare = Square size a -> Triangular loB diagB upB size a -> Square size a
forall shape width height vert horiz a.
(MultiplySquare shape, WidthOf shape ~ width, Eq width, C height,
 C vert, C horiz, Floating a) =>
Full vert horiz height width a
-> Array shape a -> Full vert horiz height width a
fullSquare (Square size a -> Triangular loB diagB upB size a -> Square size a)
-> (Triangular loA diagA upA size a -> Square size a)
-> Triangular loA diagA upA size a
-> Triangular loB diagB upB size a
-> Square size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Triangular loA diagA upA size a -> Square size a
forall lo up sh a diag.
(Content lo, Content up, C sh, Floating a) =>
Triangular lo diag up sh a -> Square sh a
Triangular.toSquare


newtype TriangularTriangularConform lo up size a diagB diagA =
   TriangularTriangularConform {
      TriangularTriangularConform lo up size a diagB diagA
-> Triangular lo diagA up size a
-> Triangular lo diagB up size a
-> Triangular lo (MultipliedDiag diagA diagB) up size a
getTriangularTriangularConform ::
         Triangular lo diagA up size a ->
         Triangular lo diagB up size a ->
         Triangular lo (MultipliedDiag diagA diagB) up size a
   }

triangularTriangularConform ::
   (Shape.C size, Eq size, Class.Floating a,
    MatrixShape.DiagUpLo lo up,
    MatrixShape.TriDiag diagA, MatrixShape.TriDiag diagB) =>
   (MultipliedDiag diagA diagB ~ diagC) =>
   Triangular lo diagA up size a ->
   Triangular lo diagB up size a ->
   Triangular lo diagC up size a
triangularTriangularConform :: Triangular lo diagA up size a
-> Triangular lo diagB up size a -> Triangular lo diagC up size a
triangularTriangularConform =
   TriangularTriangularConform lo up size a diagB diagA
-> Triangular lo diagA up size a
-> Triangular lo diagB up size a
-> Triangular lo (MultipliedDiag diagA diagB) up size a
forall lo up size a diagB diagA.
TriangularTriangularConform lo up size a diagB diagA
-> Triangular lo diagA up size a
-> Triangular lo diagB up size a
-> Triangular lo (MultipliedDiag diagA diagB) up size a
getTriangularTriangularConform (TriangularTriangularConform lo up size a diagB diagA
 -> Triangular lo diagA up size a
 -> Triangular lo diagB up size a
 -> Triangular lo (MultipliedDiag diagA diagB) up size a)
-> TriangularTriangularConform lo up size a diagB diagA
-> Triangular lo diagA up size a
-> Triangular lo diagB up size a
-> Triangular lo (MultipliedDiag diagA diagB) up size a
forall a b. (a -> b) -> a -> b
$
   TriangularTriangularConform lo up size a diagB Unit
-> TriangularTriangularConform lo up size a diagB NonUnit
-> TriangularTriangularConform lo up size a diagB diagA
forall diag (f :: * -> *).
TriDiag diag =>
f Unit -> f NonUnit -> f diag
MatrixShape.switchTriDiag
      ((Triangular lo Unit up size a
 -> Triangular lo diagB up size a
 -> Triangular lo (MultipliedDiag Unit diagB) up size a)
-> TriangularTriangularConform lo up size a diagB Unit
forall lo up size a diagB diagA.
(Triangular lo diagA up size a
 -> Triangular lo diagB up size a
 -> Triangular lo (MultipliedDiag diagA diagB) up size a)
-> TriangularTriangularConform lo up size a diagB diagA
TriangularTriangularConform ((Triangular lo Unit up size a
  -> Triangular lo diagB up size a
  -> Triangular lo (MultipliedDiag Unit diagB) up size a)
 -> TriangularTriangularConform lo up size a diagB Unit)
-> (Triangular lo Unit up size a
    -> Triangular lo diagB up size a
    -> Triangular lo (MultipliedDiag Unit diagB) up size a)
-> TriangularTriangularConform lo up size a diagB Unit
forall a b. (a -> b) -> a -> b
$ \Triangular lo Unit up size a
a Triangular lo diagB up size a
b ->
         Triangular lo diagB up size a
-> Triangular lo diagB up size a -> Triangular lo diagB up size a
forall lo up diag sh a.
(DiagUpLo lo up, TriDiag diag, C sh, Eq sh, Floating a) =>
Triangular lo diag up sh a
-> Triangular lo diag up sh a -> Triangular lo diag up sh a
Triangular.multiply (Triangular lo Unit up size a -> Triangular lo diagB up size a
forall diag lo up sh a.
TriDiag diag =>
Triangular lo Unit up sh a -> Triangular lo diag up sh a
Triangular.relaxUnitDiagonal Triangular lo Unit up size a
a) Triangular lo diagB up size a
b)
      ((Triangular lo NonUnit up size a
 -> Triangular lo diagB up size a
 -> Triangular lo (MultipliedDiag NonUnit diagB) up size a)
-> TriangularTriangularConform lo up size a diagB NonUnit
forall lo up size a diagB diagA.
(Triangular lo diagA up size a
 -> Triangular lo diagB up size a
 -> Triangular lo (MultipliedDiag diagA diagB) up size a)
-> TriangularTriangularConform lo up size a diagB diagA
TriangularTriangularConform ((Triangular lo NonUnit up size a
  -> Triangular lo diagB up size a
  -> Triangular lo (MultipliedDiag NonUnit diagB) up size a)
 -> TriangularTriangularConform lo up size a diagB NonUnit)
-> (Triangular lo NonUnit up size a
    -> Triangular lo diagB up size a
    -> Triangular lo (MultipliedDiag NonUnit diagB) up size a)
-> TriangularTriangularConform lo up size a diagB NonUnit
forall a b. (a -> b) -> a -> b
$ \Triangular lo NonUnit up size a
a Triangular lo diagB up size a
b ->
         Triangular lo NonUnit up size a
-> Triangular lo NonUnit up size a
-> Triangular lo NonUnit up size a
forall lo up diag sh a.
(DiagUpLo lo up, TriDiag diag, C sh, Eq sh, Floating a) =>
Triangular lo diag up sh a
-> Triangular lo diag up sh a -> Triangular lo diag up sh a
Triangular.multiply Triangular lo NonUnit up size a
a (Triangular lo diagB up size a -> Triangular lo NonUnit up size a
forall diag lo up sh a.
TriDiag diag =>
Triangular lo diag up sh a -> Triangular lo NonUnit up sh a
Triangular.strictNonUnitDiagonal Triangular lo diagB up size a
b))


instance
   (Unary.Natural sub, Unary.Natural super,
    Extent.C vertA, Extent.C horizA,
    Extent.C vertB, Extent.C horizB,
    Shape.C heightA, Shape.C widthA, Shape.C widthB,
    widthA ~ heightB, Eq heightB) =>
      Multiply
         (MatrixShape.Full vertA horizA heightA widthA)
         (MatrixShape.Banded sub super vertB horizB heightB widthB)
            where
   type Multiplied
         (MatrixShape.Full vertA horizA heightA widthA)
         (MatrixShape.Banded sub super vertB horizB heightB widthB) =
            MatrixShape.Full
               (ExtentPriv.Multiply vertA vertB)
               (ExtentPriv.Multiply horizA horizB)
               heightA widthB
   matrixMatrix :: Array (Full vertA horizA heightA widthA) a
-> Array (Banded sub super vertB horizB heightB widthB) a
-> Array
     (Multiplied
        (Full vertA horizA heightA widthA)
        (Banded sub super vertB horizB heightB widthB))
     a
matrixMatrix Array (Full vertA horizA heightA widthA) a
a Array (Banded sub super vertB horizB heightB widthB) a
b =
      case Extent vertA horizA heightA widthA
-> Extent vertB horizB widthA widthB
-> ((TagFact (Multiply vertA vertB),
     TagFact (Multiply horizA horizB)),
    (Map
       vertA
       horizA
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       heightA
       widthA,
     Map
       vertB
       horizB
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       widthA
       widthB))
forall vertA horizA vertB horizB vertC horizC height fuse width.
(C vertA, C horizA, C vertB, C horizB,
 Multiply vertA vertB ~ vertC, Multiply horizA horizB ~ horizC) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> ((TagFact vertC, TagFact horizC),
    (Map vertA horizA vertC horizC height fuse,
     Map vertB horizB vertC horizC fuse width))
unifyFactors (Array (Full vertA horizA heightA widthA) a
-> Extent vertA horizA heightA widthA
forall vert horiz height width a.
Full vert horiz height width a -> Extent vert horiz height width
fullExtent Array (Full vertA horizA heightA widthA) a
a) (Array (Banded sub super vertB horizB heightB widthB) a
-> Extent vertB horizB heightB widthB
forall sup super vert horiz height width a.
Banded sup super vert horiz height width a
-> Extent vert horiz height width
bandedExtent Array (Banded sub super vertB horizB heightB widthB) a
b) of
         ((TagFact (Multiply vertA vertB)
ExtentPriv.TagFact, TagFact (Multiply horizA horizB)
ExtentPriv.TagFact), (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft, Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight)) ->
            (Banded
   sub
   super
   (Multiply vertA vertB)
   (Multiply horizA horizB)
   widthA
   widthB
   a
 -> Full
      (Multiply horizA horizB) (Multiply vertA vertB) widthA heightA a
 -> Full
      (Multiply horizA horizB) (Multiply vertA vertB) widthB heightA a)
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthA a
-> Banded
     sub
     super
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     widthA
     widthB
     a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthB a
forall vertA vertB horizA horizB matrix widthA heightA a widthB
       heightB.
(C vertA, C vertB, C horizA, C horizB) =>
(matrix
 -> Full horizA vertA widthA heightA a
 -> Full horizB vertB widthB heightB a)
-> Full vertA horizA heightA widthA a
-> matrix
-> Full vertB horizB heightB widthB a
swapMultiply (Banded
  super
  sub
  (Multiply horizA horizB)
  (Multiply vertA vertB)
  widthB
  widthA
  a
-> Full
     (Multiply horizA horizB) (Multiply vertA vertB) widthA heightA a
-> Full
     (Multiply horizA horizB) (Multiply vertA vertB) widthB heightA a
forall sub super vert horiz height width fuse a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 C fuse, Eq fuse, Floating a) =>
Banded sub super vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Banded.multiplyFull (Banded
   super
   sub
   (Multiply horizA horizB)
   (Multiply vertA vertB)
   widthB
   widthA
   a
 -> Full
      (Multiply horizA horizB) (Multiply vertA vertB) widthA heightA a
 -> Full
      (Multiply horizA horizB) (Multiply vertA vertB) widthB heightA a)
-> (Banded
      sub
      super
      (Multiply vertA vertB)
      (Multiply horizA horizB)
      widthA
      widthB
      a
    -> Banded
         super
         sub
         (Multiply horizA horizB)
         (Multiply vertA vertB)
         widthB
         widthA
         a)
-> Banded
     sub
     super
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     widthA
     widthB
     a
-> Full
     (Multiply horizA horizB) (Multiply vertA vertB) widthA heightA a
-> Full
     (Multiply horizA horizB) (Multiply vertA vertB) widthB heightA a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Banded
  sub
  super
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
  a
-> Banded
     super
     sub
     (Multiply horizA horizB)
     (Multiply vertA vertB)
     widthB
     widthA
     a
forall vert horiz sub super height width a.
(C vert, C horiz) =>
Banded sub super vert horiz height width a
-> Banded super sub horiz vert width height a
Banded.transpose)
               (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
-> Array (Full vertA horizA heightA widthA) a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthA a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft Array (Full vertA horizA heightA widthA) a
a)
               (Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
-> Banded sub super vertB horizB widthA widthB a
-> Banded
     sub
     super
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     widthA
     widthB
     a
forall vertA horizA vertB horizB height width super sub a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Banded super sub vertA horizA height width a
-> Banded super sub vertB horizB height width a
Banded.mapExtent Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight Banded sub super vertB horizB widthA widthB a
Array (Banded sub super vertB horizB heightB widthB) a
b)

instance
   (Unary.Natural sub, Unary.Natural super,
    Extent.C vertA, Extent.C horizA,
    Extent.C vertB, Extent.C horizB,
    Shape.C heightA, Shape.C widthA, Shape.C widthB,
    widthA ~ heightB, Eq heightB) =>
      Multiply
         (MatrixShape.Banded sub super vertA horizA heightA widthA)
         (MatrixShape.Full vertB horizB heightB widthB)
            where
   type Multiplied
         (MatrixShape.Banded sub super vertA horizA heightA widthA)
         (MatrixShape.Full vertB horizB heightB widthB) =
            MatrixShape.Full
               (ExtentPriv.Multiply vertA vertB)
               (ExtentPriv.Multiply horizA horizB)
               heightA widthB
   matrixMatrix :: Array (Banded sub super vertA horizA heightA widthA) a
-> Array (Full vertB horizB heightB widthB) a
-> Array
     (Multiplied
        (Banded sub super vertA horizA heightA widthA)
        (Full vertB horizB heightB widthB))
     a
matrixMatrix Array (Banded sub super vertA horizA heightA widthA) a
a Array (Full vertB horizB heightB widthB) a
b =
      case Extent vertA horizA heightA widthA
-> Extent vertB horizB widthA widthB
-> ((TagFact (Multiply vertA vertB),
     TagFact (Multiply horizA horizB)),
    (Map
       vertA
       horizA
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       heightA
       widthA,
     Map
       vertB
       horizB
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       widthA
       widthB))
forall vertA horizA vertB horizB vertC horizC height fuse width.
(C vertA, C horizA, C vertB, C horizB,
 Multiply vertA vertB ~ vertC, Multiply horizA horizB ~ horizC) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> ((TagFact vertC, TagFact horizC),
    (Map vertA horizA vertC horizC height fuse,
     Map vertB horizB vertC horizC fuse width))
unifyFactors (Array (Banded sub super vertA horizA heightA widthA) a
-> Extent vertA horizA heightA widthA
forall sup super vert horiz height width a.
Banded sup super vert horiz height width a
-> Extent vert horiz height width
bandedExtent Array (Banded sub super vertA horizA heightA widthA) a
a) (Array (Full vertB horizB heightB widthB) a
-> Extent vertB horizB heightB widthB
forall vert horiz height width a.
Full vert horiz height width a -> Extent vert horiz height width
fullExtent Array (Full vertB horizB heightB widthB) a
b) of
         ((TagFact (Multiply vertA vertB)
ExtentPriv.TagFact, TagFact (Multiply horizA horizB)
ExtentPriv.TagFact), (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft, Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight)) ->
            Banded
  sub
  super
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
  a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) widthA widthB a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) heightA widthB a
forall sub super vert horiz height width fuse a.
(Natural sub, Natural super, C vert, C horiz, C height, C width,
 C fuse, Eq fuse, Floating a) =>
Banded sub super vert horiz height fuse a
-> Full vert horiz fuse width a -> Full vert horiz height width a
Banded.multiplyFull
               (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
-> Array (Banded sub super vertA horizA heightA widthA) a
-> Banded
     sub
     super
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     heightA
     widthA
     a
forall vertA horizA vertB horizB height width super sub a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Banded super sub vertA horizA height width a
-> Banded super sub vertB horizB height width a
Banded.mapExtent Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft Array (Banded sub super vertA horizA heightA widthA) a
a)
               (Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
-> Full vertB horizB widthA widthB a
-> Full
     (Multiply vertA vertB) (Multiply horizA horizB) widthA widthB a
forall vertA horizA vertB horizB height width a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Full vertA horizA height width a
-> Full vertB horizB height width a
mapExtent Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight Full vertB horizB widthA widthB a
Array (Full vertB horizB heightB widthB) a
b)

instance
   (Unary.Natural subA, Unary.Natural superA,
    Unary.Natural subB, Unary.Natural superB,
    Extent.C vertA, Extent.C horizA,
    Extent.C vertB, Extent.C horizB,
    Shape.C heightA, Shape.C widthA, Shape.C widthB,
    widthA ~ heightB, Eq heightB) =>
      Multiply
         (MatrixShape.Banded subA superA vertA horizA heightA widthA)
         (MatrixShape.Banded subB superB vertB horizB heightB widthB) where
   type Multiplied
         (MatrixShape.Banded subA superA vertA horizA heightA widthA)
         (MatrixShape.Banded subB superB vertB horizB heightB widthB) =
            MatrixShape.Banded
               (subA :+: subB) (superA :+: superB)
               (ExtentPriv.Multiply vertA vertB)
               (ExtentPriv.Multiply horizA horizB)
               heightA widthB
   matrixMatrix :: Array (Banded subA superA vertA horizA heightA widthA) a
-> Array (Banded subB superB vertB horizB heightB widthB) a
-> Array
     (Multiplied
        (Banded subA superA vertA horizA heightA widthA)
        (Banded subB superB vertB horizB heightB widthB))
     a
matrixMatrix Array (Banded subA superA vertA horizA heightA widthA) a
a Array (Banded subB superB vertB horizB heightB widthB) a
b =
      case Extent vertA horizA heightA widthA
-> Extent vertB horizB widthA widthB
-> ((TagFact (Multiply vertA vertB),
     TagFact (Multiply horizA horizB)),
    (Map
       vertA
       horizA
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       heightA
       widthA,
     Map
       vertB
       horizB
       (Multiply vertA vertB)
       (Multiply horizA horizB)
       widthA
       widthB))
forall vertA horizA vertB horizB vertC horizC height fuse width.
(C vertA, C horizA, C vertB, C horizB,
 Multiply vertA vertB ~ vertC, Multiply horizA horizB ~ horizC) =>
Extent vertA horizA height fuse
-> Extent vertB horizB fuse width
-> ((TagFact vertC, TagFact horizC),
    (Map vertA horizA vertC horizC height fuse,
     Map vertB horizB vertC horizC fuse width))
unifyFactors (Array (Banded subA superA vertA horizA heightA widthA) a
-> Extent vertA horizA heightA widthA
forall sup super vert horiz height width a.
Banded sup super vert horiz height width a
-> Extent vert horiz height width
bandedExtent Array (Banded subA superA vertA horizA heightA widthA) a
a) (Array (Banded subB superB vertB horizB heightB widthB) a
-> Extent vertB horizB heightB widthB
forall sup super vert horiz height width a.
Banded sup super vert horiz height width a
-> Extent vert horiz height width
bandedExtent Array (Banded subB superB vertB horizB heightB widthB) a
b) of
         ((TagFact (Multiply vertA vertB)
ExtentPriv.TagFact, TagFact (Multiply horizA horizB)
ExtentPriv.TagFact), (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft, Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight)) ->
            Banded
  subA
  superA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
  a
-> Banded
     subB
     superB
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     widthA
     widthB
     a
-> Banded
     (subA :+: subB)
     (superA :+: superB)
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     heightA
     widthB
     a
forall subA superA subB superB subC superC vert horiz height width
       fuse a.
(Natural subA, Natural superA, Natural subB, Natural superB,
 (subA :+: subB) ~ subC, (superA :+: superB) ~ superC, C vert,
 C horiz, C height, C width, C fuse, Eq fuse, Floating a) =>
Banded subA superA vert horiz height fuse a
-> Banded subB superB vert horiz fuse width a
-> Banded subC superC vert horiz height width a
Banded.multiply
               (Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
-> Array (Banded subA superA vertA horizA heightA widthA) a
-> Banded
     subA
     superA
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     heightA
     widthA
     a
forall vertA horizA vertB horizB height width super sub a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Banded super sub vertA horizA height width a
-> Banded super sub vertB horizB height width a
Banded.mapExtent Map
  vertA
  horizA
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  heightA
  widthA
unifyLeft Array (Banded subA superA vertA horizA heightA widthA) a
a)
               (Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
-> Banded subB superB vertB horizB widthA widthB a
-> Banded
     subB
     superB
     (Multiply vertA vertB)
     (Multiply horizA horizB)
     widthA
     widthB
     a
forall vertA horizA vertB horizB height width super sub a.
(C vertA, C horizA, C vertB, C horizB) =>
Map vertA horizA vertB horizB height width
-> Banded super sub vertA horizA height width a
-> Banded super sub vertB horizB height width a
Banded.mapExtent Map
  vertB
  horizB
  (Multiply vertA vertB)
  (Multiply horizA horizB)
  widthA
  widthB
unifyRight Banded subB superB vertB horizB widthA widthB a
Array (Banded subB superB vertB horizB heightB widthB) a
b)

bandedExtent ::
   Banded.Banded sup super vert horiz height width a ->
   Extent.Extent vert horiz height width
bandedExtent :: Banded sup super vert horiz height width a
-> Extent vert horiz height width
bandedExtent = Banded sup super vert horiz height width
-> Extent vert horiz height width
forall sub super vert horiz height width.
Banded sub super vert horiz height width
-> Extent vert horiz height width
MatrixShape.bandedExtent (Banded sup super vert horiz height width
 -> Extent vert horiz height width)
-> (Banded sup super vert horiz height width a
    -> Banded sup super vert horiz height width)
-> Banded sup super vert horiz height width a
-> Extent vert horiz height width
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Banded sup super vert horiz height width a
-> Banded sup super vert horiz height width
forall sh a. Array sh a -> sh
Array.shape


instance
   (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ width, Eq width, Shape.C height, Eq height) =>
      Multiply
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.BandedHermitian offDiag size)
            where
   type Multiplied
         (MatrixShape.Full vert horiz height width)
         (MatrixShape.BandedHermitian offDiag size) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (Full vert horiz height width) a
-> Array (BandedHermitian offDiag size) a
-> Array
     (Multiplied
        (Full vert horiz height width) (BandedHermitian offDiag size))
     a
matrixMatrix = Array (Full vert horiz height width) a
-> Array (BandedHermitian offDiag size) a
-> Array
     (Multiplied
        (Full vert horiz height width) (BandedHermitian offDiag size))
     a
forall shape width height vert horiz a.
(MultiplySquare shape, WidthOf shape ~ width, Eq width, C height,
 C vert, C horiz, Floating a) =>
Full vert horiz height width a
-> Array shape a -> Full vert horiz height width a
fullSquare

instance
   (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ height, Eq height, Shape.C width, Eq width) =>
      Multiply
         (MatrixShape.BandedHermitian offDiag size)
         (MatrixShape.Full vert horiz height width)
            where
   type Multiplied
         (MatrixShape.BandedHermitian offDiag size)
         (MatrixShape.Full vert horiz height width) =
            MatrixShape.Full vert horiz height width
   matrixMatrix :: Array (BandedHermitian offDiag size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied
        (BandedHermitian offDiag size) (Full vert horiz height width))
     a
matrixMatrix = Array (BandedHermitian offDiag size) a
-> Array (Full vert horiz height width) a
-> Array
     (Multiplied
        (BandedHermitian offDiag size) (Full vert horiz height width))
     a
forall shape height width vert horiz a.
(MultiplySquare shape, HeightOf shape ~ height, Eq height, C width,
 C vert, C horiz, Floating a) =>
Array shape a
-> Full vert horiz height width a -> Full vert horiz height width a
squareFull

instance
   (Unary.Natural offDiag, Unary.Natural sub, Unary.Natural super,
    Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ width, Eq width, Shape.C height, Eq height) =>
      Multiply
         (MatrixShape.Banded sub super vert horiz height width)
         (MatrixShape.BandedHermitian offDiag size)
            where
   type Multiplied
         (MatrixShape.Banded sub super vert horiz height width)
         (MatrixShape.BandedHermitian offDiag size) =
            MatrixShape.Banded
               (sub:+:offDiag) (super:+:offDiag) vert horiz height width
   matrixMatrix :: Array (Banded sub super vert horiz height width) a
-> Array (BandedHermitian offDiag size) a
-> Array
     (Multiplied
        (Banded sub super vert horiz height width)
        (BandedHermitian offDiag size))
     a
matrixMatrix Array (Banded sub super vert horiz height width) a
a Array (BandedHermitian offDiag size) a
b =
      Array (Banded sub super vert horiz height width) a
-> Banded offDiag offDiag vert horiz width size a
-> Banded
     (sub :+: offDiag) (super :+: offDiag) vert horiz height size a
forall subA superA subB superB subC superC vert horiz height width
       fuse a.
(Natural subA, Natural superA, Natural subB, Natural superB,
 (subA :+: subB) ~ subC, (superA :+: superB) ~ superC, C vert,
 C horiz, C height, C width, C fuse, Eq fuse, Floating a) =>
Banded subA superA vert horiz height fuse a
-> Banded subB superB vert horiz fuse width a
-> Banded subC superC vert horiz height width a
Banded.multiply Array (Banded sub super vert horiz height width) a
a (Square offDiag offDiag size a
-> Banded offDiag offDiag vert horiz size size a
forall vert horiz sub super size a.
(C vert, C horiz) =>
Square sub super size a -> Banded sub super vert horiz size size a
bandedGenSquare (Square offDiag offDiag size a
 -> Banded offDiag offDiag vert horiz size size a)
-> Square offDiag offDiag size a
-> Banded offDiag offDiag vert horiz size size a
forall a b. (a -> b) -> a -> b
$ Array (BandedHermitian offDiag size) a
-> Square offDiag offDiag size a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Square offDiag offDiag size a
BandedHermitian.toBanded Array (BandedHermitian offDiag size) a
b)

instance
   (Unary.Natural offDiag, Unary.Natural sub, Unary.Natural super,
    Extent.C vert, Extent.C horiz,
    Shape.C size, size ~ height, Eq height, Shape.C width, Eq width) =>
      Multiply
         (MatrixShape.BandedHermitian offDiag size)
         (MatrixShape.Banded sub super vert horiz height width)
            where
   type Multiplied
         (MatrixShape.BandedHermitian offDiag size)
         (MatrixShape.Banded sub super vert horiz height width) =
            MatrixShape.Banded
               (offDiag:+:sub) (offDiag:+:super) vert horiz height width
   matrixMatrix :: Array (BandedHermitian offDiag size) a
-> Array (Banded sub super vert horiz height width) a
-> Array
     (Multiplied
        (BandedHermitian offDiag size)
        (Banded sub super vert horiz height width))
     a
matrixMatrix Array (BandedHermitian offDiag size) a
a Array (Banded sub super vert horiz height width) a
b =
      Banded offDiag offDiag vert horiz size size a
-> Banded sub super vert horiz size width a
-> Banded
     (offDiag :+: sub) (offDiag :+: super) vert horiz size width a
forall subA superA subB superB subC superC vert horiz height width
       fuse a.
(Natural subA, Natural superA, Natural subB, Natural superB,
 (subA :+: subB) ~ subC, (superA :+: superB) ~ superC, C vert,
 C horiz, C height, C width, C fuse, Eq fuse, Floating a) =>
Banded subA superA vert horiz height fuse a
-> Banded subB superB vert horiz fuse width a
-> Banded subC superC vert horiz height width a
Banded.multiply (Square offDiag offDiag size a
-> Banded offDiag offDiag vert horiz size size a
forall vert horiz sub super size a.
(C vert, C horiz) =>
Square sub super size a -> Banded sub super vert horiz size size a
bandedGenSquare (Square offDiag offDiag size a
 -> Banded offDiag offDiag vert horiz size size a)
-> Square offDiag offDiag size a
-> Banded offDiag offDiag vert horiz size size a
forall a b. (a -> b) -> a -> b
$ Array (BandedHermitian offDiag size) a
-> Square offDiag offDiag size a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Square offDiag offDiag size a
BandedHermitian.toBanded Array (BandedHermitian offDiag size) a
a) Banded sub super vert horiz size width a
Array (Banded sub super vert horiz height width) a
b

instance
   (Unary.Natural offDiagA, Unary.Natural offDiagB,
    Shape.C sizeA, sizeA ~ sizeB, Shape.C sizeB, Eq sizeB) =>
      Multiply
         (MatrixShape.BandedHermitian offDiagA sizeA)
         (MatrixShape.BandedHermitian offDiagB sizeB)
            where
   type Multiplied
         (MatrixShape.BandedHermitian offDiagA sizeA)
         (MatrixShape.BandedHermitian offDiagB sizeB) =
            MatrixShape.Banded
               (offDiagA:+:offDiagB) (offDiagA:+:offDiagB)
               Small Small sizeA sizeB
   matrixMatrix :: Array (BandedHermitian offDiagA sizeA) a
-> Array (BandedHermitian offDiagB sizeB) a
-> Array
     (Multiplied
        (BandedHermitian offDiagA sizeA) (BandedHermitian offDiagB sizeB))
     a
matrixMatrix Array (BandedHermitian offDiagA sizeA) a
a Array (BandedHermitian offDiagB sizeB) a
b =
      Banded offDiagA offDiagA Small Small sizeA sizeA a
-> Banded offDiagB offDiagB Small Small sizeA sizeB a
-> Banded
     (offDiagA :+: offDiagB)
     (offDiagA :+: offDiagB)
     Small
     Small
     sizeA
     sizeB
     a
forall subA superA subB superB subC superC vert horiz height width
       fuse a.
(Natural subA, Natural superA, Natural subB, Natural superB,
 (subA :+: subB) ~ subC, (superA :+: superB) ~ superC, C vert,
 C horiz, C height, C width, C fuse, Eq fuse, Floating a) =>
Banded subA superA vert horiz height fuse a
-> Banded subB superB vert horiz fuse width a
-> Banded subC superC vert horiz height width a
Banded.multiply (Array (BandedHermitian offDiagA sizeA) a
-> Banded offDiagA offDiagA Small Small sizeA sizeA a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Square offDiag offDiag size a
BandedHermitian.toBanded Array (BandedHermitian offDiagA sizeA) a
a) (Array (BandedHermitian offDiagB sizeB) a
-> Square offDiagB offDiagB sizeB a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Square offDiag offDiag size a
BandedHermitian.toBanded Array (BandedHermitian offDiagB sizeB) a
b)