{-# LANGUAGE GADTs #-}
module Numeric.LAPACK.Matrix.Mosaic.Generic where

import qualified Numeric.LAPACK.Matrix.Mosaic.Private as Mos
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Vector as Vector
import Numeric.LAPACK.Matrix.Mosaic.Private
            (Mosaic, MosaicPacked, MosaicUnpacked)
import Numeric.LAPACK.Matrix.Layout.Private (Order, TriTransposed, uploOrder)
import Numeric.LAPACK.Matrix.Private (ShapeInt, shapeInt)

import qualified Numeric.Netlib.Class as Class

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

import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (Storable)



fromList ::
   (Layout.Packing pack, Layout.Mirror mirror,
    Layout.UpLo uplo, Shape.C sh, Storable a) =>
   Order -> sh -> [a] -> Mosaic pack mirror uplo sh a
fromList :: Order -> sh -> [a] -> Mosaic pack mirror uplo sh a
fromList Order
order sh
sh =
   Mosaic pack mirror uplo sh -> [a] -> Mosaic pack mirror uplo sh a
forall sh a. (C sh, Storable a) => sh -> [a] -> Array sh a
CheckedArray.fromList
      (PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> sh
-> Mosaic pack mirror uplo sh
forall pack mirror uplo size.
PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> size
-> Mosaic pack mirror uplo size
Layout.Mosaic PackingSingleton pack
forall pack. Packing pack => PackingSingleton pack
Layout.autoPacking MirrorSingleton mirror
forall mirror. Mirror mirror => MirrorSingleton mirror
Layout.autoMirror
         UpLoSingleton uplo
forall uplo. UpLo uplo => UpLoSingleton uplo
Layout.autoUplo Order
order sh
sh)

autoFromList ::
   (Layout.Packing pack, Layout.Mirror mirror,
    Layout.UpLo uplo, Storable a) =>
   Order -> [a] -> Mosaic pack mirror uplo ShapeInt a
autoFromList :: Order -> [a] -> Mosaic pack mirror uplo ShapeInt a
autoFromList Order
order [a]
xs =
   let n :: Int
n = [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs
       packed :: PackingSingleton pack
packed = PackingSingleton pack
forall pack. Packing pack => PackingSingleton pack
Layout.autoPacking
       name :: [Char]
name = [Char]
"Triangular.autoFromList"
       size :: Int
size =
          case PackingSingleton pack
packed of
             PackingSingleton pack
Layout.Packed -> [Char] -> Int -> Int
Layout.triangleExtent [Char]
name Int
n
             PackingSingleton pack
Layout.Unpacked -> [Char] -> Int -> Int
Layout.squareExtent [Char]
name Int
n
   in Mosaic pack mirror uplo ShapeInt
-> [a] -> Mosaic pack mirror uplo ShapeInt a
forall sh a. (C sh, Storable a) => sh -> [a] -> Array sh a
Array.fromList
         (PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> ShapeInt
-> Mosaic pack mirror uplo ShapeInt
forall pack mirror uplo size.
PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> size
-> Mosaic pack mirror uplo size
Layout.Mosaic PackingSingleton pack
packed MirrorSingleton mirror
forall mirror. Mirror mirror => MirrorSingleton mirror
Layout.autoMirror UpLoSingleton uplo
forall uplo. UpLo uplo => UpLoSingleton uplo
Layout.autoUplo
            Order
order (Int -> ShapeInt
shapeInt Int
size))
         [a]
xs


transpose ::
   (Layout.UpLo uplo) =>
   Mosaic pack mirror uplo sh a -> Mosaic pack mirror (TriTransposed uplo) sh a
transpose :: Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose (Array Mosaic pack mirror uplo sh
sh ForeignPtr a
a) = Mosaic pack mirror (TriTransposed uplo) sh
-> ForeignPtr a -> Mosaic pack mirror (TriTransposed uplo) sh a
forall sh a. sh -> ForeignPtr a -> Array sh a
Array (Mosaic pack mirror uplo sh
-> Mosaic pack mirror (TriTransposed uplo) sh
forall uplo pack mirror sh.
UpLo uplo =>
Mosaic pack mirror uplo sh
-> Mosaic pack mirror (TriTransposed uplo) sh
Layout.triangularTranspose Mosaic pack mirror uplo sh
sh) ForeignPtr a
a

adjoint ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   Mosaic pack mirror uplo sh a -> Mosaic pack mirror (TriTransposed uplo) sh a
adjoint :: Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
adjoint = Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
forall uplo pack mirror sh a.
UpLo uplo =>
Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
transpose (Mosaic pack mirror uplo sh a
 -> Mosaic pack mirror (TriTransposed uplo) sh a)
-> (Mosaic pack mirror uplo sh a -> Mosaic pack mirror uplo sh a)
-> Mosaic pack mirror uplo sh a
-> Mosaic pack mirror (TriTransposed uplo) sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mosaic pack mirror uplo sh a -> Mosaic pack mirror uplo sh a
forall sh a. (C sh, Floating a) => Vector sh a -> Vector sh a
Vector.conjugate


unpackDirty ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   Mosaic pack mirror uplo sh a ->
   MosaicUnpacked mirror uplo sh a
unpackDirty :: Mosaic pack mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
unpackDirty Mosaic pack mirror uplo sh a
a =
   case Mosaic pack mirror uplo sh -> PackingSingleton pack
forall pack mirror uplo size.
Mosaic pack mirror uplo size -> PackingSingleton pack
Layout.mosaicPack (Mosaic pack mirror uplo sh -> PackingSingleton pack)
-> Mosaic pack mirror uplo sh -> PackingSingleton pack
forall a b. (a -> b) -> a -> b
$ Mosaic pack mirror uplo sh a -> Mosaic pack mirror uplo sh
forall sh a. Array sh a -> sh
Array.shape Mosaic pack mirror uplo sh a
a of
      PackingSingleton pack
Layout.Unpacked -> Mosaic pack mirror uplo sh a
MosaicUnpacked mirror uplo sh a
a
      PackingSingleton pack
Layout.Packed -> MosaicPacked mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
forall uplo sh a mirror.
(UpLo uplo, C sh, Floating a) =>
MosaicPacked mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
unpackDirtyAux Mosaic pack mirror uplo sh a
MosaicPacked mirror uplo sh a
a

unpackDirtyAux ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   MosaicPacked mirror uplo sh a ->
   MosaicUnpacked mirror uplo sh a
unpackDirtyAux :: MosaicPacked mirror uplo sh a -> MosaicUnpacked mirror uplo sh a
unpackDirtyAux
      (Array (Layout.Mosaic PackingSingleton Packed
Layout.Packed MirrorSingleton mirror
mirror UpLoSingleton uplo
uplo Order
order sh
sh) ForeignPtr a
a) =
   Mosaic Unpacked mirror uplo sh
-> (Ptr a -> IO ()) -> MosaicUnpacked mirror uplo sh a
forall sh a.
(C sh, Storable a) =>
sh -> (Ptr a -> IO ()) -> Array sh a
Array.unsafeCreate
      (PackingSingleton Unpacked
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> sh
-> Mosaic Unpacked mirror uplo sh
forall pack mirror uplo size.
PackingSingleton pack
-> MirrorSingleton mirror
-> UpLoSingleton uplo
-> Order
-> size
-> Mosaic pack mirror uplo size
Layout.Mosaic PackingSingleton Unpacked
Layout.Unpacked MirrorSingleton mirror
mirror UpLoSingleton uplo
uplo Order
order sh
sh) ((Ptr a -> IO ()) -> MosaicUnpacked mirror uplo sh a)
-> (Ptr a -> IO ()) -> MosaicUnpacked mirror uplo sh a
forall a b. (a -> b) -> a -> b
$
   \Ptr a
bPtr ->
      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 ->
         Order -> Int -> Ptr a -> Ptr a -> IO ()
forall a. Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()
Mos.unpack (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
aPtr Ptr a
bPtr


pack ::
   (Layout.UpLo uplo, Shape.C sh, Class.Floating a) =>
   MosaicUnpacked mirror uplo sh a ->
   MosaicPacked mirror uplo sh a
pack :: MosaicUnpacked mirror uplo sh a -> MosaicPacked mirror uplo sh a
pack (Array (Layout.Mosaic PackingSingleton Unpacked
Layout.Unpacked MirrorSingleton mirror
mirror UpLoSingleton uplo
uplo Order
order sh
sh) ForeignPtr a
a) =
   Mosaic Packed mirror uplo sh
-> (Ptr a -> IO ()) -> MosaicPacked mirror uplo sh a
forall sh a.
(C sh, Storable a) =>
sh -> (Ptr a -> IO ()) -> Array sh a
Array.unsafeCreate
      (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
mirror UpLoSingleton uplo
uplo Order
order sh
sh) ((Ptr a -> IO ()) -> MosaicPacked mirror uplo sh a)
-> (Ptr a -> IO ()) -> MosaicPacked mirror uplo sh a
forall a b. (a -> b) -> a -> b
$
   \Ptr a
bPtr ->
      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 ->
         Order -> Int -> Ptr a -> Ptr a -> IO ()
forall a. Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()
Mos.pack (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
aPtr Ptr a
bPtr

withPack ::
   (Layout.Packing pack) =>
   (Layout.PackingSingleton pack -> Mosaic pack mirror uplo sh a) ->
   Mosaic pack mirror uplo sh a
withPack :: (PackingSingleton pack -> Mosaic pack mirror uplo sh a)
-> Mosaic pack mirror uplo sh a
withPack = ((PackingSingleton pack -> Mosaic pack mirror uplo sh a)
-> PackingSingleton pack -> Mosaic pack mirror uplo sh a
forall a b. (a -> b) -> a -> b
$ PackingSingleton pack
forall pack. Packing pack => PackingSingleton pack
Layout.autoPacking)

repack ::
   (Layout.Packing pack, Layout.UpLo uplo,
    Shape.C sh, Class.Floating a) =>
   MosaicUnpacked mirror uplo sh a ->
   Mosaic pack mirror uplo sh a
repack :: MosaicUnpacked mirror uplo sh a -> Mosaic pack mirror uplo sh a
repack MosaicUnpacked mirror uplo sh a
a = (PackingSingleton pack -> Mosaic pack mirror uplo sh a)
-> Mosaic pack mirror uplo sh a
forall pack mirror uplo sh a.
Packing pack =>
(PackingSingleton pack -> Mosaic pack mirror uplo sh a)
-> Mosaic pack mirror uplo sh a
withPack ((PackingSingleton pack -> Mosaic pack mirror uplo sh a)
 -> Mosaic pack mirror uplo sh a)
-> (PackingSingleton pack -> Mosaic pack mirror uplo sh a)
-> Mosaic pack mirror uplo sh a
forall a b. (a -> b) -> a -> b
$ \PackingSingleton pack
packing ->
   case PackingSingleton pack
packing of
      PackingSingleton pack
Layout.Unpacked -> Mosaic pack mirror uplo sh a
MosaicUnpacked mirror uplo sh a
a
      PackingSingleton pack
Layout.Packed -> MosaicUnpacked mirror uplo sh a -> MosaicPacked 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
a