{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
module Numeric.LAPACK.Matrix.Mosaic.Packed (
   Mosaic,
   Triangular,
   identity,
   diagonal,
   takeDiagonal,
   forceOrder,

   stackLower,
   stackUpper,
   takeTopLeft,
   Mos.takeTopRight,
   takeBottomLeft,
   takeBottomRight,
   ) where

import qualified Numeric.LAPACK.Matrix.Mosaic.Private as Mos
import qualified Numeric.LAPACK.Matrix.Mosaic.Unpacked as Unpacked
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Matrix.Basic as Basic
import qualified Numeric.LAPACK.Matrix.Private as Matrix
import Numeric.LAPACK.Matrix.Mosaic.Private
         (MosaicLower, MosaicUpper, diagonalPointers, diagonalPointerPairs)
import Numeric.LAPACK.Matrix.Mosaic.Generic (transpose, unpackDirty, pack)
import Numeric.LAPACK.Matrix.Layout.Private (Order, uploOrder)
import Numeric.LAPACK.Vector (Vector)
import Numeric.LAPACK.Scalar (zero, one)
import Numeric.LAPACK.Private (fill)

import qualified Numeric.Netlib.Class as Class

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

import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (poke, peek)

import Data.Foldable (forM_)



type Mosaic mirror uplo sh =
         Array (Layout.Mosaic Layout.Packed mirror uplo sh)
type Triangular uplo sh =
         Array (Layout.TriangularP Layout.Packed uplo sh)


identity ::
   (Layout.Mirror mirror, Layout.UpLo uplo,
    Shape.C sh, Class.Floating a) =>
   Order -> sh -> Mosaic mirror uplo sh a
identity :: Order -> sh -> Mosaic mirror uplo sh a
identity Order
order sh
sh =
   let (Order
realOrder, UpLoSingleton uplo
uplo) = Order -> (Order, UpLoSingleton uplo)
forall uplo. UpLo uplo => Order -> (Order, UpLoSingleton uplo)
autoUploOrder Order
order
   in Mosaic Packed mirror uplo sh
-> (Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a
forall sh a.
(C sh, Storable a) =>
sh -> (Int -> Ptr a -> IO ()) -> Array sh a
Array.unsafeCreateWithSize
         (PackingSingleton Packed
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> sh
-> Mosaic Packed mirror uplo sh
forall pack mirror uplo size.
PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> size
-> Mosaic pack mirror uplo size
Layout.Mosaic
            PackingSingleton Packed
Layout.Packed MirrorSingleton mirror
forall mirror. Mirror mirror => MirrorSingleton mirror
Layout.autoMirror UpLoSingleton uplo
uplo Order
order sh
sh) ((Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a)
-> (Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a
forall a b. (a -> b) -> a -> b
$
         \Int
size Ptr a
aPtr -> do
      let n :: Int
n = sh -> Int
forall sh. C sh => sh -> Int
Shape.size sh
sh
      a -> Int -> Ptr a -> IO ()
forall a. Floating a => a -> Int -> Ptr a -> IO ()
fill a
forall a. Floating a => a
zero Int
size Ptr a
aPtr
      (Ptr a -> IO ()) -> [Ptr a] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((Ptr a -> a -> IO ()) -> a -> Ptr a -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke a
forall a. Floating a => a
one) (Order -> Int -> Ptr a -> [Ptr a]
forall a. Storable a => Order -> Int -> Ptr a -> [Ptr a]
diagonalPointers Order
realOrder Int
n Ptr a
aPtr)

diagonal ::
   (Layout.Mirror mirror, Layout.UpLo uplo,
    Shape.C sh, Class.Floating a) =>
   Order -> Vector sh a -> Mosaic mirror uplo sh a
diagonal :: Order -> Vector sh a -> Mosaic mirror uplo sh a
diagonal Order
order (Array sh
sh ForeignPtr a
x) = do
   let (Order
realOrder, UpLoSingleton uplo
uplo) = Order -> (Order, UpLoSingleton uplo)
forall uplo. UpLo uplo => Order -> (Order, UpLoSingleton uplo)
autoUploOrder Order
order
   Mosaic Packed mirror uplo sh
-> (Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a
forall sh a.
(C sh, Storable a) =>
sh -> (Int -> Ptr a -> IO ()) -> Array sh a
Array.unsafeCreateWithSize
      (PackingSingleton Packed
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> sh
-> Mosaic Packed mirror uplo sh
forall pack mirror uplo size.
PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> size
-> Mosaic pack mirror uplo size
Layout.Mosaic PackingSingleton Packed
Layout.Packed MirrorSingleton mirror
forall mirror. Mirror mirror => MirrorSingleton mirror
Layout.autoMirror
         UpLoSingleton uplo
uplo Order
order sh
sh) ((Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a)
-> (Int -> Ptr a -> IO ()) -> Mosaic mirror uplo sh a
forall a b. (a -> b) -> a -> b
$
            \Int
size Ptr a
aPtr -> do
      let n :: Int
n = sh -> Int
forall sh. C sh => sh -> Int
Shape.size sh
sh
      a -> Int -> Ptr a -> IO ()
forall a. Floating a => a -> Int -> Ptr a -> IO ()
fill a
forall a. Floating a => a
zero Int
size Ptr a
aPtr
      ForeignPtr a -> (Ptr a -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr a
x ((Ptr a -> IO ()) -> IO ()) -> (Ptr a -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr a
xPtr ->
         [(Ptr a, Ptr a)] -> ((Ptr a, Ptr a) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Order -> Int -> Ptr a -> Ptr a -> [(Ptr a, Ptr a)]
forall a b.
(Storable a, Storable b) =>
Order -> Int -> Ptr a -> Ptr b -> [(Ptr a, Ptr b)]
diagonalPointerPairs Order
realOrder Int
n Ptr a
xPtr Ptr a
aPtr) (((Ptr a, Ptr a) -> IO ()) -> IO ())
-> ((Ptr a, Ptr a) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$
            \(Ptr a
srcPtr,Ptr a
dstPtr) -> Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr a
dstPtr (a -> IO ()) -> IO a -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
srcPtr

takeDiagonal ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   Mosaic mirror uplo sh a -> Vector sh a
takeDiagonal :: Mosaic mirror uplo sh a -> Vector sh a
takeDiagonal (Array (Layout.Mosaic PackingSingleton Packed
_pack MirrorSingleton mirror
_mirror UpLoSingleton uplo
uplo Order
order sh
sh) ForeignPtr a
a) =
   sh -> (Ptr a -> IO ()) -> Vector sh a
forall sh a.
(C sh, Storable a) =>
sh -> (Ptr a -> IO ()) -> Array sh a
Array.unsafeCreate sh
sh ((Ptr a -> IO ()) -> Vector sh a)
-> (Ptr a -> IO ()) -> Vector sh a
forall a b. (a -> b) -> a -> b
$ \Ptr a
xPtr ->
   ForeignPtr a -> (Ptr a -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr a
a ((Ptr a -> IO ()) -> IO ()) -> (Ptr a -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr a
aPtr ->
      ((Ptr a, Ptr a) -> IO ()) -> [(Ptr a, Ptr a)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_
         (\(Ptr a
dstPtr,Ptr a
srcPtr) -> Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr a
dstPtr (a -> IO ()) -> IO a -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
srcPtr)
         (Order -> Int -> Ptr a -> Ptr a -> [(Ptr a, Ptr a)]
forall a b.
(Storable a, Storable b) =>
Order -> Int -> Ptr a -> Ptr b -> [(Ptr a, Ptr b)]
diagonalPointerPairs (UpLoSingleton uplo -> Order -> Order
forall uplo. UpLoSingleton uplo -> Order -> Order
uploOrder UpLoSingleton uplo
uplo Order
order) (sh -> Int
forall sh. C sh => sh -> Int
Shape.size sh
sh) Ptr a
xPtr Ptr a
aPtr)


{-
This is not maximally efficient.
It fills up a whole square.
This wastes memory but enables more regular memory access patterns.
-}
forceOrder ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   Order -> Mosaic mirror uplo sh a -> Mosaic mirror uplo sh a
forceOrder :: Order -> Mosaic mirror uplo sh a -> Mosaic mirror uplo sh a
forceOrder Order
newOrder Mosaic mirror uplo sh a
a =
   let shape :: Mosaic Packed mirror uplo sh
shape = Mosaic mirror uplo sh a -> Mosaic Packed mirror uplo sh
forall sh a. Array sh a -> sh
Array.shape Mosaic mirror uplo sh a
a
   in if Mosaic Packed mirror uplo sh -> Order
forall pack mirror uplo size. Mosaic pack mirror uplo size -> Order
Layout.mosaicOrder Mosaic Packed mirror uplo sh
shape Order -> Order -> Bool
forall a. Eq a => a -> a -> Bool
== Order
newOrder
         then Mosaic mirror uplo sh a
a
         else MosaicUnpacked mirror uplo sh a -> Mosaic mirror uplo sh a
forall uplo sh a mirror.
(UpLo uplo, C sh, Floating a) =>
MosaicUnpacked mirror uplo sh a -> MosaicPacked mirror uplo sh a
pack (MosaicUnpacked mirror uplo sh a -> Mosaic mirror uplo sh a)
-> MosaicUnpacked mirror uplo sh a -> Mosaic mirror uplo sh a
forall a b. (a -> b) -> a -> b
$ Order
-> MosaicUnpacked mirror uplo sh a
-> MosaicUnpacked mirror uplo sh a
forall uplo sh a mirror.
(UpLo uplo, C sh, Floating a) =>
Order -> Mosaic mirror uplo sh a -> Mosaic mirror uplo sh a
Unpacked.forceOrder Order
newOrder (MosaicUnpacked mirror uplo sh a
 -> MosaicUnpacked mirror uplo sh a)
-> MosaicUnpacked mirror uplo sh a
-> MosaicUnpacked mirror uplo sh a
forall a b. (a -> b) -> a -> b
$ Mosaic mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
forall uplo sh a pack mirror.
(UpLo uplo, C sh, Floating a) =>
Mosaic pack mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
unpackDirty Mosaic mirror uplo sh a
a


autoUploOrder ::
   (Layout.UpLo uplo) =>
   Order -> (Order, Layout.UpLoSingleton uplo)
autoUploOrder :: Order -> (Order, UpLoSingleton uplo)
autoUploOrder Order
order =
   case UpLoSingleton uplo
forall uplo. UpLo uplo => UpLoSingleton uplo
Layout.autoUplo of
      UpLoSingleton uplo
uplo -> (UpLoSingleton uplo -> Order -> Order
forall uplo. UpLoSingleton uplo -> Order -> Order
uploOrder UpLoSingleton uplo
uplo Order
order, UpLoSingleton uplo
uplo)


{-
It does not make much sense to put
'stackLower', 'stackUpper', 'stackSymmetric' in one function
because in 'stackLower' and 'stackUpper'
the height and width of matrix b is swapped.
-}
stackLower ::
   (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>
   MosaicLower mirror width a ->
   Matrix.General height width a ->
   MosaicLower mirror height a ->
   MosaicLower mirror (width::+height) a
stackLower :: MosaicLower mirror width a
-> General height width a
-> MosaicLower mirror height a
-> MosaicLower mirror (width ::+ height) a
stackLower MosaicLower mirror width a
a General height width a
b MosaicLower mirror height a
c =
   Mosaic Packed mirror Upper (width ::+ height) a
-> Mosaic Packed mirror (TriTransposed Upper) (width ::+ height) a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose (Mosaic Packed mirror Upper (width ::+ height) a
 -> Mosaic Packed mirror (TriTransposed Upper) (width ::+ height) a)
-> Mosaic Packed mirror Upper (width ::+ height) a
-> Mosaic Packed mirror (TriTransposed Upper) (width ::+ height) a
forall a b. (a -> b) -> a -> b
$ MosaicUpper mirror width a
-> General width height a
-> MosaicUpper mirror height a
-> Mosaic Packed mirror Upper (width ::+ height) a
forall height width a mirror.
(C height, Eq height, C width, Eq width, Floating a) =>
MosaicUpper mirror height a
-> General height width a
-> MosaicUpper mirror width a
-> MosaicUpper mirror (height ::+ width) a
stackUpper (MosaicLower mirror width a
-> Mosaic Packed mirror (TriTransposed Lower) width a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose MosaicLower mirror width a
a) (General height width a -> General width height a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz) =>
Full meas vert horiz height width a
-> Full meas horiz vert width height a
Basic.transpose General height width a
b) (MosaicLower mirror height a
-> Mosaic Packed mirror (TriTransposed Lower) height a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose MosaicLower mirror height a
c)

stackUpper ::
   (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>
   MosaicUpper mirror height a ->
   Matrix.General height width a ->
   MosaicUpper mirror width a ->
   MosaicUpper mirror (height::+width) a
stackUpper :: MosaicUpper mirror height a
-> General height width a
-> MosaicUpper mirror width a
-> MosaicUpper mirror (height ::+ width) a
stackUpper MosaicUpper mirror height a
a General height width a
b MosaicUpper mirror width a
c =
   let order :: Order
order = Full Size Big Big height width -> Order
forall meas vert horiz height width.
Full meas vert horiz height width -> Order
Layout.fullOrder (Full Size Big Big height width -> Order)
-> Full Size Big Big height width -> Order
forall a b. (a -> b) -> a -> b
$ General height width a -> Full Size Big Big height width
forall sh a. Array sh a -> sh
Array.shape General height width a
b
   in MosaicUpper mirror height a
-> General height width a
-> MosaicUpper mirror width a
-> MosaicUpper mirror (height ::+ width) a
forall height width a mirror.
(C height, Eq height, C width, Eq width, Floating a) =>
MosaicUpper mirror height a
-> General height width a
-> MosaicUpper mirror width a
-> MosaicUpper mirror (height ::+ width) a
Mos.stack (Order -> MosaicUpper mirror height a -> MosaicUpper mirror height a
forall uplo sh a mirror.
(UpLo uplo, C sh, Floating a) =>
Order -> Mosaic mirror uplo sh a -> Mosaic mirror uplo sh a
forceOrder Order
order MosaicUpper mirror height a
a) General height width a
b (Order -> MosaicUpper mirror width a -> MosaicUpper mirror width a
forall uplo sh a mirror.
(UpLo uplo, C sh, Floating a) =>
Order -> Mosaic mirror uplo sh a -> Mosaic mirror uplo sh a
forceOrder Order
order MosaicUpper mirror width a
c)

takeTopLeft ::
   (Layout.UpLo uplo, Shape.C height, Shape.C width, Class.Floating a) =>
   Mosaic mirror uplo (height::+width) a ->
   Mosaic mirror uplo height a
takeTopLeft :: Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo height a
takeTopLeft =
   Map Packed mirror (height ::+ width) height a uplo
-> Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo height a
forall pack mirror sh0 sh1 a uplo.
Map pack mirror sh0 sh1 a uplo
-> Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a
Mos.getMap (Map Packed mirror (height ::+ width) height a uplo
 -> Mosaic mirror uplo (height ::+ width) a
 -> Mosaic mirror uplo height a)
-> Map Packed mirror (height ::+ width) height a uplo
-> Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo height a
forall a b. (a -> b) -> a -> b
$
   Map Packed mirror (height ::+ width) height a Upper
-> Map Packed mirror (height ::+ width) height a Lower
-> Map Packed mirror (height ::+ width) height a uplo
forall uplo (f :: * -> *).
UpLo uplo =>
f Upper -> f Lower -> f uplo
Layout.switchUpLo
      ((Mosaic Packed mirror Upper (height ::+ width) a
 -> Mosaic Packed mirror Upper height a)
-> Map Packed mirror (height ::+ width) height a Upper
forall pack mirror sh0 sh1 a uplo.
(Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a)
-> Map pack mirror sh0 sh1 a uplo
Mos.Map ((Mosaic Packed mirror Upper (height ::+ width) a
  -> Mosaic Packed mirror Upper height a)
 -> Map Packed mirror (height ::+ width) height a Upper)
-> (Mosaic Packed mirror Upper (height ::+ width) a
    -> Mosaic Packed mirror Upper height a)
-> Map Packed mirror (height ::+ width) height a Upper
forall a b. (a -> b) -> a -> b
$ Mosaic Packed mirror Upper (height ::+ width) a
-> Mosaic Packed mirror Upper height a
forall height width a mirror.
(C height, C width, Floating a) =>
MosaicUpper mirror (height ::+ width) a
-> MosaicUpper mirror height a
Mos.takeTopLeft)
      ((Mosaic Packed mirror Lower (height ::+ width) a
 -> Mosaic Packed mirror Lower height a)
-> Map Packed mirror (height ::+ width) height a Lower
forall pack mirror sh0 sh1 a uplo.
(Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a)
-> Map pack mirror sh0 sh1 a uplo
Mos.Map ((Mosaic Packed mirror Lower (height ::+ width) a
  -> Mosaic Packed mirror Lower height a)
 -> Map Packed mirror (height ::+ width) height a Lower)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Lower height a)
-> Map Packed mirror (height ::+ width) height a Lower
forall a b. (a -> b) -> a -> b
$ Mosaic Packed mirror Upper height a
-> Mosaic Packed mirror Lower height a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose (Mosaic Packed mirror Upper height a
 -> Mosaic Packed mirror Lower height a)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Upper height a)
-> Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Lower height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mosaic Packed mirror Upper (height ::+ width) a
-> Mosaic Packed mirror Upper height a
forall height width a mirror.
(C height, C width, Floating a) =>
MosaicUpper mirror (height ::+ width) a
-> MosaicUpper mirror height a
Mos.takeTopLeft (Mosaic Packed mirror Upper (height ::+ width) a
 -> Mosaic Packed mirror Upper height a)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Upper (height ::+ width) a)
-> Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Upper height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Upper (height ::+ width) a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose)

takeBottomLeft ::
   (Shape.C height, Shape.C width, Class.Floating a) =>
   MosaicLower mirror (width::+height) a -> Matrix.General height width a
takeBottomLeft :: MosaicLower mirror (width ::+ height) a -> General height width a
takeBottomLeft = Full Size Big Big width height a -> General height width a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz) =>
Full meas vert horiz height width a
-> Full meas horiz vert width height a
Basic.transpose (Full Size Big Big width height a -> General height width a)
-> (MosaicLower mirror (width ::+ height) a
    -> Full Size Big Big width height a)
-> MosaicLower mirror (width ::+ height) a
-> General height width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MosaicUpper mirror (width ::+ height) a
-> Full Size Big Big width height a
forall height width a mirror.
(C height, C width, Floating a) =>
MosaicUpper mirror (height ::+ width) a -> General height width a
Mos.takeTopRight (MosaicUpper mirror (width ::+ height) a
 -> Full Size Big Big width height a)
-> (MosaicLower mirror (width ::+ height) a
    -> MosaicUpper mirror (width ::+ height) a)
-> MosaicLower mirror (width ::+ height) a
-> Full Size Big Big width height a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MosaicLower mirror (width ::+ height) a
-> MosaicUpper mirror (width ::+ height) a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose

takeBottomRight ::
   (Layout.UpLo uplo, Shape.C height, Shape.C width, Class.Floating a) =>
   Mosaic mirror uplo (height::+width) a ->
   Mosaic mirror uplo width a
takeBottomRight :: Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo width a
takeBottomRight =
   Map Packed mirror (height ::+ width) width a uplo
-> Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo width a
forall pack mirror sh0 sh1 a uplo.
Map pack mirror sh0 sh1 a uplo
-> Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a
Mos.getMap (Map Packed mirror (height ::+ width) width a uplo
 -> Mosaic mirror uplo (height ::+ width) a
 -> Mosaic mirror uplo width a)
-> Map Packed mirror (height ::+ width) width a uplo
-> Mosaic mirror uplo (height ::+ width) a
-> Mosaic mirror uplo width a
forall a b. (a -> b) -> a -> b
$
   Map Packed mirror (height ::+ width) width a Upper
-> Map Packed mirror (height ::+ width) width a Lower
-> Map Packed mirror (height ::+ width) width a uplo
forall uplo (f :: * -> *).
UpLo uplo =>
f Upper -> f Lower -> f uplo
Layout.switchUpLo
      ((Mosaic Packed mirror Upper (height ::+ width) a
 -> Mosaic Packed mirror Upper width a)
-> Map Packed mirror (height ::+ width) width a Upper
forall pack mirror sh0 sh1 a uplo.
(Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a)
-> Map pack mirror sh0 sh1 a uplo
Mos.Map ((Mosaic Packed mirror Upper (height ::+ width) a
  -> Mosaic Packed mirror Upper width a)
 -> Map Packed mirror (height ::+ width) width a Upper)
-> (Mosaic Packed mirror Upper (height ::+ width) a
    -> Mosaic Packed mirror Upper width a)
-> Map Packed mirror (height ::+ width) width a Upper
forall a b. (a -> b) -> a -> b
$ Mosaic Packed mirror Upper (height ::+ width) a
-> Mosaic Packed mirror Upper width a
forall height width a mirror.
(C height, C width, Floating a) =>
MosaicUpper mirror (height ::+ width) a
-> MosaicUpper mirror width a
Mos.takeBottomRight)
      ((Mosaic Packed mirror Lower (height ::+ width) a
 -> Mosaic Packed mirror Lower width a)
-> Map Packed mirror (height ::+ width) width a Lower
forall pack mirror sh0 sh1 a uplo.
(Mosaic pack mirror uplo sh0 a -> Mosaic pack mirror uplo sh1 a)
-> Map pack mirror sh0 sh1 a uplo
Mos.Map ((Mosaic Packed mirror Lower (height ::+ width) a
  -> Mosaic Packed mirror Lower width a)
 -> Map Packed mirror (height ::+ width) width a Lower)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Lower width a)
-> Map Packed mirror (height ::+ width) width a Lower
forall a b. (a -> b) -> a -> b
$ Mosaic Packed mirror Upper width a
-> Mosaic Packed mirror Lower width a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose (Mosaic Packed mirror Upper width a
 -> Mosaic Packed mirror Lower width a)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Upper width a)
-> Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Lower width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mosaic Packed mirror Upper (height ::+ width) a
-> Mosaic Packed mirror Upper width a
forall height width a mirror.
(C height, C width, Floating a) =>
MosaicUpper mirror (height ::+ width) a
-> MosaicUpper mirror width a
Mos.takeBottomRight (Mosaic Packed mirror Upper (height ::+ width) a
 -> Mosaic Packed mirror Upper width a)
-> (Mosaic Packed mirror Lower (height ::+ width) a
    -> Mosaic Packed mirror Upper (height ::+ width) a)
-> Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Upper width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mosaic Packed mirror Lower (height ::+ width) a
-> Mosaic Packed mirror Upper (height ::+ width) a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose)