{-# LANGUAGE TypeFamilies #-}
module Numeric.LAPACK.Orthogonal (
   leastSquares,
   minimumNorm,
   leastSquaresMinimumNormRCond,
   pseudoInverseRCond,

   project,
   leastSquaresConstraint,
   gaussMarkovLinearModel,

   determinant,
   determinantAbsolute,
   complement,
   affineSpanFromKernel,
   affineKernelFromSpan,

   householder,
   householderTall,
   ) where

import qualified Numeric.LAPACK.Orthogonal.Householder as HH
import qualified Numeric.LAPACK.Orthogonal.Plain as Plain

import qualified Numeric.LAPACK.Matrix.Multiply as Multiply
import qualified Numeric.LAPACK.Matrix.Triangular as Triangular
import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape
import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix
import qualified Numeric.LAPACK.Matrix.Basic as Basic
import qualified Numeric.LAPACK.Matrix.Type as Matrix
import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent
import qualified Numeric.LAPACK.Vector as Vector
import Numeric.LAPACK.Matrix.Array (Full, General, Tall, Wide, Square)
import Numeric.LAPACK.Matrix.Private (ShapeInt)
import Numeric.LAPACK.Vector (Vector, (|-|))
import Numeric.LAPACK.Scalar (RealOf)

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Shape as Shape

import Data.Tuple.HT (mapSnd)


{- |
If @x = leastSquares a b@
then @x@ minimizes @Vector.norm2 (multiply a x `sub` b)@.

Precondition: @a@ must have full rank and @height a >= width a@.
-}
leastSquares ::
   (Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>
   Full horiz Extent.Small height width a ->
   Full vert horiz height nrhs a ->
   Full vert horiz width nrhs a
leastSquares :: Full horiz Small height width a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
leastSquares = (Array (Full horiz Small height width) a
 -> Array (Full vert horiz height nrhs) a
 -> Array (Full vert horiz width nrhs) a)
-> Full horiz Small height width a
-> Full vert horiz height nrhs a
-> Full vert horiz width nrhs a
forall shA a shB b shC c.
(Array shA a -> Array shB b -> Array shC c)
-> ArrayMatrix shA a -> ArrayMatrix shB b -> ArrayMatrix shC c
ArrMatrix.lift2 Array (Full horiz Small height width) a
-> Array (Full vert horiz height nrhs) a
-> Array (Full vert horiz width nrhs) a
forall vert horiz height width nrhs a.
(C vert, C horiz, C height, Eq height, C width, C nrhs,
 Floating a) =>
Full horiz Small height width a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
Plain.leastSquares

{- |
The vector @x@ with @x = minimumNorm a b@
is the vector with minimal @Vector.norm2 x@
that satisfies @multiply a x == b@.

Precondition: @a@ must have full rank and @height a <= width a@.
-}
minimumNorm ::
   (Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>
   Full Extent.Small vert height width a ->
   Full vert horiz height nrhs a ->
   Full vert horiz width nrhs a
minimumNorm :: Full Small vert height width a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
minimumNorm = (Array (Full Small vert height width) a
 -> Array (Full vert horiz height nrhs) a
 -> Array (Full vert horiz width nrhs) a)
-> Full Small vert height width a
-> Full vert horiz height nrhs a
-> Full vert horiz width nrhs a
forall shA a shB b shC c.
(Array shA a -> Array shB b -> Array shC c)
-> ArrayMatrix shA a -> ArrayMatrix shB b -> ArrayMatrix shC c
ArrMatrix.lift2 Array (Full Small vert height width) a
-> Array (Full vert horiz height nrhs) a
-> Array (Full vert horiz width nrhs) a
forall vert horiz height width nrhs a.
(C vert, C horiz, C height, Eq height, C width, C nrhs,
 Floating a) =>
Full Small vert height width a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
Plain.minimumNorm


{- |
If @(rank,x) = leastSquaresMinimumNormRCond rcond a b@
then @x@ is the vector with minimum @Vector.norm2 x@
that minimizes @Vector.norm2 (a #*| x `sub` b)@.

Matrix @a@ can have any rank
but you must specify the reciprocal condition of the rank-truncated matrix.
-}
leastSquaresMinimumNormRCond ::
   (Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>
   RealOf a ->
   Full horiz vert height width a ->
   Full vert horiz height nrhs a ->
   (Int, Full vert horiz width nrhs a)
leastSquaresMinimumNormRCond :: RealOf a
-> Full horiz vert height width a
-> Full vert horiz height nrhs a
-> (Int, Full vert horiz width nrhs a)
leastSquaresMinimumNormRCond RealOf a
rcond Full horiz vert height width a
a Full vert horiz height nrhs a
b =
   (Array (Full vert horiz width nrhs) a
 -> Full vert horiz width nrhs a)
-> (Int, Array (Full vert horiz width nrhs) a)
-> (Int, Full vert horiz width nrhs a)
forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd Array (Full vert horiz width nrhs) a
-> Full vert horiz width nrhs a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 ((Int, Array (Full vert horiz width nrhs) a)
 -> (Int, Full vert horiz width nrhs a))
-> (Int, Array (Full vert horiz width nrhs) a)
-> (Int, Full vert horiz width nrhs a)
forall a b. (a -> b) -> a -> b
$
   RealOf a
-> Full horiz vert height width a
-> Full vert horiz height nrhs a
-> (Int, Array (Full vert horiz width nrhs) a)
forall vert horiz height width nrhs a.
(C vert, C horiz, C height, Eq height, C width, C nrhs,
 Floating a) =>
RealOf a
-> Full horiz vert height width a
-> Full vert horiz height nrhs a
-> (Int, Full vert horiz width nrhs a)
Plain.leastSquaresMinimumNormRCond
      RealOf a
rcond (Full horiz vert height width a -> Full horiz vert height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector Full horiz vert height width a
a) (Full vert horiz height nrhs a -> Full vert horiz height nrhs a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector Full vert horiz height nrhs a
b)


pseudoInverseRCond ::
   (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,
    Class.Floating a) =>
   RealOf a ->
   Full vert horiz height width a ->
   (Int, Full horiz vert width height a)
pseudoInverseRCond :: RealOf a
-> Full vert horiz height width a
-> (Int, Full horiz vert width height a)
pseudoInverseRCond RealOf a
rcond =
   (Full horiz vert (Unchecked width) (Unchecked height) a
 -> Full horiz vert width height a)
-> (Int, Full horiz vert (Unchecked width) (Unchecked height) a)
-> (Int, Full horiz vert width height a)
forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd (Array (Full horiz vert width height) a
-> Full horiz vert width height a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (Full horiz vert width height) a
 -> Full horiz vert width height a)
-> (Full horiz vert (Unchecked width) (Unchecked height) a
    -> Array (Full horiz vert width height) a)
-> Full horiz vert (Unchecked width) (Unchecked height) a
-> Full horiz vert width height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full horiz vert (Unchecked width) (Unchecked height) a
-> Array (Full horiz vert width height) a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz (Unchecked height) (Unchecked width) a
-> Full vert horiz height width a
Basic.recheck) ((Int, Full horiz vert (Unchecked width) (Unchecked height) a)
 -> (Int, Full horiz vert width height a))
-> (Full vert horiz height width a
    -> (Int, Full horiz vert (Unchecked width) (Unchecked height) a))
-> Full vert horiz height width a
-> (Int, Full horiz vert width height a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   RealOf a
-> Full vert horiz (Unchecked height) (Unchecked width) a
-> (Int, Full horiz vert (Unchecked width) (Unchecked height) a)
forall vert horiz height width a.
(C vert, C horiz, C height, Eq height, C width, Eq width,
 Floating a) =>
RealOf a
-> Full vert horiz height width a
-> (Int, Full horiz vert width height a)
Plain.pseudoInverseRCond RealOf a
rcond (Full vert horiz (Unchecked height) (Unchecked width) a
 -> (Int, Full horiz vert (Unchecked width) (Unchecked height) a))
-> (Full vert horiz height width a
    -> Full vert horiz (Unchecked height) (Unchecked width) a)
-> Full vert horiz height width a
-> (Int, Full horiz vert (Unchecked width) (Unchecked height) a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   Full vert horiz height width a
-> Full vert horiz (Unchecked height) (Unchecked width) a
forall vert horiz height width a.
(C vert, C horiz) =>
Full vert horiz height width a
-> Full vert horiz (Unchecked height) (Unchecked width) a
Basic.uncheck (Full vert horiz height width a
 -> Full vert horiz (Unchecked height) (Unchecked width) a)
-> (Full vert horiz height width a
    -> Full vert horiz height width a)
-> Full vert horiz height width a
-> Full vert horiz (Unchecked height) (Unchecked width) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full vert horiz height width a -> Full vert horiz height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector


{- |
@project b d x@ projects @x@ on the plane described by @B*x = d@.

@b@ must have full rank.
-}
project ::
   (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>
   Wide height width a -> Vector height a ->
   Vector width a -> Vector width a
project :: Wide height width a
-> Vector height a -> Vector width a -> Vector width a
project Wide height width a
b Vector height a
d Vector width a
x =
   Vector width a
x
   Vector width a -> Vector width a -> Vector width a
forall sh a.
(C sh, Eq sh, Floating a) =>
Vector sh a -> Vector sh a -> Vector sh a
|-|
   Order
-> (General height () a -> General width () a)
-> Vector height a
-> Vector width a
forall height0 a height1 b.
Order
-> (General height0 () a -> General height1 () b)
-> Vector height0 a
-> Vector height1 b
ArrMatrix.unliftColumn Order
MatrixShape.ColumnMajor
      (Wide height width a -> General height () a -> General width () a
forall vert horiz height width nrhs a.
(C vert, C horiz, C height, Eq height, C width, C nrhs,
 Floating a) =>
Full Small vert height width a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
minimumNorm Wide height width a
b) (Wide height width a
-> Vector width a
-> Vector (HeightOf (Array (Wide height width))) a
forall typ width a.
(MultiplyVector typ, WidthOf typ ~ width, Eq width, Floating a) =>
Matrix typ a -> Vector width a -> Vector (HeightOf typ) a
Multiply.matrixVector Wide height width a
b Vector width a
x Vector height a -> Vector height a -> Vector height a
forall sh a.
(C sh, Eq sh, Floating a) =>
Vector sh a -> Vector sh a -> Vector sh a
|-| Vector height a
d)


{- |
@leastSquaresConstraint a c b d@ computes @x@
with minimal @|| c - A*x ||_2@ and constraint @B*x = d@.

@b@ must be wide and @a===b@ must be tall
and both matrices must have full rank.
-}
leastSquaresConstraint ::
   (Shape.C height, Eq height,
    Shape.C width, Eq width,
    Shape.C constraints, Eq constraints, Class.Floating a) =>
   General height width a -> Vector height a ->
   Wide constraints width a -> Vector constraints a ->
   Vector width a
leastSquaresConstraint :: General height width a
-> Vector height a
-> Wide constraints width a
-> Vector constraints a
-> Vector width a
leastSquaresConstraint General height width a
a Vector height a
c Wide constraints width a
b Vector constraints a
d =
   General height width a
-> Vector height a
-> Wide constraints width a
-> Vector constraints a
-> Vector width a
forall height width constraints a.
(C height, Eq height, C width, Eq width, C constraints,
 Eq constraints, Floating a) =>
General height width a
-> Vector height a
-> Wide constraints width a
-> Vector constraints a
-> Vector width a
Plain.leastSquaresConstraint
      (General height width a -> General height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector General height width a
a) Vector height a
c
      (Wide constraints width a -> Wide constraints width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector Wide constraints width a
b) Vector constraints a
d

{- |
@gaussMarkovLinearModel a b d@ computes @(x,y)@
with minimal @|| y ||_2@ and constraint @d = A*x + B*y@.

@a@ must be tall and @a|||b@ must be wide
and both matrices must have full rank.
-}
gaussMarkovLinearModel ::
   (Shape.C height, Eq height,
    Shape.C width, Eq width,
    Shape.C opt, Eq opt, Class.Floating a) =>
   Tall height width a -> General height opt a -> Vector height a ->
   (Vector width a, Vector opt a)
gaussMarkovLinearModel :: Tall height width a
-> General height opt a
-> Vector height a
-> (Vector width a, Vector opt a)
gaussMarkovLinearModel Tall height width a
a General height opt a
b Vector height a
d =
   {-
   Fortran-LAPACK and OpenBLAS would leave Y uninitalized
   instead of setting Y to zeros.
   -}
   if height -> Int
forall sh. C sh => sh -> Int
Shape.size (Tall height width a -> HeightOf (Array (Tall height width))
forall typ a. Box typ => Matrix typ a -> HeightOf typ
Matrix.height Tall height width a
a) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
      then (width -> Vector width a
forall sh a. (C sh, Floating a) => sh -> Vector sh a
Vector.zero (Tall height width a -> WidthOf (Array (Tall height width))
forall typ a. Box typ => Matrix typ a -> WidthOf typ
Matrix.width Tall height width a
a), opt -> Vector opt a
forall sh a. (C sh, Floating a) => sh -> Vector sh a
Vector.zero (General height opt a -> WidthOf (Array (General height opt))
forall typ a. Box typ => Matrix typ a -> WidthOf typ
Matrix.width General height opt a
b))
      else Tall height width a
-> General height opt a
-> Vector height a
-> (Vector width a, Vector opt a)
forall height width opt a.
(C height, Eq height, C width, Eq width, C opt, Eq opt,
 Floating a) =>
Tall height width a
-> General height opt a
-> Vector height a
-> (Vector width a, Vector opt a)
Plain.gaussMarkovLinearModel
               (Tall height width a -> Tall height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector Tall height width a
a) (General height opt a -> General height opt a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector General height opt a
b) Vector height a
d


{-
@(q,r) = householder a@
means that @q@ is unitary and @r@ is upper triangular and @a = multiply q r@.
-}
householder ::
   (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,
    Class.Floating a) =>
   Full vert horiz height width a ->
   (Square height a, Full vert horiz height width a)
householder :: Full vert horiz height width a
-> (Square height a, Full vert horiz height width a)
householder Full vert horiz height width a
a =
   let hh :: Householder vert horiz height width a
hh = Full vert horiz height width a
-> Householder vert horiz height width a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a
-> Householder vert horiz height width a
HH.fromMatrix Full vert horiz height width a
a
   in  (Householder vert horiz height width a -> Square height a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Householder vert horiz height width a -> Square height a
HH.extractQ Householder vert horiz height width a
hh, Householder vert horiz height width a
-> Full vert horiz height width a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Householder vert horiz height width a
-> Full vert horiz height width a
HH.extractR Householder vert horiz height width a
hh)

householderTall ::
   (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>
   Full vert Extent.Small height width a ->
   (Full vert Extent.Small height width a, Triangular.Upper width a)
householderTall :: Full vert Small height width a
-> (Full vert Small height width a, Upper width a)
householderTall Full vert Small height width a
a =
   let hh :: Householder vert Small height width a
hh = Full vert Small height width a
-> Householder vert Small height width a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a
-> Householder vert horiz height width a
HH.fromMatrix Full vert Small height width a
a
   in  (Householder vert Small height width a
-> Full vert Small height width a
forall vert height width a.
(C vert, C height, C width, Floating a) =>
Householder vert Small height width a
-> Full vert Small height width a
HH.tallExtractQ Householder vert Small height width a
hh, Householder vert Small height width a -> Upper width a
forall vert height width a.
(C vert, C height, C width, Floating a) =>
Householder vert Small height width a -> Upper width a
HH.tallExtractR Householder vert Small height width a
hh)


determinant :: (Shape.C sh, Class.Floating a) => Square sh a -> a
determinant :: Square sh a -> a
determinant = Square sh a -> a
forall sh a. (C sh, Floating a) => Square sh a -> a
HH.determinant (Square sh a -> a)
-> (Square sh a -> Square sh a) -> Square sh a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square sh a -> Square sh a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a
-> Householder vert horiz height width a
HH.fromMatrix

{-|
Gramian determinant -
works also for non-square matrices, but is sensitive to transposition.

> determinantAbsolute a = sqrt (Herm.determinant (Herm.gramian a))
-}
determinantAbsolute ::
   (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,
    Class.Floating a) =>
   Full vert horiz height width a -> RealOf a
determinantAbsolute :: Full vert horiz height width a -> RealOf a
determinantAbsolute = Full vert horiz height width a -> RealOf a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a -> RealOf a
Plain.determinantAbsolute (Full vert horiz height width a -> RealOf a)
-> (Full vert horiz height width a
    -> Full vert horiz height width a)
-> Full vert horiz height width a
-> RealOf a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Full vert horiz height width a -> Full vert horiz height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector


{- |
For an m-by-n-matrix @a@ with m>=n
this function computes an m-by-(m-n)-matrix @b@
such that @Matrix.multiply (adjoint b) a@ is a zero matrix.
The function does not try to compensate a rank deficiency of @a@.
That is, @a|||b@ has full rank if and only if @a@ has full rank.

For full-rank matrices you might also call this @kernel@ or @nullspace@.
-}
complement ::
   (Shape.C height, Shape.C width, Class.Floating a) =>
   Tall height width a -> Tall height ShapeInt a
complement :: Tall height width a -> Tall height ShapeInt a
complement = (Array (Tall height width) a -> Array (Tall height ShapeInt) a)
-> Tall height width a -> Tall height ShapeInt a
forall shA a shB b.
(Array shA a -> Array shB b)
-> ArrayMatrix shA a -> ArrayMatrix shB b
ArrMatrix.lift1 Array (Tall height width) a -> Array (Tall height ShapeInt) a
forall height width a.
(C height, C width, Floating a) =>
Tall height width a -> Tall height ShapeInt a
Plain.complement


{- |
> affineSpanFromKernel a b == (c,d)

Means:
An affine subspace is given implicitly by {x : a#*|x == b}.
Convert this into an explicit representation {c#*|y|+|d : y}.
Matrix @a@ must have full rank,
otherwise the explicit representation will miss dimensions
and we cannot easily determine the origin @d@ as a minimum norm solution.
-}
affineSpanFromKernel ::
   (Shape.C width, Eq width, Shape.C height, Eq height, Class.Floating a) =>
   Wide height width a -> Vector height a ->
   (Tall width ShapeInt a, Vector width a)
affineSpanFromKernel :: Wide height width a
-> Vector height a -> (Tall width ShapeInt a, Vector width a)
affineSpanFromKernel Wide height width a
a Vector height a
b =
   let qr :: Householder Big Small width height a
qr = Full Big Small width height a
-> Householder Big Small width height a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a
-> Householder vert horiz height width a
HH.fromMatrix (Full Big Small width height a
 -> Householder Big Small width height a)
-> Full Big Small width height a
-> Householder Big Small width height a
forall a b. (a -> b) -> a -> b
$ (Array (Full Small Big height width) a
 -> Array (Full Big Small width height) a)
-> Wide height width a -> Full Big Small width height a
forall shA a shB b.
(Array shA a -> Array shB b)
-> ArrayMatrix shA a -> ArrayMatrix shB b
ArrMatrix.lift1 Array (Full Small Big height width) a
-> Array (Full Big Small width height) a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a -> Full horiz vert width height a
Basic.adjoint Wide height width a
a
   in (Array (Tall width ShapeInt) a -> Tall width ShapeInt a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (Tall width ShapeInt) a -> Tall width ShapeInt a)
-> Array (Tall width ShapeInt) a -> Tall width ShapeInt a
forall a b. (a -> b) -> a -> b
$ Householder Big Small width height a
-> Array (Tall width ShapeInt) a
forall height width a.
(C height, C width, Floating a) =>
Tall height width a -> Tall height ShapeInt a
Plain.extractComplement Householder Big Small width height a
qr,
       Order
-> (General height () a -> General width () a)
-> Vector height a
-> Vector width a
forall height0 a height1 b.
Order
-> (General height0 () a -> General height1 () b)
-> Vector height0 a
-> Vector height1 b
ArrMatrix.unliftColumn Order
MatrixShape.ColumnMajor (Householder Big Small width height a
-> General height () a -> General width () a
forall vert horiz height width nrhs a.
(C vert, C horiz, C height, Eq height, C width, Eq width, C nrhs,
 Floating a) =>
Householder vert Small width height a
-> Full vert horiz height nrhs a -> Full vert horiz width nrhs a
HH.minimumNorm Householder Big Small width height a
qr) Vector height a
b)

{- |
This conversion is somehow inverse to 'affineSpanFromKernel'.
However, it is not precisely inverse in either direction.
This is because both 'affineSpanFromKernel' and 'affineKernelFromSpan'
accept non-orthogonal matrices but always return orthogonal ones.

In @affineKernelFromSpan c d@,
matrix @c@ should have full rank,
otherwise the implicit representation will miss dimensions.
-}
affineKernelFromSpan ::
   (Shape.C width, Eq width, Shape.C height, Eq height, Class.Floating a) =>
   Tall height width a -> Vector height a ->
   (Wide ShapeInt height a, Vector ShapeInt a)
affineKernelFromSpan :: Tall height width a
-> Vector height a -> (Wide ShapeInt height a, Vector ShapeInt a)
affineKernelFromSpan Tall height width a
c Vector height a
d =
   let a :: Full Small Big ShapeInt height a
a = Full Big Small height ShapeInt a
-> Full Small Big ShapeInt height a
forall vert horiz height width a.
(C vert, C horiz, C height, C width, Floating a) =>
Full vert horiz height width a -> Full horiz vert width height a
Basic.adjoint (Full Big Small height ShapeInt a
 -> Full Small Big ShapeInt height a)
-> Full Big Small height ShapeInt a
-> Full Small Big ShapeInt height a
forall a b. (a -> b) -> a -> b
$ Tall height width a -> Full Big Small height ShapeInt a
forall height width a.
(C height, C width, Floating a) =>
Tall height width a -> Tall height ShapeInt a
Plain.complement (Tall height width a -> Full Big Small height ShapeInt a)
-> Tall height width a -> Full Big Small height ShapeInt a
forall a b. (a -> b) -> a -> b
$ Tall height width a -> Tall height width a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector Tall height width a
c
   in (Full Small Big ShapeInt height a -> Wide ShapeInt height a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 Full Small Big ShapeInt height a
a, Full Small Big ShapeInt height a
-> Vector height a -> Vector ShapeInt 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 Full Small Big ShapeInt height a
a Vector height a
d)