lapack 0.1 → 0.2
raw patch · 76 files changed
+14092/−3413 lines, 76 filesdep +ChasingBottomsdep +QuickCheckdep +boxesdep ~basedep ~blas-ffidep ~comfort-arraynew-component:exe:lapack-economic
Dependencies added: ChasingBottoms, QuickCheck, boxes, deepseq, fixed-length, guarded-allocation, lapack, lazyio, semigroups, tfp
Dependency ranges changed: base, blas-ffi, comfort-array, netlib-ffi, non-empty, transformers, utility-ht
Files
- Makefile +6/−0
- example/EconomicAllocation.hs +71/−0
- lapack.cabal +107/−15
- src/Numeric/LAPACK/Eigen/General.hs +0/−319
- src/Numeric/LAPACK/Eigen/Hermitian.hs +0/−142
- src/Numeric/LAPACK/Eigen/Triangular.hs +0/−176
- src/Numeric/LAPACK/Format.hs +268/−114
- src/Numeric/LAPACK/Linear/General.hs +0/−88
- src/Numeric/LAPACK/Linear/Hermitian.hs +0/−87
- src/Numeric/LAPACK/Linear/HermitianPositiveDefinite.hs +0/−105
- src/Numeric/LAPACK/Linear/LowerUpper.hs +437/−0
- src/Numeric/LAPACK/Linear/Private.hs +68/−0
- src/Numeric/LAPACK/Linear/Triangular.hs +0/−88
- src/Numeric/LAPACK/Matrix.hs +510/−171
- src/Numeric/LAPACK/Matrix/Banded.hs +28/−0
- src/Numeric/LAPACK/Matrix/Banded/Basic.hs +555/−0
- src/Numeric/LAPACK/Matrix/Banded/Linear.hs +115/−0
- src/Numeric/LAPACK/Matrix/BandedHermitian.hs +34/−0
- src/Numeric/LAPACK/Matrix/BandedHermitian/Basic.hs +480/−0
- src/Numeric/LAPACK/Matrix/BandedHermitian/Eigen.hs +135/−0
- src/Numeric/LAPACK/Matrix/BandedHermitianPositiveDefinite.hs +5/−0
- src/Numeric/LAPACK/Matrix/BandedHermitianPositiveDefinite/Linear.hs +116/−0
- src/Numeric/LAPACK/Matrix/Basic.hs +108/−0
- src/Numeric/LAPACK/Matrix/Divide.hs +97/−0
- src/Numeric/LAPACK/Matrix/Extent.hs +41/−0
- src/Numeric/LAPACK/Matrix/Extent/Kind.hs +35/−0
- src/Numeric/LAPACK/Matrix/Extent/Private.hs +480/−0
- src/Numeric/LAPACK/Matrix/Hermitian.hs +17/−523
- src/Numeric/LAPACK/Matrix/Hermitian/Basic.hs +460/−0
- src/Numeric/LAPACK/Matrix/Hermitian/Eigen.hs +121/−0
- src/Numeric/LAPACK/Matrix/Hermitian/Linear.hs +73/−0
- src/Numeric/LAPACK/Matrix/Hermitian/Private.hs +14/−0
- src/Numeric/LAPACK/Matrix/HermitianPositiveDefinite.hs +5/−0
- src/Numeric/LAPACK/Matrix/HermitianPositiveDefinite/Linear.hs +114/−0
- src/Numeric/LAPACK/Matrix/Multiply.hs +474/−184
- src/Numeric/LAPACK/Matrix/Private.hs +76/−1
- src/Numeric/LAPACK/Matrix/Shape.hs +97/−0
- src/Numeric/LAPACK/Matrix/Shape/Private.hs +1010/−326
- src/Numeric/LAPACK/Matrix/Square.hs +32/−183
- src/Numeric/LAPACK/Matrix/Square/Basic.hs +214/−0
- src/Numeric/LAPACK/Matrix/Square/Eigen.hs +302/−0
- src/Numeric/LAPACK/Matrix/Square/Linear.hs +98/−0
- src/Numeric/LAPACK/Matrix/Symmetric/Private.hs +158/−0
- src/Numeric/LAPACK/Matrix/Triangular.hs +39/−296
- src/Numeric/LAPACK/Matrix/Triangular/Basic.hs +548/−0
- src/Numeric/LAPACK/Matrix/Triangular/Eigen.hs +161/−0
- src/Numeric/LAPACK/Matrix/Triangular/Linear.hs +173/−0
- src/Numeric/LAPACK/Matrix/Triangular/Private.hs +123/−27
- src/Numeric/LAPACK/Orthogonal.hs +181/−208
- src/Numeric/LAPACK/Orthogonal/Householder.hs +30/−0
- src/Numeric/LAPACK/Orthogonal/Private.hs +427/−0
- src/Numeric/LAPACK/Permutation.hs +15/−0
- src/Numeric/LAPACK/Permutation/Private.hs +193/−0
- src/Numeric/LAPACK/Private.hs +183/−98
- src/Numeric/LAPACK/Scalar.hs +133/−0
- src/Numeric/LAPACK/ShapeStatic.hs +49/−0
- src/Numeric/LAPACK/Singular.hs +238/−168
- src/Numeric/LAPACK/Split.hs +244/−0
- src/Numeric/LAPACK/Vector.hs +310/−94
- src/Numeric/LAPACK/Wrapper.hs +4/−0
- test/Main.hs +74/−0
- test/Test/Banded.hs +266/−0
- test/Test/Banded/Utility.hs +73/−0
- test/Test/BandedHermitian.hs +411/−0
- test/Test/Format.hs +153/−0
- test/Test/Generator.hs +497/−0
- test/Test/Hermitian.hs +373/−0
- test/Test/Matrix.hs +503/−0
- test/Test/Orthogonal.hs +415/−0
- test/Test/Permutation.hs +40/−0
- test/Test/Shape.hs +219/−0
- test/Test/Singular.hs +143/−0
- test/Test/Square.hs +170/−0
- test/Test/Triangular.hs +404/−0
- test/Test/Utility.hs +205/−0
- test/Test/Vector.hs +134/−0
+ Makefile view
@@ -0,0 +1,6 @@+run-test:+ runhaskell Setup configure --user --enable-tests -fbuildExamples+ runhaskell Setup build+ runhaskell Setup haddock+ ./dist/build/lapack-test/lapack-test+ ./dist/build/lapack-economic/lapack-economic
+ example/EconomicAllocation.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE TypeOperators #-}+module Main where++import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix (ZeroInt, (#>), (|||))+import Numeric.LAPACK.Format ((##))++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Shape ((:+:)((:+:)))+import Data.Function.HT (nest)+++type ZeroInt2 = ZeroInt:+:ZeroInt+type Vector sh = Vector.Vector sh Double+type Matrix height width = Matrix.General height width Double+type SquareMatrix size = Square.Square size Double+++balances :: Vector ZeroInt2+balances =+ Vector.fromList (Matrix.zeroInt 2 :+: Matrix.zeroInt 2)+ [100000, 90000, -50000, -120000]++expenses :: Matrix ZeroInt ZeroInt2+expenses =+ Matrix.fromList (Matrix.zeroInt 2) (Matrix.zeroInt 2 :+: Matrix.zeroInt 2) $+ [16000, 4000, 8000, 12000,+ 10000, 30000, 40000, 20000]++normalize ::+ (Eq height, Shape.C height, Shape.C width) =>+ Matrix height width -> Matrix height width+normalize x = Matrix.scaleRows (Array.map recip (Matrix.rowSums x)) x+++subtractIdentity :: (Eq sh, Shape.C sh) => SquareMatrix sh -> SquareMatrix sh+subtractIdentity x = Matrix.sub x $ Square.identityFrom x++completeIdSquare :: Matrix ZeroInt2 ZeroInt -> SquareMatrix ZeroInt2+completeIdSquare x =+ Square.fromGeneral $+ (Matrix.takeLeftColumns $ Matrix.fromFull $ Square.identityFromHeight x)+ |||+ x++iterationMatrix :: SquareMatrix ZeroInt2+iterationMatrix =+ completeIdSquare $ Matrix.transpose $ normalize expenses++iterated :: Vector ZeroInt2+iterated = nest 30 (iterationMatrix #>) balances++++compensated :: Vector ZeroInt+compensated =+ let a = Matrix.transpose $ normalize expenses+ p = Matrix.takeTopRows a+ k = Square.fromGeneral $ Matrix.takeBottomRows a+ x = Vector.takeLeft balances+ y = Vector.takeRight balances+ in Vector.sub x $ p #> Matrix.solveVector (subtractIdentity k) y+++main :: IO ()+main = do+ Array.mapShape (Shape.ZeroBased . Shape.size) iterated ## "%10.2f"+ compensated ## "%10.2f"
lapack.cabal view
@@ -1,5 +1,5 @@ Name: lapack-Version: 0.1+Version: 0.2 License: BSD3 License-File: LICENSE Author: Henning Thielemann <haskell@henning-thielemann.de>@@ -17,7 +17,7 @@ . * Based on @comfort-array@: Allows to precisely express one-column or one-row matrices,- as well as dense, square, triangular, banded and symmetric matrices.+ as well as dense, square, triangular, banded, symmetric and block matrices. . * Support all data types that are supported by LAPACK, i.e. Float, Double, Complex Float, Complex Double@@ -26,6 +26,8 @@ . * Dependency only on BLAS and LAPACK, no GSL .+ * Works with matrices and vectors with zero dimensions.+ . * Separate formatting operator @(##)@: Works better for tuples of matrices and vectors than 'show'. 'Show' is used for code one-liners@@ -33,11 +35,17 @@ . See also: @hmatrix@. Tested-With: GHC==7.4.2, GHC==7.8.4, GHC==8.2.2-Cabal-Version: >=1.6+Cabal-Version: >=1.8 Build-Type: Simple+Extra-Source-Files:+ Makefile +Flag buildExamples+ description: Build example executables+ default: False+ Source-Repository this- Tag: 0.1+ Tag: 0.2 Type: darcs Location: http://hub.darcs.net/thielema/lapack/ @@ -48,10 +56,16 @@ Library Build-Depends: lapack-ffi >=0.0.1 && <0.1,- blas-ffi >=0.0 && <0.1,- netlib-ffi >=0.1 && <0.2,- comfort-array >=0.0.1 && <0.1,+ blas-ffi >=0.0 && <0.2,+ netlib-ffi >=0.1.1 && <0.2,+ comfort-array >=0.2 && <0.3,+ guarded-allocation >=0.0 && <0.1,+ boxes >=0.1.5 && <0.2,+ deepseq >=1.3 && <1.5,+ lazyio >=0.1 && <0.2, transformers >=0.3 && <0.6,+ tfp >=1.0.1 && <1.1,+ fixed-length >=0.2 && <0.3, non-empty >=0.3 && <0.4, utility-ht >=0.0.10 && <0.1, base >=4.5 && <5@@ -60,24 +74,102 @@ Hs-Source-Dirs: src Exposed-Modules: Numeric.LAPACK.Matrix+ Numeric.LAPACK.Matrix.Extent Numeric.LAPACK.Matrix.Shape Numeric.LAPACK.Matrix.Square Numeric.LAPACK.Matrix.Hermitian+ Numeric.LAPACK.Matrix.HermitianPositiveDefinite Numeric.LAPACK.Matrix.Triangular+ Numeric.LAPACK.Matrix.Banded+ Numeric.LAPACK.Matrix.BandedHermitian+ Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite Numeric.LAPACK.Vector+ Numeric.LAPACK.Scalar Numeric.LAPACK.Orthogonal- Numeric.LAPACK.Linear.General- Numeric.LAPACK.Linear.HermitianPositiveDefinite- Numeric.LAPACK.Linear.Hermitian- Numeric.LAPACK.Linear.Triangular- Numeric.LAPACK.Eigen.General- Numeric.LAPACK.Eigen.Hermitian- Numeric.LAPACK.Eigen.Triangular+ Numeric.LAPACK.Orthogonal.Householder+ Numeric.LAPACK.Permutation+ Numeric.LAPACK.Linear.LowerUpper Numeric.LAPACK.Singular+ Numeric.LAPACK.ShapeStatic+ Numeric.LAPACK.Format Other-Modules:+ Numeric.LAPACK.Orthogonal.Private+ Numeric.LAPACK.Linear.Private+ Numeric.LAPACK.Split+ Numeric.LAPACK.Permutation.Private+ Numeric.LAPACK.Matrix.Square.Basic+ Numeric.LAPACK.Matrix.Square.Linear+ Numeric.LAPACK.Matrix.Square.Eigen Numeric.LAPACK.Matrix.Triangular.Private+ Numeric.LAPACK.Matrix.Triangular.Basic+ Numeric.LAPACK.Matrix.Triangular.Linear+ Numeric.LAPACK.Matrix.Triangular.Eigen+ Numeric.LAPACK.Matrix.Hermitian.Private+ Numeric.LAPACK.Matrix.Hermitian.Basic+ Numeric.LAPACK.Matrix.Hermitian.Linear+ Numeric.LAPACK.Matrix.Hermitian.Eigen+ Numeric.LAPACK.Matrix.HermitianPositiveDefinite.Linear+ Numeric.LAPACK.Matrix.Symmetric.Private+ Numeric.LAPACK.Matrix.Banded.Basic+ Numeric.LAPACK.Matrix.Banded.Linear+ Numeric.LAPACK.Matrix.BandedHermitian.Basic+ Numeric.LAPACK.Matrix.BandedHermitian.Eigen+ Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite.Linear Numeric.LAPACK.Matrix.Shape.Private+ Numeric.LAPACK.Matrix.Extent.Private+ Numeric.LAPACK.Matrix.Extent.Kind Numeric.LAPACK.Matrix.Multiply+ Numeric.LAPACK.Matrix.Divide+ Numeric.LAPACK.Matrix.Basic Numeric.LAPACK.Matrix.Private Numeric.LAPACK.Private- Numeric.LAPACK.Format+ Numeric.LAPACK.Wrapper++Test-Suite lapack-test+ Type: exitcode-stdio-1.0+ Build-Depends:+ lapack,+ netlib-ffi,+ tfp,+ comfort-array,+ QuickCheck >=2.5 && <3,+ ChasingBottoms >=1.2.2 && <1.4,+ transformers,+ semigroups >=0.18.3 && <0.19,+ non-empty >=0.3.1,+ utility-ht,+ base++ GHC-Options: -Wall+ Hs-Source-Dirs: test+ Main-Is: Main.hs+ Other-Modules:+ Test.Shape+ Test.Permutation+ Test.Vector+ Test.Matrix+ Test.Square+ Test.Triangular+ Test.Hermitian+ Test.Orthogonal+ Test.Banded+ Test.BandedHermitian+ Test.Banded.Utility+ Test.Singular+ Test.Generator+ Test.Format+ Test.Utility++Executable lapack-economic+ If flag(buildExamples)+ Build-Depends:+ lapack,+ comfort-array,+ utility-ht,+ base+ Else+ Buildable: False++ GHC-Options: -Wall+ Hs-Source-Dirs: example+ Main-Is: EconomicAllocation.hs
− src/Numeric/LAPACK/Eigen/General.hs
@@ -1,319 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Eigen.General (- values,- schur,- decompose,- ComplexOf,- ) where--import Numeric.LAPACK.Matrix.Square (Square)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor,ColumnMajor))-import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private- (ComplexOf, RealOf, zero, withAutoWorkspaceInfo,- copyToTemp, copyToColumnMajor, allocArray)--import qualified Numeric.LAPACK.FFI.Complex as LapackComplex-import qualified Numeric.LAPACK.FFI.Real as LapackReal-import qualified Numeric.BLAS.FFI.Complex as BlasComplex-import qualified Numeric.BLAS.FFI.Real as BlasReal-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import System.IO.Unsafe (unsafePerformIO)--import Foreign.Marshal.Array (advancePtr, peekArray)-import Foreign.C.Types (CInt, CChar)-import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr, nullPtr, nullFunPtr, castPtr)-import Foreign.Storable (Storable)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)--import Data.Complex (Complex)---values ::- (Shape.C sh, Class.Floating a) =>- Square sh a -> Vector sh (ComplexOf a)-values =- getValues $- Class.switchFloating- (Values valuesAux) (Values valuesAux)- (Values valuesAux) (Values valuesAux)--type Values_ sh a = Square sh a -> Vector sh (ComplexOf a)--newtype Values sh a = Values {getValues :: Values_ sh a}--valuesAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Values_ sh a-valuesAux (Array (MatrixShape.Square _order size) a) =- Array.unsafeCreateWithSize size $ \n wPtr -> do- let lda = n- evalContT $ do- jobvsPtr <- Call.char 'N'- sortPtr <- Call.char 'N'- aPtr <- copyToTemp (n*n) a- ldaPtr <- Call.cint lda- sdimPtr <- Call.alloca- let vsPtr = nullPtr- ldvsPtr <- Call.cint n- let bworkPtr = nullPtr- liftIO $ withAutoWorkspaceInfo "gees" $ \workPtr lworkPtr infoPtr ->- gees- jobvsPtr sortPtr n aPtr ldaPtr sdimPtr- wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr---{- |-If @(q,r) = schur a@, then @a = q \<#\> r \<#\> adjoint q@,-where @q@ is unitary (orthogonal)-and @r@ is a right-upper triangular matrix for complex @a@-and a 1x1-or-2x2-block upper triangular matrix for real @a@.-With @getDiagonal r@ you get all eigenvalues of @a@ if @a@ is complex-and the real parts of the eigenvalues if @a@ is real.-Complex conjugated eigenvalues of a real matrix @a@-are encoded as 2x2 blocks along the diagonal.--}-schur ::- (Shape.C sh, Class.Floating a) =>- Square sh a -> (Square sh a, Square sh a)-schur =- getSchur $- Class.switchFloating- (Schur schurAux) (Schur schurAux)- (Schur schurAux) (Schur schurAux)--type Schur_ sh a = Square sh a -> (Square sh a, Square sh a)--newtype Schur sh a = Schur {getSchur :: Schur_ sh a}--schurAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Schur_ sh a-schurAux (Array (MatrixShape.Square order size) a) = unsafePerformIO $ do- let n = Shape.size size- let lda = n- let sh = MatrixShape.Square ColumnMajor size- evalContT $ do- jobvsPtr <- Call.char 'V'- sortPtr <- Call.char 'N'- aPtr <- ContT $ withForeignPtr a- (s,sPtr) <- allocArray sh- liftIO $ copyToColumnMajor order n n aPtr sPtr- ldaPtr <- Call.cint lda- sdimPtr <- Call.alloca- wPtr <- Call.allocaArray n- (vs,vsPtr) <- allocArray sh- ldvsPtr <- Call.cint n- let bworkPtr = nullPtr- liftIO $ withAutoWorkspaceInfo "gees" $ \workPtr lworkPtr infoPtr ->- gees- jobvsPtr sortPtr n sPtr ldaPtr sdimPtr- wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr- return (vs, s)----type GEES_ ar a =- Ptr CChar -> Ptr CChar -> Int -> Ptr a -> Ptr CInt ->- Ptr CInt -> Ptr (Complex ar) -> Ptr a -> Ptr CInt ->- Ptr a -> Ptr CInt -> Ptr Bool -> Ptr CInt -> IO ()--newtype GEES a = GEES {getGEES :: GEES_ (RealOf a) a}--gees :: Class.Floating a => GEES_ (RealOf a) a-gees =- getGEES $- Class.switchFloating- (GEES geesReal) (GEES geesReal) (GEES geesComplex) (GEES geesComplex)--geesReal :: Class.Real a => GEES_ a a-geesReal- jobvsPtr sortPtr n aPtr ldaPtr sdimPtr- wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr =- evalContT $ do- let selectPtr = nullFunPtr- nPtr <- Call.cint n- wrPtr <- Call.allocaArray n- wiPtr <- Call.allocaArray n- liftIO $- LapackReal.gees- jobvsPtr sortPtr selectPtr nPtr aPtr ldaPtr sdimPtr- wrPtr wiPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr- liftIO $ zipComplex n wrPtr wiPtr wPtr--geesComplex :: Class.Real a => GEES_ a (Complex a)-geesComplex- jobvsPtr sortPtr n aPtr ldaPtr sdimPtr- wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr =- evalContT $ do- let selectPtr = nullFunPtr- nPtr <- Call.cint n- rworkPtr <- Call.allocaArray n- liftIO $- LapackComplex.gees- jobvsPtr sortPtr selectPtr nPtr aPtr ldaPtr sdimPtr- wPtr vsPtr ldvsPtr workPtr lworkPtr rworkPtr bworkPtr infoPtr----{- |-@(vr,d,vl) = Eigen.decompose a@--Counterintuitively, @vr@ contains the right eigenvectors-and @vl@ contains the left eigenvectors as columns.-The idea is to provide a decomposition of @a@.-If @a@ is diagonalizable, then @vr@ and @vl@ are almost inverse to each other.-More precisely, @adjoint vl \<#\> vr@ is a diagonal matrix.-This is because all eigenvectors are normalized to Euclidean norm 1.-With the following scaling, the decomposition becomes perfect:--> let scal = Array.map recip $ getDiagonal $ adjoint vl <#> vr-> a == vr <#> diagonal d <#> diagonal scal <#> adjoint vl--If @a@ is non-diagonalizable then some columns of @vr@ and @vl@ are left zero-and the above property does not hold.--}-decompose ::- (Shape.C sh, Class.Floating a) =>- Square sh a ->- (Square sh (ComplexOf a),- Vector sh (ComplexOf a),- Square sh (ComplexOf a))-decompose =- getDecompose $- Class.switchFloating- (Decompose decomposeReal)- (Decompose decomposeReal)- (Decompose decomposeComplex)- (Decompose decomposeComplex)--newtype Decompose sh a =- Decompose {- getDecompose ::- Square sh a ->- (Square sh (ComplexOf a),- Vector sh (ComplexOf a),- Square sh (ComplexOf a))- }--decomposeReal ::- (Shape.C sh, Class.Real a) =>- Square sh a ->- (Square sh (Complex a), Vector sh (Complex a), Square sh (Complex a))-decomposeReal (Array (MatrixShape.Square order size) a) =- unsafePerformIO $ do- let n = Shape.size size- let lda = n- evalContT $ do- jobvlPtr <- Call.char 'V'- jobvrPtr <- Call.char 'V'- nPtr <- Call.cint n- aPtr <- copyToTemp (n*n) a- ldaPtr <- Call.cint lda- wrPtr <- Call.allocaArray n- wiPtr <- Call.allocaArray n- vlPtr <- Call.allocaArray (n*n)- ldvlPtr <- Call.cint n- vrPtr <- Call.allocaArray (n*n)- ldvrPtr <- Call.cint n- liftIO $ withAutoWorkspaceInfo "geev" $- LapackReal.geev- jobvlPtr jobvrPtr nPtr aPtr ldaPtr- wrPtr wiPtr vlPtr ldvlPtr vrPtr ldvrPtr- (w,wPtr) <- allocArray size- liftIO $ zipComplex n wrPtr wiPtr wPtr- let sh = MatrixShape.Square ColumnMajor size- (vlc,vlcPtr) <- allocArray sh- (vrc,vrcPtr) <- allocArray sh- liftIO $ eigenvectorsToComplex n wiPtr vlPtr vlcPtr- liftIO $ eigenvectorsToComplex n wiPtr vrPtr vrcPtr- return $- case order of- RowMajor -> (vlc, w, vrc)- ColumnMajor -> (vrc, w, vlc)--eigenvectorsToComplex ::- (Eq a, Class.Real a) =>- Int -> Ptr a -> Ptr a -> Ptr (Complex a) -> IO ()-eigenvectorsToComplex n wiPtr vPtr vcPtr = evalContT $ do- nPtr <- Call.cint n- zeroPtr <- Call.real zero- inc0Ptr <- Call.cint 0- inc1Ptr <- Call.cint 1- inc2Ptr <- Call.cint 2- liftIO $ do- let go _ _ [] = return ()- go xPtr yPtr (False:wi) = do- let yrPtr = castPtr yPtr- let yiPtr = advancePtr yrPtr 1- BlasReal.copy nPtr xPtr inc1Ptr yrPtr inc2Ptr- BlasReal.copy nPtr zeroPtr inc0Ptr yiPtr inc2Ptr- go (advancePtr xPtr n) (advancePtr yPtr n) wi- go xPtr yPtr (True:True:wi) = do- let xrPtr = xPtr- let xiPtr = advancePtr xPtr n- let yrPtr = castPtr yPtr- let yiPtr = advancePtr yrPtr 1- let y1Ptr = advancePtr yPtr n- BlasReal.copy nPtr xrPtr inc1Ptr yrPtr inc2Ptr- BlasReal.copy nPtr xiPtr inc1Ptr yiPtr inc2Ptr- BlasComplex.copy nPtr yPtr inc1Ptr y1Ptr inc1Ptr- LapackComplex.lacgv nPtr y1Ptr inc1Ptr- go (advancePtr xPtr (2*n)) (advancePtr yPtr (2*n)) wi- go _xPtr _yPtr wi =- error $ "eigenvectorToComplex: invalid non-real pattern " ++ show wi- go vPtr vcPtr . map (zero/=) =<< peekArray n wiPtr--decomposeComplex ::- (Shape.C sh, Class.Real a) =>- Square sh (Complex a) ->- (Square sh (Complex a), Vector sh (Complex a), Square sh (Complex a))-decomposeComplex (Array (MatrixShape.Square order size) a) =- unsafePerformIO $ do- let n = Shape.size size- let lda = n- evalContT $ do- jobvlPtr <- Call.char 'V'- jobvrPtr <- Call.char 'V'- nPtr <- Call.cint n- aPtr <- copyToTemp (n*n) a- ldaPtr <- Call.cint lda- (w,wPtr) <- allocArray size- let sh = MatrixShape.Square ColumnMajor size- (vl,vlPtr) <- allocArray sh- ldvlPtr <- Call.cint n- (vr,vrPtr) <- allocArray sh- ldvrPtr <- Call.cint n- rworkPtr <- Call.allocaArray (2*n)- liftIO $ withAutoWorkspaceInfo "geev" $ \workPtr lworkPtr infoPtr ->- LapackComplex.geev- jobvlPtr jobvrPtr nPtr aPtr ldaPtr- wPtr vlPtr ldvlPtr vrPtr ldvrPtr- workPtr lworkPtr rworkPtr infoPtr- return $- case order of- RowMajor -> (vl, w, vr)- ColumnMajor -> (vr, w, vl)---zipComplex ::- (Class.Real a) => Int -> Ptr a -> Ptr a -> Ptr (Complex a) -> IO ()-zipComplex n vr vi vc =- evalContT $ do- nPtr <- Call.cint n- incxPtr <- Call.cint 1- incyPtr <- Call.cint 2- let yPtr = castPtr vc- liftIO $ BlasReal.copy nPtr vr incxPtr yPtr incyPtr- liftIO $ BlasReal.copy nPtr vi incxPtr (advancePtr yPtr 1) incyPtr
− src/Numeric/LAPACK/Eigen/Hermitian.hs
@@ -1,142 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Eigen.Hermitian (- values,- decompose,- ) where--import Numeric.LAPACK.Matrix.Hermitian (Hermitian)-import Numeric.LAPACK.Matrix.Square (Square)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Shape.Private- (Order(ColumnMajor), uploFromOrder, triangleSize)-import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private (RealOf, copyToTemp, allocArray)--import qualified Numeric.LAPACK.FFI.Complex as LapackComplex-import qualified Numeric.LAPACK.FFI.Real as LapackReal-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import System.IO.Unsafe (unsafePerformIO)--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt, CChar)-import Foreign.Ptr (Ptr, nullPtr)-import Foreign.Storable (Storable, peek)--import Control.Monad.Trans.Cont (evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)--import Data.Complex (Complex)---values ::- (Shape.C sh, Class.Floating a) =>- Hermitian sh a -> Vector sh (RealOf a)-values =- getValues $- Class.switchFloating- (Values valuesAux) (Values valuesAux)- (Values valuesAux) (Values valuesAux)--newtype Values sh a =- Values {getValues :: Hermitian sh a -> Vector sh (RealOf a)}--valuesAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Hermitian sh a -> Vector sh ar-valuesAux (Array (MatrixShape.Hermitian order size) a) =- Array.unsafeCreateWithSize size $ \n wPtr -> do- evalContT $ do- jobzPtr <- Call.char 'N'- uploPtr <- Call.char $ uploFromOrder order- aPtr <- copyToTemp (triangleSize n) a- let zPtr = nullPtr- ldzPtr <- Call.cint (max 1 n)- liftIO $ withInfo "hpev" $- hpev jobzPtr uploPtr n aPtr wPtr zPtr ldzPtr---{- |-For symmetric eigenvalue problems, @Eigen.decompose@ and @schur@ coincide.--}-decompose ::- (Shape.C sh, Class.Floating a) =>- Hermitian sh a -> (Square sh a, Vector sh (RealOf a))-decompose =- getDecompose $- Class.switchFloating- (Decompose decomposeAux) (Decompose decomposeAux)- (Decompose decomposeAux) (Decompose decomposeAux)--type Decompose_ sh a = Hermitian sh a -> (Square sh a, Vector sh (RealOf a))--newtype Decompose sh a = Decompose {getDecompose :: Decompose_ sh a}--decomposeAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Decompose_ sh a-decomposeAux (Array (MatrixShape.Hermitian order size) a) = unsafePerformIO $ do- let n = Shape.size size- let shZ = MatrixShape.Square ColumnMajor size- evalContT $ do- jobzPtr <- Call.char 'V'- uploPtr <- Call.char $ uploFromOrder order- aPtr <- copyToTemp (triangleSize n) a- (w,wPtr) <- allocArray size- (z,zPtr) <- allocArray shZ- ldzPtr <- Call.cint n- liftIO $ withInfo "hpev" $- hpev jobzPtr uploPtr n aPtr wPtr zPtr ldzPtr- return (z, w)---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $- printf "%s: %d off-diagonal elements not converging" name info---type HPEV_ ar a =- Ptr CChar -> Ptr CChar -> Int -> Ptr a -> Ptr ar ->- Ptr a -> Ptr CInt -> Ptr CInt -> IO ()--newtype HPEV a = HPEV {getHPEV :: HPEV_ (RealOf a) a}--hpev :: Class.Floating a => HPEV_ (RealOf a) a-hpev =- getHPEV $- Class.switchFloating- (HPEV spevReal) (HPEV spevReal) (HPEV hpevComplex) (HPEV hpevComplex)--spevReal :: Class.Real a => HPEV_ a a-spevReal jobzPtr uploPtr n apPtr wPtr zPtr ldzPtr infoPtr =- evalContT $ do- nPtr <- Call.cint n- workPtr <- Call.allocaArray (3*n)- liftIO $- LapackReal.spev- jobzPtr uploPtr nPtr apPtr wPtr zPtr ldzPtr workPtr infoPtr--hpevComplex :: Class.Real a => HPEV_ a (Complex a)-hpevComplex jobzPtr uploPtr n apPtr wPtr zPtr ldzPtr infoPtr =- evalContT $ do- nPtr <- Call.cint n- workPtr <- Call.allocaArray (max 1 (2*n-1))- rworkPtr <- Call.allocaArray (max 1 (3*n-2))- liftIO $- LapackComplex.hpev- jobzPtr uploPtr nPtr apPtr wPtr zPtr ldzPtr workPtr rworkPtr infoPtr
− src/Numeric/LAPACK/Eigen/Triangular.hs
@@ -1,176 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Eigen.Triangular (- values,- decompose,- ) where--import qualified Numeric.LAPACK.Matrix.Triangular as Triangular-import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Triangular.Private- (unpackZero, pack, unpackToTemp, fillTriangle,- forPointers, rowMajorPointers)-import Numeric.LAPACK.Matrix.Triangular (Triangular)-import Numeric.LAPACK.Matrix.Shape.Private- (Order(ColumnMajor,RowMajor), caseUplo, uploOrder, triangleSize)-import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private (zero, lacgv, allocArray)--import qualified Numeric.LAPACK.FFI.Complex as LapackComplex-import qualified Numeric.LAPACK.FFI.Real as LapackReal-import qualified Numeric.BLAS.FFI.Generic as BlasGen-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import System.IO.Unsafe (unsafePerformIO)--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt, CChar)-import Foreign.Ptr (Ptr, nullPtr)-import Foreign.Storable (peek)--import Control.Monad.Trans.Cont (evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)--import Data.Complex (Complex)---values ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a -> Vector sh a-values = Triangular.getDiagonal---{- |-@(vr,d,vlAdj) = TriEigen.decompose a@--Counterintuitively, @vr@ contains the right eigenvectors as columns-and @vlAdj@ contains the left conjugated eigenvectors as rows.-The idea is to provide a decomposition of @a@.-If @a@ is diagonalizable, then @vr@ and @vlAdj@-are almost inverse to each other.-More precisely, @vlAdj \<#\> vr@ is a diagonal matrix.-This is because the eigenvectors are not normalized.-With the following scaling, the decomposition becomes perfect:--> let scal = Array.map recip $ getDiagonal $ vlAdj <#> vr-> a == vr <#> diagonal d <#> diagonal scal <#> vlAdj--If @a@ is non-diagonalizable-then some columns of @vr@ and corresponding rows of @vlAdj@ are left zero-and the above property does not hold.--}-decompose ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a ->- (Triangular uplo sh a, Vector sh a, Triangular uplo sh a)-decompose a =- let (vr,vl) = decomposePlain a- in (vr, values a, vl)--decomposePlain ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a -> (Triangular uplo sh a, Triangular uplo sh a)-decomposePlain (Array (MatrixShape.Triangular uplo order sh) a) =- unsafePerformIO $ do- let n = Shape.size sh- let n2 = n*n- let triSize = triangleSize n- evalContT $ do- sidePtr <- Call.char 'B'- howManyPtr <- Call.char 'A'- let selectPtr = nullPtr- let unpk =- case uploOrder uplo order of- ColumnMajor -> unpackZero ColumnMajor- RowMajor -> unpackZeroRowMajor- aPtr <- unpackToTemp unpk n a- ldaPtr <- Call.cint n- vlPtr <- Call.allocaArray n2- vrPtr <- Call.allocaArray n2- mmPtr <- Call.cint n- mPtr <- Call.alloca- liftIO $ withInfo "trevc" $- trevc sidePtr howManyPtr selectPtr n- aPtr ldaPtr vlPtr ldaPtr vrPtr ldaPtr mmPtr mPtr- (vl,vlpPtr) <-- allocArray $- MatrixShape.Triangular uplo (uploOrder uplo RowMajor) sh- (vr,vrpPtr) <-- allocArray $- MatrixShape.Triangular uplo (uploOrder uplo ColumnMajor) sh- sizePtr <- Call.cint triSize- incPtr <- Call.cint 1- liftIO $ do- pack ColumnMajor n vrPtr vrpPtr- pack RowMajor n vlPtr vlpPtr- lacgv sizePtr vlpPtr incPtr- return $ caseUplo uplo (vl,vr) (vr,vl)---unpackZeroRowMajor :: Class.Floating a => Int -> Ptr a -> Ptr a -> IO ()-unpackZeroRowMajor n packedPtr fullPtr = do- fillTriangle zero RowMajor n fullPtr- unpackRowMajor n packedPtr fullPtr--unpackRowMajor :: Class.Floating a => Int -> Ptr a -> Ptr a -> IO ()-unpackRowMajor n packedPtr fullPtr = evalContT $ do- incxPtr <- Call.cint 1- incyPtr <- Call.cint n- liftIO $- forPointers (rowMajorPointers n fullPtr packedPtr) $- \nPtr (dstPtr,srcPtr) ->- BlasGen.copy nPtr srcPtr incxPtr dstPtr incyPtr---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $- printf "%s: %d off-diagonal elements not converging" name info---type TREVC_ a =- Ptr CChar -> Ptr CChar -> Ptr Bool ->- Int -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt ->- Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ()--newtype TREVC a = TREVC {getTREVC :: TREVC_ a}--trevc :: Class.Floating a => TREVC_ a-trevc =- getTREVC $- Class.switchFloating- (TREVC trevcReal) (TREVC trevcReal)- (TREVC trevcComplex) (TREVC trevcComplex)--trevcReal :: Class.Real a => TREVC_ a-trevcReal sidePtr howmnyPtr selectPtr n- tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr infoPtr =- evalContT $ do- nPtr <- Call.cint n- workPtr <- Call.allocaArray (3*n)- liftIO $- LapackReal.trevc sidePtr howmnyPtr selectPtr nPtr- tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr workPtr infoPtr--trevcComplex :: Class.Real a => TREVC_ (Complex a)-trevcComplex sidePtr howmnyPtr selectPtr n- tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr infoPtr =- evalContT $ do- nPtr <- Call.cint n- workPtr <- Call.allocaArray (2*n)- rworkPtr <- Call.allocaArray n- liftIO $- LapackComplex.trevc sidePtr howmnyPtr selectPtr nPtr- tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr- workPtr rworkPtr infoPtr
src/Numeric/LAPACK/Format.hs view
@@ -1,114 +1,158 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-} module Numeric.LAPACK.Format ( (##), Format(format), FormatArray(formatArray),+ deflt, ) where import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Matrix.Square as Square-import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor))-import Numeric.LAPACK.Matrix.Private (General)+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor, ColumnMajor), Filled(Filled), UnaryProxy)+import Numeric.LAPACK.Matrix.Private (Full)+import Numeric.LAPACK.Scalar (conjugate)+import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip)) import qualified Numeric.Netlib.Class as Class +import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num (integralFromProxy)+ import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape import Data.Array.Comfort.Storable (Array) +import qualified Text.PrettyPrint.Boxes as TextBox+import Text.PrettyPrint.Boxes (Box, (/+/)) import Text.Printf (PrintfArg, printf) +import qualified Data.List.Reverse.StrictSpine as ListRev+import qualified Data.List.Match as Match import qualified Data.List.HT as ListHT-import qualified Data.Complex as Complex-import Data.Monoid (Endo(Endo,appEndo))+import qualified Data.List as List+import Data.Functor.Compose (Compose(Compose, getCompose))+import Data.Foldable (foldMap) import Data.List (mapAccumL, transpose) import Data.Complex (Complex((:+)))+import Data.Maybe.HT (toMaybe)+import Data.Maybe (fromMaybe)+import Data.Char (isSpace) infix 0 ## (##) :: (Format a) => a -> String -> IO ()-a ## fmt = putStr $ unlines $ format fmt a+a ## fmt = putStr $ trim $ TextBox.render $ format fmt a +trim :: String -> String+trim = unlines . map (ListRev.dropWhile isSpace) . lines ++deflt :: String+deflt = "%.4g"++ class Format a where- format :: String -> a -> [String]+ format :: String -> a -> Box instance Format Int where- format _fmt a = [show a]+ format _fmt = TextBox.text . show instance Format Float where- format fmt a = [printf fmt a]+ format fmt = TextBox.text . printf fmt instance Format Double where- format fmt a = [printf fmt a]+ format fmt = TextBox.text . printf fmt -instance (PrintfArg a, Class.Real a) => Format (Complex a) where- format fmt a = [printfComplex fmt a]+instance (Class.Real a) => Format (Complex a) where+ format fmt = TextBox.text . concat . printfComplex fmt +instance (Format a) => Format [a] where+ format fmt = TextBox.vsep 1 TextBox.right . map (format fmt)+ instance (Format a, Format b) => Format (a,b) where- format fmt (a,b) = format fmt a ++ [""] ++ format fmt b+ format fmt (a,b) = format fmt a /+/ format fmt b instance (Format a, Format b, Format c) => Format (a,b,c) where- format fmt (a,b,c) =- format fmt a ++ [""] ++ format fmt b ++ [""] ++ format fmt c+ format fmt (a,b,c) = format fmt a /+/ format fmt b /+/ format fmt c instance (FormatArray sh, Class.Floating a) => Format (Array sh a) where format = formatArray class (Shape.C sh) => FormatArray sh where- formatArray :: (Class.Floating a) => String -> Array sh a -> [String]+ {-+ We use constraint @(Class.Floating a)@ and not @(Format a)@+ because it allows us to align the components of complex numbers.+ -}+ formatArray :: (Class.Floating a) => String -> Array sh a -> Box instance (Integral i) => FormatArray (Shape.ZeroBased i) where- formatArray fmt m = [unwords $ map (printfFloating fmt) $ Array.toList m]+ formatArray = formatVector instance (Integral i) => FormatArray (Shape.OneBased i) where- formatArray fmt m = [unwords $ map (printfFloating fmt) $ Array.toList m]+ formatArray = formatVector -instance (Shape.C sh) => FormatArray (MatrixShape.Square sh) where- formatArray fmt = formatGeneral fmt . Square.toGeneral+formatVector :: (Shape.C sh, Class.Floating a) => String -> Array sh a -> Box+formatVector fmt =+ TextBox.hsep 1 TextBox.right .+ map (TextBox.text . concat . printfFloating fmt) . Array.toList instance- (Shape.C height, Shape.C width) =>- FormatArray (MatrixShape.General height width) where- formatArray = formatGeneral+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ FormatArray (MatrixShape.Full vert horiz height width) where+ formatArray = formatFull -formatGeneral ::- (Shape.C height, Shape.C width, Class.Floating a) =>- String -> General height width a -> [String]-formatGeneral fmt m =- let MatrixShape.General order height width = Array.shape m- in formatAligned $ formatRows fmt order (height,width) $ Array.toList m+formatFull ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ String -> Full vert horiz height width a -> Box+formatFull fmt m =+ let MatrixShape.Full order extent = Array.shape m+ in formatAligned (printfFloating fmt) $+ splitRows order (Extent.dimensions extent) $ Array.toList m instance- (Shape.C height, Shape.C width) =>- FormatArray (MatrixShape.Householder height width) where+ (Eq lower, Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ FormatArray (MatrixShape.Split lower vert horiz height width) where formatArray = formatHouseholder formatHouseholder ::- (Shape.C height, Shape.C width, Class.Floating a) =>- String -> Array (MatrixShape.Householder height width) a -> [String]+ (Eq lower, Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ String -> Array (MatrixShape.Split lower vert horiz height width) a -> Box formatHouseholder fmt m =- let MatrixShape.Householder order height width = Array.shape m- in formatSeparateTriangle $- formatRows fmt order (height,width) $ Array.toList m+ let MatrixShape.Split _ order extent = Array.shape m+ in formatSeparateTriangle (printfFloating fmt) $+ splitRows order (Extent.dimensions extent) $ Array.toList m instance (Shape.C size) => FormatArray (MatrixShape.Hermitian size) where formatArray = formatHermitian formatHermitian :: (Shape.C size, Class.Floating a) =>- String -> Array (MatrixShape.Hermitian size) a -> [String]+ String -> Array (MatrixShape.Hermitian size) a -> Box formatHermitian fmt m = let MatrixShape.Hermitian order size = Array.shape m- in formatSeparateTriangle $- map (map (printfFloating fmt)) $- complementTriangle order (Shape.size size) $ Array.toList m+ in formatSeparateTriangle (printfFloating fmt) $+ complementTriangle conjugate order (Shape.size size) $ Array.toList m -complementTriangle :: (Class.Floating a) => Order -> Int -> [a] -> [[a]]-complementTriangle order n xs =+formatSymmetric ::+ (Shape.C size, Class.Floating a) =>+ String -> Array (MatrixShape.Symmetric size) a -> Box+formatSymmetric fmt m =+ let MatrixShape.Triangular _diag (Filled, Filled) order size = Array.shape m+ in formatSeparateTriangle (printfFloating fmt) $+ complementTriangle id order (Shape.size size) $ Array.toList m++complementTriangle ::+ (Class.Floating a) => (a -> a) -> Order -> Int -> [a] -> [[a]]+complementTriangle adapt order n xs = let mergeTriangles lower upper =- zipWith (++) (map (map conjugate . init) lower) upper+ zipWith (++) (map (map adapt . init) lower) upper in case order of RowMajor -> let tri = slice (take n $ iterate pred n) xs@@ -118,49 +162,57 @@ let tri = slice (take n [1..]) xs in mergeTriangles tri (transpose tri) -conjugate :: (Class.Floating a) => a -> a-conjugate =- appEndo $- Class.switchFloating- (Endo id) (Endo id) (Endo Complex.conjugate) (Endo Complex.conjugate)- instance- (MatrixShape.Uplo uplo, Shape.C size) =>- FormatArray (MatrixShape.Triangular uplo size) where- formatArray = formatTriangular+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag, Shape.C size) =>+ FormatArray (MatrixShape.Triangular lo diag up size) where+ formatArray fmt =+ getFormatTriangular $+ MatrixShape.switchDiagUpLoSym+ (FormatTriangular $ \m ->+ let MatrixShape.Triangular _diag _uplo order size = Array.shape m+ n0 = Unary.unary TypeNum.u0+ in formatAligned (printfFloatingMaybe fmt) $+ formatBanded (n0,n0) order (size,size) $ Array.toList m)+ (FormatTriangular $ formatTriangular fmt)+ (FormatTriangular $ formatTriangular fmt)+ (FormatTriangular $+ formatSymmetric fmt .+ Array.mapShape MatrixShape.strictNonUnitDiagonal) +newtype FormatTriangular diag size a b lo up =+ FormatTriangular {+ getFormatTriangular ::+ Array (MatrixShape.Triangular lo diag up size) a -> b+ }+ formatTriangular ::- (MatrixShape.Uplo uplo, Shape.C size, Class.Floating a) =>- String -> Array (MatrixShape.Triangular uplo size) a -> [String]+ (MatrixShape.TriDiag diag, MatrixShape.UpLo lo up,+ Shape.C size, Class.Floating a) =>+ String -> Array (MatrixShape.Triangular lo diag up size) a -> Box formatTriangular fmt m =- let MatrixShape.Triangular uplo order size = Array.shape m- in formatAligned $- MatrixShape.caseUplo uplo+ let MatrixShape.Triangular _diag uplo order size = Array.shape m+ in formatAligned (printfFloatingMaybe fmt) $+ MatrixShape.caseLoUp uplo padLowerTriangle padUpperTriangle order (Shape.size size) $- map (printfFloating fmt) $ Array.toList m+ Array.toList m -padUpperTriangle :: Order -> Int -> [String] -> [[String]]+padUpperTriangle :: Order -> Int -> [a] -> [[Maybe a]] padUpperTriangle order n xs =- case order of- RowMajor ->- zipWith (++) (iterate ("":) []) (slice (take n $ iterate pred n) xs)- ColumnMajor ->- transpose $- zipWith (++)- (slice (take n [1..]) xs)- (reverse $ take n $ iterate ("":) [])+ let mxs = map Just xs+ nothings = iterate (Nothing:) []+ in case order of+ RowMajor ->+ zipWith (++) nothings (slice (take n $ iterate pred n) mxs)+ ColumnMajor ->+ transpose $+ zipWith (++)+ (slice (take n [1..]) mxs)+ (reverse $ take n nothings) -padLowerTriangle :: Order -> Int -> [String] -> [[String]]+padLowerTriangle :: Order -> Int -> [a] -> [[Maybe a]] padLowerTriangle order n xs =- case order of- RowMajor ->- map (take n) $ map (++ repeat "") $ slice (take n [1..]) xs- ColumnMajor ->- transpose $- zipWith (++) (iterate ("":) []) (slice (take n $ iterate pred n) xs)--_padLowerTriangle :: Order -> Int -> [a] -> [[a]]-_padLowerTriangle order n xs =+ map (map Just) $ case order of RowMajor -> slice (take n [1..]) xs ColumnMajor ->@@ -171,50 +223,152 @@ slice ns xs = snd $ mapAccumL (\ys n -> let (vs,ws) = splitAt n ys in (ws,vs)) xs ns -formatSeparateTriangle :: [[String]] -> [String]-formatSeparateTriangle xss =- let strWidths = columnWidths xss- in zipWith- (\row xs ->- concat $- zipWith (\col cell -> (if row==col then '|' else ' '):cell) [0..] $- zipWith (ListHT.padLeft ' ') strWidths xs)- [(0::Int)..] xss+formatSeparateTriangle :: (a -> [String]) -> [[a]] -> Box+formatSeparateTriangle printFmt =+ alignSeparated . map concat .+ zipWith+ (zipWith (\sep -> attachSeparators sep . printFmt))+ (ListHT.outerProduct+ (\row col -> if row==col then Bar else Space)+ [(0::Int)..] [0..]) -formatRows ::- (Class.Floating a, Shape.C height, Shape.C width) =>- String -> Order -> (height, width) -> [a] -> [[String]]-formatRows fmt order (height,width) =- (case order of++instance+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ FormatArray (MatrixShape.Banded sub super vert horiz height width) where+ formatArray fmt m =+ let MatrixShape.Banded offDiag order extent = Array.shape m+ in formatAligned (printfFloatingMaybe fmt) $+ formatBanded offDiag order (Extent.dimensions extent) $+ Array.toList m++formatBanded ::+ (Shape.C height, Shape.C width, Unary.Natural sub, Unary.Natural super) =>+ (UnaryProxy sub, UnaryProxy super) -> Order ->+ (height, width) -> [a] -> [[Maybe a]]+formatBanded (sub,super) order (height,width) xs =+ let slices =+ ListHT.sliceVertical (MatrixShape.bandedBreadth (sub,super)) xs+ m = Shape.size height+ n = Shape.size width+ in case order of+ RowMajor ->+ map (take n) $+ zipWith (shiftRow Nothing)+ (iterate (1+) (- integralFromProxy sub))+ (map (map Just) slices)+ ColumnMajor ->+ let ku = integralFromProxy super+ in take m $ drop ku $+ foldr+ (\col mat ->+ zipWith (:) (map Just col ++ repeat Nothing) ([]:mat))+ (replicate (ku + m - n) [])+ slices+++instance+ (Unary.Natural offDiag, Shape.C size) =>+ FormatArray (MatrixShape.BandedHermitian offDiag size) where+ formatArray fmt m =+ let MatrixShape.BandedHermitian offDiag order size = Array.shape m+ in formatSeparateTriangle (printfFloatingMaybe fmt) $+ formatBandedHermitian offDiag order size $ Array.toList m++formatBandedHermitian ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ UnaryProxy offDiag -> Order -> size -> [a] -> [[Maybe a]]+formatBandedHermitian offDiag order _size xs =+ let k = integralFromProxy offDiag+ slices = ListHT.sliceVertical (k + 1) xs+ in case order of+ RowMajor ->+ foldr+ (\row square ->+ Match.take ([]:square) (map Just row)+ :+ zipWith (:)+ (tail $ map (Just . conjugate) row ++ repeat Nothing)+ square)+ [] slices+ ColumnMajor ->+ zipWith (shiftRow Nothing) (iterate (1+) (-k)) $ map (map Just) $+ zipWith (++)+ (map (map conjugate . init) slices)+ (drop k $+ foldr+ (\column band ->+ zipWith (++) (map (:[]) column ++ repeat []) ([]:band))+ (replicate k [])+ slices)++shiftRow :: a -> Int -> [a] -> [a]+shiftRow pad k = if k<=0 then drop (-k) else (replicate k pad ++)++splitRows ::+ (Shape.C height, Shape.C width) =>+ Order -> (height, width) -> [a] -> [[a]]+splitRows order (height,width) =+ case order of RowMajor -> ListHT.sliceVertical (Shape.size width)- ColumnMajor -> ListHT.sliceHorizontal (Shape.size height)) .- map (printfFloating fmt)+ ColumnMajor -> ListHT.sliceHorizontal (Shape.size height) -formatAligned :: [[String]] -> [String]-formatAligned xss =- let strWidths = columnWidths xss- in map (unwords . zipWith (ListHT.padLeft ' ') strWidths) xss+formatAligned :: (a -> [String]) -> [[a]] -> Box+formatAligned printFmt =+ alignSeparated . map (concatMap (attachSeparators Space . printFmt)) -columnWidths :: [[[a]]] -> [Int]-columnWidths xss =- case map (map length) xss of- [] -> []- w:ws -> foldl (zipWith max) w ws +data Separator = Empty | Space | Bar+ deriving (Eq, Ord, Show) -newtype Printf a = Printf {runPrintf :: String -> a -> String}+alignSeparated :: [[(Separator, String)]] -> Box+alignSeparated =+ TextBox.hcat TextBox.top .+ map (TextBox.vcat TextBox.right . map TextBox.text) .+ concatMap ((\(seps,column) -> [map formatSeparator seps, column]) . unzip) .+ List.unfoldr (viewLAll (Empty,"")) -printfFloating :: (Class.Floating a) => String -> a -> String-printfFloating =- runPrintf $+viewLAll :: a -> [[a]] -> Maybe ([a], [[a]])+viewLAll x0 xs =+ toMaybe (any (not.null) xs)+ (unzip $ map (fromMaybe (x0,[]) . ListHT.viewL) xs)++formatSeparator :: Separator -> String+formatSeparator sep = case sep of Empty -> ""; Space -> " "; Bar -> "|"++attachSeparators :: Separator -> [str] -> [(Separator, str)]+attachSeparators sep = zip (sep:repeat Empty)+++printfFloating :: (Class.Floating a) => String -> a -> [String]+printfFloating fmt =+ getFlip $ Class.switchFloating- (Printf printf)- (Printf printf)- (Printf printfComplex)- (Printf printfComplex)+ (Flip $ (:[]) . printf fmt)+ (Flip $ (:[]) . printf fmt)+ (Flip $ printfComplex fmt)+ (Flip $ printfComplex fmt) -printfComplex :: (PrintfArg a, Class.Real a) => String -> Complex a -> String-printfComplex fmt (r:+i) =+printfFloatingMaybe :: (Class.Floating a) => String -> Maybe a -> [String]+printfFloatingMaybe fmt =+ getFlip $ getCompose $+ Class.switchFloating+ (Compose $ Flip $ (:[]) . foldMap (printf fmt))+ (Compose $ Flip $ (:[]) . foldMap (printf fmt))+ (Compose $ Flip $ maybe ["",""] (printfComplex fmt))+ (Compose $ Flip $ maybe ["",""] (printfComplex fmt))++printfComplex :: (Class.Real a) => String -> Complex a -> [String]+printfComplex fmt =+ getFlip $ getCompose $+ Class.switchReal+ (Compose $ Flip $ printfComplexAux fmt)+ (Compose $ Flip $ printfComplexAux fmt)++printfComplexAux ::+ (PrintfArg a, Class.Real a) => String -> Complex a -> [String]+printfComplexAux fmt (r:+i) = if i<0 || isNegativeZero i- then printf (fmt ++ "-i" ++ fmt) r (-i)- else printf (fmt ++ "+i" ++ fmt) r i+ then [printf (fmt ++ "-") r, printf (fmt ++ "i") (-i)]+ else [printf (fmt ++ "+") r, printf (fmt ++ "i") i]
− src/Numeric/LAPACK/Linear/General.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Linear.General (- solve,- inverse,- ) where--import Numeric.LAPACK.Matrix.Square (Square)-import Numeric.LAPACK.Matrix (General)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor))-import Numeric.LAPACK.Private (withAutoWorkspace, copyBlock, copyToColumnMajor)--import qualified Numeric.LAPACK.FFI.Generic as LapackGen-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (peek)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)---solve ::- (Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>- Square sh a -> General sh nrhs a -> General sh nrhs a-solve- (Array (MatrixShape.Square orderA shA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor heightB widthB) $- \xPtr -> do- Call.assert "Square.solve: height shapes mismatch"- (shA == heightB)- let n = Shape.size heightB- let nrhs = Shape.size widthB- let ldb = n- evalContT $ do- nPtr <- Call.cint n- nrhsPtr <- Call.cint nrhs- aPtr <- ContT $ withForeignPtr a- atmpPtr <- Call.allocaArray (n*n)- ldaPtr <- Call.cint ldb- ipivPtr <- Call.allocaArray n- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb- liftIO $ do- copyToColumnMajor orderA n n aPtr atmpPtr- copyToColumnMajor orderB n nrhs bPtr xPtr- withInfo "gesv" $- LapackGen.gesv nPtr nrhsPtr atmpPtr ldaPtr ipivPtr xPtr ldbPtr---inverse :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a-inverse (Array shape@(MatrixShape.Square _order sh) a) =- Array.unsafeCreateWithSize shape $ \blockSize bPtr -> do- let n = Shape.size sh- evalContT $ do- nPtr <- Call.cint n- aPtr <- ContT $ withForeignPtr a- ldbPtr <- Call.cint n- ipivPtr <- Call.allocaArray n- liftIO $ do- copyBlock blockSize aPtr bPtr- withInfo "getrf" $ LapackGen.getrf nPtr nPtr bPtr ldbPtr ipivPtr- withInfo "getri" $ \infoPtr ->- withAutoWorkspace $ \workPtr lworkPtr ->- LapackGen.getri nPtr bPtr ldbPtr ipivPtr workPtr lworkPtr infoPtr---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $ printf "%s: %d-th diagonal value is zero" name info
− src/Numeric/LAPACK/Linear/Hermitian.hs
@@ -1,87 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Linear.Hermitian (- solve,- inverse,- ) where--import Numeric.LAPACK.Matrix.Hermitian (Hermitian)-import Numeric.LAPACK.Matrix (General)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Triangular.Private (copyTriangleToTemp)-import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor), uploFromOrder)-import Numeric.LAPACK.Private (copyBlock, copyToColumnMajor)--import qualified Numeric.LAPACK.FFI.Generic as LapackGen-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (peek)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)---solve ::- (Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>- Hermitian sh a -> General sh nrhs a -> General sh nrhs a-solve- (Array (MatrixShape.Hermitian orderA shA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor heightB widthB) $- \xPtr -> do- Call.assert "Hermitian.solve: height shapes mismatch"- (shA == heightB)- let n = Shape.size heightB- let nrhs = Shape.size widthB- let ldb = n- evalContT $ do- uploPtr <- Call.char $ uploFromOrder orderA- nPtr <- Call.cint n- nrhsPtr <- Call.cint nrhs- apPtr <- copyTriangleToTemp orderA n a- ipivPtr <- Call.allocaArray n- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb- liftIO $ do- copyToColumnMajor orderB n nrhs bPtr xPtr- withInfo "hpsv" $- LapackGen.hpsv uploPtr nPtr nrhsPtr apPtr ipivPtr xPtr ldbPtr---inverse ::- (Shape.C sh, Class.Floating a) => Hermitian sh a -> Hermitian sh a-inverse (Array shape@(MatrixShape.Hermitian order sh) a) =- Array.unsafeCreateWithSize shape $ \triSize bPtr -> do- let n = Shape.size sh- evalContT $ do- uploPtr <- Call.char $ uploFromOrder order- nPtr <- Call.cint n- aPtr <- ContT $ withForeignPtr a- ipivPtr <- Call.allocaArray n- workPtr <- Call.allocaArray n- liftIO $ do- copyBlock triSize aPtr bPtr- withInfo "hptrf" $ LapackGen.hptrf uploPtr nPtr bPtr ipivPtr- withInfo "hptri" $ LapackGen.hptri uploPtr nPtr bPtr ipivPtr workPtr---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $ printf "%s: %d-th diagonal value is zero" name info
− src/Numeric/LAPACK/Linear/HermitianPositiveDefinite.hs
@@ -1,105 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Linear.HermitianPositiveDefinite (- solve,- inverse,- decompose,- ) where--import Numeric.LAPACK.Matrix.Hermitian (Hermitian)-import Numeric.LAPACK.Matrix.Triangular (Upper)-import Numeric.LAPACK.Matrix (General)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Triangular.Private (copyTriangleToTemp)-import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor), uploFromOrder)-import Numeric.LAPACK.Private (copyBlock, copyToColumnMajor)--import qualified Numeric.LAPACK.FFI.Generic as LapackGen-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (peek)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)---solve ::- (Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>- Hermitian sh a -> General sh nrhs a -> General sh nrhs a-solve- (Array (MatrixShape.Hermitian orderA shA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor heightB widthB) $- \xPtr -> do- Call.assert "Hermitian.solve: height shapes mismatch"- (shA == heightB)- let n = Shape.size heightB- let nrhs = Shape.size widthB- let ldb = n- evalContT $ do- uploPtr <- Call.char $ uploFromOrder orderA- nPtr <- Call.cint n- nrhsPtr <- Call.cint nrhs- apPtr <- copyTriangleToTemp orderA n a- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb- liftIO $ do- copyToColumnMajor orderB n nrhs bPtr xPtr- withInfo "ppsv" $- LapackGen.ppsv uploPtr nPtr nrhsPtr apPtr xPtr ldbPtr---inverse ::- (Shape.C sh, Class.Floating a) => Hermitian sh a -> Hermitian sh a-inverse- (Array shape@(MatrixShape.Hermitian order sh) a) =- Array.unsafeCreateWithSize shape $ \triSize bPtr -> do- evalContT $ do- uploPtr <- Call.char $ uploFromOrder order- nPtr <- Call.cint $ Shape.size sh- aPtr <- ContT $ withForeignPtr a- liftIO $ do- copyBlock triSize aPtr bPtr- withInfo "pptrf" $ LapackGen.pptrf uploPtr nPtr bPtr- withInfo "pptri" $ LapackGen.pptri uploPtr nPtr bPtr--{- |-Cholesky decomposition--}-decompose ::- (Shape.C sh, Class.Floating a) => Hermitian sh a -> Upper sh a-decompose- (Array (MatrixShape.Hermitian order sh) a) =- Array.unsafeCreateWithSize- (MatrixShape.Triangular MatrixShape.Upper order sh) $- \triSize bPtr -> do- evalContT $ do- uploPtr <- Call.char $ uploFromOrder order- nPtr <- Call.cint $ Shape.size sh- aPtr <- ContT $ withForeignPtr a- liftIO $ do- copyBlock triSize aPtr bPtr- withInfo "pptrf" $ LapackGen.pptrf uploPtr nPtr bPtr---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $- printf "%s: minor of order %d not positive definite" name info
+ src/Numeric/LAPACK/Linear/LowerUpper.hs view
@@ -0,0 +1,437 @@+module Numeric.LAPACK.Linear.LowerUpper (+ LowerUpper,+ Square,+ Transposition(..),+ Conjugation(..),+ Inversion(..),+ mapExtent,+ fromMatrix,+ toMatrix,+ solve,+ multiplyFullRight,++ determinant,++ extractP,+ multiplyP,++ extractL,+ wideExtractL,+ wideMultiplyL,+ wideSolveL,++ extractU,+ tallExtractU,+ tallMultiplyU,+ tallSolveU,++ caseTallWide,+ ) where++import qualified Numeric.LAPACK.Matrix.Multiply as MM+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Matrix.Basic as Basic+import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Permutation.Private as Perm+import qualified Numeric.LAPACK.Split as Split+import Numeric.LAPACK.Matrix.Triangular.Basic (UnitLower, Upper)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor, ColumnMajor), Triangle(Triangle))+import Numeric.LAPACK.Matrix.Private+ (Full, ZeroInt, zeroInt,+ Transposition(NonTransposed, Transposed),+ Conjugation(NonConjugated, Conjugated),+ Inversion(NonInverted, Inverted), flipInversion)+import Numeric.LAPACK.Linear.Private (solver, withInfo)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Format (Format(format))+import Numeric.LAPACK.Private+ (pointerSeq, peekCInt,+ copyBlock, copyTransposed, copyToColumnMajor)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.Marshal.Array (advancePtr)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (forM_)+import Control.Applicative ((<$>))+++data LowerUpper vert horiz height width a =+ LowerUpper {+ _pivot :: Vector ZeroInt CInt,+ split_ ::+ Array+ (MatrixShape.Split MatrixShape.Triangle vert horiz height width) a+ } deriving (Show)++type Square sh = LowerUpper Extent.Small Extent.Small sh sh++instance+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Format (LowerUpper vert horiz height width a) where+ format fmt lu@(LowerUpper _ipiv m) = format fmt (extractP NonInverted lu, m)++mapExtent ::+ (Extent.C vertA, Extent.C horizA) =>+ (Extent.C vertB, Extent.C horizB) =>+ Extent.Map vertA horizA vertB horizB height width ->+ LowerUpper vertA horizA height width a ->+ LowerUpper vertB horizB height width a+mapExtent f (LowerUpper pivot split) =+ LowerUpper pivot $ Array.mapShape (MatrixShape.splitMapExtent f) split++{- |+@LowerUpper.fromMatrix a@+computes the LU decomposition of matrix @a@ with row pivotisation.++You can reconstruct @a@ from @lu@ depending on wether @a@ is tall or wide.++> LU.multiplyP False lu $ LU.extractL lu <#> LU.tallExtractU lu+> LU.multiplyP False lu $ LU.wideExtractL lu <#> LU.extractU lu+-}+fromMatrix ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a ->+ LowerUpper vert horiz height width a+fromMatrix (Array (MatrixShape.Full order extent) a) =+ let (height,width) = Extent.dimensions extent+ m = Shape.size height+ n = Shape.size width+ in uncurry LowerUpper $+ Array.unsafeCreateWithSizeAndResult (zeroInt $ min m n) $ \_ ipivPtr ->+ ArrayIO.unsafeCreate+ (MatrixShape.Split MatrixShape.Triangle ColumnMajor extent) $ \luPtr ->++ evalContT $ do+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim m+ liftIO $ do+ copyToColumnMajor order m n aPtr luPtr+ withInfo "getrf" $ LapackGen.getrf mPtr nPtr luPtr ldaPtr ipivPtr++solve ::+ (Extent.C vert, Extent.C horiz, Eq height, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Square height a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+solve+ (LowerUpper+ (Array _ ipiv)+ (Array (MatrixShape.Split MatrixShape.Triangle orderLU extentLU) lu)) =++ solver "LowerUpper.solve" (Extent.squareSize extentLU) $+ \n nPtr nrhsPtr xPtr ldxPtr -> do+ let lda = n+ transPtr <- Call.char 'N'+ aPtr <-+ case orderLU of+ RowMajor -> do+ aPtr <- ContT $ withForeignPtr lu+ atmpPtr <- Call.allocaArray (n*n)+ liftIO $ copyToColumnMajor orderLU n n aPtr atmpPtr+ return atmpPtr+ ColumnMajor -> ContT $ withForeignPtr lu+ ldaPtr <- Call.leadingDim lda+ ipivPtr <- ContT $ withForeignPtr ipiv+ liftIO $+ withInfo "getrs" $+ LapackGen.getrs transPtr+ nPtr nrhsPtr aPtr ldaPtr ipivPtr xPtr ldxPtr++{- |+Caution:+@LU.determinant . LU.fromMatrix@ will fail for singular matrices.+-}+determinant :: (Shape.C sh, Class.Floating a, Eq a) => Square sh a -> a+determinant (LowerUpper ipiv split) =+ let det = Split.determinantR split+ in if Split.oddPermutation $ Array.toList ipiv then -det else det+++extractP ::+ (Extent.C vert, Extent.C horiz, Shape.C height) =>+ Inversion -> LowerUpper vert horiz height width a -> Perm.Permutation height+extractP inverted (LowerUpper ipiv (Array shape _)) =+ Perm.fromPivots (flipInversion inverted) (MatrixShape.splitHeight shape) ipiv++multiplyP ::+ (Extent.C vertA, Extent.C horizA, Extent.C vertB, Extent.C horizB,+ Eq height, Shape.C height, Shape.C widthA, Shape.C widthB,+ Class.Floating a) =>+ Inversion ->+ LowerUpper vertA horizA height widthA a ->+ Full vertB horizB height widthB a ->+ Full vertB horizB height widthB a+multiplyP inverted+ (LowerUpper (Array shapeIPiv ipiv)+ (Array (MatrixShape.Split _ _ extentLU) _lu))+ (Array shape@(MatrixShape.Full order extent) a) =+ Array.unsafeCreate shape $ \bPtr -> do++ Call.assert "multiplyP: heights mismatch"+ (Extent.height extentLU == Extent.height extent)++ let (height,width) = Extent.dimensions extent+ let m = Shape.size height+ let n = Shape.size width+ let k = Shape.size shapeIPiv++ evalContT $ do+ aPtr <- ContT $ withForeignPtr a+ ipivPtr <- ContT $ withForeignPtr ipiv+ liftIO $ copyBlock (n*m) aPtr bPtr+ case order of+ ColumnMajor -> do+ nPtr <- Call.cint n+ ldaPtr <- Call.leadingDim m+ k1Ptr <- Call.cint 1+ k2Ptr <- Call.cint k+ incxPtr <-+ Call.cint $+ case inverted of+ Inverted -> 1+ NonInverted -> -1+ liftIO $+ LapackGen.laswp nPtr bPtr ldaPtr k1Ptr k2Ptr ipivPtr incxPtr+ RowMajor ->+ liftIO $ swapColumns m bPtr $ take k $+ case inverted of+ Inverted -> zip [0..] $ pointerSeq 1 ipivPtr+ NonInverted ->+ zip (iterate (subtract 1) (k-1)) $+ pointerSeq (-1) (advancePtr ipivPtr (k-1))++{-# INLINE swapColumns #-}+swapColumns ::+ (Class.Floating a) =>+ Int -> Ptr a -> [(Int, Ptr CInt)] -> IO ()+swapColumns m xPtr ptrs = evalContT $ do+ mPtr <- Call.cint m+ incPtr <- Call.cint 1+ let columnPtr k = advancePtr xPtr (m*k)+ liftIO $ forM_ ptrs $ \(i,ipivPtr) -> do+ j <- subtract 1 <$> peekCInt ipivPtr+ BlasGen.swap mPtr (columnPtr i) incPtr (columnPtr j) incPtr++++extractL ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ LowerUpper vert horiz height width a ->+ Full vert horiz height width a+extractL = Split.extractTriangle (Left Triangle) . split_++wideExtractL ::+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ LowerUpper Extent.Small horiz height width a -> UnitLower height a+wideExtractL = Split.wideExtractL . split_++{- |+@wideMultiplyL transposed lu a@ multiplies the square part of @lu@+containing the lower triangular matrix with @a@.++> wideMultiplyL False lu a == wideExtractL lu <#> a+> wideMultiplyL True lu a == wideExtractL (Tri.transposeUp lu) <#> a+-}+wideMultiplyL ::+ (Extent.C horizA, Extent.C vert, Extent.C horiz, Shape.C height, Eq height,+ Shape.C widthA, Shape.C widthB, Class.Floating a) =>+ Transposition ->+ LowerUpper Extent.Small horizA height widthA a ->+ Full vert horiz height widthB a ->+ Full vert horiz height widthB a+wideMultiplyL transposed = Split.wideMultiplyL transposed . split_++wideSolveL ::+ (Extent.C horizA, Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>+ Transposition -> Conjugation ->+ LowerUpper Extent.Small horizA height width a ->+ Full vert horiz height nrhs a -> Full vert horiz height nrhs a+wideSolveL transposed conjugated =+ Split.wideSolveL transposed conjugated . split_+++extractU ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ LowerUpper vert horiz height width a ->+ Full vert horiz height width a+extractU = Split.extractTriangle (Right Triangle) . split_++tallExtractU ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ LowerUpper vert Extent.Small height width a -> Upper width a+tallExtractU = Split.tallExtractR . split_++{- |+@tallMultiplyU transposed lu a@ multiplies the square part of @lu@+containing the upper triangular matrix with @a@.++> tallMultiplyU False lu a == tallExtractU lu <#> a+> tallMultiplyU True lu a == tallExtractU (Tri.transposeDown lu) <#> a+-}+tallMultiplyU ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz, Shape.C height, Eq height,+ Shape.C heightA, Shape.C widthB, Class.Floating a) =>+ Transposition ->+ LowerUpper vertA Extent.Small heightA height a ->+ Full vert horiz height widthB a ->+ Full vert horiz height widthB a+tallMultiplyU transposed = Split.tallMultiplyR transposed . split_++tallSolveU ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Shape.C nrhs, Class.Floating a) =>+ Transposition -> Conjugation ->+ LowerUpper vertA Extent.Small height width a ->+ Full vert horiz width nrhs a -> Full vert horiz width nrhs a+tallSolveU transposed conjugated =+ Split.tallSolveR transposed conjugated . split_++++toMatrix ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ LowerUpper vert horiz height width a ->+ Full vert horiz height width a+toMatrix =+ getToMatrix $+ Extent.switchTagPair+ (ToMatrix wideToMatrix)+ (ToMatrix wideToMatrix)+ (ToMatrix tallToMatrix)+ (ToMatrix $+ either+ (Matrix.fromFull . tallToMatrix)+ (Matrix.fromFull . wideToMatrix) .+ caseTallWide)++newtype ToMatrix height width a vert horiz =+ ToMatrix {+ getToMatrix ::+ LowerUpper vert horiz height width a ->+ Full vert horiz height width a+ }++tallToMatrix ::+ (Extent.C vert, Shape.C height, Shape.C width, Eq height, Eq width,+ Class.Floating a) =>+ LowerUpper vert Extent.Small height width a ->+ Full vert Extent.Small height width a+tallToMatrix a =+ multiplyP NonInverted a $ Basic.transpose $+ tallMultiplyU Transposed a $ Basic.transpose $ extractL a++wideToMatrix ::+ (Extent.C horiz, Shape.C height, Shape.C width, Eq height, Eq width,+ Class.Floating a) =>+ LowerUpper Extent.Small horiz height width a ->+ Full Extent.Small horiz height width a+wideToMatrix a =+ multiplyP NonInverted a $ wideMultiplyL NonTransposed a $ extractU a+++multiplyFullRight ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Shape.C fuse, Eq fuse,+ Class.Floating a) =>+ LowerUpper vert horiz height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+multiplyFullRight =+ getMultiplyFullRight $+ Extent.switchTagPair+ (MultiplyFullRight wideMultiplyFullRight)+ (MultiplyFullRight wideMultiplyFullRight)+ (MultiplyFullRight tallMultiplyFullRight)+ (MultiplyFullRight $+ either tallMultiplyFullRight wideMultiplyFullRight . caseTallWide)++newtype MultiplyFullRight height fuse width a vert horiz =+ MultiplyFullRight {+ getMultiplyFullRight ::+ LowerUpper vert horiz height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+ }++tallMultiplyFullRight ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse, Eq height, Eq fuse,+ Class.Floating a) =>+ LowerUpper vert Extent.Small height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+tallMultiplyFullRight a =+ multiplyP NonInverted a .+ MM.multiply (Matrix.generalizeTall (extractL a)) .+ tallMultiplyU NonTransposed a++wideMultiplyFullRight ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse, Eq height, Eq fuse,+ Class.Floating a) =>+ LowerUpper Extent.Small horiz height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+wideMultiplyFullRight a =+ multiplyP NonInverted a . wideMultiplyL NonTransposed a .+ MM.multiply (Matrix.generalizeWide (extractU a))+++type Tall = LowerUpper Extent.Big Extent.Small+type Wide = LowerUpper Extent.Small Extent.Big++caseTallWide ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ LowerUpper vert horiz height width a ->+ Either (Tall height width a) (Wide height width a)+caseTallWide (LowerUpper ipiv (Array shape a)) =+ either+ (Left . LowerUpper ipiv . flip Array a)+ (Right . LowerUpper ipiv . flip Array a) $+ MatrixShape.caseTallWideSplit shape+++_toRowMajor ::+ (Extent.C vert, Extent.C horiz, Eq height, Shape.C height, Shape.C width,+ Class.Floating a) =>+ LowerUpper vert horiz height width a ->+ LowerUpper vert horiz height width a+_toRowMajor+ (LowerUpper ipiv+ arr@(Array (MatrixShape.Split MatrixShape.Triangle order extent) a)) =+ LowerUpper ipiv $+ case order of+ RowMajor -> arr+ ColumnMajor ->+ Array.unsafeCreate+ (MatrixShape.Split MatrixShape.Triangle RowMajor extent) $ \bPtr ->+ withForeignPtr a $ \aPtr -> do+ let (height, width) = Extent.dimensions extent+ let n = Shape.size width+ let m = Shape.size height+ copyTransposed n m aPtr n bPtr
+ src/Numeric/LAPACK/Linear/Private.hs view
@@ -0,0 +1,68 @@+module Numeric.LAPACK.Linear.Private where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor))+import Numeric.LAPACK.Matrix.Private (Full)+import Numeric.LAPACK.Scalar (zero)+import Numeric.LAPACK.Private (copyToColumnMajor, peekCInt, argMsg)++import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.Marshal.Alloc (alloca)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)++import Text.Printf (printf)+++solver ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width, Eq height,+ Class.Floating a) =>+ String -> height ->+ (Int -> Ptr CInt -> Ptr CInt -> Ptr a -> Ptr CInt -> ContT () IO ()) ->+ Full vert horiz height width a ->+ Full vert horiz height width a+solver name sh f (Array (MatrixShape.Full order extent) b) =+ Array.unsafeCreate (MatrixShape.Full ColumnMajor extent) $+ \xPtr -> do+ let (height,width) = Extent.dimensions extent+ Call.assert (name ++ ": height shapes mismatch") (sh == height)+ let n = Shape.size height+ let nrhs = Shape.size width+ evalContT $ do+ nPtr <- Call.cint n+ nrhsPtr <- Call.cint nrhs+ bPtr <- ContT $ withForeignPtr b+ liftIO $ copyToColumnMajor order n nrhs bPtr xPtr+ ldxPtr <- Call.leadingDim n+ f n nPtr nrhsPtr xPtr ldxPtr+++withDeterminantInfo ::+ (Class.Floating a) =>+ String -> (Ptr CInt -> IO ()) -> IO a -> IO a+withDeterminantInfo name computation evaluation = alloca $ \infoPtr -> do+ computation infoPtr+ info <- peekCInt infoPtr+ case compare info (0::Int) of+ LT -> error $ printf argMsg name (-info)+ GT -> return zero+ EQ -> evaluation+++withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()+withInfo = Private.withInfo diagonalMsg++diagonalMsg :: String+diagonalMsg = "%d-th diagonal value is zero"
− src/Numeric/LAPACK/Linear/Triangular.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Linear.Triangular (- solve,- inverse,- ) where--import Numeric.LAPACK.Matrix.Triangular (Triangular)-import Numeric.LAPACK.Matrix (General)--import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Shape.Private- (Order(ColumnMajor),- transposeFromOrder, uploFromOrder, uploOrder, triangleSize)-import Numeric.LAPACK.Private- (copyBlock, copyToTemp, copyToColumnMajor)--import qualified Numeric.LAPACK.FFI.Generic as LapackGen-import qualified Numeric.Netlib.Utility as Call-import qualified Numeric.Netlib.Class as Class--import qualified Data.Array.Comfort.Storable.Internal as Array-import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))--import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (peek)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>))--import Text.Printf (printf)---solve ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>- Triangular uplo sh a -> General sh nrhs a -> General sh nrhs a-solve- (Array (MatrixShape.Triangular uplo orderA shA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor heightB widthB) $- \xPtr -> do- Call.assert "Triangular.solve: height shapes mismatch" (shA == heightB)- let n = Shape.size heightB- let nrhs = Shape.size widthB- let ldb = n- evalContT $ do- uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo orderA- transPtr <- Call.char $ transposeFromOrder orderA- diagPtr <- Call.char 'N'- nPtr <- Call.cint n- nrhsPtr <- Call.cint nrhs- apPtr <- copyToTemp (triangleSize n) a- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb- liftIO $ do- copyToColumnMajor orderB n nrhs bPtr xPtr- withInfo "tptrs" $- LapackGen.tptrs uploPtr transPtr diagPtr- nPtr nrhsPtr apPtr xPtr ldbPtr---inverse ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a -> Triangular uplo sh a-inverse (Array shape@(MatrixShape.Triangular uplo order sh) a) =- Array.unsafeCreateWithSize shape $ \triSize bPtr -> do- evalContT $ do- uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo order- diagPtr <- Call.char 'N'- nPtr <- Call.cint $ Shape.size sh- aPtr <- ContT $ withForeignPtr a- liftIO $ do- copyBlock triSize aPtr bPtr- withInfo "tptri" $ LapackGen.tptri uploPtr diagPtr nPtr bPtr---withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $ printf "%s: %d-th diagonal element zero" name info
src/Numeric/LAPACK/Matrix.hs view
@@ -1,56 +1,84 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module Numeric.LAPACK.Matrix (- General,- (##),- Format,- FormatArray,+ Full,+ General, Tall, Wide, ZeroInt, zeroInt, transpose, adjoint,+ Matrix.height, Matrix.width,+ caseTallWide, fromScalar, toScalar, fromList,+ mapExtent, fromFull,+ generalizeTall, generalizeWide, identity,- diagonal, getDiagonal,- fromRows, fromRowsWithSize,- fromColumns, fromColumnsWithSize,- singleRow, singleColumn,- flattenRow, flattenColumn,- pickRow, pickColumn,- takeRows, takeColumns,- dropRows, dropColumns,+ diagonal,+ fromRowsNonEmpty, fromRowArray, fromRows,+ fromColumnsNonEmpty, fromColumnArray, fromColumns,+ Basic.singleRow, Basic.singleColumn,+ Basic.flattenRow, Basic.flattenColumn,+ toRows, toColumns,+ toRowArray, toColumnArray,+ takeRow, takeColumn,+ takeRows, takeColumns, takeEqually,+ dropRows, dropColumns, dropEqually,+ takeTopRows, takeBottomRows,+ takeLeftColumns, takeRightColumns, reverseRows, reverseColumns, fromRowMajor, toRowMajor, flatten,+ forceOrder, adaptOrder, (|||), (===), + tensorProduct,+ outer,+ sumRank1,++ RealOf,+ add, sub, rowSums, columnSums, scaleRows, scaleColumns,+ scaleRowsComplex, scaleColumnsComplex,+ scaleRowsReal, scaleColumnsReal, multiply, multiplyVector, Multiply, (<#>), MultiplyLeft, (<#), MultiplyRight, (#>),++ Solve, solve, solveVector,+ Inverse, inverse, ) where import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Square.Basic as Square+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Matrix.Basic as Basic+import qualified Numeric.LAPACK.Matrix.Private as Matrix import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Format (Format, FormatArray, (##))+import qualified Numeric.LAPACK.Private as Private import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor)) import Numeric.LAPACK.Matrix.Multiply (Multiply((<#>)), MultiplyLeft((<#)), MultiplyRight((#>)),- transpose, multiplyVector, multiply, multiplyVectorUnchecked)-import Numeric.LAPACK.Matrix.Private (General, ZeroInt, zeroInt)+ multiplyVector, multiply, multiplyVectorUnchecked)+import Numeric.LAPACK.Matrix.Divide+ (Solve(solve), solveVector, Inverse(inverse))+import Numeric.LAPACK.Matrix.Basic (transpose, scaleRows, scaleColumns)+import Numeric.LAPACK.Matrix.Private+ (Full, Tall, Wide, General, argGeneral, ZeroInt, zeroInt,+ mapExtent, fromFull, generalizeTall, generalizeWide) import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, zero, one) import Numeric.LAPACK.Private- (zero, one, pointerSeq, copyTransposed, copySubMatrix, copyBlock)+ (pointerSeq, fill, copyTransposed, copySubMatrix, copyBlock) import qualified Numeric.LAPACK.FFI.Generic as LapackGen import qualified Numeric.BLAS.FFI.Generic as BlasGen import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class +import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape import Data.Array.Comfort.Storable.Internal (Array(Array))@@ -58,7 +86,7 @@ import Foreign.Marshal.Array (copyArray, advancePtr, pokeArray) import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr)+import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (Storable, poke, peek) import System.IO.Unsafe (unsafePerformIO)@@ -67,31 +95,49 @@ import Control.Monad.IO.Class (liftIO) import qualified Data.NonEmpty as NonEmpty+import Data.Complex (Complex) import Data.Foldable (forM_) import Data.Bool.HT (if') {- | conjugate transpose++Problem: @adjoint a <#> a@ is always square,+but how to convince the type checker to choose the Square type?+Anser: Use @Hermitian.toSquare $ Hermitian.covariance a@ instead. -} adjoint ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> General width height a+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a -> Full horiz vert width height a adjoint = transpose . Vector.conjugate +{- |+Square matrices will be classified as 'Tall'.+-}+caseTallWide ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Full vert horiz height width a ->+ Either (Tall height width a) (Wide height width a)+caseTallWide (Array shape a) =+ either (Left . flip Array a) (Right . flip Array a) $+ MatrixShape.caseTallWide shape++ fromScalar :: (Storable a) => a -> General () () a fromScalar = Square.toGeneral . Square.fromScalar toScalar :: (Storable a) => General () () a -> a-toScalar (Array (MatrixShape.General _ () ()) a) =+toScalar = argGeneral $ \_ () () a -> unsafePerformIO $ withForeignPtr a peek fromList :: (Shape.C height, Shape.C width, Storable a) => height -> width -> [a] -> General height width a fromList height width =- Array.fromList (MatrixShape.General RowMajor height width)+ Array.fromList (MatrixShape.general RowMajor height width) identity ::@@ -104,53 +150,48 @@ Vector sh a -> General sh sh a diagonal = Square.toGeneral . Square.diagonal -getDiagonal ::- (Shape.C sh, Eq sh, Class.Floating a) =>- General sh sh a -> Vector sh a-getDiagonal = Square.getDiagonal . Square.fromGeneral --singleRow :: Vector width a -> General () width a-singleRow (Array sh fptr) =- Array (MatrixShape.General RowMajor () sh) fptr--singleColumn :: Vector width a -> General width () a-singleColumn (Array sh fptr) =- Array (MatrixShape.General ColumnMajor sh ()) fptr--flattenRow :: General () width a -> Vector width a-flattenRow (Array (MatrixShape.General _ () sh) fptr) = Array sh fptr--flattenColumn :: General width () a -> Vector width a-flattenColumn (Array (MatrixShape.General _ sh ()) fptr) = Array sh fptr---fromRows ::+fromRowsNonEmpty :: (Shape.C width, Eq width, Storable a) => NonEmpty.T [] (Vector width a) -> General ZeroInt width a-fromRows (NonEmpty.Cons row rows) =- fromRowsWithSize (Array.shape row) (row:rows)+fromRowsNonEmpty (NonEmpty.Cons row rows) =+ fromRows (Array.shape row) (row:rows) -fromRowsWithSize ::+fromRowArray ::+ (Shape.C height, Shape.C width, Eq width, Storable a) =>+ width -> BoxedArray.Array height (Vector width a) -> General height width a+fromRowArray width rows =+ Array.reshape (MatrixShape.general RowMajor (BoxedArray.shape rows) width) $+ fromRows width $ BoxedArray.toList rows++fromRows :: (Shape.C width, Eq width, Storable a) => width -> [Vector width a] -> General ZeroInt width a-fromRowsWithSize width rows =+fromRows width rows = Array.unsafeCreate- (MatrixShape.General RowMajor (zeroInt $ length rows) width)+ (MatrixShape.general RowMajor (zeroInt $ length rows) width) (gather width rows) -fromColumns ::+fromColumnsNonEmpty :: (Shape.C height, Eq height, Storable a) => NonEmpty.T [] (Vector height a) -> General height ZeroInt a-fromColumns (NonEmpty.Cons column columns) =- fromColumnsWithSize (Array.shape column) (column:columns)+fromColumnsNonEmpty (NonEmpty.Cons column columns) =+ fromColumns (Array.shape column) (column:columns) -fromColumnsWithSize ::+fromColumnArray ::+ (Shape.C height, Eq height, Shape.C width, Storable a) =>+ height -> BoxedArray.Array width (Vector height a) -> General height width a+fromColumnArray height columns =+ Array.reshape+ (MatrixShape.general ColumnMajor height (BoxedArray.shape columns)) $+ fromColumns height $ BoxedArray.toList columns++fromColumns :: (Shape.C height, Eq height, Storable a) => height -> [Vector height a] -> General height ZeroInt a-fromColumnsWithSize height columns =+fromColumns height columns = Array.unsafeCreate- (MatrixShape.General ColumnMajor height (zeroInt $ length columns))+ (MatrixShape.general ColumnMajor height (zeroInt $ length columns)) (gather height columns) gather ::@@ -162,31 +203,64 @@ \(dstRowPtr, Array.Array rowWidth srcFPtr) -> withForeignPtr srcFPtr $ \srcPtr -> do Call.assert- "Matrix.fromRows/fromColumns: non-matching vector size"+ "Matrix.fromRows/fromColumnsNonEmpty: non-matching vector size" (width == rowWidth) copyArray dstRowPtr srcPtr widthSize -pickRow ::- (Shape.C height, Shape.C width, Shape.Index height ~ ix,+toRows ::+ (Extent.C vert, Extent.C horiz,+ Shape.Indexed height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> [Vector width a]+toRows a = map (takeRow a) $ Shape.indices $ Matrix.height a++toColumns ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.Indexed width, Class.Floating a) =>+ Full vert horiz height width a -> [Vector height a]+toColumns a = map (takeColumn a) $ Shape.indices $ Matrix.width a++toRowArray ::+ (Extent.C vert, Extent.C horiz,+ Shape.Indexed height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> BoxedArray.Array height (Vector width a)+toRowArray a =+ let height = Matrix.height a+ in BoxedArray.fromList height $ map (takeRow a) $ Shape.indices height++toColumnArray ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.Indexed width, Class.Floating a) =>+ Full vert horiz height width a -> BoxedArray.Array width (Vector height a)+toColumnArray a =+ let width = Matrix.width a+ in BoxedArray.fromList width $ map (takeColumn a) $ Shape.indices width+++takeRow ::+ (Extent.C vert, Extent.C horiz,+ Shape.Indexed height, Shape.C width, Shape.Index height ~ ix, Class.Floating a) =>- General height width a -> ix -> Vector width a-pickRow (Array (MatrixShape.General order height width) x) ix =- case order of- RowMajor -> pickConsecutive height width x ix- ColumnMajor -> pickScattered width height x ix+ Full vert horiz height width a -> ix -> Vector width a+takeRow (Array (MatrixShape.Full order extent) x) ix =+ let (height,width) = Extent.dimensions extent+ in case order of+ RowMajor -> pickConsecutive height width x ix+ ColumnMajor -> pickScattered width height x ix -pickColumn ::- (Shape.C height, Shape.C width, Shape.Index width ~ ix,+takeColumn ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.Indexed width, Shape.Index width ~ ix, Class.Floating a) =>- General height width a -> ix -> Vector height a-pickColumn (Array (MatrixShape.General order height width) x) ix =- case order of- RowMajor -> pickScattered height width x ix- ColumnMajor -> pickConsecutive width height x ix+ Full vert horiz height width a -> ix -> Vector height a+takeColumn (Array (MatrixShape.Full order extent) x) ix =+ let (height,width) = Extent.dimensions extent+ in case order of+ RowMajor -> pickScattered height width x ix+ ColumnMajor -> pickConsecutive width height x ix pickConsecutive ::- (Shape.C height, Shape.C width, Shape.Index height ~ ix,+ (Shape.Indexed height, Shape.C width, Shape.Index height ~ ix, Class.Floating a) => height -> width -> ForeignPtr a -> ix -> Vector width a pickConsecutive height width x ix =@@ -200,7 +274,7 @@ BlasGen.copy nPtr (advancePtr xPtr (n*offset)) incxPtr yPtr incyPtr pickScattered ::- (Shape.C height, Shape.C width, Shape.Index width ~ ix,+ (Shape.C height, Shape.Indexed width, Shape.Index width ~ ix, Class.Floating a) => height -> width -> ForeignPtr a -> ix -> Vector height a pickScattered height width x ix =@@ -214,51 +288,153 @@ BlasGen.copy nPtr (advancePtr xPtr offset) incxPtr yPtr incyPtr -takeRows, dropRows ::- (Shape.C width, Class.Floating a) =>- Int -> General ZeroInt width a -> General ZeroInt width a-takeRows k- (Array (MatrixShape.General order (Shape.ZeroBased heightA) width) a) =- let heightB = min k heightA+takeTopRows ::+ (Extent.C vert, Shape.C height0, Shape.C height1, Shape.C width,+ Class.Floating a) =>+ Full vert Extent.Big (height0:+:height1) width a ->+ Full vert Extent.Big height0 width a+takeTopRows (Array (MatrixShape.Full order extentA) a) =+ let (heightA@(heightB:+:_), width) = Extent.dimensions extentA+ extentB = Extent.reduceWideHeight heightB extentA+ ma = Shape.size heightA+ mb = Shape.size heightB n = Shape.size width- in if' (k<0) (error "take: negative number") $- Array.unsafeCreateWithSize- (MatrixShape.General order (Shape.ZeroBased heightB) width) $+ in Array.unsafeCreateWithSize (MatrixShape.Full order extentB) $ \blockSize bPtr -> withForeignPtr a $ \aPtr -> case order of RowMajor -> copyBlock blockSize aPtr bPtr- ColumnMajor -> copySubMatrix heightB n heightA aPtr heightB bPtr+ ColumnMajor -> copySubMatrix mb n ma aPtr mb bPtr -dropRows k0- (Array (MatrixShape.General order (Shape.ZeroBased heightA) width) a) =- let k = min k0 heightA- heightB = heightA - k+takeBottomRows ::+ (Extent.C vert, Shape.C height0, Shape.C height1, Shape.C width,+ Class.Floating a) =>+ Full vert Extent.Big (height0:+:height1) width a ->+ Full vert Extent.Big height1 width a+takeBottomRows (Array (MatrixShape.Full order extentA) a) =+ let (heightA@(height0:+:heightB), width) = Extent.dimensions extentA+ extentB = Extent.reduceWideHeight heightB extentA+ k = Shape.size height0+ ma = Shape.size heightA+ mb = Shape.size heightB n = Shape.size width- in if' (k<0) (error "take: negative number") $- Array.unsafeCreateWithSize- (MatrixShape.General order (Shape.ZeroBased heightB) width) $+ in Array.unsafeCreateWithSize (MatrixShape.Full order extentB) $ \blockSize bPtr -> withForeignPtr a $ \aPtr -> case order of RowMajor -> copyBlock blockSize (advancePtr aPtr (k*n)) bPtr- ColumnMajor ->- copySubMatrix heightB n heightA (advancePtr aPtr k) heightB bPtr+ ColumnMajor -> copySubMatrix mb n ma (advancePtr aPtr k) mb bPtr +takeLeftColumns ::+ (Extent.C vert, Shape.C height, Shape.C width0, Shape.C width1,+ Class.Floating a) =>+ Full Extent.Big vert height (width0:+:width1) a ->+ Full Extent.Big vert height width0 a+takeLeftColumns = transpose . takeTopRows . transpose +takeRightColumns ::+ (Extent.C vert, Shape.C height, Shape.C width0, Shape.C width1,+ Class.Floating a) =>+ Full Extent.Big vert height (width0:+:width1) a ->+ Full Extent.Big vert height width1 a+takeRightColumns = transpose . takeBottomRows . transpose+++splitRows ::+ (Extent.C vert, Shape.C width, Class.Floating a) =>+ Int ->+ Full vert Extent.Big ZeroInt width a ->+ Full vert Extent.Big (ZeroInt:+:ZeroInt) width a+splitRows k =+ Array.mapShape+ (\(MatrixShape.Full order extentA) ->+ let (Shape.ZeroBased heightA) = Extent.height extentA+ heightB = min k heightA+ in if' (k<0) (error "split: negative number") $+ MatrixShape.Full order $+ Extent.reduceWideHeight+ (Shape.ZeroBased heightB :+: Shape.ZeroBased (heightA-heightB))+ extentA)++takeRows, dropRows ::+ (Extent.C vert, Shape.C width, Class.Floating a) =>+ Int ->+ Full vert Extent.Big ZeroInt width a ->+ Full vert Extent.Big ZeroInt width a+takeRows k = takeTopRows . splitRows k+dropRows k = takeBottomRows . splitRows k+ takeColumns, dropColumns ::- (Shape.C height, Class.Floating a) =>- Int -> General height ZeroInt a -> General height ZeroInt a+ (Extent.C horiz, Shape.C height, Class.Floating a) =>+ Int ->+ Full Extent.Big horiz height ZeroInt a ->+ Full Extent.Big horiz height ZeroInt a takeColumns k = transpose . takeRows k . transpose dropColumns k = transpose . dropRows k . transpose +{- |+Take a left-top aligned square or as much as possible of it.+The advantange of this function is that it maintains the matrix size relation,+e.g. Square remains Square, Tall remains Tall.+-}+takeEqually ::+ (Extent.C vert, Extent.C horiz, Class.Floating a) =>+ Int ->+ Full vert horiz ZeroInt ZeroInt a ->+ Full vert horiz ZeroInt ZeroInt a+takeEqually k (Array (MatrixShape.Full order extentA) a) =+ let (Shape.ZeroBased heightA, Shape.ZeroBased widthA) =+ Extent.dimensions extentA+ heightB = min k heightA+ widthB = min k widthA+ extentB =+ Extent.reduceConsistent+ (Shape.ZeroBased heightB) (Shape.ZeroBased widthB) extentA+ in if' (k<0) (error "take: negative number") $+ Array.unsafeCreate (MatrixShape.Full order extentB) $ \bPtr ->+ withForeignPtr a $ \aPtr ->+ case order of+ RowMajor -> copySubMatrix widthB heightB widthA aPtr widthB bPtr+ ColumnMajor -> copySubMatrix heightB widthB heightA aPtr heightB bPtr++{- |+Drop the same number of top-most rows and left-most columns.+The advantange of this function is that it maintains the matrix size relation,+e.g. Square remains Square, Tall remains Tall.+-}+dropEqually ::+ (Extent.C vert, Extent.C horiz, Class.Floating a) =>+ Int ->+ Full vert horiz ZeroInt ZeroInt a ->+ Full vert horiz ZeroInt ZeroInt a+dropEqually k (Array (MatrixShape.Full order extentA) a) =+ let (Shape.ZeroBased heightA, Shape.ZeroBased widthA) =+ Extent.dimensions extentA+ heightB = heightA - top; top = min k heightA+ widthB = widthA - left; left = min k widthA+ extentB =+ Extent.reduceConsistent+ (Shape.ZeroBased heightB) (Shape.ZeroBased widthB) extentA+ in if' (k<0) (error "drop: negative number") $+ Array.unsafeCreate (MatrixShape.Full order extentB) $ \bPtr ->+ withForeignPtr a $ \aPtr ->+ case order of+ RowMajor ->+ copySubMatrix widthB heightB+ widthA (advancePtr aPtr (top*widthA+left)) widthB bPtr+ ColumnMajor ->+ copySubMatrix heightB widthB+ heightA (advancePtr aPtr (left*heightA+top)) heightB bPtr++ -- alternative: laswp reverseRows ::- (Shape.C width, Class.Floating a) =>- General ZeroInt width a -> General ZeroInt width a-reverseRows (Array shape@(MatrixShape.General order height width) a) =+ (Extent.C vert, Extent.C horiz, Shape.C width, Class.Floating a) =>+ Full vert horiz ZeroInt width a -> Full vert horiz ZeroInt width a+reverseRows (Array shape@(MatrixShape.Full order extent) a) = Array.unsafeCreateWithSize shape $ \blockSize bPtr -> evalContT $ do+ let (height,width) = Extent.dimensions extent let n = Shape.size height let m = Shape.size width fwdPtr <- Call.bool True@@ -274,65 +450,93 @@ ColumnMajor -> LapackGen.lapmr fwdPtr nPtr mPtr bPtr nPtr kPtr reverseColumns ::- (Shape.C height, Class.Floating a) =>- General height ZeroInt a -> General height ZeroInt a+ (Extent.C vert, Extent.C horiz, Shape.C height, Class.Floating a) =>+ Full vert horiz height ZeroInt a -> Full vert horiz height ZeroInt a reverseColumns = transpose . reverseRows . transpose fromRowMajor :: (Shape.C height, Shape.C width, Class.Floating a) => Array (height,width) a -> General height width a-fromRowMajor (Array (height,width) x) =- Array (MatrixShape.General RowMajor height width) x+fromRowMajor = Array.mapShape (uncurry $ MatrixShape.general RowMajor) toRowMajor ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Array (height,width) a-toRowMajor (Array (MatrixShape.General order height width) x) =- let shape = (height, width)- in case order of- RowMajor -> Array shape x- ColumnMajor -> Array.unsafeCreate shape $ \yPtr -> evalContT $ do+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> Array (height,width) a+toRowMajor =+ Array.mapShape+ (\shape -> (MatrixShape.fullHeight shape, MatrixShape.fullWidth shape)) .+ forceRowMajor++forceRowMajor ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a ->+ Full vert horiz height width a+forceRowMajor (Array shape@(MatrixShape.Full order extent) x) =+ case order of+ RowMajor -> Array shape x+ ColumnMajor ->+ Array.unsafeCreate (MatrixShape.Full RowMajor extent) $ \yPtr ->+ withForeignPtr x $ \xPtr -> do+ let (height, width) = Extent.dimensions extent let n = Shape.size width let m = Shape.size height- nPtr <- Call.cint n- xPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint m- incyPtr <- Call.cint 1- liftIO $ sequence_ $ take m $- zipWith- (\xkPtr ykPtr ->- BlasGen.copy nPtr xkPtr incxPtr ykPtr incyPtr)- (pointerSeq 1 xPtr)- (pointerSeq n yPtr)+ copyTransposed n m xPtr n yPtr +forceOrder ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Order ->+ Full vert horiz height width a ->+ Full vert horiz height width a+forceOrder order =+ case order of+ RowMajor -> forceRowMajor+ ColumnMajor -> transpose . forceRowMajor . transpose++{- |+@adaptOrder x y@ contains the data of @y@ with the layout of @x@.+-}+adaptOrder ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+adaptOrder x = forceOrder (MatrixShape.fullOrder $ Array.shape x)+ flatten ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Vector ZeroInt a-flatten x =- case toRowMajor x of- Array shape fptr -> Array (zeroInt $ Shape.size shape) fptr+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> Vector ZeroInt a+flatten = Array.mapShape (zeroInt . Shape.size) . toRowMajor infixl 3 ||| infixl 2 === (|||) ::- (Shape.C height, Eq height, Shape.C widtha, Shape.C widthb,+ (Extent.C vert, Shape.C height, Eq height, Shape.C widtha, Shape.C widthb, Class.Floating a) =>- General height widtha a ->- General height widthb a ->- General height (widtha:+:widthb) a+ Full vert Extent.Big height widtha a ->+ Full vert Extent.Big height widthb a ->+ Full vert Extent.Big height (widtha:+:widthb) a (|||)- (Array (MatrixShape.General orderA heightA widthA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- if heightA /= heightB+ (Array (MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ let (heightA,widthA) = Extent.dimensions extentA+ (heightB,widthB) = Extent.dimensions extentB+ extent = Extent.widen (widthA:+:widthB) extentA+ shape order = MatrixShape.Full order extent+ in+ if heightA /= heightB then error "(|||): mismatching heights" else case (orderA,orderB) of (RowMajor,RowMajor) ->- Array.unsafeCreate- (MatrixShape.General RowMajor heightA (widthA:+:widthB)) $+ Array.unsafeCreate (shape RowMajor) $ \cPtr -> evalContT $ do let n = Shape.size heightA let ma = Shape.size widthA@@ -355,8 +559,7 @@ (pointerSeq mb bPtr) (pointerSeq m cPtr) (RowMajor,ColumnMajor) ->- Array.unsafeCreate- (MatrixShape.General ColumnMajor heightA (widthA:+:widthB)) $+ Array.unsafeCreate (shape ColumnMajor) $ \cPtr -> evalContT $ do let n = Shape.size heightA let ma = Shape.size widthA@@ -367,8 +570,7 @@ copyTransposed n ma aPtr n cPtr copyBlock (n*mb) bPtr (advancePtr cPtr (n*ma)) (ColumnMajor,RowMajor) ->- Array.unsafeCreate- (MatrixShape.General ColumnMajor heightA (widthA:+:widthB)) $+ Array.unsafeCreate (shape ColumnMajor) $ \cPtr -> evalContT $ do let n = Shape.size heightA let ma = Shape.size widthA@@ -380,8 +582,7 @@ copyBlock volA aPtr cPtr copyTransposed n mb bPtr n (advancePtr cPtr volA) (ColumnMajor,ColumnMajor) ->- Array.unsafeCreate- (MatrixShape.General ColumnMajor heightA (widthA:+:widthB)) $+ Array.unsafeCreate (shape ColumnMajor) $ \cPtr -> evalContT $ do let n = Shape.size heightA let na = n * Shape.size widthA@@ -398,44 +599,62 @@ (cPtr `advancePtr` na) incyPtr (===) ::- (Shape.C width, Eq width, Shape.C heighta, Shape.C heightb,+ (Extent.C horiz, Shape.C width, Eq width, Shape.C heighta, Shape.C heightb, Class.Floating a) =>- General heighta width a ->- General heightb width a ->- General (heighta:+:heightb) width a+ Full Extent.Big horiz heighta width a ->+ Full Extent.Big horiz heightb width a ->+ Full Extent.Big horiz (heighta:+:heightb) width a (===) a b = transpose (transpose a ||| transpose b) +add, sub ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq height, Eq width,+ Class.Floating a) =>+ Full vert horiz height width a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+add x y = Vector.add (adaptOrder y x) y+sub x y = Vector.sub (adaptOrder y x) y++ rowSums ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Vector height a+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> Vector height a rowSums m =- let MatrixShape.General _ _ width = Array.shape m+ let width = MatrixShape.fullWidth $ Array.shape m in multiplyVectorUnchecked m (Vector.constant width one) columnSums ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Vector width a+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert horiz height width a -> Vector width a columnSums m =- let MatrixShape.General _ height _ = Array.shape m+ let height = MatrixShape.fullHeight $ Array.shape m in multiplyVectorUnchecked (transpose m) (Vector.constant height one) -scaleRows ::- (Shape.C height, Eq height, Shape.C width, Class.Floating a) =>- Vector height a -> General height width a -> General height width a-scaleRows- (Array heightX x) (Array shape@(MatrixShape.General order height width) a) =- Array.unsafeCreate shape $ \bPtr -> do- Call.assert "scaleRows: sizes mismatch" (heightX == height)+scaleRowsComplex ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Class.Real a) =>+ Vector height a ->+ Full vert horiz height width (Complex a) ->+ Full vert horiz height width (Complex a)+scaleRowsComplex+ (Array heightX x) (Array shape@(MatrixShape.Full order extent) a) =+ Array.unsafeCreate shape $ \bComplexPtr -> do+ let (height,width) = Extent.dimensions extent+ Call.assert "scaleRowsComplex: sizes mismatch" (heightX == height)+ let bPtr = castPtr bComplexPtr case order of RowMajor -> evalContT $ do let m = Shape.size height- let n = Shape.size width+ let n = Shape.size width * 2 alphaPtr <- Call.alloca nPtr <- Call.cint n xPtr <- ContT $ withForeignPtr x- aPtr <- ContT $ withForeignPtr a+ aPtr <- fmap castPtr $ ContT $ withForeignPtr a incaPtr <- Call.cint 1 incbPtr <- Call.cint 1 liftIO $ sequence_ $ take m $@@ -449,28 +668,148 @@ (pointerSeq n bPtr) ColumnMajor -> evalContT $ do let m = Shape.size width- let n = Shape.size height+ let nr = Shape.size height+ let n = 2*nr transPtr <- Call.char 'N'+ nrPtr <- Call.cint nr nPtr <- Call.cint n klPtr <- Call.cint 0 kuPtr <- Call.cint 0 alphaPtr <- Call.number one- xPtr <- ContT $ withForeignPtr x- ldxPtr <- Call.cint 1- aPtr <- ContT $ withForeignPtr a+ xrPtr <- ContT $ withForeignPtr x+ xPtr <- Call.allocaArray n+ incxrPtr <- Call.cint 1+ incxPtr <- Call.cint 2+ ldxPtr <- Call.leadingDim 1+ aPtr <- fmap castPtr $ ContT $ withForeignPtr a incaPtr <- Call.cint 1 betaPtr <- Call.number zero incbPtr <- Call.cint 1- liftIO $ sequence_ $ take m $- zipWith- (\akPtr bkPtr ->- BlasGen.gbmv transPtr- nPtr nPtr klPtr kuPtr alphaPtr xPtr ldxPtr- akPtr incaPtr betaPtr bkPtr incbPtr)- (pointerSeq n aPtr)- (pointerSeq n bPtr)+ liftIO $ do+ BlasGen.copy nrPtr xrPtr incxrPtr xPtr incxPtr+ BlasGen.copy nrPtr xrPtr incxrPtr (advancePtr xPtr 1) incxPtr+ sequence_ $ take m $+ zipWith+ (\akPtr bkPtr ->+ Private.gbmv transPtr+ nPtr nPtr klPtr kuPtr alphaPtr xPtr ldxPtr+ akPtr incaPtr betaPtr bkPtr incbPtr)+ (pointerSeq n aPtr)+ (pointerSeq n bPtr) -scaleColumns ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- Vector width a -> General height width a -> General height width a-scaleColumns x = transpose . scaleRows x . transpose+scaleColumnsComplex ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Class.Real a) =>+ Vector width a ->+ Full vert horiz height width (Complex a) ->+ Full vert horiz height width (Complex a)+scaleColumnsComplex x = transpose . scaleRowsComplex x . transpose+++scaleRowsReal ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Eq height, Shape.C width,+ Class.Floating a) =>+ Vector height (RealOf a) ->+ Full vert horiz height width a ->+ Full vert horiz height width a+scaleRowsReal =+ getScaleRowsReal $+ Class.switchFloating+ (ScaleRowsReal scaleRows)+ (ScaleRowsReal scaleRows)+ (ScaleRowsReal scaleRowsComplex)+ (ScaleRowsReal scaleRowsComplex)++newtype ScaleRowsReal f g a =+ ScaleRowsReal {getScaleRowsReal :: f (RealOf a) -> g a -> g a}++scaleColumnsReal ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Class.Floating a) =>+ Vector width (RealOf a) ->+ Full vert horiz height width a ->+ Full vert horiz height width a+scaleColumnsReal x = transpose . scaleRowsReal x . transpose+++{- |+> tensorProduct order x y = singleColumn order x <#> singleRow order y+-}+tensorProduct ::+ (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ Order -> Vector height a -> Vector width a -> General height width a+tensorProduct order x y =+ case order of+ ColumnMajor -> tensorProd 'T' order x y+ RowMajor -> transpose $ tensorProd 'T' order y x++{- |+> outer order x y = tensorProduct order x (Vector.conjugate y)+-}+outer ::+ (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ Order -> Vector height a -> Vector width a -> General height width a+outer order x y =+ case order of+ ColumnMajor -> tensorProd 'C' ColumnMajor x y+ RowMajor -> transpose $ tensorProd 'C' RowMajor y x++{-# INLINE tensorProd #-}+tensorProd ::+ (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ Char -> Order ->+ Vector height a -> Vector width a -> General height width a+tensorProd trans order (Array shX x) (Array shY y) =+ Array.unsafeCreate (MatrixShape.general MatrixShape.ColumnMajor shX shY) $+ \cPtr -> do+ let m = Shape.size shX+ let n = Shape.size shY+ let ((transa,transb),(lda,ldb)) =+ case order of+ ColumnMajor -> (('N',trans),(m,n))+ RowMajor -> ((trans,'N'),(1,1))+ evalContT $ do+ transaPtr <- Call.char transa+ transbPtr <- Call.char transb+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ kPtr <- Call.cint 1+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr x+ ldaPtr <- Call.leadingDim lda+ bPtr <- ContT $ withForeignPtr y+ ldbPtr <- Call.leadingDim ldb+ betaPtr <- Call.number zero+ ldcPtr <- Call.leadingDim m+ liftIO $+ BlasGen.gemm+ transaPtr transbPtr mPtr nPtr kPtr alphaPtr+ aPtr ldaPtr bPtr ldbPtr betaPtr cPtr ldcPtr+++sumRank1 ::+ (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ (height,width) ->+ [(a, (Vector height a, Vector width a))] -> General height width a+sumRank1 (height,width) xys =+ Array.unsafeCreateWithSize (MatrixShape.general ColumnMajor height width) $+ \size aPtr ->+ evalContT $ do+ let m = Shape.size height+ let n = Shape.size width+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ alphaPtr <- Call.alloca+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ ldaPtr <- Call.leadingDim m+ liftIO $ do+ fill zero size aPtr+ forM_ xys $ \(alpha, (Array shX x, Array shY y)) ->+ withForeignPtr x $ \xPtr ->+ withForeignPtr y $ \yPtr -> do+ Call.assert "Matrix.sumRank1: non-matching height" (height==shX)+ Call.assert "Matrix.sumRank1: non-matching width" (width==shY)+ poke alphaPtr alpha+ BlasGen.gerc mPtr nPtr+ alphaPtr xPtr incxPtr yPtr incyPtr aPtr ldaPtr
+ src/Numeric/LAPACK/Matrix/Banded.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+module Numeric.LAPACK.Matrix.Banded (+ module Numeric.LAPACK.Matrix.Banded.Basic,+ height, width,++ solve,+ determinant,+ ) where++import Numeric.LAPACK.Matrix.Banded.Basic+import Numeric.LAPACK.Matrix.Banded.Linear++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent++import qualified Data.Array.Comfort.Storable as Array+++height ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width a -> height+height = MatrixShape.bandedHeight . Array.shape++width ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width a -> width+width = MatrixShape.bandedWidth . Array.shape
+ src/Numeric/LAPACK/Matrix/Banded/Basic.hs view
@@ -0,0 +1,555 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+module Numeric.LAPACK.Matrix.Banded.Basic (+ Banded,+ General,+ Square,+ Upper,+ Lower,+ Diagonal,+ fromList,+ squareFromList,+ lowerFromList,+ upperFromList,+ mapExtent,+ diagonal,+ takeDiagonal,+ toFull,+ toLowerTriangular,+ toUpperTriangular,+ transpose,+ adjoint,+ multiplyVector,+ multiply,+ multiplyFull,+ ) where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Matrix.Triangular.Private as TriangularPriv+import qualified Numeric.LAPACK.Matrix.Triangular.Basic as Triangular+import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), transposeFromOrder, swapOnRowMajor,+ UnaryProxy, addOffDiagonals)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private+ (fill, pointerSeq, pokeCInt, copySubMatrix, copySubTrapezoid)++import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary ((:+:))+import Type.Data.Num (integralFromProxy)+import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.Marshal.Array (advancePtr)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable)++import qualified Control.Monad.Trans.Maybe as MM+import qualified Control.Monad.Trans.Reader as MR+import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (mzero, void)++import Data.Foldable (forM_)+import Data.Tuple.HT (swap)+import Data.Ord.HT (limit)+++type Banded sub super vert horiz height width =+ Array (MatrixShape.Banded sub super vert horiz height width)++type General sub super height width =+ Array (MatrixShape.BandedGeneral sub super height width)++type Square sub super size =+ Array (MatrixShape.BandedSquare sub super size)++type Lower sub size = Square sub TypeNum.U0 size+type Upper super size = Square TypeNum.U0 super size++type Diagonal size = Square TypeNum.U0 TypeNum.U0 size+++fromList ::+ (Unary.Natural sub, Unary.Natural super,+ Shape.C height, Shape.C width, Storable a) =>+ (UnaryProxy sub, UnaryProxy super) -> Order -> height -> width -> [a] ->+ General sub super height width a+fromList offDiag order height width =+ fromListGen offDiag order (Extent.general height width)++squareFromList ::+ (Unary.Natural sub, Unary.Natural super, Shape.C size, Storable a) =>+ (UnaryProxy sub, UnaryProxy super) -> Order -> size -> [a] ->+ Square sub super size a+squareFromList offDiag order size =+ fromListGen offDiag order (Extent.square size)++lowerFromList ::+ (Unary.Natural sub, Shape.C size, Storable a) =>+ UnaryProxy sub -> Order -> size -> [a] -> Lower sub size a+lowerFromList numOff order size =+ fromListGen (numOff,Proxy) order (Extent.square size)++upperFromList ::+ (Unary.Natural super, Shape.C size, Storable a) =>+ UnaryProxy super -> Order -> size -> [a] -> Upper super size a+upperFromList numOff order size =+ fromListGen (Proxy,numOff) order (Extent.square size)++fromListGen ::+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Storable a) =>+ (UnaryProxy sub, UnaryProxy super) -> Order ->+ Extent.Extent vert horiz height width -> [a] ->+ Banded sub super vert horiz height width a+fromListGen offDiag order extent =+ Array.fromList (MatrixShape.Banded offDiag order extent)+++mapExtent ::+ (Extent.C vertA, Extent.C horizA) =>+ (Extent.C vertB, Extent.C horizB) =>+ Extent.Map vertA horizA vertB horizB height width ->+ Banded super sub vertA horizA height width a ->+ Banded super sub vertB horizB height width a+mapExtent f = Array.mapShape $ MatrixShape.bandedMapExtent f++transpose ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width a ->+ Banded super sub horiz vert width height a+transpose = Array.mapShape MatrixShape.bandedTranspose++adjoint ::+ (Unary.Natural super, Unary.Natural sub, Extent.C vert, Extent.C horiz,+ Shape.C width, Shape.C height, Class.Floating a) =>+ Banded sub super vert horiz height width a ->+ Banded super sub horiz vert width height a+adjoint = Vector.conjugate . transpose+++diagonal :: (Shape.C sh, Class.Floating a) => Vector sh a -> Diagonal sh a+diagonal (Array sh x) =+ Array (MatrixShape.bandedSquare (Proxy,Proxy) ColumnMajor sh) x++takeDiagonal ::+ (Unary.Natural sub, Unary.Natural super, Shape.C sh, Class.Floating a) =>+ Square sub super sh a -> Vector sh a+takeDiagonal (Array (MatrixShape.Banded (sub,super) order extent) x) =+ let size = Extent.squareSize extent+ kl = integralFromProxy sub+ ku = integralFromProxy super+ in if (kl,ku) == (0,0)+ then Array size x+ else+ Array.unsafeCreateWithSize size $ \n yPtr -> evalContT $ do+ nPtr <- Call.cint n+ xPtr <- ContT $ withForeignPtr x+ let k =+ case order of+ RowMajor -> kl+ ColumnMajor -> ku+ incxPtr <- Call.cint (kl+ku+1)+ incyPtr <- Call.cint 1+ liftIO $+ BlasGen.copy nPtr (advancePtr xPtr k) incxPtr yPtr incyPtr+++multiplyVector ::+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width, Eq width,+ Class.Floating a) =>+ Banded sub super vert horiz height width a ->+ Vector width a -> Vector height a+multiplyVector+ (Array (MatrixShape.Banded numOff order extent) a) (Array width x) =+ let height = Extent.height extent+ in Array.unsafeCreate height $ \yPtr -> do++ Call.assert "Banded.multiplyVector: shapes mismatch"+ (Extent.width extent == width)+ let (m,n) = MatrixShape.dimensions $ MatrixShape.Full order extent+ let (kl,ku) = MatrixShape.numOffDiagonals order numOff+ evalContT $ do+ transPtr <- Call.char $ transposeFromOrder order+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ klPtr <- Call.cint kl+ kuPtr <- Call.cint ku+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim $ kl+1+ku+ xPtr <- ContT $ withForeignPtr x+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $+ Private.gbmv transPtr mPtr nPtr klPtr kuPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr+++multiply ::+ (Unary.Natural subA, Unary.Natural superA,+ Unary.Natural subB, Unary.Natural superB,+ (subA :+: subB) ~ subC,+ (superA :+: superB) ~ superC,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse, Eq fuse,+ Class.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+multiply+ (Array (MatrixShape.Banded numOffA orderA extentA) a)+ (Array (MatrixShape.Banded numOffB orderB extentB) b) =+ case (addOffDiagonals numOffA numOffB, Extent.fuse extentA extentB) of+ (_, Nothing) -> error "Banded.multiply: shapes mismatch"+ (((Proof.Nat, Proof.Nat), numOffC), Just extent) ->+ Array.unsafeCreate+ (MatrixShape.Banded numOffC orderB extent) $ \cPtr ->+ let (height,fuse) = Extent.dimensions extentA+ width = Extent.width extentB+ in case (orderA,orderB) of+ (ColumnMajor,ColumnMajor) ->+ multiplyColumnMajor ColumnMajor+ numOffA numOffB (height,fuse,width) a b cPtr+ (RowMajor,ColumnMajor) ->+ multiplyColumnMajor RowMajor+ numOffA numOffB (height,fuse,width) a b cPtr+ (ColumnMajor,RowMajor) ->+ multiplyColumnRowMajor+ (swap numOffB) (swap numOffA)+ (width,fuse,height) b a cPtr+ (RowMajor,RowMajor) ->+ multiplyColumnMajor ColumnMajor+ (swap numOffB) (swap numOffA)+ (width,fuse,height) b a cPtr++multiplyColumnMajor ::+ (Unary.Natural subA, Unary.Natural superA,+ Unary.Natural subB, Unary.Natural superB,+ Shape.C height, Shape.C width, Shape.C fuse,+ Class.Floating a) =>+ Order ->+ (UnaryProxy subA, UnaryProxy superA) ->+ (UnaryProxy subB, UnaryProxy superB) ->+ (height, fuse, width) ->+ ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyColumnMajor orderA (subA,superA) (subB,superB)+ (height,fuse,width) a b cPtr = do+ let m = Shape.size height+ let k = Shape.size fuse+ let n = Shape.size width+ let (kla,kua) = (integralFromProxy subA, integralFromProxy superA)+ let (klb,kub) = (integralFromProxy subB, integralFromProxy superB)+ let ku = kua+kub+ let kl = kla+klb+ let lda0 = kla+kua+ let ldb0 = klb+kub+ let ldc0 = lda0+ldb0+ let lda = lda0+1+ let ldc = ldc0+1+ evalContT $ do+ transPtr <- Call.char $ transposeFromOrder orderA+ mPtr <- Call.alloca+ nPtr <- Call.alloca+ klPtr <- Call.alloca+ kuPtr <- Call.alloca+ let ((miPtr,kliPtr),(niPtr,kuiPtr)) =+ swapOnRowMajor orderA ((mPtr,klPtr),(nPtr,kuPtr))+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim lda+ bPtr <- ContT $ withForeignPtr b+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $+ forM_ (take n [0..]) $ \i -> do+ let top = max 0 (i-ku)+ let bottom = min m (i+kl+1)+ let left = max 0 (i-kub)+ let right = min k (i+klb+1)+ pokeCInt miPtr $ max 0 $ bottom-top+ pokeCInt niPtr $ max 0 $ right-left+ let d = top-left; kli = kla-d; kui = kua+d+ pokeCInt kuiPtr kui+ pokeCInt kliPtr kli+ let j0 = i*ldc+ let j1 = i*ldc0 + top+ku+ let j2 = i*ldc0 + bottom+ku+ fill zero (j1-j0) (advancePtr cPtr j0)+ let aOffset =+ case orderA of+ ColumnMajor -> left+ RowMajor -> top+ Private.gbmv transPtr mPtr nPtr klPtr kuPtr+ alphaPtr+ (advancePtr aPtr (aOffset*lda)) ldaPtr+ (advancePtr bPtr (i*ldb0 + left+kub)) incxPtr+ betaPtr+ (advancePtr cPtr j1) incyPtr+ fill zero (j0+ldc-j2) (advancePtr cPtr j2)++multiplyColumnRowMajor ::+ (Unary.Natural subA, Unary.Natural superA,+ Unary.Natural subB, Unary.Natural superB,+ Shape.C height, Shape.C width, Shape.C fuse,+ Class.Floating a) =>+ (UnaryProxy subA, UnaryProxy superA) ->+ (UnaryProxy subB, UnaryProxy superB) ->+ (height, fuse, width) ->+ ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyColumnRowMajor (subA,superA) (subB,superB)+ (height,fuse,width) a b cPtr = do+ let m = Shape.size height+ let k = Shape.size fuse+ let n = Shape.size width+ let (kla,kua) = (integralFromProxy subA, integralFromProxy superA)+ let (klb,kub) = (integralFromProxy subB, integralFromProxy superB)+ let ku = kua+kub+ let kl = kla+klb+ let lda0 = kla+kua+ let ldb0 = klb+kub+ let ldc0 = kl+ku+ let ldc = ldc0+1+ fill zero (ldc*n) cPtr+ evalContT $ do+ mPtr <- Call.alloca+ nPtr <- Call.alloca+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ bPtr <- ContT $ withForeignPtr b+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ ldc0Ptr <- Call.leadingDim $ ldc0 + if ldb0==0 then 1 else 0+ liftIO $+ forM_ (take k [0..]) $ \i -> do+ let top = max 0 (i-kua)+ let bottom = min m (i+kla+1)+ let left = max 0 (i-klb)+ let right = min n (i+kub+1)+ pokeCInt mPtr $ max 0 $ bottom-top+ pokeCInt nPtr $ max 0 $ right-left+ BlasGen.geru mPtr nPtr alphaPtr+ (advancePtr aPtr (i*lda0+top+kua)) incxPtr+ (advancePtr bPtr (i*ldb0+left+klb)) incyPtr+ (advancePtr cPtr (left*ldc0+top+ku)) ldc0Ptr+++multiplyFull ::+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse, Eq fuse,+ Class.Floating a) =>+ Banded sub super vert horiz height fuse a ->+ Matrix.Full vert horiz fuse width a -> Matrix.Full vert horiz height width a+multiplyFull+ (Array (MatrixShape.Banded numOff orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ case Extent.fuse extentA extentB of+ Nothing -> error "Banded.multiplyFull: shapes mismatch"+ Just extent ->+ Array.unsafeCreate (MatrixShape.Full orderB extent) $ \cPtr ->+ let (height,fuse) = Extent.dimensions extentA+ width = Extent.width extentB+ in case orderB of+ ColumnMajor ->+ multiplyFullColumnMajor+ numOff (height,fuse,width) orderA extentA a b cPtr+ RowMajor ->+ multiplyFullRowMajor+ numOff (height,fuse,width) orderA a b cPtr++multiplyFullColumnMajor ::+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse,+ Class.Floating a) =>+ (UnaryProxy sub, UnaryProxy super) ->+ (height, fuse, width) ->+ Order -> Extent.Extent vert horiz height fuse ->+ ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyFullColumnMajor numOff (height,fuse,width) orderA extentA a b cPtr = do+ let (m,n) = MatrixShape.dimensions $ MatrixShape.Full orderA extentA+ let k = Shape.size width+ let (kl,ku) = MatrixShape.numOffDiagonals orderA numOff+ evalContT $ do+ transPtr <- Call.char $ transposeFromOrder orderA+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ klPtr <- Call.cint kl+ kuPtr <- Call.cint ku+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim $ kl+1+ku+ bPtr <- ContT $ withForeignPtr b+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $+ forM_ (take k $+ zip (pointerSeq (Shape.size fuse) bPtr)+ (pointerSeq (Shape.size height) cPtr)) $+ \(xPtr,yPtr) ->+ Private.gbmv transPtr mPtr nPtr klPtr kuPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr+ betaPtr yPtr incyPtr++multiplyFullRowMajor ::+ (Unary.Natural sub, Unary.Natural super,+ Shape.C height, Shape.C width, Shape.C fuse,+ Class.Floating a) =>+ (UnaryProxy sub, UnaryProxy super) ->+ (height, fuse, width) ->+ Order -> ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyFullRowMajor (sub,super) (height,fuse,width) orderA a b cPtr = do+ let m = Shape.size height+ let n = Shape.size fuse+ let k = Shape.size width+ let kl = integralFromProxy sub+ let ku = integralFromProxy super+ let lda0 = kl+ku+ let lda = lda0+1+ evalContT $ do+ transPtr <- Call.char 'N'+ kPtr <- Call.cint k+ dPtr <- Call.alloca+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ bPtr <- ContT $ withForeignPtr b+ ldbPtr <- Call.leadingDim k+ incxPtr <- Call.cint $+ case orderA of+ RowMajor -> 1+ ColumnMajor -> max 1 lda0+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $+ forM_ (take m $ zip [0..] $+ zip (pointerSeq lda aPtr) (pointerSeq k cPtr)) $+ \(i,(xPtr,yPtr)) -> do+ let firstRow = limit (0,n) (i-kl)+ let last1Row = limit (0,n) (i+ku+1)+ let biPtr = advancePtr bPtr (firstRow*k)+ let xOffset =+ case orderA of+ RowMajor -> firstRow-i+kl+ ColumnMajor -> (firstRow-i)*lda0+ku+ let xiPtr = advancePtr xPtr xOffset+ pokeCInt dPtr $ last1Row - firstRow+ Private.gemv transPtr kPtr dPtr+ alphaPtr biPtr ldbPtr xiPtr incxPtr+ betaPtr yPtr incyPtr+++toLowerTriangular ::+ (Unary.Natural sub, Shape.C sh, Class.Floating a) =>+ Lower sub sh a -> Triangular.Lower sh a+toLowerTriangular =+ Triangular.transpose . toUpperTriangular . transpose++toUpperTriangular ::+ (Unary.Natural super, Shape.C sh, Class.Floating a) =>+ Upper super sh a -> Triangular.Upper sh a+toUpperTriangular (Array (MatrixShape.Banded (_sub,super) order extent) a) =+ let size = Extent.squareSize extent+ in Array.unsafeCreateWithSize+ (MatrixShape.Triangular MatrixShape.NonUnit MatrixShape.upper+ order size) $+ TriangularPriv.fromBanded+ (integralFromProxy super) order (Shape.size size) a++toFull ::+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Banded sub super vert horiz height width a ->+ Matrix.Full vert horiz height width a+toFull (Array (MatrixShape.Banded (sub,super) order extent) a) =+ Array.unsafeCreateWithSize (MatrixShape.Full order extent) $ \bSize bPtr ->+ withForeignPtr a $ \aPtr -> do+ let (height,width) = Extent.dimensions extent+ fill zero bSize bPtr+ case order of+ ColumnMajor -> toFullColumnMajor (sub,super) (height,width) aPtr bPtr+ RowMajor -> toFullColumnMajor (super,sub) (width,height) aPtr bPtr++toFullColumnMajor ::+ (Unary.Natural sub, Unary.Natural super, Shape.C height, Shape.C width,+ Class.Floating a) =>+ (UnaryProxy sub, UnaryProxy super) -> (height,width) ->+ Ptr a -> Ptr a -> IO ()+toFullColumnMajor (sub,super) (height,width) aPtr bPtr = do+ let m = Shape.size height+ let n = Shape.size width+ let kl = integralFromProxy sub+ let ku = integralFromProxy super+ let lda0 = kl+ku+ let lda = lda0+1++ void $ MM.runMaybeT $ flip MR.runReaderT n $+ if m > lda0+ then do -- diagonal stripe+ let col0 = ku+ withRightBound col0 $ \col ->+ copyUpperTrapezoid (col+kl) col lda0 (advancePtr aPtr ku) m bPtr+ let col1 = m-kl+ withRightBound col1 $ \col ->+ copySubMatrix lda (col-col0)+ lda (advancePtr aPtr (col0*lda))+ (m+1) (advancePtr bPtr (col0*m))+ let col2 = m+ku+ withRightBound col2 $ \col ->+ copySubTrapezoid 'L' lda0 (col-col1)+ lda0 (advancePtr aPtr (col1*lda))+ m (advancePtr bPtr (col1*m+m-lda0))+ else do -- full block in the middle+ let col0 = max 0 $ m-kl+ withRightBound col0 $ \col ->+ copyUpperTrapezoid (col+kl) col lda0 (advancePtr aPtr ku) m bPtr+ let col1 = ku+ withRightBound col1 $ \col ->+ copySubMatrix m (col-col0)+ lda0 (advancePtr aPtr (col0*lda+(col1-col0)))+ m (advancePtr bPtr (col0*m))+ let col2 = m+ku+ withRightBound col2 $ \col ->+ copySubTrapezoid 'L' m (col-col1)+ lda0 (advancePtr aPtr (ku*lda))+ m (advancePtr bPtr (ku*m))++withRightBound ::+ Int -> (Int -> IO a) -> MR.ReaderT Int (MM.MaybeT IO) a+withRightBound col act = do+ n <- MR.ask+ if n<=col+ then liftIO (act n) >> mzero+ else liftIO (act col)++copyUpperTrapezoid ::+ (Class.Floating a) =>+ Int -> Int -> Int -> Ptr a -> Int -> Ptr a -> IO ()+copyUpperTrapezoid m n lda aPtr ldb bPtr = do+ let d = m-n+ copySubMatrix d n lda aPtr ldb bPtr+ copySubTrapezoid 'U' n n+ lda (advancePtr aPtr d)+ ldb (advancePtr bPtr d)
+ src/Numeric/LAPACK/Matrix/Banded/Linear.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Banded.Linear (+ solve,+ solveColumnMajor,+ determinant,+ ) where++import qualified Numeric.LAPACK.Matrix.Banded.Basic as Banded+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Split as Split+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Linear.Private (solver, withDeterminantInfo, withInfo)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), transposeFromOrder)+import Numeric.LAPACK.Matrix.Private (Full)+import Numeric.LAPACK.Private (copySubMatrix)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num (integralFromProxy)++import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import System.IO.Unsafe (unsafePerformIO)++import Foreign.Marshal.Array (peekArray, advancePtr)+import Foreign.ForeignPtr (withForeignPtr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++solve ::+ (Unary.Natural sub, Unary.Natural super, Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Banded.Square sub super sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solve (Array (MatrixShape.Banded numOff order extent) a) =+ solver "Banded.solve" (Extent.squareSize extent) $+ \n nPtr nrhsPtr xPtr ldxPtr -> do+ let (kl,ku) = MatrixShape.numOffDiagonals order numOff+ let k = kl+1+ku+ let ldab = kl+k+ transPtr <- Call.char $ transposeFromOrder order+ klPtr <- Call.cint kl+ kuPtr <- Call.cint ku+ aPtr <- ContT $ withForeignPtr a+ abPtr <- Call.allocaArray (n*ldab)+ ldabPtr <- Call.leadingDim ldab+ ipivPtr <- Call.allocaArray n+ liftIO $ do+ copySubMatrix k n k aPtr ldab (advancePtr abPtr kl)+ withInfo "gbtrf" $+ LapackGen.gbtrf nPtr nPtr klPtr kuPtr abPtr ldabPtr ipivPtr+ withInfo "gbtrs" $+ LapackGen.gbtrs transPtr nPtr klPtr kuPtr nrhsPtr+ abPtr ldabPtr ipivPtr xPtr ldxPtr++solveColumnMajor ::+ (Unary.Natural sub, Unary.Natural super, Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Banded.Square sub super sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solveColumnMajor+ (Array (MatrixShape.Banded (sub,super) ColumnMajor extent) a) =+ solver "Banded.solve" (Extent.squareSize extent) $+ \n nPtr nrhsPtr xPtr ldxPtr -> do+ let kl = integralFromProxy sub+ let ku = integralFromProxy super+ let k = kl+1+ku+ let ldab = kl+k+ klPtr <- Call.cint kl+ kuPtr <- Call.cint ku+ aPtr <- ContT $ withForeignPtr a+ abPtr <- Call.allocaArray (n*ldab)+ ldabPtr <- Call.leadingDim ldab+ ipivPtr <- Call.allocaArray n+ liftIO $ do+ copySubMatrix k n k aPtr ldab (advancePtr abPtr kl)+ withInfo "gbsv" $+ LapackGen.gbsv nPtr klPtr kuPtr nrhsPtr+ abPtr ldabPtr ipivPtr xPtr ldxPtr+solveColumnMajor (Array (MatrixShape.Banded _ RowMajor _) _) =+ error "Linear.Banded.solveColumnMajor: RowMajor intentionally unimplemented"++determinant ::+ (Unary.Natural sub, Unary.Natural super, Shape.C sh, Class.Floating a) =>+ Banded.Square sub super sh a -> a+determinant (Array (MatrixShape.Banded numOff order extent) a) =+ unsafePerformIO $ do+ let n = Shape.size $ Extent.squareSize extent+ evalContT $ do+ let (kl,ku) = MatrixShape.numOffDiagonals order numOff+ let k = kl+1+ku+ let ldab = kl+k+ nPtr <- Call.cint n+ klPtr <- Call.cint kl+ kuPtr <- Call.cint ku+ aPtr <- ContT $ withForeignPtr a+ abPtr <- Call.allocaArray (n*ldab)+ ldabPtr <- Call.leadingDim ldab+ ipivPtr <- Call.allocaArray n+ liftIO $ do+ copySubMatrix k n k aPtr ldab (advancePtr abPtr kl)+ withDeterminantInfo "gbtrf"+ (LapackGen.gbtrf nPtr nPtr klPtr kuPtr abPtr ldabPtr ipivPtr)+ (do+ det <- Private.product n (advancePtr abPtr (kl+ku)) ldab+ ipiv <- peekArray n ipivPtr+ return $ if Split.oddPermutation ipiv then -det else det)
+ src/Numeric/LAPACK/Matrix/BandedHermitian.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.BandedHermitian (+ module Numeric.LAPACK.Matrix.BandedHermitian.Basic,++ eigenvalues,+ eigensystem,+ ) where++import qualified Numeric.LAPACK.Matrix.BandedHermitian.Eigen as Eigen+import Numeric.LAPACK.Matrix.BandedHermitian.Basic++import qualified Numeric.LAPACK.Matrix.Private as Matrix+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf)++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary as Unary++import qualified Data.Array.Comfort.Shape as Shape+++eigenvalues ::+ (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>+ BandedHermitian offDiag sh a -> Vector sh (RealOf a)+eigenvalues = Eigen.values++{- |+For symmetric eigenvalue problems, @eigensystem@ and @schur@ coincide.+-}+eigensystem ::+ (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>+ BandedHermitian offDiag sh a -> (Matrix.Square sh a, Vector sh (RealOf a))+eigensystem = Eigen.decompose
+ src/Numeric/LAPACK/Matrix/BandedHermitian/Basic.hs view
@@ -0,0 +1,480 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE GADTs #-}+module Numeric.LAPACK.Matrix.BandedHermitian.Basic (+ BandedHermitian,+ Transposition(..),+ fromList,+ identity,+ diagonal,+ takeDiagonal,+ toHermitian,+ toBanded,+ multiplyVector,+ multiplyFull,+ covariance,+ sumRank1,+ ) where++import qualified Numeric.LAPACK.ShapeStatic as ShapeStatic+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import qualified Numeric.LAPACK.Matrix.Banded.Basic as Banded+import qualified Numeric.LAPACK.Matrix.Triangular.Private as TriangularPriv+import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Hermitian.Private (TakeDiagonal(..))+import Numeric.LAPACK.Matrix.Hermitian.Basic (Hermitian)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), flipOrder, uploFromOrder,+ UnaryProxy, natFromProxy)+import Numeric.LAPACK.Matrix.Private+ (Transposition(NonTransposed, Transposed), transposeOrder)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, zero, one)+import Numeric.LAPACK.Private+ (fill, lacgv, copyConjugate, condConjugateToTemp,+ pointerSeq, pokeCInt, copySubMatrix)++import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.BLAS.FFI.Complex as BlasComplex+import qualified Numeric.BLAS.FFI.Real as BlasReal+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary ((:+:))+import Type.Data.Num (integralFromProxy)+import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.Marshal.Array (advancePtr)+import Foreign.C.Types (CInt, CChar)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr, castPtr)+import Foreign.Storable (Storable, poke, peek, peekElemOff)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (when)++import Data.Foldable (for_)+import Data.Tuple.HT (mapPair)++import Data.Complex (Complex, conjugate)+++type BandedHermitian offDiag size =+ Array (MatrixShape.BandedHermitian offDiag size)++type Diagonal size = BandedHermitian TypeNum.U0 size+++fromList ::+ (Unary.Natural offDiag, Shape.C size, Storable a) =>+ UnaryProxy offDiag -> Order -> size -> [a] ->+ BandedHermitian offDiag size a+fromList numOff order size =+ Array.fromList (MatrixShape.BandedHermitian numOff order size)++identity ::+ (Shape.C sh, Class.Floating a) => sh -> Diagonal sh a+identity sh =+ Array.mapShape (MatrixShape.BandedHermitian Proxy ColumnMajor) $+ Vector.constant sh one++diagonal ::+ (Shape.C sh, Class.Floating a) => Vector sh (RealOf a) -> Diagonal sh a+diagonal =+ Array.mapShape (MatrixShape.BandedHermitian Proxy ColumnMajor) .+ Vector.fromReal++takeDiagonal ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a -> Vector size (RealOf a)+takeDiagonal =+ runTakeDiagonal $+ Class.switchFloating+ (TakeDiagonal $ takeDiagonalAux 1) (TakeDiagonal $ takeDiagonalAux 1)+ (TakeDiagonal $ takeDiagonalAux 2) (TakeDiagonal $ takeDiagonalAux 2)++takeDiagonalAux ::+ (Unary.Natural offDiag, Shape.C size,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Int -> BandedHermitian offDiag size a -> Vector size ar+takeDiagonalAux dim (Array (MatrixShape.BandedHermitian numOff order size) a) =+ let k = integralFromProxy numOff+ in Array.unsafeCreateWithSize size $ \n yPtr -> evalContT $ do+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ let xPtr =+ castPtr $ advancePtr aPtr $+ case order of+ RowMajor -> 0+ ColumnMajor -> k+ incxPtr <- Call.cint (dim * (k+1))+ incyPtr <- Call.cint 1+ liftIO $ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr+++toHermitian ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a -> Hermitian size a+toHermitian (Array (MatrixShape.BandedHermitian numOff order size) a) =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order size) $+ TriangularPriv.fromBanded+ (integralFromProxy numOff) order (Shape.size size) a+++toBanded ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a ->+ Banded.Square offDiag offDiag size a+toBanded (Array (MatrixShape.BandedHermitian numOff order sh) a) =+ Array.unsafeCreate+ (MatrixShape.Banded (numOff,numOff) order (Extent.square sh)) $ \bPtr ->+ withForeignPtr a $ \aPtr ->+ case order of+ ColumnMajor -> toBandedColumnMajor numOff sh aPtr bPtr+ RowMajor -> toBandedRowMajor numOff sh aPtr bPtr++toBandedColumnMajor ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ UnaryProxy offDiag -> size -> Ptr a -> Ptr a -> IO ()+toBandedColumnMajor numOff size aPtr bPtr = do+ let n = Shape.size size+ let k = integralFromProxy numOff+ let lda0 = k+ let lda = lda0+1+ let ldb0 = 2*k+ let ldb = ldb0+1+ copySubMatrix lda n lda aPtr ldb bPtr+ evalContT $ do+ incxPtr <- Call.cint lda0+ incyPtr <- Call.cint 1+ inczPtr <- Call.cint 0+ zPtr <- Call.number zero+ nPtr <- Call.alloca+ liftIO $ for_ (take n [0..]) $ \i -> do+ let top = i+1+ let bottom = min n (i+k+1)+ let xPtr = advancePtr aPtr ((i+1)*lda0+top+k-1)+ let yPtr = advancePtr bPtr (i*ldb0+k)+ pokeCInt nPtr (bottom-top)+ copyConjugate nPtr xPtr incxPtr (advancePtr yPtr top) incyPtr+ pokeCInt nPtr (i+k+1 - bottom)+ BlasGen.copy nPtr zPtr inczPtr (advancePtr yPtr bottom) incyPtr++toBandedRowMajor ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ UnaryProxy offDiag -> size -> Ptr a -> Ptr a -> IO ()+toBandedRowMajor numOff size aPtr bPtr = do+ let n = Shape.size size+ let k = integralFromProxy numOff+ let lda0 = k+ let lda = lda0+1+ let ldb0 = 2*k+ let ldb = ldb0+1+ copySubMatrix lda n lda aPtr ldb (advancePtr bPtr k)+ evalContT $ do+ incxPtr <- Call.cint lda0+ incyPtr <- Call.cint 1+ inczPtr <- Call.cint 0+ zPtr <- Call.number zero+ nPtr <- Call.alloca+ liftIO $ for_ (take n [0..]) $ \i -> do+ let left = max 0 (i-k)+ let xPtr = advancePtr aPtr (left*lda0+i)+ let yPtr = advancePtr bPtr (i*ldb0)+ pokeCInt nPtr (k-i+left)+ BlasGen.copy nPtr zPtr inczPtr (advancePtr yPtr i) incyPtr+ pokeCInt nPtr (i-left)+ copyConjugate nPtr xPtr incxPtr (advancePtr yPtr (left+k)) incyPtr+++multiplyVector ::+ (Unary.Natural offDiag, Shape.C size, Eq size, Class.Floating a) =>+ Transposition -> BandedHermitian offDiag size a ->+ Vector size a -> Vector size a+multiplyVector transposed+ (Array (MatrixShape.BandedHermitian numOff order size) a) (Array sizeX x) =+ Array.unsafeCreateWithSize size $ \n yPtr -> do++ Call.assert "BandedHermitian.multiplyVector: shapes mismatch"+ (size == sizeX)+ let k = integralFromProxy numOff+ evalContT $ do+ let conj = transposeOrder transposed order == RowMajor+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint n+ kPtr <- Call.cint k+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim $ k+1+ xPtr <- condConjugateToTemp conj n x+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $ do+ BlasGen.hbmv uploPtr nPtr kPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr+ when conj $ lacgv nPtr yPtr incyPtr+++covariance ::+ (Shape.C size, Eq size, Class.Floating a,+ Unary.Natural sub, Unary.Natural super) =>+ Banded.Square sub super size a ->+ BandedHermitian (sub :+: super) size a+covariance a =+ case mapPair (natFromProxy,natFromProxy) $+ MatrixShape.bandedOffDiagonals $ Array.shape a of+ (sub,super) ->+ case (Proof.addNat sub super, Proof.addComm sub super) of+ (Proof.Nat, Proof.AddComm) ->+ fromUpperPart $ Banded.multiply (Banded.adjoint a) a++fromUpperPart ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ Banded.Square offDiag offDiag size a -> BandedHermitian offDiag size a+fromUpperPart (Array (MatrixShape.Banded (sub,super) order extent) a) =+ let sh = Extent.squareSize extent+ n = Shape.size sh+ kl = integralFromProxy sub+ ku = integralFromProxy super+ lda = kl+1+ku+ ldb = ku+1+ in Array.unsafeCreate (MatrixShape.BandedHermitian super order sh) $ \bPtr ->+ withForeignPtr a $ \aPtr ->+ case order of+ ColumnMajor -> copySubMatrix ldb n lda aPtr ldb bPtr+ RowMajor -> copySubMatrix ldb n lda (advancePtr aPtr kl) ldb bPtr+++multiplyFull ::+ (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ Transposition -> BandedHermitian offDiag height a ->+ Matrix.Full vert horiz height width a ->+ Matrix.Full vert horiz height width a+multiplyFull transposed a b =+ case MatrixShape.fullOrder $ Array.shape b of+ ColumnMajor -> multiplyFullSpecial transposed a b+ RowMajor -> multiplyFullGeneric transposed a b++multiplyFullSpecial ::+ (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,+ Eq height, Shape.C height, Shape.C width, Class.Floating a) =>+ Transposition -> BandedHermitian offDiag height a ->+ Matrix.Full vert horiz height width a ->+ Matrix.Full vert horiz height width a+multiplyFullSpecial transposed+ (Array (MatrixShape.BandedHermitian numOff orderA sizeA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ Array.unsafeCreate (MatrixShape.Full orderB extentB) $ \cPtr -> do+ Call.assert "BandedHermitian.multiplyFull: shapes mismatch"+ (sizeA == Extent.height extentB)+ let (height,width) = Extent.dimensions extentB+ case orderB of+ ColumnMajor ->+ multiplyFullColumnMajor+ transposed numOff (height,width) orderA a b cPtr+ RowMajor ->+ multiplyFullRowMajor+ transposed numOff (height,width) orderA a b cPtr++multiplyFullColumnMajor ::+ (Unary.Natural offDiag, Shape.C height, Shape.C width, Class.Floating a) =>+ Transposition -> UnaryProxy offDiag -> (height, width) ->+ Order -> ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyFullColumnMajor transposed numOff (height,width) order a b cPtr = do+ let n = Shape.size height+ let nrhs = Shape.size width+ let k = integralFromProxy numOff+ evalContT $ do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint n+ kPtr <- Call.cint k+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim $ k+1+ bPtr <- ContT $ withForeignPtr b+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ let pointers = take nrhs $ zip (pointerSeq n bPtr) (pointerSeq n cPtr)+ case transposeOrder transposed order of+ RowMajor -> do+ xPtr <- Call.allocaArray n+ liftIO $ for_ pointers $ \(biPtr,yPtr) -> do+ copyConjugate nPtr biPtr incxPtr xPtr incxPtr+ BlasGen.hbmv uploPtr nPtr kPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr+ lacgv nPtr yPtr incyPtr+ ColumnMajor ->+ liftIO $ for_ pointers $ \(xPtr,yPtr) ->+ BlasGen.hbmv uploPtr nPtr kPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr++multiplyFullRowMajor ::+ (Unary.Natural offDiag, Shape.C height, Shape.C width, Class.Floating a) =>+ Transposition -> UnaryProxy offDiag -> (height, width) ->+ Order -> ForeignPtr a -> ForeignPtr a -> Ptr a -> IO ()+multiplyFullRowMajor =+ error "BandedHermitian.multiplyFullRowMajor: not implemented"+++multiplyFullGeneric ::+ (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ Transposition -> BandedHermitian offDiag height a ->+ Matrix.Full vert horiz height width a ->+ Matrix.Full vert horiz height width a+multiplyFullGeneric transposed a b =+ let (lower,upper) = (takeStrictLower a, takeUpper a)+ (lowerT,upperT) =+ case transposed of+ Transposed -> (Banded.transpose upper, Banded.transpose lower)+ NonTransposed -> (lower,upper)+ in Banded.multiplyFull (Banded.mapExtent Extent.fromSquare lowerT) b+ `Vector.add`+ Banded.multiplyFull (Banded.mapExtent Extent.fromSquare upperT) b++takeUpper ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a ->+ Banded.Square TypeNum.U0 offDiag size a+takeUpper =+ Array.mapShape+ (\(MatrixShape.BandedHermitian numOff order sh) ->+ MatrixShape.bandedSquare (Proxy,numOff) order sh)++takeStrictLower ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a ->+ Banded.Square offDiag TypeNum.U0 size a+takeStrictLower (Array (MatrixShape.BandedHermitian numOff order sh) x) =+ Array.unsafeCreateWithSize+ (MatrixShape.bandedSquare (numOff,Proxy) (flipOrder order) sh) $+ \size yPtr -> evalContT $ do+ let k = integralFromProxy numOff+ nPtr <- Call.cint $ Shape.size sh+ xPtr <- ContT $ withForeignPtr x+ sizePtr <- Call.cint size+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ inczPtr <- Call.cint 0+ ldbPtr <- Call.leadingDim $ k+1+ zPtr <- Call.number zero+ liftIO $ do+ copyConjugate sizePtr xPtr incxPtr yPtr incyPtr+ let offset = case order of ColumnMajor -> k; RowMajor -> 0+ BlasGen.copy nPtr zPtr inczPtr (advancePtr yPtr offset) ldbPtr+++type StaticVector n = Vector (ShapeStatic.ZeroBased n)++{-+The list represents ragged rows of a sparse matrix.+-}+sumRank1 ::+ (Unary.Natural k, Shape.Indexed sh, Class.Floating a) =>+ Order -> sh ->+ [(RealOf a, (Shape.Index sh, StaticVector (Unary.Succ k) a))] ->+ BandedHermitian k sh a+sumRank1 =+ getSumRank1 $+ Class.switchFloating+ (SumRank1 $ sumRank1Aux Proxy)+ (SumRank1 $ sumRank1Aux Proxy)+ (SumRank1 $ sumRank1Aux Proxy)+ (SumRank1 $ sumRank1Aux Proxy)++newtype SumRank1 k sh a = SumRank1 {getSumRank1 :: SumRank1_ k sh (RealOf a) a}++type SumRank1_ k sh ar a =+ Order -> sh ->+ [(ar, (Shape.Index sh, StaticVector (Unary.Succ k) a))] ->+ BandedHermitian k sh a++sumRank1Aux ::+ (Unary.Natural k, Shape.Indexed sh,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ UnaryProxy k -> SumRank1_ k sh ar a+sumRank1Aux numOff order size xs =+ Array.unsafeCreateWithSize+ (MatrixShape.BandedHermitian numOff order size) $+ \bSize aPtr -> evalContT $ do+ let k = integralFromProxy numOff+ let n = Shape.size size+ let lda = k+1+ uploPtr <- Call.char $ uploFromOrder order+ mPtr <- Call.cint lda+ alphaPtr <- Call.alloca+ incxPtr <- Call.cint 1+ kPtr <- Call.cint k+ ldbPtr <- Call.leadingDim k+ bSizePtr <- Call.cint bSize+ liftIO $ do+ fill zero bSize aPtr+ for_ xs $ \(alpha, (offset, Array _shX x)) ->+ withForeignPtr x $ \xPtr -> do+ let i = Shape.offset size offset+ Call.assert "BandedHermitian.sumRank1: index too large" (i+k < n)+ let bPtr = advancePtr aPtr (lda*i)+ hbr order k alpha+ uploPtr mPtr kPtr alphaPtr xPtr incxPtr bPtr incxPtr ldbPtr+ case order of+ RowMajor -> lacgv bSizePtr aPtr incxPtr+ ColumnMajor -> return ()+++type HBR_ ar a =+ Order -> Int -> ar -> Ptr CChar -> Ptr CInt -> Ptr CInt ->+ Ptr a -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr CInt -> IO ()++newtype HBR a = HBR {getHBR :: HBR_ (RealOf a) a}++hbr :: Class.Floating a => HBR_ (RealOf a) a+hbr = getHBR $ Class.switchFloating (HBR syr) (HBR syr) (HBR her) (HBR her)++syr :: (Class.Real a) => HBR_ a a+syr order k alpha uploPtr nPtr kPtr alphaPtr xPtr incxPtr a0Ptr incaPtr ldaPtr =+ case order of+ ColumnMajor -> do+ let aPtr = advancePtr a0Ptr k+ poke alphaPtr alpha+ BlasReal.syr uploPtr kPtr alphaPtr xPtr incxPtr aPtr ldaPtr+ poke alphaPtr . (alpha*) =<< peekElemOff xPtr k+ BlasGen.axpy nPtr alphaPtr xPtr incxPtr (advancePtr aPtr (k*k)) incaPtr+ RowMajor -> do+ let aPtr = a0Ptr+ poke alphaPtr . (alpha*) =<< peek xPtr+ BlasGen.axpy nPtr alphaPtr xPtr incxPtr aPtr incaPtr+ poke alphaPtr alpha+ BlasReal.syr uploPtr kPtr alphaPtr+ (advancePtr xPtr 1) incxPtr (advancePtr aPtr (k+1)) ldaPtr++her :: (Class.Real a) => HBR_ a (Complex a)+her order k alpha uploPtr nPtr kPtr alphaPtr xPtr incxPtr a0Ptr incaPtr ldaPtr =+ case order of+ ColumnMajor -> do+ let aPtr = advancePtr a0Ptr k+ let alphaRealPtr = castPtr alphaPtr+ poke alphaRealPtr alpha+ BlasComplex.her uploPtr kPtr alphaRealPtr xPtr incxPtr aPtr ldaPtr+ poke alphaPtr . fmap (alpha*) . conjugate =<< peekElemOff xPtr k+ BlasGen.axpy nPtr alphaPtr xPtr incxPtr (advancePtr aPtr (k*k)) incaPtr+ RowMajor -> do+ let aPtr = a0Ptr+ let alphaRealPtr = castPtr alphaPtr+ poke alphaPtr . fmap (alpha*) . conjugate =<< peek xPtr+ BlasGen.axpy nPtr alphaPtr xPtr incxPtr aPtr incaPtr+ poke alphaRealPtr alpha+ BlasComplex.her uploPtr kPtr alphaRealPtr+ (advancePtr xPtr 1) incxPtr (advancePtr aPtr (k+1)) ldaPtr
+ src/Numeric/LAPACK/Matrix/BandedHermitian/Eigen.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.BandedHermitian.Eigen (+ values,+ decompose,+ ) where++import Numeric.LAPACK.Matrix.BandedHermitian.Basic (BandedHermitian)++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Private as Matrix+import Numeric.LAPACK.Matrix.Hermitian.Private (TakeDiagonal(..))+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), uploFromOrder)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf)+import Numeric.LAPACK.Private+ (copyToTemp, copyCondConjugateToTemp, withInfo, eigenMsg)++import qualified Numeric.LAPACK.FFI.Complex as LapackComplex+import qualified Numeric.LAPACK.FFI.Real as LapackReal+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num (integralFromProxy)++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.C.Types (CInt, CChar)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable)++import Control.Monad.Trans.Cont (evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Complex (Complex)+++values ::+ (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>+ BandedHermitian offDiag sh a -> Vector sh (RealOf a)+values =+ runTakeDiagonal $+ Class.switchFloating+ (TakeDiagonal valuesAux) (TakeDiagonal valuesAux)+ (TakeDiagonal valuesAux) (TakeDiagonal valuesAux)++valuesAux ::+ (Unary.Natural offDiag, Shape.C sh,+ Class.Floating a, RealOf a ~ ar, Storable ar) =>+ BandedHermitian offDiag sh a -> Vector sh ar+valuesAux (Array (MatrixShape.BandedHermitian numOff order size) a) =+ Array.unsafeCreateWithSize size $ \n wPtr -> evalContT $ do+ let k = integralFromProxy numOff+ let lda = k+1+ jobzPtr <- Call.char 'N'+ uploPtr <- Call.char $ uploFromOrder order+ kPtr <- Call.cint k+ aPtr <- copyToTemp (n*lda) a+ ldaPtr <- Call.leadingDim lda+ let zPtr = nullPtr+ ldzPtr <- Call.leadingDim n+ liftIO $ withInfo eigenMsg "hbev" $+ hbev jobzPtr uploPtr n kPtr aPtr ldaPtr wPtr zPtr ldzPtr+++decompose ::+ (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>+ BandedHermitian offDiag sh a -> (Matrix.Square sh a, Vector sh (RealOf a))+decompose =+ getDecompose $+ Class.switchFloating+ (Decompose decomposeAux) (Decompose decomposeAux)+ (Decompose decomposeAux) (Decompose decomposeAux)++type Decompose_ offDiag sh a =+ BandedHermitian offDiag sh a -> (Matrix.Square sh a, Vector sh (RealOf a))++newtype Decompose offDiag sh a =+ Decompose {getDecompose :: Decompose_ offDiag sh a}++decomposeAux ::+ (Unary.Natural offDiag, Shape.C sh,+ Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Decompose_ offDiag sh a+decomposeAux (Array (MatrixShape.BandedHermitian numOff order size) a) =+ Array.unsafeCreateWithSizeAndResult (MatrixShape.square ColumnMajor size) $+ \_ zPtr ->+ ArrayIO.unsafeCreateWithSize size $ \n wPtr ->+ evalContT $ do+ let k = integralFromProxy numOff+ let lda = k+1+ jobzPtr <- Call.char 'V'+ uploPtr <- Call.char $ uploFromOrder order+ kPtr <- Call.cint k+ aPtr <- copyCondConjugateToTemp (order==RowMajor) (n*lda) a+ ldaPtr <- Call.leadingDim lda+ ldzPtr <- Call.leadingDim n+ liftIO $ withInfo eigenMsg "hbev" $+ hbev jobzPtr uploPtr n kPtr aPtr ldaPtr wPtr zPtr ldzPtr+++type HBEV_ ar a =+ Ptr CChar -> Ptr CChar -> Int -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr ar ->+ Ptr a -> Ptr CInt -> Ptr CInt -> IO ()++newtype HBEV a = HBEV {getHBEV :: HBEV_ (RealOf a) a}++hbev :: Class.Floating a => HBEV_ (RealOf a) a+hbev =+ getHBEV $+ Class.switchFloating+ (HBEV sbevReal) (HBEV sbevReal) (HBEV hbevComplex) (HBEV hbevComplex)++sbevReal :: Class.Real a => HBEV_ a a+sbevReal jobzPtr uploPtr n kdPtr aPtr ldaPtr wPtr zPtr ldzPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray (max 1 (3*n-2))+ liftIO $+ LapackReal.sbev jobzPtr uploPtr+ nPtr kdPtr aPtr ldaPtr wPtr zPtr ldzPtr workPtr infoPtr++hbevComplex :: Class.Real a => HBEV_ a (Complex a)+hbevComplex jobzPtr uploPtr n kdPtr aPtr ldaPtr wPtr zPtr ldzPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray n+ rworkPtr <- Call.allocaArray (max 1 (3*n-2))+ liftIO $+ LapackComplex.hbev jobzPtr uploPtr+ nPtr kdPtr aPtr ldaPtr wPtr zPtr ldzPtr workPtr rworkPtr infoPtr
+ src/Numeric/LAPACK/Matrix/BandedHermitianPositiveDefinite.hs view
@@ -0,0 +1,5 @@+module Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite (+ module Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite.Linear,+ ) where++import Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite.Linear
+ src/Numeric/LAPACK/Matrix/BandedHermitianPositiveDefinite/Linear.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite.Linear (+ solve,+ solveDecomposed,+ decompose,+ determinant,+ ) where++import qualified Numeric.LAPACK.Matrix.Banded.Basic as Banded+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Linear.Private (solver)+import Numeric.LAPACK.Matrix.BandedHermitian.Basic (BandedHermitian)+import Numeric.LAPACK.Matrix.Hermitian.Private (Determinant(..))+import Numeric.LAPACK.Matrix.Triangular.Private (copyTriangleToTemp)+import Numeric.LAPACK.Matrix.Shape.Private (uploFromOrder)+import Numeric.LAPACK.Matrix.Private (Full, Conjugation(Conjugated))+import Numeric.LAPACK.Scalar (RealOf, realPart)+import Numeric.LAPACK.Private (copyBlock, withInfo, rankMsg, definiteMsg)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num (integralFromProxy)+import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.ForeignPtr (withForeignPtr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++solve ::+ (Unary.Natural offDiag, Shape.C size, Eq size,+ Extent.C vert, Extent.C horiz, Shape.C nrhs, Class.Floating a) =>+ BandedHermitian offDiag size a ->+ Full vert horiz size nrhs a -> Full vert horiz size nrhs a+solve (Array (MatrixShape.BandedHermitian numOff orderA shA) a) =+ solver "BandedHermitian.solve" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder orderA+ let k = integralFromProxy numOff+ let lda = k+1+ kPtr <- Call.cint k+ aPtr <- copyTriangleToTemp Conjugated orderA (n*lda) a+ ldaPtr <- Call.leadingDim lda+ liftIO $+ withInfo definiteMsg "pbsv" $+ LapackGen.pbsv uploPtr nPtr kPtr nrhsPtr aPtr ldaPtr xPtr ldxPtr++{- |+> solve a b == solveDecomposed (decompose a) b+> solve (covariance u) b == solveDecomposed u b+-}+solveDecomposed ::+ (Unary.Natural offDiag, Shape.C size, Eq size,+ Extent.C vert, Extent.C horiz, Shape.C nrhs, Class.Floating a) =>+ Banded.Upper offDiag size a ->+ Full vert horiz size nrhs a -> Full vert horiz size nrhs a+solveDecomposed (Array (MatrixShape.Banded (_zero,numOff) orderA shA) a) =+ solver "BandedHermitian.solveDecomposed" (Extent.squareSize shA) $+ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder orderA+ let k = integralFromProxy numOff+ let lda = k+1+ kPtr <- Call.cint k+ aPtr <- copyTriangleToTemp Conjugated orderA (n*lda) a+ ldaPtr <- Call.leadingDim lda+ liftIO $+ withInfo rankMsg "pbtrs" $+ LapackGen.pbtrs uploPtr nPtr kPtr nrhsPtr aPtr ldaPtr xPtr ldxPtr+++{- |+Cholesky decomposition+-}+decompose ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a -> Banded.Upper offDiag size a+decompose (Array (MatrixShape.BandedHermitian numOff order sh) a) =+ Array.unsafeCreateWithSize+ (MatrixShape.bandedSquare (Proxy,numOff) order sh) $ \bSize bPtr -> do+ evalContT $ do+ let k = integralFromProxy numOff+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint $ Shape.size sh+ kPtr <- Call.cint k+ aPtr <- ContT $ withForeignPtr a+ ldbPtr <- Call.leadingDim $ k+1+ liftIO $ do+ copyBlock bSize aPtr bPtr+ withInfo definiteMsg "pbtrf" $+ LapackGen.pbtrf uploPtr nPtr kPtr bPtr ldbPtr+++determinant ::+ (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>+ BandedHermitian offDiag size a -> RealOf a+determinant =+ getDeterminant $+ Class.switchFloating+ (Determinant determinantAux) (Determinant determinantAux)+ (Determinant determinantAux) (Determinant determinantAux)++determinantAux ::+ (Unary.Natural offDiag, Shape.C size,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian offDiag size a -> ar+determinantAux =+ (^(2::Int)) . product . map realPart . Array.toList .+ Banded.takeDiagonal . decompose
+ src/Numeric/LAPACK/Matrix/Basic.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+module Numeric.LAPACK.Matrix.Basic where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor))+import Numeric.LAPACK.Matrix.Private (Full, General)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (pointerSeq)++import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Storable (poke, peek)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++transpose ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert horiz height width a -> Full horiz vert width height a+transpose = Array.mapShape MatrixShape.transpose+++singleRow :: Order -> Vector width a -> General () width a+singleRow order = Array.mapShape (MatrixShape.general order ())++singleColumn :: Order -> Vector height a -> General height () a+singleColumn order = Array.mapShape (flip (MatrixShape.general order) ())++flattenRow :: General () width a -> Vector width a+flattenRow = Array.mapShape MatrixShape.fullWidth++flattenColumn :: General height () a -> Vector height a+flattenColumn = Array.mapShape MatrixShape.fullHeight++++scaleRows ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Class.Floating a) =>+ Vector height a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+scaleRows+ (Array heightX x) (Array shape@(MatrixShape.Full order extent) a) =+ Array.unsafeCreate shape $ \bPtr -> do+ let (height,width) = Extent.dimensions extent+ Call.assert "scaleRows: sizes mismatch" (heightX == height)+ case order of+ RowMajor -> evalContT $ do+ let m = Shape.size height+ let n = Shape.size width+ alphaPtr <- Call.alloca+ nPtr <- Call.cint n+ xPtr <- ContT $ withForeignPtr x+ aPtr <- ContT $ withForeignPtr a+ incaPtr <- Call.cint 1+ incbPtr <- Call.cint 1+ liftIO $ sequence_ $ take m $+ zipWith3+ (\xkPtr akPtr bkPtr -> do+ poke alphaPtr =<< peek xkPtr+ BlasGen.copy nPtr akPtr incaPtr bkPtr incbPtr+ BlasGen.scal nPtr alphaPtr bkPtr incbPtr)+ (pointerSeq 1 xPtr)+ (pointerSeq n aPtr)+ (pointerSeq n bPtr)+ ColumnMajor -> evalContT $ do+ let m = Shape.size width+ let n = Shape.size height+ transPtr <- Call.char 'N'+ nPtr <- Call.cint n+ klPtr <- Call.cint 0+ kuPtr <- Call.cint 0+ alphaPtr <- Call.number one+ xPtr <- ContT $ withForeignPtr x+ ldxPtr <- Call.leadingDim 1+ aPtr <- ContT $ withForeignPtr a+ incaPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incbPtr <- Call.cint 1+ liftIO $ sequence_ $ take m $+ zipWith+ (\akPtr bkPtr ->+ Private.gbmv transPtr+ nPtr nPtr klPtr kuPtr alphaPtr xPtr ldxPtr+ akPtr incaPtr betaPtr bkPtr incbPtr)+ (pointerSeq n aPtr)+ (pointerSeq n bPtr)++scaleColumns ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Class.Floating a) =>+ Vector width a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+scaleColumns x = transpose . scaleRows x . transpose
+ src/Numeric/LAPACK/Matrix/Divide.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE UndecidableInstances #-}+module Numeric.LAPACK.Matrix.Divide where++import qualified Numeric.LAPACK.Matrix.Square.Linear+ as Square+import qualified Numeric.LAPACK.Matrix.Triangular.Linear+ as Triangular+import qualified Numeric.LAPACK.Matrix.Hermitian.Linear+ as Hermitian+import qualified Numeric.LAPACK.Matrix.Banded.Linear+ as Banded+import qualified Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite.Linear+ as BandedHermitianPositiveDefinite++import qualified Numeric.LAPACK.Matrix.Basic as Basic+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Shape.Private (HeightOf)+import Numeric.LAPACK.Matrix.Extent.Private (Small)+import Numeric.LAPACK.Matrix.Private (Full)+import Numeric.LAPACK.Vector (Vector)++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary as Unary++import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)+++class (Shape.C shape) => Solve shape where+ solve ::+ (Class.Floating a, HeightOf shape ~ height, Eq height,+ Extent.C horiz, Extent.C vert, Shape.C nrhs) =>+ Array shape a ->+ Full vert horiz height nrhs a -> Full vert horiz height nrhs a++class (Solve shape) => Inverse shape where+ inverse :: (Class.Floating a) => Array shape a -> Array shape a++solveVector ::+ (Solve shape, HeightOf shape ~ height, Eq height, Class.Floating a) =>+ Array shape a -> Vector height a -> Vector height a+solveVector m =+ Basic.flattenColumn . solve m . Basic.singleColumn MatrixShape.ColumnMajor+++instance+ (vert ~ Small, horiz ~ Small,+ Shape.C width, Shape.C height, height ~ width) =>+ Solve (MatrixShape.Full vert horiz height width) where+ solve = Square.solve++instance+ (vert ~ Small, horiz ~ Small,+ Shape.C width, Shape.C height, height ~ width) =>+ Inverse (MatrixShape.Full vert horiz height width) where+ inverse = Square.inverse+++instance (Shape.C shape) => Solve (MatrixShape.Hermitian shape) where+ solve = Hermitian.solve++instance (Shape.C shape) => Inverse (MatrixShape.Hermitian shape) where+ inverse = Hermitian.inverse+++instance+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag, Shape.C shape) =>+ Solve (MatrixShape.Triangular lo diag up shape) where+ solve = Triangular.solve++instance+ (MatrixShape.DiagUpLo lo up,+ MatrixShape.TriDiag diag, Shape.C shape) =>+ Inverse (MatrixShape.Triangular lo diag up shape) where+ inverse = Triangular.inverse+++instance+ (Unary.Natural sub, Unary.Natural super, vert ~ Small, horiz ~ Small,+ Shape.C width, Shape.C height, width ~ height) =>+ Solve (MatrixShape.Banded sub super vert horiz height width) where+ solve = Banded.solve+++{- |+There is no solver for indefinite matrices.+Thus the instance will fail for indefinite but solvable systems.+-}+instance+ (Unary.Natural offDiag, Shape.C size) =>+ Solve (MatrixShape.BandedHermitian offDiag size) where+ solve = BandedHermitianPositiveDefinite.solve
+ src/Numeric/LAPACK/Matrix/Extent.hs view
@@ -0,0 +1,41 @@+module Numeric.LAPACK.Matrix.Extent (+ Extent.C(switchTag),+ Extent.Extent,+ Map,+ Small, Big,+ Extent.height,+ Extent.width,+ Extent.squareSize,+ Extent.dimensions,+ Extent.transpose,+ Extent.fuse,++ Extent.square,++ toGeneral,+ fromSquare,+ fromSquareLiberal,+ generalizeTall,+ generalizeWide,+ ) where++import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Extent.Private (C, Small, Big, Map(Map))+++toGeneral ::+ (C vert, C horiz) => Map vert horiz Big Big height width+toGeneral = Map Extent.toGeneral++fromSquare :: (C vert, C horiz) => Map Small Small vert horiz size size+fromSquare = Map Extent.fromSquare++fromSquareLiberal ::+ (C vert, C horiz) => Map Small Small vert horiz height width+fromSquareLiberal = Map Extent.fromSquareLiberal++generalizeTall :: (C vert, C horiz) => Map vert Small vert horiz height width+generalizeTall = Map Extent.generalizeTall++generalizeWide :: (C vert, C horiz) => Map Small horiz vert horiz height width+generalizeWide = Map Extent.generalizeWide
+ src/Numeric/LAPACK/Matrix/Extent/Kind.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GADTs #-}+module Numeric.LAPACK.Matrix.Extent.Kind where+++data General height width =+ General {+ generalHeight :: height,+ generalWidth :: width+ } deriving (Eq, Show)++data Tall height width =+ Tall {+ tallHeight :: height,+ tallWidth :: width+ } deriving (Eq, Show)++data Wide height width =+ Wide {+ wideHeight :: height,+ wideWidth :: width+ } deriving (Eq, Show)++data Square height width =+ (height ~ width) =>+ Square {+ squareSize :: height+ }++instance (Eq height, Eq width) => Eq (Square height width) where+ Square a == Square b = a==b++instance (Show height, Show width) => Show (Square height width) where+ showsPrec p (Square s) =+ showParen (p>10) (showString "Square " . showsPrec 11 s)
+ src/Numeric/LAPACK/Matrix/Extent/Private.hs view
@@ -0,0 +1,480 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GADTs #-}+module Numeric.LAPACK.Matrix.Extent.Private where++import qualified Numeric.LAPACK.Matrix.Extent.Kind as EK+import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip))++import Control.DeepSeq (NFData, rnf)++import Data.Maybe.HT (toMaybe)+import Data.Tuple.HT (swap)+import Data.Eq.HT (equating)+++data Extent vertical horizontal height width =+ Extent {+ extentDir :: (vertical,horizontal),+ extentDim :: Dimensions vertical horizontal height width+ }++instance+ (C vertical, C horizontal, NFData height, NFData width) =>+ NFData (Extent vertical horizontal height width) where+ rnf =+ getAccessor $+ switchTagPair+ (Accessor $ \(Extent o (EK.Square s)) -> rnf (o,s))+ (Accessor $ \(Extent o (EK.Wide h w)) -> rnf (o,(h,w)))+ (Accessor $ \(Extent o (EK.Tall h w)) -> rnf (o,(h,w)))+ (Accessor $ \(Extent o (EK.General h w)) -> rnf (o,(h,w)))+++data Big = Big deriving (Eq,Show)+data Small = Small deriving (Eq,Show)++instance NFData Big where rnf Big = ()+instance NFData Small where rnf Small = ()++type General = Extent Big Big+type Tall = Extent Big Small+type Wide = Extent Small Big+type Square sh = Extent Small Small sh sh+++type family Dimensions vertical horizontal :: * -> * -> *++type instance Dimensions Big Big = EK.General+type instance Dimensions Big Small = EK.Tall+type instance Dimensions Small Big = EK.Wide+type instance Dimensions Small Small = EK.Square+++general :: height -> width -> General height width+general h w = Extent (Big,Big) $ EK.General h w++tall :: height -> width -> Tall height width+tall h w = Extent (Big,Small) $ EK.Tall h w++wide :: height -> width -> Wide height width+wide h w = Extent (Small,Big) $ EK.Wide h w++square :: sh -> Square sh+square sh = Extent (Small,Small) $ EK.Square sh+++newtype Map vertA horizA vertB horizB height width =+ Map {+ apply ::+ Extent vertA horizA height width ->+ Extent vertB horizB height width+ }+++class C tag where switchTag :: f Small -> f Big -> f tag+instance C Small where switchTag f _ = f+instance C Big where switchTag _ f = f+++switchTagPair ::+ (C vert, C horiz) =>+ f Small Small -> f Small Big -> f Big Small -> f Big Big -> f vert horiz+switchTagPair fSquare fWide fTall fGeneral =+ getFlip $+ switchTag+ (Flip $ switchTag fSquare fWide)+ (Flip $ switchTag fTall fGeneral)+++newtype CaseTallWide height width vert horiz =+ CaseTallWide {+ getCaseTallWide ::+ Extent vert horiz height width ->+ Either (Tall height width) (Wide height width)+ }++caseTallWide ::+ (C vert, C horiz) =>+ (height -> width -> Bool) ->+ Extent vert horiz height width ->+ Either (Tall height width) (Wide height width)+caseTallWide ge =+ getCaseTallWide $+ switchTagPair+ (CaseTallWide $ \(Extent _ (EK.Square sh)) -> Left $ tall sh sh)+ (CaseTallWide Right)+ (CaseTallWide Left)+ (CaseTallWide $ \(Extent _ (EK.General h w)) ->+ if ge h w+ then Left $ tall h w+ else Right $ wide h w)+++newtype GenSquare sh vert horiz =+ GenSquare {getGenSquare :: sh -> Extent vert horiz sh sh}++genSquare :: (C vert, C horiz) => sh -> Extent vert horiz sh sh+genSquare =+ getGenSquare $+ switchTagPair+ (GenSquare square)+ (GenSquare (\sh -> wide sh sh))+ (GenSquare (\sh -> tall sh sh))+ (GenSquare (\sh -> general sh sh))++newtype GenTall height width vert horiz =+ GenTall {+ getGenTall ::+ Extent vert Small height width -> Extent vert horiz height width+ }++generalizeTall :: (C vert, C horiz) =>+ Extent vert Small height width -> Extent vert horiz height width+generalizeTall =+ getGenTall $+ switchTagPair+ (GenTall id) (GenTall $ \(Extent _ (EK.Square s)) -> wide s s)+ (GenTall id) (GenTall $ \(Extent _ (EK.Tall h w)) -> general h w)++newtype GenWide height width vert horiz =+ GenWide {+ getGenWide ::+ Extent Small horiz height width -> Extent vert horiz height width+ }++generalizeWide :: (C vert, C horiz) =>+ Extent Small horiz height width -> Extent vert horiz height width+generalizeWide =+ getGenWide $+ switchTagPair+ (GenWide id)+ (GenWide id)+ (GenWide $ \(Extent _ (EK.Square s)) -> tall s s)+ (GenWide $ \(Extent _ (EK.Wide h w)) -> general h w)+++newtype GenToTall height width vert horiz =+ GenToTall {+ getGenToTall ::+ Extent vert horiz height width -> Extent Big horiz height width+ }++genToTall :: (C vert, C horiz) =>+ Extent vert horiz height width -> Extent Big horiz height width+genToTall =+ getGenToTall $+ switchTagPair+ (GenToTall $ \(Extent _ (EK.Square s)) -> tall s s)+ (GenToTall $ \(Extent _ (EK.Wide h w)) -> general h w)+ (GenToTall id)+ (GenToTall id)+++newtype GenToWide height width vert horiz =+ GenToWide {+ getGenToWide ::+ Extent vert horiz height width -> Extent vert Big height width+ }++genToWide :: (C vert, C horiz) =>+ Extent vert horiz height width -> Extent vert Big height width+genToWide =+ getGenToWide $+ switchTagPair+ (GenToWide $ \(Extent _ (EK.Square s)) -> wide s s)+ (GenToWide id)+ (GenToWide $ \(Extent _ (EK.Tall h w)) -> general h w)+ (GenToWide id)+++squareSize :: Square sh -> sh+squareSize (Extent (Small,Small) (EK.Square sh)) = sh+++newtype Accessor a height width vert horiz =+ Accessor {getAccessor :: Extent vert horiz height width -> a}++height :: (C vert, C horiz) => Extent vert horiz height width -> height+height =+ getAccessor $+ switchTagPair+ (Accessor (\(Extent _ (EK.Square s)) -> s))+ (Accessor (EK.wideHeight . extentDim))+ (Accessor (EK.tallHeight . extentDim))+ (Accessor (EK.generalHeight . extentDim))++width :: (C vert, C horiz) => Extent vert horiz height width -> width+width =+ getAccessor $+ switchTagPair+ (Accessor (\(Extent _ (EK.Square s)) -> s))+ (Accessor (EK.wideWidth . extentDim))+ (Accessor (EK.tallWidth . extentDim))+ (Accessor (EK.generalWidth . extentDim))+++dimensions ::+ (C vert, C horiz) => Extent vert horiz height width -> (height,width)+dimensions x = (height x, width x)+++toGeneral ::+ (C vert, C horiz) => Extent vert horiz height width -> General height width+toGeneral x = general (height x) (width x)++fromSquare :: (C vert, C horiz) => Square size -> Extent vert horiz size size+fromSquare = genSquare . squareSize++fromSquareLiberal :: (C vert, C horiz) =>+ Extent Small Small height width -> Extent vert horiz height width+fromSquareLiberal x@(Extent _ (EK.Square _)) = genSquare $ height x++squareFromGeneral ::+ (C vert, C horiz, Eq size) =>+ Extent vert horiz size size -> Square size+squareFromGeneral x =+ let size = height x+ in if size == width x+ then square size+ else error "Extent.squareFromGeneral: no square shape"+++newtype Transpose height width vert horiz =+ Transpose {+ getTranspose ::+ Extent vert horiz height width ->+ Extent horiz vert width height+ }++transpose ::+ (C vert, C horiz) =>+ Extent vert horiz height width ->+ Extent horiz vert width height+transpose =+ getTranspose $+ switchTagPair+ (Transpose $ \(Extent o (EK.Square s)) -> Extent o (EK.Square s))+ (Transpose $ \(Extent o (EK.Wide h w)) -> Extent (swap o) (EK.Tall w h))+ (Transpose $ \(Extent o (EK.Tall h w)) -> Extent (swap o) (EK.Wide w h))+ (Transpose $ \(Extent o (EK.General h w)) -> Extent o (EK.General w h))+++newtype Equal height width vert horiz =+ Equal {+ getEqual ::+ Extent vert horiz height width ->+ Extent vert horiz height width -> Bool+ }++instance+ (C vert, C horiz, Eq height, Eq width) =>+ Eq (Extent vert horiz height width) where+ (==) =+ getEqual $+ switchTagPair+ (Equal $ equating extentDim)+ (Equal $ equating extentDim)+ (Equal $ equating extentDim)+ (Equal $ equating extentDim)+++instance+ (C vert, C horiz, Show height, Show width) =>+ Show (Extent vert horiz height width) where+ showsPrec prec =+ getAccessor $+ switchTagPair+ (Accessor $ showsPrecSquare prec)+ (Accessor $ showsPrecAny "Extent.wide" prec)+ (Accessor $ showsPrecAny "Extent.tall" prec)+ (Accessor $ showsPrecAny "Extent.general" prec)++showsPrecSquare ::+ (Show height) =>+ Int -> Extent Small Small height width -> ShowS+showsPrecSquare p x =+ showParen (p>10) $+ showString "Extent.square " . showsPrec 11 (height x)++showsPrecAny ::+ (C vert, C horiz, Show height, Show width) =>+ String -> Int -> Extent vert horiz height width -> ShowS+showsPrecAny name p x =+ showParen (p>10) $+ showString name .+ showString " " . showsPrec 11 (height x) .+ showString " " . showsPrec 11 (width x)+++newtype Widen heightA widthA heightB widthB vert =+ Widen {+ getWiden ::+ Extent vert Big heightA widthA ->+ Extent vert Big heightB widthB+ }++widen ::+ (C vert) =>+ widthB -> Extent vert Big height widthA -> Extent vert Big height widthB+widen w =+ getWiden $+ switchTag+ (Widen (\(Extent o x) -> Extent o (x{EK.wideWidth = w})))+ (Widen (\(Extent o x) -> Extent o (x{EK.generalWidth = w})))++reduceWideHeight ::+ (C vert) =>+ heightB -> Extent vert Big heightA width -> Extent vert Big heightB width+reduceWideHeight h =+ getWiden $+ switchTag+ (Widen (\(Extent o x) -> Extent o (x{EK.wideHeight = h})))+ (Widen (\(Extent o x) -> Extent o (x{EK.generalHeight = h})))+++newtype Adapt height width vert horiz =+ Adapt {+ getAdapt ::+ Extent vert horiz height width ->+ Extent vert horiz height width+ }++reduceConsistent ::+ (C vert, C horiz) =>+ height -> width ->+ Extent vert horiz height width -> Extent vert horiz height width+reduceConsistent h w =+ getAdapt $+ switchTagPair+ (Adapt $ \(Extent o (EK.Square _)) -> Extent o (EK.Square h))+ (Adapt $ \(Extent o (EK.Wide _ _)) -> Extent o (EK.Wide h w))+ (Adapt $ \(Extent o (EK.Tall _ _)) -> Extent o (EK.Tall h w))+ (Adapt $ \(Extent o (EK.General _ _)) -> Extent o (EK.General h w))+++newtype Fuse height fuse width vert horiz =+ Fuse {+ getFuse ::+ Extent vert horiz height fuse ->+ Extent vert horiz fuse width ->+ Maybe (Extent vert horiz height width)+ }++fuse ::+ (C vert, C horiz, Eq fuse) =>+ Extent vert horiz height fuse ->+ Extent vert horiz fuse width ->+ Maybe (Extent vert horiz height width)+fuse =+ getFuse $+ switchTagPair+ (Fuse $+ \(Extent o (EK.Square s0)) (Extent _ (EK.Square s1)) ->+ toMaybe (s0==s1) $ Extent o (EK.Square s0))+ (Fuse $+ \(Extent o (EK.Wide h f0)) (Extent _ (EK.Wide f1 w)) ->+ toMaybe (f0==f1) $ Extent o (EK.Wide h w))+ (Fuse $+ \(Extent o (EK.Tall h f0)) (Extent _ (EK.Tall f1 w)) ->+ toMaybe (f0==f1) $ Extent o (EK.Tall h w))+ (Fuse $+ \(Extent o (EK.General h f0)) (Extent _ (EK.General f1 w)) ->+ toMaybe (f0==f1) $ Extent o (EK.General h w))+++type family Multiply a b+type instance Multiply Small b = b+type instance Multiply Big b = Big+++data TagFact a = C a => TagFact++newtype MultiplyTagLaw b a =+ MultiplyTagLaw {+ getMultiplyTagLaw :: TagFact a -> TagFact b -> TagFact (Multiply a b)+ }++multiplyTagLaw :: TagFact a -> TagFact b -> TagFact (Multiply a b)+multiplyTagLaw a@TagFact =+ ($a) $ getMultiplyTagLaw $+ switchTag+ (MultiplyTagLaw $ flip const)+ (MultiplyTagLaw const)++heightFact :: (C vert) => Extent vert horiz height width -> TagFact vert+heightFact _ = TagFact++widthFact :: (C horiz) => Extent vert horiz height width -> TagFact horiz+widthFact _ = TagFact+++newtype Unify height fuse width heightC widthC vertB horizB vertA horizA =+ Unify {+ getUnify ::+ Extent vertA horizA height fuse ->+ Extent vertB horizB fuse width ->+ Extent (Multiply vertA vertB) (Multiply horizA horizB) heightC widthC+ }++unifyLeft ::+ (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+unifyLeft =+ getUnify $+ switchTagPair+ (Unify $ const . fromSquareLiberal)+ (Unify $ const . generalizeWide)+ (Unify $ const . generalizeTall)+ (Unify $ const . toGeneral)++unifyRight ::+ (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+unifyRight =+ getUnify $+ switchTagPair+ (Unify $ const id)+ (Unify $ const genToWide)+ (Unify $ const genToTall)+ (Unify $ const toGeneral)+++{-+Square Square -> Square+Square Wide -> Wide+Square Tall -> Tall+Square General -> General+Wide Square -> Wide+Wide Wide -> Wide+Wide Tall -> General+Wide General -> General+Tall Square -> Tall+Tall Wide -> General+Tall Tall -> Tall+Tall General -> General+General Square -> General+General Wide -> General+General Tall -> General+General General -> General++Small Small Small Small -> Small Small+Small Small Small Big -> Small Big+Small Small Big Small -> Big Small+Small Small Big Big -> Big Big+Small Big Small Small -> Small Big+Small Big Small Big -> Small Big+Small Big Big Small -> Big Big+Small Big Big Big -> Big Big+Big Small Small Small -> Big Small+Big Small Small Big -> Big Big+Big Small Big Small -> Big Small+Big Small Big Big -> Big Big+Big Big Small Small -> Big Big+Big Big Small Big -> Big Big+Big Big Big Small -> Big Big+Big Big Big Big -> Big Big+-}
src/Numeric/LAPACK/Matrix/Hermitian.hs view
@@ -1,540 +1,34 @@ {-# LANGUAGE TypeFamilies #-} module Numeric.LAPACK.Matrix.Hermitian (- Hermitian,- fromList,- autoFromList,- identity,- diagonal,- getDiagonal,-- multiplyVector,- square,- multiplySquareLeft,- multiplyGeneralLeft,- multiplySquareRight,- multiplyGeneralRight,- outer,- sumRank1,- sumRank2,+ module Numeric.LAPACK.Matrix.Hermitian.Basic,+ module Numeric.LAPACK.Matrix.Hermitian.Linear, - toSquare,- covariance,- addTransposed,+ eigenvalues,+ eigensystem, ) where -import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Numeric.LAPACK.Matrix.Triangular.Private- (forPointers, pack, unpack, unpackToTemp,- diagonalPointers, rowMajorPointers, columnMajorPointers)-import Numeric.LAPACK.Matrix.Shape.Private- (Order(RowMajor,ColumnMajor), flipOrder, uploFromOrder)-import Numeric.LAPACK.Matrix.Square (Square)-import Numeric.LAPACK.Matrix.Private (General, ZeroInt, zeroInt)+import qualified Numeric.LAPACK.Matrix.Hermitian.Eigen as Eigen+import Numeric.LAPACK.Matrix.Hermitian.Basic+import Numeric.LAPACK.Matrix.Hermitian.Linear++import Numeric.LAPACK.Matrix.Private (Square) import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private- (RealOf, fill, zero, one, lacgv, fromReal, realPart, copyToTemp)+import Numeric.LAPACK.Scalar (RealOf) -import qualified Numeric.LAPACK.FFI.Complex as LapackComplex-import qualified Numeric.BLAS.FFI.Generic as BlasGen-import qualified Numeric.BLAS.FFI.Complex as BlasComplex-import qualified Numeric.BLAS.FFI.Real as BlasReal-import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class -import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array)) -import Foreign.C.Types (CInt, CChar)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (Storable, poke, peek) -import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)-import Control.Monad (when)--import qualified Data.NonEmpty as NonEmpty-import Data.Foldable (forM_)-import Data.Complex (Complex)---type Hermitian sh = Array (MatrixShape.Hermitian sh)---fromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Hermitian sh a-fromList order sh =- Array.fromList (MatrixShape.Hermitian order sh)--autoFromList :: (Storable a) => Order -> [a] -> Hermitian ZeroInt a-autoFromList order xs =- fromList order- (zeroInt $ MatrixShape.triangleExtent "Hermitian.autoFromList" $- length xs)- xs---identity :: (Shape.C sh, Class.Floating a) => Order -> sh -> Hermitian sh a-identity order sh =- Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $- \triSize aPtr -> do- fill zero triSize aPtr- mapM_ (flip poke one . snd) $- diagonalPointers order (Shape.size sh) aPtr aPtr--diagonal ::- (Shape.C sh, Class.Floating a) =>- Order -> Vector sh (RealOf a) -> Hermitian sh a-diagonal order =- runDiagonal $- Class.switchFloating- (Diagonal $ diagonalAux order) (Diagonal $ diagonalAux order)- (Diagonal $ diagonalAux order) (Diagonal $ diagonalAux order)--newtype Diagonal sh a =- Diagonal {runDiagonal :: Vector sh (RealOf a) -> Hermitian sh a}--diagonalAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Order -> Vector sh ar -> Hermitian sh a-diagonalAux order (Array sh x) =- Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $- \triSize aPtr -> do- fill zero triSize aPtr- withForeignPtr x $ \xPtr ->- forM_ (diagonalPointers order (Shape.size sh) xPtr aPtr) $- \(srcPtr,dstPtr) -> poke dstPtr . fromReal =<< peek srcPtr---getDiagonal ::+eigenvalues :: (Shape.C sh, Class.Floating a) => Hermitian sh a -> Vector sh (RealOf a)-getDiagonal =- runGetDiagonal $- Class.switchFloating- (GetDiagonal $ getDiagonalAux) (GetDiagonal $ getDiagonalAux)- (GetDiagonal $ getDiagonalAux) (GetDiagonal $ getDiagonalAux)--newtype GetDiagonal sh a =- GetDiagonal {runGetDiagonal :: Hermitian sh a -> Vector sh (RealOf a)}--getDiagonalAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>- Hermitian sh a -> Vector sh ar-getDiagonalAux (Array (MatrixShape.Hermitian order sh) a) =- Array.unsafeCreateWithSize sh $ \n xPtr ->- withForeignPtr a $ \aPtr ->- forM_ (diagonalPointers order n xPtr aPtr) $- \(dstPtr,srcPtr) -> poke dstPtr . realPart =<< peek srcPtr---multiplyVector ::- (Shape.C sh, Eq sh, Class.Floating a) =>- Hermitian sh a -> Vector sh a -> Vector sh a-multiplyVector (Array (MatrixShape.Hermitian order shA) a) (Array shX x) =- Array.unsafeCreateWithSize shX $ \n yPtr -> do- Call.assert "Hermitian.multiplyVector: width shapes mismatch" (shA == shX)- evalContT $ do- uploPtr <- Call.char $ uploFromOrder order- nPtr <- Call.cint n- alphaPtr <- Call.number one- aPtr <- ContT $ withForeignPtr a- xPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- betaPtr <- Call.number zero- incyPtr <- Call.cint 1- liftIO $- BlasGen.hpmv- uploPtr nPtr alphaPtr aPtr xPtr incxPtr betaPtr yPtr incyPtr---square ::- (Shape.C sh, Eq sh, Class.Floating a) =>- Hermitian sh a -> Hermitian sh a-square- (Array shape@(MatrixShape.Hermitian order sh) a) =- Array.unsafeCreate shape $ \cpPtr -> do- let n = Shape.size sh- evalContT $ do- sidePtr <- Call.char 'L'- uploPtr <- Call.char 'U'- nPtr <- Call.cint n- let ldPtr = nPtr- bPtr <- unpackToTemp (unpackFull order) n a- cPtr <- Call.allocaArray (n*n)- alphaPtr <- Call.number one- betaPtr <- Call.number zero- liftIO $ do- BlasGen.hemm sidePtr uploPtr- nPtr nPtr alphaPtr bPtr ldPtr- bPtr ldPtr betaPtr cPtr ldPtr- pack order n cPtr cpPtr---multiplySquareLeft ::- (Shape.C sh, Eq sh, Class.Floating a) =>- Square sh a -> Hermitian sh a -> Square sh a-multiplySquareLeft- (Array shapeB@(MatrixShape.Square orderB shB) b)- (Array (MatrixShape.Hermitian orderA shA) a) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Hermitian.multiplySquareLeft: shapes mismatch" (shA == shB)- let n = Shape.size shB- multiplyAux True orderA n a (flipOrder orderB) n b cPtr--multiplyGeneralLeft ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- General height width a -> Hermitian width a -> General height width a-multiplyGeneralLeft- (Array shapeB@(MatrixShape.General orderB height width) b)- (Array (MatrixShape.Hermitian orderA shA) a) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Hermitian.multiplyGeneralLeft: shapes mismatch" (shA == width)- multiplyAux True- orderA (Shape.size width) a (flipOrder orderB) (Shape.size height) b cPtr--multiplySquareRight ::- (Shape.C sh, Eq sh, Class.Floating a) =>- Hermitian sh a -> Square sh a -> Square sh a-multiplySquareRight- (Array (MatrixShape.Hermitian orderA shA) a)- (Array shapeB@(MatrixShape.Square orderB shB) b) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Hermitian.multiplySquareRight: shapes mismatch" (shA == shB)- let n = Shape.size shB- multiplyAux False orderA n a orderB n b cPtr--multiplyGeneralRight ::- (Shape.C height, Eq height, Shape.C width, Class.Floating a) =>- Hermitian height a -> General height width a -> General height width a-multiplyGeneralRight- (Array (MatrixShape.Hermitian orderA shA) a)- (Array shapeB@(MatrixShape.General orderB height width) b) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Hermitian.multiplyGeneralRight: shapes mismatch" (shA == height)- multiplyAux False- orderA (Shape.size height) a orderB (Shape.size width) b cPtr--multiplyAux ::- Class.Floating a =>- Bool ->- Order -> Int -> ForeignPtr a ->- Order -> Int -> ForeignPtr a -> Ptr a -> IO ()-multiplyAux extraConjugate orderA m0 a orderB n0 b cPtr = do- let size = m0*m0- evalContT $ do- let (side,(m,n)) =- case orderB of- ColumnMajor -> ('L',(m0,n0))- RowMajor -> ('R',(n0,m0))- sidePtr <- Call.char side- uploPtr <- Call.char $ uploFromOrder orderA- mPtr <- Call.cint m- nPtr <- Call.cint n- alphaPtr <- Call.number one- aPtr <- unpackToTemp (unpack orderA) m0 a- ldaPtr <- Call.cint m0- incaPtr <- Call.cint 1- sizePtr <- Call.cint size- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint m- betaPtr <- Call.number zero- ldcPtr <- Call.cint m- liftIO $ do- when ((orderA/=orderB) /= extraConjugate) $- lacgv sizePtr aPtr incaPtr- BlasGen.hemm sidePtr uploPtr- mPtr nPtr alphaPtr aPtr ldaPtr- bPtr ldbPtr betaPtr cPtr ldcPtr---outer :: (Shape.C sh, Class.Floating a) => Vector sh a -> Hermitian sh a-outer =- getMap $- Class.switchFloating- (Map outerAux) (Map outerAux)- (Map outerAux) (Map outerAux)--outerAux ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>- Vector sh a -> Hermitian sh a-outerAux (Array sh x) =- Array.unsafeCreateWithSize (MatrixShape.Hermitian ColumnMajor sh) $- \triSize aPtr -> do- let n = Shape.size sh- evalContT $ do- uploPtr <- Call.char $ uploFromOrder ColumnMajor- nPtr <- Call.cint n- alphaPtr <- Call.real one- xPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ fill zero triSize aPtr- liftIO $ hpr uploPtr nPtr alphaPtr xPtr incxPtr aPtr---sumRank1 ::- (Shape.C sh, Eq sh, Class.Floating a) =>- NonEmpty.T [] (RealOf a, Vector sh a) -> Hermitian sh a-sumRank1 =- getSumRank1 $- Class.switchFloating- (SumRank1 sumRank1Aux) (SumRank1 sumRank1Aux)- (SumRank1 sumRank1Aux) (SumRank1 sumRank1Aux)--type SumRank1_ sh a = NonEmpty.T [] (RealOf a, Vector sh a) -> Hermitian sh a--newtype SumRank1 sh a = SumRank1 {getSumRank1 :: SumRank1_ sh a}--sumRank1Aux ::- (Shape.C sh, Eq sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>- SumRank1_ sh a-sumRank1Aux xs@(NonEmpty.Cons (_, Array sh _) _) =- Array.unsafeCreateWithSize (MatrixShape.Hermitian ColumnMajor sh) $- \triSize aPtr -> do- let n = Shape.size sh- evalContT $ do- uploPtr <- Call.char $ uploFromOrder ColumnMajor- nPtr <- Call.cint n- alphaPtr <- Call.alloca- incxPtr <- Call.cint 1- liftIO $ do- fill zero triSize aPtr- forM_ xs $ \(alpha, Array shX x) ->- withForeignPtr x $ \xPtr -> do- Call.assert- "Hermitian.sumRank1: non-matching vector size" (sh==shX)- poke alphaPtr alpha- hpr uploPtr nPtr alphaPtr xPtr incxPtr aPtr---type HPR_ a =- Ptr CChar -> Ptr CInt ->- Ptr (RealOf a) -> Ptr a -> Ptr CInt -> Ptr a -> IO ()--newtype HPR a = HPR {getHPR :: HPR_ a}--hpr :: Class.Floating a => HPR_ a-hpr =- getHPR $- Class.switchFloating- (HPR BlasReal.spr) (HPR BlasReal.spr)- (HPR BlasComplex.hpr) (HPR BlasComplex.hpr)---sumRank2 ::- (Shape.C sh, Eq sh, Class.Floating a) =>- NonEmpty.T [] (a, (Vector sh a, Vector sh a)) -> Hermitian sh a-sumRank2 xys@(NonEmpty.Cons (_, (Array sh _, _)) _) =- Array.unsafeCreateWithSize (MatrixShape.Hermitian ColumnMajor sh) $- \triSize aPtr -> do- let n = Shape.size sh- evalContT $ do- uploPtr <- Call.char $ uploFromOrder ColumnMajor- nPtr <- Call.cint n- alphaPtr <- Call.alloca- incPtr <- Call.cint 1- liftIO $ do- fill zero triSize aPtr- forM_ xys $ \(alpha, (Array shX x, Array shY y)) ->- withForeignPtr x $ \xPtr ->- withForeignPtr y $ \yPtr -> do- Call.assert- "Hermitian.sumRank2: non-matching x vector size" (sh==shX)- Call.assert- "Hermitian.sumRank2: non-matching y vector size" (sh==shY)- poke alphaPtr alpha- BlasGen.hpr2 uploPtr nPtr alphaPtr xPtr incPtr yPtr incPtr aPtr---{--It is not strictly necessary to keep the 'order'.-It would be neither more complicated nor less efficient-to change the order via the conversion.--}-toSquare, _toSquare ::- (Shape.C sh, Class.Floating a) => Hermitian sh a -> Square sh a-_toSquare (Array (MatrixShape.Hermitian order sh) a) =- Array.unsafeCreate (MatrixShape.Square order sh) $ \bPtr ->- evalContT $ do- let n = Shape.size sh- aPtr <- ContT $ withForeignPtr a- conjPtr <- conjugateToTemp (MatrixShape.triangleSize n) a- liftIO $ do- unpack (flipOrder order) n conjPtr bPtr -- wrong- unpack order n aPtr bPtr--toSquare (Array (MatrixShape.Hermitian order sh) a) =- Array.unsafeCreate (MatrixShape.Square order sh) $ \bPtr ->- withForeignPtr a $ \aPtr ->- unpackFull order (Shape.size sh) aPtr bPtr---{- |-Make a temporary copy only for complex matrices.--}-conjugateToTemp ::- (Class.Floating a) => Int -> ForeignPtr a -> ContT r IO (Ptr a)-conjugateToTemp n =- runCopyToTemp $- Class.switchFloating- (CopyToTemp $ ContT . withForeignPtr)- (CopyToTemp $ ContT . withForeignPtr)- (CopyToTemp $ complexConjugateToTemp n)- (CopyToTemp $ complexConjugateToTemp n)--newtype CopyToTemp r a =- CopyToTemp {runCopyToTemp :: ForeignPtr a -> ContT r IO (Ptr a)}--complexConjugateToTemp ::- Class.Real a =>- Int -> ForeignPtr (Complex a) -> ContT r IO (Ptr (Complex a))-complexConjugateToTemp n x = do- nPtr <- Call.cint n- xPtr <- copyToTemp n x- incxPtr <- Call.cint 1- liftIO $ LapackComplex.lacgv nPtr xPtr incxPtr- return xPtr---{- |-A^H * A--}-covariance ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Hermitian width a-covariance =- getMap $- Class.switchFloating- (Map covarianceAux) (Map covarianceAux)- (Map covarianceAux) (Map covarianceAux)--newtype Map f g a = Map {getMap :: f a -> g a}--covarianceAux ::- (Shape.C height, Shape.C width,- Class.Floating a, RealOf a ~ ar, Class.Real ar) =>- General height width a -> Hermitian width a-covarianceAux (Array (MatrixShape.General order height width) a) =- Array.unsafeCreate (MatrixShape.Hermitian order width) $ \bPtr -> do- let n = Shape.size width- let k = Shape.size height- evalContT $ do- nPtr <- Call.cint n- kPtr <- Call.cint k- alphaPtr <- Call.number one- aPtr <- ContT $ withForeignPtr a- betaPtr <- Call.number zero- cPtr <- Call.allocaArray (n*n)- ldcPtr <- Call.cint n-- case order of- ColumnMajor -> do- uploPtr <- Call.char 'U'- transPtr <- Call.char 'C'- ldaPtr <- Call.cint k- liftIO $ do- herk uploPtr transPtr- nPtr kPtr alphaPtr aPtr ldaPtr betaPtr cPtr ldcPtr- pack ColumnMajor n cPtr bPtr-- RowMajor -> do- uploPtr <- Call.char 'L'- transPtr <- Call.char 'N'- ldaPtr <- Call.cint n- liftIO $ do- herk uploPtr transPtr- nPtr kPtr alphaPtr aPtr ldaPtr betaPtr cPtr ldcPtr- pack RowMajor n cPtr bPtr---type HERK_ a =- Ptr CChar -> Ptr CChar -> Ptr CInt -> Ptr CInt -> Ptr (RealOf a) -> Ptr a ->- Ptr CInt -> Ptr (RealOf a) -> Ptr a -> Ptr CInt -> IO ()--newtype HERK a = HERK {getHERK :: HERK_ a}--herk :: Class.Floating a => HERK_ a-herk =- getHERK $- Class.switchFloating- (HERK BlasReal.syrk)- (HERK BlasReal.syrk)- (HERK BlasComplex.herk)- (HERK BlasComplex.herk)-+eigenvalues = Eigen.values {- |-A^H + A+For symmetric eigenvalue problems, @eigensystem@ and @schur@ coincide. -}-addTransposed, _addTransposed ::- (Shape.C sh, Class.Floating a) => Square sh a -> Hermitian sh a-_addTransposed (Array (MatrixShape.Square order sh) a) =- Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $ \bSize bPtr -> do- let n = Shape.size sh- evalContT $ do- alphaPtr <- Call.number one- incxPtr <- Call.cint 1- aPtr <- ContT $ withForeignPtr a- sizePtr <- Call.cint bSize- conjPtr <- Call.allocaArray bSize- liftIO $ do- pack order n aPtr bPtr- pack (flipOrder order) n aPtr conjPtr -- wrong- lacgv sizePtr conjPtr incxPtr- BlasGen.axpy sizePtr alphaPtr conjPtr incxPtr bPtr incxPtr--addTransposed (Array (MatrixShape.Square order sh) a) =- Array.unsafeCreate (MatrixShape.Hermitian order sh) $ \bPtr -> do- let n = Shape.size sh- evalContT $ do- alphaPtr <- Call.number one- incxPtr <- Call.cint 1- incnPtr <- Call.cint n- aPtr <- ContT $ withForeignPtr a- liftIO $ case order of- RowMajor ->- forPointers (rowMajorPointers n aPtr bPtr) $- \nPtr (srcPtr,dstPtr) -> do- BlasGen.copy nPtr srcPtr incnPtr dstPtr incxPtr- lacgv nPtr dstPtr incxPtr- BlasGen.axpy nPtr alphaPtr srcPtr incxPtr dstPtr incxPtr- ColumnMajor ->- forPointers (columnMajorPointers n aPtr bPtr) $- \nPtr ((srcRowPtr,srcColumnPtr),dstPtr) -> do- BlasGen.copy nPtr srcRowPtr incnPtr dstPtr incxPtr- lacgv nPtr dstPtr incxPtr- BlasGen.axpy nPtr alphaPtr srcColumnPtr incxPtr dstPtr incxPtr---unpackFull :: Class.Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()-unpackFull order n packedPtr fullPtr = evalContT $ do- incxPtr <- Call.cint 1- incyPtr <- Call.cint n- liftIO $ case order of- RowMajor ->- forPointers (rowMajorPointers n fullPtr packedPtr) $- \nPtr (dstPtr,srcPtr) -> do- BlasGen.copy nPtr srcPtr incxPtr dstPtr incyPtr- lacgv nPtr dstPtr incyPtr- BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr- ColumnMajor ->- forPointers (columnMajorPointers n fullPtr packedPtr) $- \nPtr ((dstRowPtr,dstColumnPtr),srcPtr) -> do- BlasGen.copy nPtr srcPtr incxPtr dstRowPtr incyPtr- lacgv nPtr dstRowPtr incyPtr- BlasGen.copy nPtr srcPtr incxPtr dstColumnPtr incxPtr--_pack :: Class.Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()-_pack order n fullPtr packedPtr =- evalContT $ do- incxPtr <- Call.cint 1- liftIO $- case order of- ColumnMajor ->- forPointers (columnMajorPointers n fullPtr packedPtr) $- \nPtr ((_,srcPtr),dstPtr) ->- BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr- RowMajor ->- forPointers (rowMajorPointers n fullPtr packedPtr) $- \nPtr (srcPtr,dstPtr) ->- BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr+eigensystem ::+ (Shape.C sh, Class.Floating a) =>+ Hermitian sh a -> (Square sh a, Vector sh (RealOf a))+eigensystem = Eigen.decompose
+ src/Numeric/LAPACK/Matrix/Hermitian/Basic.hs view
@@ -0,0 +1,460 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Hermitian.Basic (+ Hermitian,+ Transposition(..),+ fromList,+ autoFromList,+ identity,+ diagonal,+ takeDiagonal,++ multiplyVector,+ square,+ multiplyFull,+ outer,+ sumRank1, sumRank1NonEmpty,+ sumRank2, sumRank2NonEmpty,++ toSquare,+ covariance,+ addAdjoint,+ ) where++import qualified Numeric.LAPACK.Matrix.Symmetric.Private as Symmetric+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Hermitian.Private (Diagonal(..), TakeDiagonal(..))+import Numeric.LAPACK.Matrix.Triangular.Private+ (forPointers, pack, unpack, unpackToTemp,+ diagonalPointers, diagonalPointerPairs,+ rowMajorPointers, columnMajorPointers)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), flipOrder, sideSwapFromOrder,+ uploFromOrder)+import Numeric.LAPACK.Matrix.Private+ (Full, General, argGeneral, Square, argSquare, ZeroInt, zeroInt,+ Transposition(NonTransposed, Transposed), transposeOrder,+ Conjugation(Conjugated))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, zero, one, fromReal, realPart)+import Numeric.LAPACK.Private+ (fill, lacgv, copyConjugate, conjugateToTemp, condConjugateToTemp)++import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.BLAS.FFI.Complex as BlasComplex+import qualified Numeric.BLAS.FFI.Real as BlasReal+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.C.Types (CInt, CChar)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable, poke, peek)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (when)++import qualified Data.NonEmpty as NonEmpty+import Data.Foldable (forM_)+++type Hermitian sh = Array (MatrixShape.Hermitian sh)+++fromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Hermitian sh a+fromList order sh =+ Array.fromList (MatrixShape.Hermitian order sh)++autoFromList :: (Storable a) => Order -> [a] -> Hermitian ZeroInt a+autoFromList order xs =+ fromList order+ (zeroInt $ MatrixShape.triangleExtent "Hermitian.autoFromList" $+ length xs)+ xs+++identity :: (Shape.C sh, Class.Floating a) => Order -> sh -> Hermitian sh a+identity order sh =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $+ \triSize aPtr -> do+ fill zero triSize aPtr+ mapM_ (flip poke one) $ diagonalPointers order (Shape.size sh) aPtr++diagonal ::+ (Shape.C sh, Class.Floating a) =>+ Order -> Vector sh (RealOf a) -> Hermitian sh a+diagonal order =+ runDiagonal $+ Class.switchFloating+ (Diagonal $ diagonalAux order) (Diagonal $ diagonalAux order)+ (Diagonal $ diagonalAux order) (Diagonal $ diagonalAux order)++diagonalAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Order -> Vector sh ar -> Hermitian sh a+diagonalAux order (Array sh x) =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $+ \triSize aPtr -> do+ fill zero triSize aPtr+ withForeignPtr x $ \xPtr ->+ forM_ (diagonalPointerPairs order (Shape.size sh) xPtr aPtr) $+ \(srcPtr,dstPtr) -> poke dstPtr . fromReal =<< peek srcPtr+++takeDiagonal ::+ (Shape.C sh, Class.Floating a) =>+ Hermitian sh a -> Vector sh (RealOf a)+takeDiagonal =+ runTakeDiagonal $+ Class.switchFloating+ (TakeDiagonal takeDiagonalAux) (TakeDiagonal takeDiagonalAux)+ (TakeDiagonal takeDiagonalAux) (TakeDiagonal takeDiagonalAux)++takeDiagonalAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Hermitian sh a -> Vector sh ar+takeDiagonalAux (Array (MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreateWithSize sh $ \n xPtr ->+ withForeignPtr a $ \aPtr ->+ forM_ (diagonalPointerPairs order n xPtr aPtr) $+ \(dstPtr,srcPtr) -> poke dstPtr . realPart =<< peek srcPtr+++multiplyVector ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Transposition -> Hermitian sh a -> Vector sh a -> Vector sh a+multiplyVector transposed+ (Array (MatrixShape.Hermitian order shA) a) (Array shX x) =+ Array.unsafeCreateWithSize shX $ \n yPtr -> do+ Call.assert "Hermitian.multiplyVector: width shapes mismatch" (shA == shX)+ evalContT $ do+ let conj = transposeOrder transposed order == RowMajor+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint n+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ xPtr <- condConjugateToTemp conj n x+ incxPtr <- Call.cint 1+ betaPtr <- Call.number zero+ incyPtr <- Call.cint 1+ liftIO $ do+ BlasGen.hpmv+ uploPtr nPtr alphaPtr aPtr xPtr incxPtr betaPtr yPtr incyPtr+ when conj $ lacgv nPtr yPtr incyPtr+++square ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Hermitian sh a -> Hermitian sh a+square (Array shape@(MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreate shape $+ Symmetric.square Conjugated order (Shape.size sh) a+++multiplyFull ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width,+ Class.Floating a) =>+ Transposition -> Hermitian height a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+multiplyFull transposed+ (Array (MatrixShape.Hermitian orderA shA) a)+ (Array shapeB@(MatrixShape.Full orderB extentB) b) =+ Array.unsafeCreate shapeB $ \cPtr -> do+ let (height,width) = Extent.dimensions extentB+ Call.assert "Hermitian.multiplyFull: shapes mismatch" (shA == height)+ let m0 = Shape.size height+ let n0 = Shape.size width+ let size = m0*m0+ evalContT $ do+ let (side,(m,n)) = sideSwapFromOrder orderB (m0,n0)+ sidePtr <- Call.char side+ uploPtr <- Call.char $ uploFromOrder orderA+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ alphaPtr <- Call.number one+ aPtr <- unpackToTemp (unpack orderA) m0 a+ ldaPtr <- Call.leadingDim m0+ incaPtr <- Call.cint 1+ sizePtr <- Call.cint size+ bPtr <- ContT $ withForeignPtr b+ ldbPtr <- Call.leadingDim m+ betaPtr <- Call.number zero+ ldcPtr <- Call.leadingDim m+ liftIO $ do+ when (transposeOrder transposed orderA /= orderB) $+ lacgv sizePtr aPtr incaPtr+ BlasGen.hemm sidePtr uploPtr+ mPtr nPtr alphaPtr aPtr ldaPtr+ bPtr ldbPtr betaPtr cPtr ldcPtr++++withConjBuffer ::+ (Shape.C sh, Class.Floating a) =>+ Order -> sh -> Int -> Ptr a ->+ (Ptr CChar -> Ptr CInt -> Ptr CInt -> IO ()) -> ContT r IO ()+withConjBuffer order sh triSize aPtr act = do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint $ Shape.size sh+ incxPtr <- Call.cint 1+ sizePtr <- Call.cint triSize+ liftIO $ do+ fill zero triSize aPtr+ act uploPtr nPtr incxPtr+ case order of+ RowMajor -> lacgv sizePtr aPtr incxPtr+ ColumnMajor -> return ()++outer ::+ (Shape.C sh, Class.Floating a) => Order -> Vector sh a -> Hermitian sh a+outer order =+ getMap $+ Class.switchFloating+ (Map $ outerAux order) (Map $ outerAux order)+ (Map $ outerAux order) (Map $ outerAux order)++outerAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> Vector sh a -> Hermitian sh a+outerAux order (Array sh x) =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $+ \triSize aPtr ->+ evalContT $ do+ alphaPtr <- Call.real one+ xPtr <- ContT $ withForeignPtr x+ withConjBuffer order sh triSize aPtr $ \uploPtr nPtr incxPtr ->+ hpr uploPtr nPtr alphaPtr xPtr incxPtr aPtr+++sumRank1 ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Order -> sh -> [(RealOf a, Vector sh a)] -> Hermitian sh a+sumRank1 =+ getSumRank1 $+ Class.switchFloating+ (SumRank1 sumRank1Aux) (SumRank1 sumRank1Aux)+ (SumRank1 sumRank1Aux) (SumRank1 sumRank1Aux)++type SumRank1_ sh ar a = Order -> sh -> [(ar, Vector sh a)] -> Hermitian sh a++newtype SumRank1 sh a = SumRank1 {getSumRank1 :: SumRank1_ sh (RealOf a) a}++sumRank1Aux ::+ (Shape.C sh, Eq sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ SumRank1_ sh ar a+sumRank1Aux order sh xs =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $+ \triSize aPtr ->+ evalContT $ do+ alphaPtr <- Call.alloca+ withConjBuffer order sh triSize aPtr $ \uploPtr nPtr incxPtr ->+ forM_ xs $ \(alpha, Array shX x) ->+ withForeignPtr x $ \xPtr -> do+ Call.assert+ "Hermitian.sumRank1: non-matching vector size" (sh==shX)+ poke alphaPtr alpha+ hpr uploPtr nPtr alphaPtr xPtr incxPtr aPtr+++sumRank1NonEmpty ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Order -> NonEmpty.T [] (RealOf a, Vector sh a) -> Hermitian sh a+sumRank1NonEmpty order (NonEmpty.Cons x xs) =+ sumRank1 order (Array.shape $ snd x) (x:xs)+++type HPR_ a =+ Ptr CChar -> Ptr CInt ->+ Ptr (RealOf a) -> Ptr a -> Ptr CInt -> Ptr a -> IO ()++newtype HPR a = HPR {getHPR :: HPR_ a}++hpr :: Class.Floating a => HPR_ a+hpr =+ getHPR $+ Class.switchFloating+ (HPR BlasReal.spr) (HPR BlasReal.spr)+ (HPR BlasComplex.hpr) (HPR BlasComplex.hpr)+++sumRank2 ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Order -> sh -> [(a, (Vector sh a, Vector sh a))] -> Hermitian sh a+sumRank2 order sh xys =+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $+ \triSize aPtr ->+ evalContT $ do+ alphaPtr <- Call.alloca+ withConjBuffer order sh triSize aPtr $ \uploPtr nPtr incPtr ->+ forM_ xys $ \(alpha, (Array shX x, Array shY y)) ->+ withForeignPtr x $ \xPtr ->+ withForeignPtr y $ \yPtr -> do+ Call.assert+ "Hermitian.sumRank2: non-matching x vector size" (sh==shX)+ Call.assert+ "Hermitian.sumRank2: non-matching y vector size" (sh==shY)+ poke alphaPtr alpha+ BlasGen.hpr2 uploPtr nPtr alphaPtr xPtr incPtr yPtr incPtr aPtr++sumRank2NonEmpty ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Order -> NonEmpty.T [] (a, (Vector sh a, Vector sh a)) -> Hermitian sh a+sumRank2NonEmpty order (NonEmpty.Cons xy xys) =+ sumRank2 order (Array.shape $ fst $ snd xy) (xy:xys)+++{-+It is not strictly necessary to keep the 'order'.+It would be neither more complicated nor less efficient+to change the order via the conversion.+-}+toSquare, _toSquare ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> Square sh a+_toSquare (Array (MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreate (MatrixShape.square order sh) $ \bPtr ->+ evalContT $ do+ let n = Shape.size sh+ aPtr <- ContT $ withForeignPtr a+ conjPtr <- conjugateToTemp (MatrixShape.triangleSize n) a+ liftIO $ do+ unpack (flipOrder order) n conjPtr bPtr -- wrong+ unpack order n aPtr bPtr++toSquare (Array (MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreate (MatrixShape.square order sh) $ \bPtr ->+ withForeignPtr a $ \aPtr ->+ Symmetric.unpack Conjugated order (Shape.size sh) aPtr bPtr+++{- |+A^H * A+-}+covariance ::+ (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>+ General height width a -> Hermitian width a+covariance =+ getMap $+ Class.switchFloating+ (Map covarianceAux) (Map covarianceAux)+ (Map covarianceAux) (Map covarianceAux)++newtype Map f g a = Map {getMap :: f a -> g a}++covarianceAux ::+ (Shape.C height, Shape.C width, Eq width,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General height width a -> Hermitian width a+covarianceAux = argGeneral $ \order height width a ->+ Array.unsafeCreate (MatrixShape.Hermitian order width) $ \bPtr -> do++ let n = Shape.size width+ let k = Shape.size height+ evalContT $ do+ nPtr <- Call.cint n+ kPtr <- Call.cint k+ alphaPtr <- Call.number one+ aPtr <- ContT $ withForeignPtr a+ betaPtr <- Call.number zero+ cPtr <- Call.allocaArray (n*n)+ ldcPtr <- Call.leadingDim n++ case order of+ ColumnMajor -> do+ uploPtr <- Call.char 'U'+ transPtr <- Call.char 'C'+ ldaPtr <- Call.leadingDim k+ liftIO $ do+ herk uploPtr transPtr+ nPtr kPtr alphaPtr aPtr ldaPtr betaPtr cPtr ldcPtr+ pack ColumnMajor n cPtr bPtr++ RowMajor -> do+ uploPtr <- Call.char 'L'+ transPtr <- Call.char 'N'+ ldaPtr <- Call.leadingDim n+ liftIO $ do+ herk uploPtr transPtr+ nPtr kPtr alphaPtr aPtr ldaPtr betaPtr cPtr ldcPtr+ pack RowMajor n cPtr bPtr+++type HERK_ a =+ Ptr CChar -> Ptr CChar -> Ptr CInt -> Ptr CInt -> Ptr (RealOf a) -> Ptr a ->+ Ptr CInt -> Ptr (RealOf a) -> Ptr a -> Ptr CInt -> IO ()++newtype HERK a = HERK {getHERK :: HERK_ a}++herk :: Class.Floating a => HERK_ a+herk =+ getHERK $+ Class.switchFloating+ (HERK BlasReal.syrk)+ (HERK BlasReal.syrk)+ (HERK BlasComplex.herk)+ (HERK BlasComplex.herk)+++{- |+A^H + A+-}+addAdjoint, _addAdjoint ::+ (Shape.C sh, Class.Floating a) => Square sh a -> Hermitian sh a+_addAdjoint =+ argSquare $ \order sh a ->+ Array.unsafeCreateWithSize (MatrixShape.Hermitian order sh) $ \bSize bPtr -> do+ let n = Shape.size sh+ evalContT $ do+ alphaPtr <- Call.number one+ incxPtr <- Call.cint 1+ aPtr <- ContT $ withForeignPtr a+ sizePtr <- Call.cint bSize+ conjPtr <- Call.allocaArray bSize+ liftIO $ do+ pack order n aPtr bPtr+ pack (flipOrder order) n aPtr conjPtr -- wrong+ lacgv sizePtr conjPtr incxPtr+ BlasGen.axpy sizePtr alphaPtr conjPtr incxPtr bPtr incxPtr++addAdjoint =+ argSquare $ \order sh a ->+ Array.unsafeCreate (MatrixShape.Hermitian order sh) $ \bPtr -> do+ let n = Shape.size sh+ evalContT $ do+ alphaPtr <- Call.number one+ incxPtr <- Call.cint 1+ incnPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ liftIO $ case order of+ RowMajor ->+ forPointers (rowMajorPointers n aPtr bPtr) $+ \nPtr (srcPtr,dstPtr) -> do+ copyConjugate nPtr srcPtr incnPtr dstPtr incxPtr+ BlasGen.axpy nPtr alphaPtr srcPtr incxPtr dstPtr incxPtr+ ColumnMajor ->+ forPointers (columnMajorPointers n aPtr bPtr) $+ \nPtr ((srcRowPtr,srcColumnPtr),dstPtr) -> do+ copyConjugate nPtr srcRowPtr incnPtr dstPtr incxPtr+ BlasGen.axpy nPtr alphaPtr srcColumnPtr incxPtr dstPtr incxPtr+++_pack :: Class.Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()+_pack order n fullPtr packedPtr =+ evalContT $ do+ incxPtr <- Call.cint 1+ liftIO $+ case order of+ ColumnMajor ->+ forPointers (columnMajorPointers n fullPtr packedPtr) $+ \nPtr ((_,srcPtr),dstPtr) ->+ BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr+ RowMajor ->+ forPointers (rowMajorPointers n fullPtr packedPtr) $+ \nPtr (srcPtr,dstPtr) ->+ BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr
+ src/Numeric/LAPACK/Matrix/Hermitian/Eigen.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Hermitian.Eigen (+ values,+ decompose,+ ) where++import Numeric.LAPACK.Matrix.Hermitian.Basic (Hermitian)+import Numeric.LAPACK.Matrix.Square.Basic (Square)++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import Numeric.LAPACK.Matrix.Hermitian.Private (TakeDiagonal(..))+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), uploFromOrder, triangleSize)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf)+import Numeric.LAPACK.Private+ (copyToTemp, copyCondConjugateToTemp, withInfo, eigenMsg)++import qualified Numeric.LAPACK.FFI.Complex as LapackComplex+import qualified Numeric.LAPACK.FFI.Real as LapackReal+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.C.Types (CInt, CChar)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable)++import Control.Monad.Trans.Cont (evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Complex (Complex)+++values ::+ (Shape.C sh, Class.Floating a) =>+ Hermitian sh a -> Vector sh (RealOf a)+values =+ runTakeDiagonal $+ Class.switchFloating+ (TakeDiagonal valuesAux) (TakeDiagonal valuesAux)+ (TakeDiagonal valuesAux) (TakeDiagonal valuesAux)++valuesAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Hermitian sh a -> Vector sh ar+valuesAux (Array (MatrixShape.Hermitian order size) a) =+ Array.unsafeCreateWithSize size $ \n wPtr ->+ evalContT $ do+ jobzPtr <- Call.char 'N'+ uploPtr <- Call.char $ uploFromOrder order+ aPtr <- copyToTemp (triangleSize n) a+ let zPtr = nullPtr+ ldzPtr <- Call.leadingDim n+ liftIO $ withInfo eigenMsg "hpev" $+ hpev jobzPtr uploPtr n aPtr wPtr zPtr ldzPtr+++decompose ::+ (Shape.C sh, Class.Floating a) =>+ Hermitian sh a -> (Square sh a, Vector sh (RealOf a))+decompose =+ getDecompose $+ Class.switchFloating+ (Decompose decomposeAux) (Decompose decomposeAux)+ (Decompose decomposeAux) (Decompose decomposeAux)++type Decompose_ sh a = Hermitian sh a -> (Square sh a, Vector sh (RealOf a))++newtype Decompose sh a = Decompose {getDecompose :: Decompose_ sh a}++decomposeAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Decompose_ sh a+decomposeAux (Array (MatrixShape.Hermitian order size) a) =+ Array.unsafeCreateWithSizeAndResult (MatrixShape.square ColumnMajor size) $+ \_ zPtr ->+ ArrayIO.unsafeCreateWithSize size $ \n wPtr ->+ evalContT $ do+ jobzPtr <- Call.char 'V'+ uploPtr <- Call.char $ uploFromOrder order+ aPtr <- copyCondConjugateToTemp (order==RowMajor) (triangleSize n) a+ ldzPtr <- Call.leadingDim n+ liftIO $ withInfo eigenMsg "hpev" $+ hpev jobzPtr uploPtr n aPtr wPtr zPtr ldzPtr+++type HPEV_ ar a =+ Ptr CChar -> Ptr CChar -> Int -> Ptr a -> Ptr ar ->+ Ptr a -> Ptr CInt -> Ptr CInt -> IO ()++newtype HPEV a = HPEV {getHPEV :: HPEV_ (RealOf a) a}++hpev :: Class.Floating a => HPEV_ (RealOf a) a+hpev =+ getHPEV $+ Class.switchFloating+ (HPEV spevReal) (HPEV spevReal) (HPEV hpevComplex) (HPEV hpevComplex)++spevReal :: Class.Real a => HPEV_ a a+spevReal jobzPtr uploPtr n apPtr wPtr zPtr ldzPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray (3*n)+ liftIO $+ LapackReal.spev+ jobzPtr uploPtr nPtr apPtr wPtr zPtr ldzPtr workPtr infoPtr++hpevComplex :: Class.Real a => HPEV_ a (Complex a)+hpevComplex jobzPtr uploPtr n apPtr wPtr zPtr ldzPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray (max 1 (2*n-1))+ rworkPtr <- Call.allocaArray (max 1 (3*n-2))+ liftIO $+ LapackComplex.hpev+ jobzPtr uploPtr nPtr apPtr wPtr zPtr ldzPtr workPtr rworkPtr infoPtr
+ src/Numeric/LAPACK/Matrix/Hermitian/Linear.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Hermitian.Linear (+ solve,+ inverse,+ determinant,+ ) where++import Numeric.LAPACK.Matrix.Hermitian.Basic (Hermitian)+import Numeric.LAPACK.Matrix.Private (Full)++import qualified Numeric.LAPACK.Matrix.Symmetric.Private as Symmetric+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Hermitian.Private (Determinant(..))+import Numeric.LAPACK.Matrix.Private (Conjugation(Conjugated))+import Numeric.LAPACK.Scalar (RealOf, absoluteSquared)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import System.IO.Unsafe (unsafePerformIO)++import Foreign.Ptr (Ptr, castPtr)+import Foreign.Storable (peek)+++solve ::+ (Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Hermitian sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solve (Array (MatrixShape.Hermitian orderA shA) a) =+ Symmetric.solve "Hermitian.solve" Conjugated orderA shA a+++inverse ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> Hermitian sh a+inverse (Array shape@(MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreateWithSize shape $+ Symmetric.inverse Conjugated order (Shape.size sh) a+++determinant ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> RealOf a+determinant =+ getDeterminant $+ Class.switchFloating+ (Determinant determinantAux) (Determinant determinantAux)+ (Determinant determinantAux) (Determinant determinantAux)++determinantAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian sh a -> ar+determinantAux (Array (MatrixShape.Hermitian order sh) a) =+ unsafePerformIO $+ Symmetric.determinant Conjugated+ peekBlockDeterminant order (Shape.size sh) a++peekBlockDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar+peekBlockDeterminant (a0Ptr,ext) = do+ let peekReal = peek . castPtr+ a0 <- peekReal a0Ptr+ case ext of+ Nothing -> return a0+ Just (a1Ptr,bPtr) -> do+ a1 <- peekReal a1Ptr+ b <- peek bPtr+ return (a0*a1 - absoluteSquared b)
+ src/Numeric/LAPACK/Matrix/Hermitian/Private.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Hermitian.Private where++import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf)+++newtype Diagonal f sh a =+ Diagonal {runDiagonal :: Vector sh (RealOf a) -> f a}++newtype TakeDiagonal f sh a =+ TakeDiagonal {runTakeDiagonal :: f a -> Vector sh (RealOf a)}++newtype Determinant f a = Determinant {getDeterminant :: f a -> RealOf a}
+ src/Numeric/LAPACK/Matrix/HermitianPositiveDefinite.hs view
@@ -0,0 +1,5 @@+module Numeric.LAPACK.Matrix.HermitianPositiveDefinite (+ module Numeric.LAPACK.Matrix.HermitianPositiveDefinite.Linear,+ ) where++import Numeric.LAPACK.Matrix.HermitianPositiveDefinite.Linear
+ src/Numeric/LAPACK/Matrix/HermitianPositiveDefinite/Linear.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.HermitianPositiveDefinite.Linear (+ solve,+ solveDecomposed,+ inverse,+ decompose,+ determinant,+ ) where++import Numeric.LAPACK.Matrix.Hermitian.Basic (Hermitian)+import Numeric.LAPACK.Matrix.Triangular.Basic (Upper, takeDiagonal)+import Numeric.LAPACK.Matrix.Private (Full)++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Hermitian.Private (Determinant(..))+import Numeric.LAPACK.Matrix.Triangular.Private (copyTriangleToTemp)+import Numeric.LAPACK.Matrix.Shape.Private+ (NonUnit(NonUnit), uploFromOrder, triangleSize)+import Numeric.LAPACK.Matrix.Private (Conjugation(Conjugated))+import Numeric.LAPACK.Linear.Private (solver)+import Numeric.LAPACK.Scalar (RealOf, realPart)+import Numeric.LAPACK.Private (copyBlock, withInfo, rankMsg, definiteMsg)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.ForeignPtr (withForeignPtr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++solve ::+ (Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Hermitian sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solve (Array (MatrixShape.Hermitian orderA shA) a) =+ solver "Hermitian.solve" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder orderA+ apPtr <- copyTriangleToTemp Conjugated orderA (triangleSize n) a+ liftIO $+ withInfo definiteMsg "ppsv" $+ LapackGen.ppsv uploPtr nPtr nrhsPtr apPtr xPtr ldxPtr++{- |+> solve a b == solveDecomposed (decompose a) b+> solve (covariance u) b == solveDecomposed u b+-}+solveDecomposed ::+ (Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Upper sh a -> Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solveDecomposed (Array (MatrixShape.Triangular NonUnit _uplo orderA shA) a) =+ solver "Hermitian.solveDecomposed" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder orderA+ apPtr <- copyTriangleToTemp Conjugated orderA (triangleSize n) a+ liftIO $+ withInfo rankMsg "pptrs" $+ LapackGen.pptrs uploPtr nPtr nrhsPtr apPtr xPtr ldxPtr+++inverse ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> Hermitian sh a+inverse+ (Array shape@(MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreateWithSize shape $ \triSize bPtr -> do+ evalContT $ do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint $ Shape.size sh+ aPtr <- ContT $ withForeignPtr a+ liftIO $ do+ copyBlock triSize aPtr bPtr+ withInfo definiteMsg "pptrf" $ LapackGen.pptrf uploPtr nPtr bPtr+ withInfo rankMsg "pptri" $ LapackGen.pptri uploPtr nPtr bPtr++{- |+Cholesky decomposition+-}+decompose ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> Upper sh a+decompose+ (Array (MatrixShape.Hermitian order sh) a) =+ Array.unsafeCreateWithSize+ (MatrixShape.Triangular NonUnit MatrixShape.upper order sh) $+ \triSize bPtr -> do+ evalContT $ do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint $ Shape.size sh+ aPtr <- ContT $ withForeignPtr a+ liftIO $ do+ copyBlock triSize aPtr bPtr+ withInfo definiteMsg "pptrf" $ LapackGen.pptrf uploPtr nPtr bPtr+++determinant ::+ (Shape.C sh, Class.Floating a) => Hermitian sh a -> RealOf a+determinant =+ getDeterminant $+ Class.switchFloating+ (Determinant determinantAux) (Determinant determinantAux)+ (Determinant determinantAux) (Determinant determinantAux)++determinantAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian sh a -> ar+determinantAux =+ (^(2::Int)) . product . map realPart . Array.toList . takeDiagonal . decompose
src/Numeric/LAPACK/Matrix/Multiply.hs view
@@ -1,24 +1,37 @@ {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE UndecidableInstances #-} module Numeric.LAPACK.Matrix.Multiply where import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Matrix.Triangular as Triangular-import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian-import qualified Numeric.LAPACK.Matrix.Square as Square-import qualified Numeric.LAPACK.Vector as Vector+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.Private as Private import Numeric.LAPACK.Matrix.Shape.Private- (HeightOf, WidthOf, Order(ColumnMajor), transposeFromOrder)-import Numeric.LAPACK.Matrix.Triangular (Triangular)-import Numeric.LAPACK.Matrix.Private (General)+ (HeightOf, WidthOf, Empty, Filled, Unit, NonUnit,+ Order(RowMajor,ColumnMajor), flipOrder, transposeFromOrder)+import Numeric.LAPACK.Matrix.Extent.Private (Small)+import Numeric.LAPACK.Matrix.Triangular.Basic (Triangular)+import Numeric.LAPACK.Matrix.Basic (transpose)+import Numeric.LAPACK.Matrix.Private+ (Square, Full, mapExtent,+ Transposition(NonTransposed, Transposed)) import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private (zero, one)+import Numeric.LAPACK.Scalar (zero, one) -import qualified Numeric.BLAS.FFI.Generic as BlasGen import qualified Numeric.Netlib.Utility as Call 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.Internal as Array import qualified Data.Array.Comfort.Shape as Shape import Data.Array.Comfort.Storable.Internal (Array(Array))@@ -29,24 +42,23 @@ import Control.Monad.IO.Class (liftIO) -transpose :: General height width a -> General width height a-transpose = Array.mapShape MatrixShape.transpose- multiplyVector ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- General height width a -> Vector width a -> Vector height a+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width, Eq width,+ Class.Floating a) =>+ Full vert horiz height width a -> Vector width a -> Vector height a multiplyVector a x =- let MatrixShape.General _order _height width = Array.shape a+ let width = MatrixShape.fullWidth $ Array.shape a in if width == Array.shape x then multiplyVectorUnchecked a x else error "multiplyVector: width shapes mismatch" multiplyVectorUnchecked ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> Vector width a -> Vector height a+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a -> Vector width a -> Vector height a multiplyVectorUnchecked- (Array shape@(MatrixShape.General order height _width) a) (Array _ x) =- Array.unsafeCreate height $ \yPtr -> do+ (Array shape@(MatrixShape.Full order extent) a) (Array _ x) =+ Array.unsafeCreate (Extent.height extent) $ \yPtr -> do let (m,n) = MatrixShape.dimensions shape let lda = m evalContT $ do@@ -55,274 +67,552 @@ nPtr <- Call.cint n alphaPtr <- Call.number one aPtr <- ContT $ withForeignPtr a- ldaPtr <- Call.cint lda+ ldaPtr <- Call.leadingDim lda xPtr <- ContT $ withForeignPtr x incxPtr <- Call.cint 1 betaPtr <- Call.number zero incyPtr <- Call.cint 1 liftIO $- BlasGen.gemv+ Private.gemv transPtr mPtr nPtr alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr -multiply ::- (Shape.C height,+{- |+Multiply two matrices with the same dimension constraints.+E.g. you can multiply 'General' and 'General' matrices,+or 'Square' and 'Square' matrices.+It may seem to be overly strict in this respect,+but that design supports type inference the best.+You can lift the restrictions by generalizing operands+with 'Square.toFull', 'Matrix.fromFull',+'Matrix.generalizeTall' or 'Matrix.generalizeWide'.+-}+multiply, multiplyColumnMajor ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C fuse, Eq fuse, Shape.C width, Class.Floating a) =>- General height fuse a -> General fuse width a -> General height width a+ Full vert horiz height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+-- preserve order of the right factor multiply- (Array (MatrixShape.General orderA height fuseA) a)- (Array (MatrixShape.General orderB fuseB width) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor height width) $- \cPtr -> do- Call.assert "multiply: fuse shapes mismatch" (fuseA == fuseB)- let m = Shape.size height- let n = Shape.size width- let k = Shape.size fuseA- Private.multiplyMatrix orderA orderB m k n a b cPtr+ (Array (MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ case Extent.fuse extentA extentB of+ Nothing -> error "multiply: fuse shapes mismatch"+ Just extent ->+ Array.unsafeCreate (MatrixShape.Full orderB extent) $ \cPtr -> do + let (height,fuse) = Extent.dimensions extentA+ let width = Extent.width extentB+ let m = Shape.size height+ let n = Shape.size width+ let k = Shape.size fuse+ case orderB of+ RowMajor ->+ Private.multiplyMatrix (flipOrder orderB) (flipOrder orderA)+ n k m b a cPtr+ ColumnMajor -> Private.multiplyMatrix orderA orderB m k n a b cPtr +-- always return ColumnMajor+multiplyColumnMajor+ (Array (MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ case Extent.fuse extentA extentB of+ Nothing -> error "multiply: fuse shapes mismatch"+ Just extent ->+ Array.unsafeCreate (MatrixShape.Full ColumnMajor extent) $ \cPtr -> do++ let (height,fuse) = Extent.dimensions extentA+ let width = Extent.width extentB+ let m = Shape.size height+ let n = Shape.size width+ let k = Shape.size fuse+ Private.multiplyMatrix orderA orderB m k n a b cPtr++ infixl 7 <#, <#> infixr 7 #> -class MultiplyRight shape where+class (Shape.C shape) => MultiplyRight shape where (#>) :: (Class.Floating a) =>- Array shape a -> Array (WidthOf shape) a -> Array (HeightOf shape) a+ Array shape a -> Vector (WidthOf shape) a -> Vector (HeightOf shape) a -class MultiplyLeft shape where+class (Shape.C shape) => MultiplyLeft shape where (<#) :: (Class.Floating a) =>- Array (HeightOf shape) a -> Array shape a -> Array (WidthOf shape) a--class Multiply shapeA shapeB where- type Multiplied shapeA shapeB- (<#>) ::- (Class.Floating a) =>- Array shapeA a -> Array shapeB a -> Array (Multiplied shapeA shapeB) a+ Vector (HeightOf shape) a -> Array shape a -> Vector (WidthOf shape) a instance- (Eq width, Shape.C width, Shape.C height) =>- MultiplyRight (MatrixShape.General height width) where+ (Extent.C vert, Extent.C horiz, Eq width, Shape.C width, Shape.C height) =>+ MultiplyRight (MatrixShape.Full vert horiz height width) where (#>) = multiplyVector instance- (Eq height, Shape.C width, Shape.C height) =>- MultiplyLeft (MatrixShape.General height width) where+ (Extent.C vert, Extent.C horiz, Eq height, Shape.C width, Shape.C height) =>+ MultiplyLeft (MatrixShape.Full vert horiz height width) where v <# m = multiplyVector (transpose m) v instance (Eq shape, Shape.C shape) =>- MultiplyRight (MatrixShape.Square shape) where- m #> v = multiplyVector (Square.toGeneral m) v+ MultiplyRight (MatrixShape.Hermitian shape) where+ (#>) = Hermitian.multiplyVector NonTransposed instance (Eq shape, Shape.C shape) =>- MultiplyLeft (MatrixShape.Square shape) where- v <# m = multiplyVector (transpose $ Square.toGeneral m) v+ MultiplyLeft (MatrixShape.Hermitian shape) where+ (<#) = flip $ Hermitian.multiplyVector Transposed instance- (Eq shape, Shape.C shape) =>- MultiplyRight (MatrixShape.Hermitian shape) where- m #> v = Hermitian.multiplyVector m v+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag, Eq shape, Shape.C shape) =>+ MultiplyRight (MatrixShape.Triangular lo diag up shape) where+ m #> v = Triangular.multiplyVector m v instance- (Eq shape, Shape.C shape) =>- MultiplyLeft (MatrixShape.Hermitian shape) where- v <# m = Hermitian.multiplyVector (Vector.conjugate m) v+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag, Eq shape, Shape.C shape) =>+ MultiplyLeft (MatrixShape.Triangular lo diag up shape) where+ v <# m = Triangular.multiplyVector (Triangular.transpose m) v instance- (MatrixShape.Uplo uplo, Eq shape, Shape.C shape) =>- MultiplyRight (MatrixShape.Triangular uplo shape) where- m #> v = Triangular.multiplyVectorRight m v+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Eq width, Shape.C width, Shape.C height) =>+ MultiplyRight (MatrixShape.Banded sub super vert horiz height width) where+ m #> v = Banded.multiplyVector m v instance- (MatrixShape.Uplo uplo, Eq shape, Shape.C shape) =>- MultiplyLeft (MatrixShape.Triangular uplo shape) where- v <# m = Triangular.multiplyVectorLeft m v+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Eq height, Shape.C width, Shape.C height) =>+ MultiplyLeft (MatrixShape.Banded sub super vert horiz height width) where+ v <# m = Banded.multiplyVector (Banded.transpose m) v instance+ (Unary.Natural offDiag, Shape.C size, Eq size) =>+ MultiplyRight (MatrixShape.BandedHermitian offDiag size) where+ (#>) = BandedHermitian.multiplyVector NonTransposed++instance+ (Unary.Natural offDiag, Shape.C size, Eq size) =>+ MultiplyLeft (MatrixShape.BandedHermitian offDiag size) where+ (<#) = flip $ BandedHermitian.multiplyVector Transposed+++{- |+This class allows to 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 '<#>' 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 'multiply' functions+from the various modules for production use.+Btw. 'MultiplyLeft' and 'MultiplyRight' are much less problematic,+because the input and output are always dense vectors.+-}+class (Shape.C shapeA, Shape.C shapeB) => Multiply shapeA shapeB where+ type Multiplied shapeA shapeB+ (<#>) ::+ (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) =>+ widthA ~ heightB, Eq heightB,+ Extent.C vertA, Extent.C horizA, Extent.C vertB, Extent.C horizB) => Multiply- (MatrixShape.General heightA widthA)- (MatrixShape.General heightB widthB) where+ (MatrixShape.Full vertA horizA heightA widthA)+ (MatrixShape.Full vertB horizB heightB widthB) where type Multiplied- (MatrixShape.General heightA widthA)- (MatrixShape.General heightB widthB) =- MatrixShape.General heightA widthB- (<#>) = multiply+ (MatrixShape.Full vertA horizA heightA widthA)+ (MatrixShape.Full vertB horizB heightB widthB) =+ MatrixShape.Full+ (ExtentPriv.Multiply vertA vertB)+ (ExtentPriv.Multiply horizA horizB)+ heightA widthB+ a <#> b =+ case unifyFactors (fullExtent a) (fullExtent b) of+ ((ExtentPriv.TagFact, ExtentPriv.TagFact), (unifyLeft, unifyRight)) ->+ multiply+ (mapExtent unifyLeft a)+ (mapExtent unifyRight b) +fullExtent ::+ Full vert horiz height width a ->+ Extent.Extent vert horiz height width+fullExtent = MatrixShape.fullExtent . 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 a b =+ ((ExtentPriv.multiplyTagLaw+ (ExtentPriv.heightFact a) (ExtentPriv.heightFact b),+ ExtentPriv.multiplyTagLaw+ (ExtentPriv.widthFact a) (ExtentPriv.widthFact b)),+ (ExtentPriv.Map $ flip ExtentPriv.unifyLeft b,+ ExtentPriv.Map $ ExtentPriv.unifyRight a))++ instance- (Shape.C shapeA, Shape.C widthB, shapeA ~ heightB, Eq heightB) =>+ (Extent.C vert, Extent.C horiz,+ Shape.C size, size ~ width, Eq width, Shape.C height) => Multiply- (MatrixShape.Square shapeA)- (MatrixShape.General heightB widthB) where+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.Hermitian size)+ where type Multiplied- (MatrixShape.Square shapeA)- (MatrixShape.General heightB widthB) =- MatrixShape.General heightB widthB- a <#> b = multiply (Square.toGeneral a) b+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.Hermitian size) =+ MatrixShape.Full vert horiz height width+ a <#> b = transpose $ Hermitian.multiplyFull Transposed b (transpose a) instance- (Shape.C heightA, Shape.C widthA, widthA ~ shapeB, Eq shapeB) =>+ (Extent.C vert, Extent.C horiz,+ Shape.C size, size ~ height, Eq height, Shape.C width) => Multiply- (MatrixShape.General heightA widthA)- (MatrixShape.Square shapeB) where+ (MatrixShape.Hermitian size)+ (MatrixShape.Full vert horiz height width)+ where type Multiplied- (MatrixShape.General heightA widthA)- (MatrixShape.Square shapeB) =- MatrixShape.General heightA widthA- a <#> b = multiply a (Square.toGeneral b)+ (MatrixShape.Hermitian size)+ (MatrixShape.Full vert horiz height width) =+ MatrixShape.Full vert horiz height width+ (<#>) = Hermitian.multiplyFull NonTransposed instance (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Square shapeA) (MatrixShape.Square shapeB) where- type Multiplied (MatrixShape.Square shapeA) (MatrixShape.Square shapeB) =+ Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB)+ where+ type Multiplied+ (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB) = MatrixShape.Square shapeA- (<#>) = Square.multiply+ a <#> b = Hermitian.multiplyFull NonTransposed a (Hermitian.toSquare b) instance- (Shape.C shapeA, shapeA ~ width, Eq width, Shape.C height) =>+ (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.General height width)- (MatrixShape.Hermitian shapeA)+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.Triangular lo diag up size) where type Multiplied- (MatrixShape.General height width) (MatrixShape.Hermitian shapeA) =- MatrixShape.General height width- (<#>) = Hermitian.multiplyGeneralLeft+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.Triangular lo diag up size) =+ MatrixShape.Full vert horiz height width+ a <#> b =+ transpose $ Triangular.multiplyFull (Triangular.transpose b) (transpose a) instance- (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Square shapeB) (MatrixShape.Hermitian shapeA)- where+ (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.Square shapeB) (MatrixShape.Hermitian shapeA) =- MatrixShape.Square shapeA- (<#>) = Hermitian.multiplySquareLeft+ (MatrixShape.Triangular lo diag up size)+ (MatrixShape.Full vert horiz height width) =+ MatrixShape.Full vert horiz height width+ (<#>) = Triangular.multiplyFull instance- (Shape.C shapeA, shapeA ~ height, Eq height, Shape.C width) =>+ (Shape.C sizeA, sizeA ~ sizeB, Eq sizeB,+ MultiplyTriangular loA upA loB upB,+ MatrixShape.TriDiag diagA, MatrixShape.TriDiag diagB) => Multiply- (MatrixShape.Hermitian shapeA)- (MatrixShape.General height width)- where+ (MatrixShape.Triangular loA diagA upA sizeA)+ (MatrixShape.Triangular loB diagB upB sizeB) where type Multiplied- (MatrixShape.Hermitian shapeA) (MatrixShape.General height width) =- MatrixShape.General height width- (<#>) = Hermitian.multiplyGeneralRight+ (MatrixShape.Triangular loA diagA upA sizeA)+ (MatrixShape.Triangular loB diagB upB sizeB) =+ -- requires UndecidableInstances+ MultipliedTriangular loA diagA upA loB diagB upB sizeB+ (<#>) = multiplyTriangular +class+ (MatrixShape.Content loA, MatrixShape.Content upA,+ MatrixShape.Content loB, MatrixShape.Content upB) =>+ MultiplyTriangular loA upA loB upB where+ multiplyTriangular ::+ (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+ multiplyTriangular = multiplyTriangularConform++instance MultiplyTriangular Empty Empty Filled Filled where+ multiplyTriangular a = Triangular.multiplyFull a . Triangular.toSquare++instance MultiplyTriangular Empty Filled Filled Filled where+ multiplyTriangular a = Triangular.multiplyFull a . Triangular.toSquare++instance MultiplyTriangular Filled Empty Filled Filled where+ multiplyTriangular a = Triangular.multiplyFull a . Triangular.toSquare++instance MultiplyTriangular Empty Filled Empty Filled where+ multiplyTriangular = multiplyTriangularConform++instance MultiplyTriangular Filled Empty Filled Empty where+ multiplyTriangular = multiplyTriangularConform++instance MultiplyTriangular Filled Empty Empty Filled where+ multiplyTriangular a = Triangular.multiplyFull a . Triangular.toSquare++instance MultiplyTriangular Empty Filled Filled Empty where+ multiplyTriangular a = Triangular.multiplyFull a . Triangular.toSquare++instance MultiplyTriangular Filled Filled Empty Empty where+ multiplyTriangular = multiplyTriangularToSquare++instance MultiplyTriangular Filled Filled Empty Filled where+ multiplyTriangular = multiplyTriangularToSquare++instance MultiplyTriangular Filled Filled Filled Empty where+ multiplyTriangular = multiplyTriangularToSquare++instance MultiplyTriangular Filled Filled Filled Filled where+ multiplyTriangular = multiplyTriangularToSquare++multiplyTriangularToSquare ::+ (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+multiplyTriangularToSquare a b =+ transpose $ Triangular.multiplyFull (Triangular.transpose b) $+ transpose $ Triangular.toSquare a+++newtype MultiplyTriangularConform lo up size a diagB diagA =+ MultiplyTriangularConform {+ getMultiplyTriangularConform ::+ Triangular lo diagA up size a ->+ Triangular lo diagB up size a ->+ Triangular lo (MultipliedDiag diagA diagB) up size a+ }++multiplyTriangularConform ::+ (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+multiplyTriangularConform =+ getMultiplyTriangularConform $+ MatrixShape.switchTriDiag+ (MultiplyTriangularConform $ \a b ->+ Triangular.multiply (Triangular.relaxUnitDiagonal a) b)+ (MultiplyTriangularConform $ \a b ->+ Triangular.multiply a (Triangular.strictNonUnitDiagonal b))++ instance- (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Square shapeB)- where+ (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.Hermitian shapeA) (MatrixShape.Square shapeB) =- MatrixShape.Square shapeA- (<#>) = Hermitian.multiplySquareRight+ (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+ a <#> b =+ case unifyFactors (fullExtent a) (bandedExtent b) of+ ((ExtentPriv.TagFact, ExtentPriv.TagFact), (unifyLeft, unifyRight)) ->+ transpose $+ Banded.multiplyFull+ (Banded.transpose $ Banded.mapExtent unifyRight b)+ (transpose $ mapExtent unifyLeft a) instance- (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Hermitian shapeA) (MatrixShape.Hermitian shapeB)- where+ (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.Hermitian shapeA) (MatrixShape.Hermitian shapeB) =- MatrixShape.Square shapeA- a <#> b = Hermitian.multiplySquareRight a (Hermitian.toSquare b)+ (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+ a <#> b =+ case unifyFactors (bandedExtent a) (fullExtent b) of+ ((ExtentPriv.TagFact, ExtentPriv.TagFact), (unifyLeft, unifyRight)) ->+ Banded.multiplyFull+ (Banded.mapExtent unifyLeft a)+ (mapExtent unifyRight 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+ a <#> b =+ case unifyFactors (bandedExtent a) (bandedExtent b) of+ ((ExtentPriv.TagFact, ExtentPriv.TagFact), (unifyLeft, unifyRight)) ->+ Banded.multiply+ (Banded.mapExtent unifyLeft a)+ (Banded.mapExtent unifyRight b) +bandedExtent ::+ Banded.Banded sup super vert horiz height width a ->+ Extent.Extent vert horiz height width+bandedExtent = MatrixShape.bandedExtent . Array.shape instance- (MatrixShape.Uplo uplo,- Shape.C shapeA, shapeA ~ width, Eq width, Shape.C height) =>+ (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,+ Shape.C size, size ~ width, Eq width, Shape.C height, Eq height) => Multiply- (MatrixShape.General height width)- (MatrixShape.Triangular uplo shapeA)+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.BandedHermitian offDiag size) where type Multiplied- (MatrixShape.General height width)- (MatrixShape.Triangular uplo shapeA) =- MatrixShape.General height width- (<#>) = Triangular.multiplyGeneralLeft+ (MatrixShape.Full vert horiz height width)+ (MatrixShape.BandedHermitian offDiag size) =+ MatrixShape.Full vert horiz height width+ a <#> b = transpose $ BandedHermitian.multiplyFull Transposed b (transpose a) instance- (MatrixShape.Uplo uplo, Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Square shapeB) (MatrixShape.Triangular uplo shapeA)- where+ (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.Square shapeB) (MatrixShape.Triangular uplo shapeA) =- MatrixShape.Square shapeA- (<#>) = Triangular.multiplySquareLeft+ (MatrixShape.BandedHermitian offDiag size)+ (MatrixShape.Full vert horiz height width) =+ MatrixShape.Full vert horiz height width+ (<#>) = BandedHermitian.multiplyFull NonTransposed instance- (MatrixShape.Uplo uplo,- Shape.C shapeA, shapeA ~ height, Eq height, Shape.C width) =>+ (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.Triangular uplo shapeA)- (MatrixShape.General height width)+ (MatrixShape.Banded sub super vert horiz height width)+ (MatrixShape.BandedHermitian offDiag size) where type Multiplied- (MatrixShape.Triangular uplo shapeA)- (MatrixShape.General height width) =- MatrixShape.General height width- (<#>) = Triangular.multiplyGeneralRight+ (MatrixShape.Banded sub super vert horiz height width)+ (MatrixShape.BandedHermitian offDiag size) =+ MatrixShape.Banded+ (sub:+:offDiag) (super:+:offDiag) vert horiz height width+ a <#> b =+ Banded.multiply+ a (Banded.mapExtent Extent.fromSquare (BandedHermitian.toBanded b)) instance- (MatrixShape.Uplo uplo, Shape.C shapeA, shapeA ~ shapeB, Eq shapeB) =>- Multiply (MatrixShape.Triangular uplo shapeA) (MatrixShape.Square shapeB)- where+ (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.Triangular uplo shapeA) (MatrixShape.Square shapeB) =- MatrixShape.Square shapeA- (<#>) = Triangular.multiplySquareRight+ (MatrixShape.BandedHermitian offDiag size)+ (MatrixShape.Banded sub super vert horiz height width) =+ MatrixShape.Banded+ (offDiag:+:sub) (offDiag:+:super) vert horiz height width+ a <#> b =+ Banded.multiply+ (Banded.mapExtent Extent.fromSquare (BandedHermitian.toBanded a)) b instance- (Shape.C shapeA, shapeA ~ shapeB, Eq shapeB,- MultiplyTriangular uploA uploB) =>+ (Unary.Natural offDiagA, Unary.Natural offDiagB,+ Shape.C sizeA, sizeA ~ sizeB, Shape.C sizeB, Eq sizeB) => Multiply- (MatrixShape.Triangular uploA shapeA)- (MatrixShape.Triangular uploB shapeB) where+ (MatrixShape.BandedHermitian offDiagA sizeA)+ (MatrixShape.BandedHermitian offDiagB sizeB)+ where type Multiplied- (MatrixShape.Triangular uploA shapeA)- (MatrixShape.Triangular uploB shapeB) =- MultipliedTriangular uploA uploB shapeB- (<#>) = multiplyTriangular--class MultiplyTriangular uploA uploB where- type MultipliedTriangular uploA uploB :: * -> *- multiplyTriangular ::- (Class.Floating a, Shape.C shape, Eq shape) =>- Triangular uploA shape a ->- Triangular uploB shape a ->- Array (MultipliedTriangular uploA uploB shape) a--instance MultiplyTriangular MatrixShape.Lower MatrixShape.Lower where- type MultipliedTriangular MatrixShape.Lower MatrixShape.Lower =- MatrixShape.Triangular MatrixShape.Lower- multiplyTriangular = Triangular.multiply--instance MultiplyTriangular MatrixShape.Upper MatrixShape.Upper where- type MultipliedTriangular MatrixShape.Upper MatrixShape.Upper =- MatrixShape.Triangular MatrixShape.Upper- multiplyTriangular = Triangular.multiply--instance MultiplyTriangular MatrixShape.Lower MatrixShape.Upper where- type MultipliedTriangular MatrixShape.Lower MatrixShape.Upper =- MatrixShape.Square- multiplyTriangular a b =- Square.multiply (Triangular.toSquare a) (Triangular.toSquare b)--instance MultiplyTriangular MatrixShape.Upper MatrixShape.Lower where- type MultipliedTriangular MatrixShape.Upper MatrixShape.Lower =- MatrixShape.Square- multiplyTriangular a b =- Square.multiply (Triangular.toSquare a) (Triangular.toSquare b)+ (MatrixShape.BandedHermitian offDiagA sizeA)+ (MatrixShape.BandedHermitian offDiagB sizeB) =+ MatrixShape.Banded+ (offDiagA:+:offDiagB) (offDiagA:+:offDiagB)+ Small Small sizeA sizeB+ a <#> b =+ Banded.multiply (BandedHermitian.toBanded a) (BandedHermitian.toBanded b)
src/Numeric/LAPACK/Matrix/Private.hs view
@@ -1,15 +1,90 @@ module Numeric.LAPACK.Matrix.Private where import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import Data.Array.Comfort.Storable (Array)+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import Numeric.LAPACK.Matrix.Shape.Private (Order, flipOrder) +import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array)) +import Foreign.ForeignPtr (ForeignPtr) ++type Full vert horiz height width =+ Array (MatrixShape.Full vert horiz height width)+ type General height width = Array (MatrixShape.General height width)+type Tall height width = Array (MatrixShape.Tall height width)+type Wide height width = Array (MatrixShape.Wide height width)+type Square sh = Array (MatrixShape.Square sh) +argGeneral ::+ (MatrixShape.Order -> height -> width -> ForeignPtr a -> b) ->+ (General height width a -> b)+argGeneral f (Array (MatrixShape.Full order extent) a) =+ f order (Extent.height extent) (Extent.width extent) a++argSquare ::+ (MatrixShape.Order -> sh -> ForeignPtr a -> b) -> (Square sh a -> b)+argSquare f (Array (MatrixShape.Full order extent) a) =+ f order (Extent.squareSize extent) a++ type ZeroInt = Shape.ZeroBased Int zeroInt :: Int -> ZeroInt zeroInt = Shape.ZeroBased+++mapExtent ::+ (Extent.C vertA, Extent.C horizA) =>+ (Extent.C vertB, Extent.C horizB) =>+ Extent.Map vertA horizA vertB horizB height width ->+ Full vertA horizA height width a -> Full vertB horizB height width a+mapExtent f = Array.mapShape $ MatrixShape.fullMapExtent f++fromFull ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert horiz height width a -> General height width a+fromFull = mapExtent Extent.toGeneral++generalizeTall ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert Extent.Small height width a -> Full vert horiz height width a+generalizeTall = mapExtent Extent.generalizeTall++generalizeWide ::+ (Extent.C vert, Extent.C horiz) =>+ Full Extent.Small horiz height width a -> Full vert horiz height width a+generalizeWide = mapExtent Extent.generalizeWide+++height ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert horiz height width a -> height+height = MatrixShape.fullHeight . Array.shape++width ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert horiz height width a -> width+width = MatrixShape.fullWidth . Array.shape+++data Transposition = NonTransposed | Transposed+ deriving (Eq, Show, Enum, Bounded)++transposeOrder :: Transposition -> Order -> Order+transposeOrder NonTransposed = id+transposeOrder Transposed = flipOrder++data Conjugation = NonConjugated | Conjugated+ deriving (Eq, Show, Enum, Bounded)++data Inversion = NonInverted | Inverted+ deriving (Eq, Show, Enum, Bounded)++flipInversion :: Inversion -> Inversion+flipInversion NonInverted = Inverted+flipInversion Inverted = NonInverted
src/Numeric/LAPACK/Matrix/Shape.hs view
@@ -1,5 +1,102 @@ module Numeric.LAPACK.Matrix.Shape ( General,+ Tall,+ Wide,+ Square,+ Full(..), fullHeight, fullWidth,+ Order(..), flipOrder,+ general,+ square,+ wide,+ tall,++ Split,+ SplitGeneral,+ Triangle(..),+ Reflector(..),+ splitGeneral,+ splitFromFull,++ Hermitian(..),+ hermitian,++ Triangular(..),+ Identity,+ Diagonal,+ LowerTriangular,+ UpperTriangular,+ Symmetric,+ diagonal,+ lowerTriangular,+ upperTriangular,+ symmetric,+ autoDiag,+ autoUplo,+ DiagUpLo,+ Unit(Unit),+ NonUnit(NonUnit),++ Banded(..),+ BandedGeneral,+ BandedSquare,+ BandedLowerTriangular,+ BandedUpperTriangular,+ BandedDiagonal,+ BandedIndex(..),+ bandedGeneral,+ bandedSquare,+ bandedFromFull,+ UnaryProxy,+ addOffDiagonals,+ TriDiag,+ switchTriDiag,+ Content,++ BandedHermitian(..),+ bandedHermitian, ) where +import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent import Numeric.LAPACK.Matrix.Shape.Private+++type SplitGeneral lower height width =+ Split lower Extent.Big Extent.Big height width++splitGeneral ::+ lower -> Order -> height -> width -> SplitGeneral lower height width+splitGeneral lowerPart order height width =+ Split lowerPart order $ Extent.general height width++splitFromFull ::+ lower ->+ Full vert horiz height width ->+ Split lower vert horiz height width+splitFromFull lowerPart (Full order extent) = Split lowerPart order extent+++diagonal :: Order -> size -> Triangular Empty NonUnit Empty size+diagonal = Triangular NonUnit autoUplo++lowerTriangular :: Order -> size -> LowerTriangular NonUnit size+lowerTriangular = Triangular NonUnit autoUplo++upperTriangular :: Order -> size -> UpperTriangular NonUnit size+upperTriangular = Triangular NonUnit autoUplo++symmetric :: Order -> size -> Symmetric size+symmetric = Triangular NonUnit autoUplo++hermitian :: Order -> size -> Hermitian size+hermitian = Hermitian+++bandedFromFull ::+ (UnaryProxy sub, UnaryProxy super) ->+ Full vert horiz height width ->+ Banded sub super vert horiz height width+bandedFromFull offDiag (Full order extent) = Banded offDiag order extent+++bandedHermitian :: UnaryProxy off -> Order -> size -> BandedHermitian off size+bandedHermitian = BandedHermitian
src/Numeric/LAPACK/Matrix/Shape/Private.hs view
@@ -1,327 +1,1011 @@ {-# LANGUAGE TypeFamilies #-}-module Numeric.LAPACK.Matrix.Shape.Private where--import qualified Data.Array.Comfort.Shape as Shape--import Control.Applicative (Const(Const, getConst))--import Data.Functor.Identity (Identity(Identity), runIdentity)-import Data.List (tails)-import Data.Tuple.HT (swap)---data Order = RowMajor | ColumnMajor- deriving (Eq, Show)--flipOrder :: Order -> Order-flipOrder RowMajor = ColumnMajor-flipOrder ColumnMajor = RowMajor--transposeFromOrder :: Order -> Char-transposeFromOrder RowMajor = 'T'-transposeFromOrder ColumnMajor = 'N'---type family HeightOf shape-type family WidthOf shape---data General height width =- General {- generalOrder :: Order,- generalHeight :: height,- generalWidth :: width- } deriving (Eq, Show)--type instance HeightOf (General height width) = height-type instance WidthOf (General height width) = width--instance (Shape.C height, Shape.C width) => Shape.C (General height width) where- type Index (General height width) = (Shape.Index height, Shape.Index width)- indices (General _ height width) = Shape.indices (height,width)-- offset (General RowMajor height width) =- Shape.offset (height,width)- offset (General ColumnMajor height width) =- Shape.offset (width,height) . swap- uncheckedOffset (General RowMajor height width) =- Shape.uncheckedOffset (height,width)- uncheckedOffset (General ColumnMajor height width) =- Shape.uncheckedOffset (width,height) . swap-- sizeOffset (General RowMajor height width) =- Shape.sizeOffset (height,width)- sizeOffset (General ColumnMajor height width) =- Shape.sizeOffset (width,height) . swap- uncheckedSizeOffset (General RowMajor height width) =- Shape.uncheckedSizeOffset (height,width)- uncheckedSizeOffset (General ColumnMajor height width) =- Shape.uncheckedSizeOffset (width,height) . swap-- inBounds (General _ height width) = Shape.inBounds (height,width)- size (General _ height width) = Shape.size (height,width)- uncheckedSize (General _ height width) = Shape.uncheckedSize (height,width)---transpose :: General height width -> General width height-transpose (General order height width) = General (flipOrder order) width height--dimensions ::- (Shape.C height, Shape.C width) => General height width -> (Int, Int)-dimensions (General order height width) =- case order of- RowMajor -> (Shape.size width, Shape.size height)- ColumnMajor -> (Shape.size height, Shape.size width)---data Square size =- Square {- squareOrder :: Order,- squareSize :: size- } deriving (Eq, Show)--type instance HeightOf (Square size) = size-type instance WidthOf (Square size) = size--generalFromSquare :: Square size -> General size size-generalFromSquare (Square order sh) = General order sh sh--transposeSquare :: Square sh -> Square sh-transposeSquare (Square order size) = Square (flipOrder order) size--instance (Shape.C size) => Shape.C (Square size) where- type Index (Square size) = (Shape.Index size, Shape.Index size)- indices (Square _ size) = Shape.indices (size,size)-- offset (Square RowMajor size) =- Shape.offset (size,size)- offset (Square ColumnMajor size) =- Shape.offset (size,size) . swap- uncheckedOffset (Square RowMajor size) =- Shape.uncheckedOffset (size,size)- uncheckedOffset (Square ColumnMajor size) =- Shape.uncheckedOffset (size,size) . swap-- sizeOffset (Square RowMajor size) =- Shape.sizeOffset (size,size)- sizeOffset (Square ColumnMajor size) =- Shape.sizeOffset (size,size) . swap- uncheckedSizeOffset (Square RowMajor size) =- Shape.uncheckedSizeOffset (size,size)- uncheckedSizeOffset (Square ColumnMajor size) =- Shape.uncheckedSizeOffset (size,size) . swap-- inBounds (Square _ size) = Shape.inBounds (size,size)- size (Square _ size) = Shape.size (size,size)- uncheckedSize (Square _ size) = Shape.uncheckedSize (size,size)---data Householder height width =- Householder {- householderOrder :: Order,- householderHeight :: height,- householderWidth :: width- } deriving (Eq, Show)--type instance HeightOf (Householder height width) = height-type instance WidthOf (Householder height width) = width--data Reflector = Reflector deriving (Eq)-data Triangle = Triangle deriving (Eq)--householderPart ::- (Shape.C height, Shape.C width) =>- Householder height width ->- (Shape.Index height, Shape.Index width) -> Either Reflector Triangle-householderPart (Householder _ height width) (r,c) =- if Shape.offset height r > Shape.offset width c- then Left Reflector- else Right Triangle--instance- (Shape.C height, Shape.C width) =>- Shape.C (Householder height width) where-- type Index (Householder height width) =- (Either Reflector Triangle,- (Shape.Index height, Shape.Index width))-- indices sh@(Householder _ height width) =- map (\ix -> (householderPart sh ix, ix)) $- Shape.indices (height,width)-- offset sh@(Householder order height width) (part,ix) =- if part == householderPart sh ix- then- case order of- RowMajor -> Shape.offset (height,width) ix- ColumnMajor -> Shape.offset (width,height) (swap ix)- else error "Shape.Householder.offset: wrong matrix part"- uncheckedOffset (Householder RowMajor height width) =- Shape.uncheckedOffset (height,width) . snd- uncheckedOffset (Householder ColumnMajor height width) =- Shape.uncheckedOffset (width,height) . swap . snd-- sizeOffset sh@(Householder order height width) (part,ix) =- if part == householderPart sh ix- then- case order of- RowMajor -> Shape.sizeOffset (height,width) ix- ColumnMajor -> Shape.sizeOffset (width,height) (swap ix)- else error "Shape.Householder.sizeOffset: wrong matrix part"- uncheckedSizeOffset (Householder RowMajor height width) =- Shape.uncheckedSizeOffset (height,width) . snd- uncheckedSizeOffset (Householder ColumnMajor height width) =- Shape.uncheckedSizeOffset (width,height) . swap . snd-- size (Householder _ height width) = Shape.size (height,width)- uncheckedSize (Householder _ height width) =- Shape.uncheckedSize (height,width)- inBounds sh@(Householder _ height width) (part,ix) =- Shape.inBounds (height,width) ix- &&- part == householderPart sh ix---{- |-Store the upper triangular half of a real symmetric or complex Hermitian matrix.--}-data Hermitian size =- Hermitian {- hermitianOrder :: Order,- hermitianSize :: size- } deriving (Eq, Show)--type instance HeightOf (Hermitian size) = size-type instance WidthOf (Hermitian size) = size--uploFromOrder :: Order -> Char-uploFromOrder RowMajor = 'L'-uploFromOrder ColumnMajor = 'U'--instance (Shape.C size) => Shape.C (Hermitian size) where- type Index (Hermitian size) = (Shape.Index size, Shape.Index size)-- indices (Hermitian _ size) =- let ixs = Shape.indices size- in concat $ zipWith (\r cs -> map ((,) r) cs) ixs $ tails ixs-- uncheckedOffset sh ix =- snd $ Shape.uncheckedSizeOffset sh ix-- sizeOffset sh ix =- if Shape.inBounds sh ix- then Shape.uncheckedSizeOffset sh ix- else error "Shape.Hermitian.sizeOffset: wrong matrix part"-- uncheckedSizeOffset (Hermitian RowMajor size) (rs,cs) =- let (s,r) = Shape.uncheckedSizeOffset size rs- c = Shape.uncheckedOffset size cs- in (s, triangleSize s - triangleSize (s-r) + c-r)- uncheckedSizeOffset (Hermitian ColumnMajor size) (rs,cs) =- let (s,r) = Shape.uncheckedSizeOffset size rs- c = Shape.uncheckedOffset size cs- in (s, triangleSize c + r)-- size (Hermitian _ size) = triangleSize $ Shape.size size- uncheckedSize (Hermitian _ size) = triangleSize $ Shape.uncheckedSize size- inBounds (Hermitian _ size) ix@(r,c) =- Shape.inBounds (size,size) ix- &&- Shape.offset size r <= Shape.offset size c---data Triangular uplo size =- Triangular {- triangularUplo :: uplo,- triangularOrder :: Order,- triangularSize :: size- } deriving (Eq, Show)--type instance HeightOf (Triangular uplo size) = size-type instance WidthOf (Triangular uplo size) = size--data Lower = Lower deriving (Eq, Show)-data Upper = Upper deriving (Eq, Show)--type LowerTriangular = Triangular Lower-type UpperTriangular = Triangular Upper--triangularTransposeUp :: LowerTriangular sh -> UpperTriangular sh-triangularTransposeUp (Triangular Lower order size) =- Triangular Upper (flipOrder order) size--triangularTransposeDown :: UpperTriangular sh -> LowerTriangular sh-triangularTransposeDown (Triangular Upper order size) =- Triangular Lower (flipOrder order) size---class Uplo uplo where switchUplo :: f Lower -> f Upper -> f uplo-instance Uplo Lower where switchUplo f _ = f-instance Uplo Upper where switchUplo _ f = f--autoUplo :: Uplo uplo => uplo-autoUplo = runIdentity $ switchUplo (Identity Lower) (Identity Upper)--uploOrder :: Uplo uplo => uplo -> Order -> Order-uploOrder uplo order = caseUplo uplo (flipOrder order) order--getUploConst :: uplo -> Const a uplo -> a-getUploConst _ = getConst--caseUplo :: Uplo uplo => uplo -> a -> a -> a-caseUplo uplo lo up =- getUploConst uplo $ switchUplo (Const lo) (Const up)--instance (Uplo uplo, Shape.C size) => Shape.C (Triangular uplo size) where- type Index (Triangular uplo size) = (Shape.Index size, Shape.Index size)-- indices (Triangular uplo _ size) =- let ixs = Shape.indices size- rcs = concat $ zipWith (\r cs -> map ((,) r) cs) ixs $ tails ixs- in caseUplo uplo (map swap rcs) rcs-- uncheckedOffset sh ix =- snd $ Shape.uncheckedSizeOffset sh ix-- sizeOffset sh ix =- if Shape.inBounds sh ix- then Shape.uncheckedSizeOffset sh ix- else error "Shape.Triangular.sizeOffset: wrong matrix part"-- uncheckedSizeOffset (Triangular uplo RowMajor size) (rs,cs) =- let (s,r) = Shape.uncheckedSizeOffset size rs- c = Shape.uncheckedOffset size cs- in (s,- caseUplo uplo- (triangleSize r + c)- (triangleSize s - triangleSize (s-r) + c-r))- uncheckedSizeOffset (Triangular uplo ColumnMajor size) (rs,cs) =- let (s,r) = Shape.uncheckedSizeOffset size rs- c = Shape.uncheckedOffset size cs- in (s,- caseUplo uplo- (triangleSize s - triangleSize (s-c) + r-c)- (triangleSize c + r))-- size (Triangular _ _ size) = triangleSize $ Shape.size size- uncheckedSize (Triangular _ _ size) = triangleSize $ Shape.uncheckedSize size- inBounds (Triangular uplo _ size) ix@(r,c) =- Shape.inBounds (size,size) ix- &&- caseUplo uplo- (Shape.offset size r >= Shape.offset size c)- (Shape.offset size r <= Shape.offset size c)--triangleSize :: Int -> Int-triangleSize n = div (n*(n+1)) 2--triangleRoot :: Floating a => a -> a-triangleRoot size = (sqrt (8*size+1)-1)/2--triangleExtent :: String -> Int -> Int-triangleExtent name size =- let n = round (triangleRoot (fromIntegral size :: Double))- in if size == triangleSize n- then n- else error (name ++ ": no triangular number of elements")+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module Numeric.LAPACK.Matrix.Shape.Private where++import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Extent.Private (Extent)+import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip))++import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary, (:+:))+import Type.Data.Num (integralFromProxy)+import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.Array.Comfort.Shape as Shape++import Control.DeepSeq (NFData, rnf)+import Control.Applicative (Const(Const, getConst))++import qualified Data.NonEmpty as NonEmpty+import Data.Functor.Identity (Identity(Identity), runIdentity)+import Data.List (tails)+import Data.Tuple.HT (mapPair, swap, double)+import Data.Bool.HT (if')+++data Order = RowMajor | ColumnMajor+ deriving (Eq, Show)++instance NFData Order where+ rnf RowMajor = ()+ rnf ColumnMajor = ()++flipOrder :: Order -> Order+flipOrder RowMajor = ColumnMajor+flipOrder ColumnMajor = RowMajor++transposeFromOrder :: Order -> Char+transposeFromOrder RowMajor = 'T'+transposeFromOrder ColumnMajor = 'N'++swapOnRowMajor :: Order -> (a,a) -> (a,a)+swapOnRowMajor order =+ case order of+ RowMajor -> swap+ ColumnMajor -> id++sideSwapFromOrder :: Order -> (a,a) -> (Char, (a,a))+sideSwapFromOrder order (m0,n0) =+ let ((side,m), (_,n)) = swapOnRowMajor order (('L', m0), ('R', n0))+ in (side,(m,n))+++type family HeightOf shape+type family WidthOf shape+++data Full vert horiz height width =+ Full {+ fullOrder :: Order,+ fullExtent :: Extent vert horiz height width+ } deriving (Eq, Show)++type instance HeightOf (Full vert horiz height width) = height+type instance WidthOf (Full vert horiz height width) = width++instance+ (Extent.C vert, Extent.C horiz, NFData height, NFData width) =>+ NFData (Full vert horiz height width) where+ rnf (Full order extent) = rnf (order, extent)++instance+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Shape.C (Full vert horiz height width) where++ size (Full _ extent) = Shape.size (Extent.dimensions extent)+ uncheckedSize (Full _ extent) =+ Shape.uncheckedSize (Extent.dimensions extent)++instance+ (Extent.C vert, Extent.C horiz, Shape.Indexed height, Shape.Indexed width) =>+ Shape.Indexed (Full vert horiz height width) where++ type Index (Full vert horiz height width) =+ (Shape.Index height, Shape.Index width)+ indices (Full order extent) = fullIndices order extent++ offset (Full RowMajor extent) =+ Shape.offset (Extent.dimensions extent)+ offset (Full ColumnMajor extent) =+ Shape.offset (swap $ Extent.dimensions extent) . swap+ uncheckedOffset (Full RowMajor extent) =+ Shape.uncheckedOffset (Extent.dimensions extent)+ uncheckedOffset (Full ColumnMajor extent) =+ Shape.uncheckedOffset (swap $ Extent.dimensions extent) . swap++ sizeOffset (Full RowMajor extent) =+ Shape.sizeOffset (Extent.dimensions extent)+ sizeOffset (Full ColumnMajor extent) =+ Shape.sizeOffset (swap $ Extent.dimensions extent) . swap+ uncheckedSizeOffset (Full RowMajor extent) =+ Shape.uncheckedSizeOffset (Extent.dimensions extent)+ uncheckedSizeOffset (Full ColumnMajor extent) =+ Shape.uncheckedSizeOffset (swap $ Extent.dimensions extent) . swap++ inBounds (Full _ extent) = Shape.inBounds (Extent.dimensions extent)++instance+ (Extent.C vert, Extent.C horiz,+ Shape.InvIndexed height, Shape.InvIndexed width) =>+ Shape.InvIndexed (Full vert horiz height width) where++ indexFromOffset (Full order extent) = fullIndexFromOffset order extent+++transpose ::+ (Extent.C vert, Extent.C horiz) =>+ Full vert horiz height width -> Full horiz vert width height+transpose (Full order extent) = Full (flipOrder order) (Extent.transpose extent)++dimensions ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Full vert horiz height width -> (Int, Int)+dimensions (Full order extent) =+ swapOnRowMajor order+ (Shape.size $ Extent.height extent,+ Shape.size $ Extent.width extent)++fullHeight ::+ (Extent.C vert, Extent.C horiz) => Full vert horiz height width -> height+fullHeight = Extent.height . fullExtent++fullWidth ::+ (Extent.C vert, Extent.C horiz) => Full vert horiz height width -> width+fullWidth = Extent.width . fullExtent+++fullIndices ::+ (Extent.C vert, Extent.C horiz, Shape.Indexed a, Shape.Indexed b) =>+ Order -> Extent vert horiz a b -> [(Shape.Index a, Shape.Index b)]+fullIndices order extent =+ case order of+ RowMajor -> Shape.indices $ Extent.dimensions extent+ ColumnMajor -> map swap $ Shape.indices $ swap $ Extent.dimensions extent++fullIndexFromOffset ::+ (Extent.C vert, Extent.C horiz, Shape.InvIndexed a, Shape.InvIndexed b) =>+ Order -> Extent vert horiz a b -> Int ->+ (Shape.Index a, Shape.Index b)+fullIndexFromOffset order extent =+ case order of+ RowMajor ->+ Shape.indexFromOffset (Extent.dimensions extent)+ ColumnMajor ->+ swap . Shape.indexFromOffset (swap $ Extent.dimensions extent)+++type General height width = Full Extent.Big Extent.Big height width+type Tall height width = Full Extent.Big Extent.Small height width+type Wide height width = Full Extent.Small Extent.Big height width+type Square size = Full Extent.Small Extent.Small size size+++fullMapExtent ::+ Extent.Map vertA horizA vertB horizB height width ->+ Full vertA horizA height width ->+ Full vertB horizB height width+fullMapExtent f (Full order extent) = Full order $ Extent.apply f extent++general :: Order -> height -> width -> General height width+general order height width = Full order $ Extent.general height width++tall ::+ (Shape.C height, Shape.C width) =>+ Order -> height -> width -> Tall height width+tall order height width =+ if Shape.size height >= Shape.size width+ then Full order $ Extent.tall height width+ else error "MatrixShape.tall: height smaller than width"++wide ::+ (Shape.C height, Shape.C width) =>+ Order -> height -> width -> Wide height width+wide order height width =+ if Shape.size height <= Shape.size width+ then Full order $ Extent.wide height width+ else error "MatrixShape.wide: width smaller than height"++square :: Order -> sh -> Square sh+square order sh = Full order $ Extent.square sh+++caseTallWide ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Full vert horiz height width ->+ Either (Tall height width) (Wide height width)+caseTallWide (Full order extent) =+ either (Left . Full order) (Right . Full order) $+ Extent.caseTallWide (\h w -> Shape.size h >= Shape.size w) extent+++data Split lower vert horiz height width =+ Split {+ splitLower :: lower,+ splitOrder :: Order,+ splitExtent :: Extent vert horiz height width+ } deriving (Eq, Show)++splitHeight ::+ (Extent.C vert, Extent.C horiz) =>+ Split lower vert horiz height width -> height+splitHeight = Extent.height . splitExtent++splitWidth ::+ (Extent.C vert, Extent.C horiz) =>+ Split lower vert horiz height width -> width+splitWidth = Extent.width . splitExtent++splitMapExtent ::+ Extent.Map vertA horizA vertB horizB height width ->+ Split lower vertA horizA height width ->+ Split lower vertB horizB height width+splitMapExtent f (Split lowerPart order extent) =+ Split lowerPart order $ Extent.apply f extent+++caseTallWideSplit ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Split lower vert horiz height width ->+ Either+ (Split lower Extent.Big Extent.Small height width)+ (Split lower Extent.Small Extent.Big height width)+caseTallWideSplit (Split lowerPart order extent) =+ either (Left . Split lowerPart order) (Right . Split lowerPart order) $+ Extent.caseTallWide (\h w -> Shape.size h >= Shape.size w) extent+++type instance HeightOf (Split lower vert horiz height width) = height+type instance WidthOf (Split lower vert horiz height width) = width++data Reflector = Reflector deriving (Eq, Show)+data Triangle = Triangle deriving (Eq, Show)++instance NFData Reflector where rnf Reflector = ()+instance NFData Triangle where rnf Triangle = ()++splitPart ::+ (Extent.C vert, Extent.C horiz,+ Shape.Indexed height, Shape.Indexed width) =>+ Split lower vert horiz height width ->+ (Shape.Index height, Shape.Index width) -> Either lower Triangle+splitPart (Split lowerPart _ extent) (r,c) =+ if Shape.offset (Extent.height extent) r >+ Shape.offset (Extent.width extent) c+ then Left lowerPart+ else Right Triangle++instance+ (NFData lower, Extent.C vert, Extent.C horiz, NFData height, NFData width) =>+ NFData (Split lower vert horiz height width) where+ rnf (Split lowerPart order extent) = rnf (lowerPart, order, extent)++instance+ (Eq lower, Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Shape.C (Split lower vert horiz height width) where++ size (Split _ _ extent) = Shape.size (Extent.dimensions extent)+ uncheckedSize (Split _ _ extent) =+ Shape.uncheckedSize (Extent.dimensions extent)++instance+ (Eq lower, Extent.C vert, Extent.C horiz, Shape.Indexed height, Shape.Indexed width) =>+ Shape.Indexed (Split lower vert horiz height width) where++ type Index (Split lower vert horiz height width) =+ (Either lower Triangle,+ (Shape.Index height, Shape.Index width))++ indices sh@(Split _ order extent) =+ map (\ix -> (splitPart sh ix, ix)) $ fullIndices order extent++ offset sh@(Split _ order extent) (part,ix) =+ if part == splitPart sh ix+ then+ case order of+ RowMajor -> Shape.offset (Extent.dimensions extent) ix+ ColumnMajor ->+ Shape.offset (swap $ Extent.dimensions extent) (swap ix)+ else error "Shape.Split.offset: wrong matrix part"+ uncheckedOffset (Split _ RowMajor extent) =+ Shape.uncheckedOffset (Extent.dimensions extent) . snd+ uncheckedOffset (Split _ ColumnMajor extent) =+ Shape.uncheckedOffset (swap $ Extent.dimensions extent) . swap . snd++ sizeOffset sh@(Split _ order extent) (part,ix) =+ if part == splitPart sh ix+ then+ case order of+ RowMajor -> Shape.sizeOffset (Extent.dimensions extent) ix+ ColumnMajor ->+ Shape.sizeOffset (swap $ Extent.dimensions extent) (swap ix)+ else error "Shape.Split.sizeOffset: wrong matrix part"+ uncheckedSizeOffset (Split _ RowMajor extent) =+ Shape.uncheckedSizeOffset (Extent.dimensions extent) . snd+ uncheckedSizeOffset (Split _ ColumnMajor extent) =+ Shape.uncheckedSizeOffset (swap $ Extent.dimensions extent) . swap . snd++ inBounds sh@(Split _ _ extent) (part,ix) =+ Shape.inBounds (Extent.dimensions extent) ix+ &&+ part == splitPart sh ix++instance+ (Eq lower, Extent.C vert, Extent.C horiz,+ Shape.InvIndexed height, Shape.InvIndexed width) =>+ Shape.InvIndexed (Split lower vert horiz height width) where++ indexFromOffset sh@(Split _ order extent) k =+ let ix = fullIndexFromOffset order extent k+ in (splitPart sh ix, ix)+++{- |+Store the upper triangular half of a real symmetric or complex Hermitian matrix.+-}+data Hermitian size =+ Hermitian {+ hermitianOrder :: Order,+ hermitianSize :: size+ } deriving (Eq, Show)++type instance HeightOf (Hermitian size) = size+type instance WidthOf (Hermitian size) = size++uploFromOrder :: Order -> Char+uploFromOrder RowMajor = 'L'+uploFromOrder ColumnMajor = 'U'++instance (NFData size) => NFData (Hermitian size) where+ rnf (Hermitian order size) = rnf (order, size)++instance (Shape.C size) => Shape.C (Hermitian size) where+ size (Hermitian _ size) = triangleSize $ Shape.size size+ uncheckedSize (Hermitian _ size) = triangleSize $ Shape.uncheckedSize size++instance (Shape.Indexed size) => Shape.Indexed (Hermitian size) where+ type Index (Hermitian size) = (Shape.Index size, Shape.Index size)++ indices (Hermitian order size) = triangleIndices order size++ uncheckedOffset sh ix =+ snd $ Shape.uncheckedSizeOffset sh ix++ sizeOffset sh ix =+ if Shape.inBounds sh ix+ then Shape.uncheckedSizeOffset sh ix+ else error "Shape.Hermitian.sizeOffset: wrong matrix part"++ uncheckedSizeOffset (Hermitian order size) (rs,cs) =+ let (n,r) = Shape.uncheckedSizeOffset size rs+ c = Shape.uncheckedOffset size cs+ in (triangleSize n,+ case order of+ RowMajor -> triangleOffset n (r,c)+ ColumnMajor -> triangleSize c + r)++ inBounds (Hermitian _ size) ix@(r,c) =+ Shape.inBounds (size,size) ix+ &&+ Shape.offset size r <= Shape.offset size c++instance (Shape.InvIndexed size) => Shape.InvIndexed (Hermitian size) where+ indexFromOffset (Hermitian order size) k =+ triangleIndexFromOffset order size k++++data Triangular lo diag up size =+ Triangular {+ triangularDiag :: diag,+ triangularUplo :: (lo,up),+ triangularOrder :: Order,+ triangularSize :: size+ } deriving (Eq, Show)++type instance HeightOf (Triangular lo diag up size) = size+type instance WidthOf (Triangular lo diag up size) = size+++data Unit = Unit deriving (Eq, Show)+data NonUnit = NonUnit deriving (Eq, Show)++class TriDiag diag where switchTriDiag :: f Unit -> f NonUnit -> f diag+instance TriDiag Unit where switchTriDiag f _ = f+instance TriDiag NonUnit where switchTriDiag _ f = f++autoDiag :: TriDiag diag => diag+autoDiag = runIdentity $ switchTriDiag (Identity Unit) (Identity NonUnit)++caseTriDiag :: TriDiag diag => diag -> a -> a -> a+caseTriDiag diag unit nonUnit =+ getConstAs diag $ switchTriDiag (Const unit) (Const nonUnit)++charFromTriDiag :: TriDiag diag => diag -> Char+charFromTriDiag diag = caseTriDiag diag 'U' 'N'+++relaxUnitDiagonal ::+ (TriDiag diag) => Triangular lo Unit up sh -> Triangular lo diag up sh+relaxUnitDiagonal shape = shape{triangularDiag = autoDiag}++strictNonUnitDiagonal ::+ (TriDiag diag) => Triangular lo diag up sh -> Triangular lo NonUnit up sh+strictNonUnitDiagonal shape = shape{triangularDiag = NonUnit}+++data Empty = Empty deriving (Eq, Show)+data Filled = Filled deriving (Eq, Show)++lower :: (Filled,Empty)+lower = (Filled,Empty)++upper :: (Empty,Filled)+upper = (Empty,Filled)++type Identity = Triangular Empty Unit Empty+type Diagonal = Triangular Empty NonUnit Empty+type LowerTriangular diag = Triangular Filled diag Empty+type UpperTriangular diag = Triangular Empty diag Filled+type FlexSymmetric diag = Triangular Filled diag Filled+type Symmetric = FlexSymmetric NonUnit++triangularTranspose ::+ (Content lo, Content up) =>+ Triangular lo diag up sh -> Triangular up diag lo sh+triangularTranspose (Triangular diag uplo order size) =+ Triangular diag+ (swap uplo)+ (caseDiagUpLoSym uplo flipOrder flipOrder flipOrder id order)+ size+++class Content c where switchContent :: f Empty -> f Filled -> f c+instance Content Empty where switchContent f _ = f+instance Content Filled where switchContent _ f = f+++type UpLo lo up = (UpLoC lo up, UpLoC up lo)++class (DiagUpLoC lo up, UpLoSymC lo up) => UpLoC lo up where+ switchUpLo :: f Empty Filled -> f Filled Empty -> f lo up++instance UpLoC Empty Filled where switchUpLo f _ = f+instance UpLoC Filled Empty where switchUpLo _ f = f+++type DiagUpLo lo up = (DiagUpLoC lo up, DiagUpLoC up lo)++class (Content lo, Content up) => DiagUpLoC lo up where+ switchDiagUpLo ::+ f Empty Empty -> f Empty Filled -> f Filled Empty -> f lo up++instance DiagUpLoC Empty Empty where switchDiagUpLo f _ _ = f+instance DiagUpLoC Empty Filled where switchDiagUpLo _ f _ = f+instance DiagUpLoC Filled Empty where switchDiagUpLo _ _ f = f+++type UpLoSym lo up = (UpLoSymC lo up, UpLoSymC up lo)++class (Content lo, Content up) => UpLoSymC lo up where+ switchUpLoSym ::+ f Empty Filled -> f Filled Empty -> f Filled Filled -> f lo up++instance UpLoSymC Empty Filled where switchUpLoSym f _ _ = f+instance UpLoSymC Filled Empty where switchUpLoSym _ f _ = f+instance UpLoSymC Filled Filled where switchUpLoSym _ _ f = f+++switchDiagUpLoSym ::+ (Content lo, Content up) =>+ f Empty Empty -> f Empty Filled -> f Filled Empty -> f Filled Filled ->+ f lo up+switchDiagUpLoSym fDiag fUpper fLower fSymm =+ getFlip $+ switchContent+ (Flip $ switchContent fDiag fUpper)+ (Flip $ switchContent fLower fSymm)++autoContent :: Content c => c+autoContent = runIdentity $ switchContent (Identity Empty) (Identity Filled)++autoUplo :: (Content lo, Content up) => (lo,up)+autoUplo = (autoContent,autoContent)++uploOrder :: (Content lo, Content up) => (lo,up) -> Order -> Order+uploOrder (_loc,upc) = caseContent upc flipOrder id++getConstAs :: c -> Const a c -> a+getConstAs _ = getConst++caseContent :: Content c => c -> a -> a -> a+caseContent c lo up =+ getConstAs c $ switchContent (Const lo) (Const up)++caseLoUp :: UpLo lo up => (lo,up) -> a -> a -> a+caseLoUp (_loc,upc) = caseContent upc++caseDiagUpLoSym :: (Content lo, Content up) => (lo,up) -> a -> a -> a -> a -> a+caseDiagUpLoSym (loc,upc) diag up lo symm =+ caseContent loc+ (caseContent upc diag up)+ (caseContent upc lo symm)+++newtype Const2 a lo up = Const2 {getConst2 :: a}++getContentConst2 :: (lo,up) -> Const2 a lo up -> a+getContentConst2 _ = getConst2++caseUpLoSym :: (UpLoSym lo up) => (lo,up) -> a -> a -> a -> a+caseUpLoSym c lo up sym =+ getContentConst2 c $ switchUpLoSym (Const2 lo) (Const2 up) (Const2 sym)+++instance+ (Content lo, TriDiag diag, Content up, NFData size) =>+ NFData (Triangular lo diag up size) where+ rnf (Triangular diag (loc,upc) order size) =+ rnf+ (flip getFlip diag $+ switchTriDiag (Flip $ \Unit -> ()) (Flip $ \NonUnit -> ()),+ let rnfContent c =+ flip getFlip c $+ switchContent+ (Flip $ \Empty -> ())+ (Flip $ \Filled -> ())+ in (rnfContent loc, rnfContent upc),+ order, size)++instance+ (Content lo, TriDiag diag, Content up, Shape.C size) =>+ Shape.C (Triangular lo diag up size) where++ size (Triangular _diag uplo _ size) =+ let n = Shape.size size+ in caseDiagUpLoSym uplo n+ (triangleSize n)+ (triangleSize n)+ (triangleSize n)+ uncheckedSize (Triangular _diag uplo _ size) =+ let n = Shape.uncheckedSize size+ in caseDiagUpLoSym uplo n+ (triangleSize n)+ (triangleSize n)+ (triangleSize n)++instance+ (Content lo, TriDiag diag, Content up, Shape.Indexed size) =>+ Shape.Indexed (Triangular lo diag up size) where+ type Index (Triangular lo diag up size) =+ (Shape.Index size, Shape.Index size)++ indices (Triangular _diag uplo order size) =+ caseDiagUpLoSym uplo+ (map double $ Shape.indices size)+ (triangleIndices order size)+ (map swap $ triangleIndices (flipOrder order) size)+ (triangleIndices order size)++ uncheckedOffset sh ix =+ snd $ Shape.uncheckedSizeOffset sh ix++ sizeOffset sh ix =+ if Shape.inBounds sh ix+ then Shape.uncheckedSizeOffset sh ix+ else error "Shape.Triangular.sizeOffset: wrong matrix part"++ uncheckedSizeOffset (Triangular _diag uplo order size) (rs,cs) =+ let (n,r) = Shape.uncheckedSizeOffset size rs+ c = Shape.uncheckedOffset size cs+ triSize = triangleSize n+ in case order of+ RowMajor ->+ caseDiagUpLoSym uplo (n,c)+ (triSize, triangleOffset n (r,c))+ (triSize, triangleSize r + c)+ (triSize, triangleOffset n (r,c))+ ColumnMajor ->+ caseDiagUpLoSym uplo (n,c)+ (triSize, triangleSize c + r)+ (triSize, triangleOffset n (c,r))+ (triSize, triangleSize c + r)++ inBounds (Triangular _diag uplo _ size) ix@(r,c) =+ Shape.inBounds (size,size) ix+ &&+ caseDiagUpLoSym uplo+ (Shape.offset size r == Shape.offset size c)+ (Shape.offset size r <= Shape.offset size c)+ (Shape.offset size r >= Shape.offset size c)+ (Shape.offset size r <= Shape.offset size c)++instance+ (Content lo, TriDiag diag, Content up, Shape.InvIndexed size) =>+ Shape.InvIndexed (Triangular lo diag up size) where++ indexFromOffset (Triangular _diag uplo order size) k =+ caseDiagUpLoSym uplo+ (double $ Shape.indexFromOffset size k)+ (triangleIndexFromOffset order size k)+ (swap $ triangleIndexFromOffset (flipOrder order) size k)+ (triangleIndexFromOffset order size k)+++triangleSize :: Int -> Int+triangleSize n = div (n*(n+1)) 2++triangleOffset :: Int -> (Int,Int) -> Int+triangleOffset s (r,c) =+ triangleSize s - triangleSize (s-r) + c-r++triangleRoot :: Floating a => a -> a+triangleRoot size = (sqrt (8*size+1)-1)/2++triangleRootDouble :: Int -> Double+triangleRootDouble = triangleRoot . fromIntegral++triangleExtent :: String -> Int -> Int+triangleExtent name size =+ let n = round $ triangleRootDouble size+ in if size == triangleSize n+ then n+ else error (name ++ ": no triangular number of elements")++triangleIndices ::+ (Shape.Indexed sh) => Order -> sh -> [(Shape.Index sh, Shape.Index sh)]+triangleIndices RowMajor size =+ let ixs = Shape.indices size+ in concat $ zipWith (\r cs -> map ((,) r) cs) ixs $ tails ixs+triangleIndices ColumnMajor size =+ let ixs = Shape.indices size+ in concat $+ zipWith (\rs c -> map (flip (,) c) rs)+ (NonEmpty.tail $ NonEmpty.inits ixs) ixs++triangleIndexFromOffset ::+ (Shape.InvIndexed sh) =>+ Order -> sh -> Int -> (Shape.Index sh, Shape.Index sh)+triangleIndexFromOffset order size k =+ mapPair (Shape.indexFromOffset size, Shape.indexFromOffset size) $+ case order of+ RowMajor ->+ let n = Shape.size size+ triSize = triangleSize n+ rr = ceiling (triangleRootDouble (triSize-k))+ r = n - rr+ in (r, k+r - (triSize - triangleSize rr))+ ColumnMajor ->+ let c = floor (triangleRootDouble k)+ in (k - triangleSize c, c)+++type UnaryProxy a = Proxy (Unary.Un a)++data Banded sub super vert horiz height width =+ Banded {+ bandedOffDiagonals :: (UnaryProxy sub, UnaryProxy super),+ bandedOrder :: Order,+ bandedExtent :: Extent vert horiz height width+ } deriving (Eq, Show)++type BandedGeneral sub super = Banded sub super Extent.Big Extent.Big+type BandedSquare sub super size =+ Banded sub super Extent.Small Extent.Small size size++type BandedLowerTriangular sub size = BandedSquare sub TypeNum.U0 size+type BandedUpperTriangular super size = BandedSquare TypeNum.U0 super size++type BandedDiagonal size = BandedSquare TypeNum.U0 TypeNum.U0 size+++bandedHeight ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width -> height+bandedHeight = Extent.height . bandedExtent++bandedWidth ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width -> width+bandedWidth = Extent.width . bandedExtent++bandedMapExtent ::+ Extent.Map vertA horizA vertB horizB height width ->+ Banded sub super vertA horizA height width ->+ Banded sub super vertB horizB height width+bandedMapExtent f (Banded numDiag order extent) =+ Banded numDiag order $ Extent.apply f extent++type instance HeightOf (Banded sub super vert horiz height width) = height+type instance WidthOf (Banded sub super vert horiz height width) = width++bandedBreadth ::+ (Unary.Natural sub, Unary.Natural super) =>+ (UnaryProxy sub, UnaryProxy super) -> Int+bandedBreadth (sub,super) =+ integralFromProxy sub + 1 + integralFromProxy super++numOffDiagonals ::+ (Unary.Natural sub, Unary.Natural super) =>+ Order -> (UnaryProxy sub, UnaryProxy super) -> (Int,Int)+numOffDiagonals order (sub,super) =+ swapOnRowMajor order (integralFromProxy sub, integralFromProxy super)++natFromProxy :: (Unary.Natural n) => UnaryProxy n -> Proof.Nat n+natFromProxy Proxy = Proof.Nat++addOffDiagonals ::+ (Unary.Natural subA, Unary.Natural superA,+ Unary.Natural subB, Unary.Natural superB,+ (subA :+: subB) ~ subC,+ (superA :+: superB) ~ superC) =>+ (UnaryProxy subA, UnaryProxy superA) ->+ (UnaryProxy subB, UnaryProxy superB) ->+ ((Proof.Nat subC, Proof.Nat superC),+ (UnaryProxy subC, UnaryProxy superC))+addOffDiagonals (subA,superA) (subB,superB) =+ ((Proof.addNat (natFromProxy subA) (natFromProxy subB),+ Proof.addNat (natFromProxy superA) (natFromProxy superB)),+ (Proxy,Proxy))++bandedTranspose ::+ (Extent.C vert, Extent.C horiz) =>+ Banded sub super vert horiz height width ->+ Banded super sub horiz vert width height+bandedTranspose (Banded (sub,super) order extent) =+ Banded (super,sub) (flipOrder order) (Extent.transpose extent)+++bandedGeneral ::+ (UnaryProxy sub, UnaryProxy super) -> Order -> height -> width ->+ Banded sub super Extent.Big Extent.Big height width+bandedGeneral offDiag order height width =+ Banded offDiag order (Extent.general height width)++bandedSquare ::+ (UnaryProxy sub, UnaryProxy super) -> Order -> size ->+ Banded sub super Extent.Small Extent.Small size size+bandedSquare offDiag order = Banded offDiag order . Extent.square+++data BandedIndex row column =+ InsideBox row column+ | VertOutsideBox Int column+ | HorizOutsideBox row Int+ deriving (Eq, Show)++instance+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, NFData height, NFData width) =>+ NFData (Banded sub super vert horiz height width) where+ rnf (Banded (Proxy,Proxy) order extent) = rnf (order, extent)++instance+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Shape.C (Banded sub super vert horiz height width) where++ size (Banded offDiag order extent) =+ bandedBreadth offDiag *+ case order of+ RowMajor -> Shape.size (Extent.height extent)+ ColumnMajor -> Shape.size (Extent.width extent)+ uncheckedSize (Banded offDiag order extent) =+ bandedBreadth offDiag *+ case order of+ RowMajor -> Shape.uncheckedSize (Extent.height extent)+ ColumnMajor -> Shape.uncheckedSize (Extent.width extent)++instance+ (Unary.Natural sub, Unary.Natural super,+ Extent.C vert, Extent.C horiz, Shape.Indexed height, Shape.Indexed width) =>+ Shape.Indexed (Banded sub super vert horiz height width) where++ type Index (Banded sub super vert horiz height width) =+ BandedIndex (Shape.Index height) (Shape.Index width)+ indices (Banded (sub,super) order extent) =+ let (height,width) = Extent.dimensions extent+ in case order of+ RowMajor ->+ map (\(r,c) -> either (HorizOutsideBox r) (InsideBox r) c) $+ bandedIndicesRowMajor (sub,super) (height,width)+ ColumnMajor ->+ map (\(c,r) ->+ either (flip VertOutsideBox c) (flip InsideBox c) r) $+ bandedIndicesRowMajor (super,sub) (width,height)++ offset shape ix =+ if Shape.inBounds shape ix+ then Shape.uncheckedOffset shape ix+ else error "Banded.offset: index outside band"++ uncheckedOffset (Banded (sub,super) order extent) ix =+ let (height,width) = Extent.dimensions extent+ kl = integralFromProxy sub+ ku = integralFromProxy super+ in bandedOffset (kl,ku) order (height,width) ix++ inBounds (Banded (sub,super) order extent) ix =+ let (height,width) = Extent.dimensions extent+ kl = integralFromProxy sub+ ku = integralFromProxy super+ insideBand r c = Shape.inBounds (Shape.Range (-kl) ku) (c-r)+ in case (order,ix) of+ (_, InsideBox r c) ->+ Shape.inBounds (height,width) (r,c)+ &&+ insideBand (Shape.offset height r) (Shape.offset width c)+ (RowMajor, HorizOutsideBox r c) ->+ Shape.inBounds height r+ &&+ insideBand (Shape.offset height r) (outsideOffset width c)+ (ColumnMajor, VertOutsideBox r c) ->+ Shape.inBounds width c+ &&+ insideBand (outsideOffset height r) (Shape.offset width c)+ _ -> False++instance+ (Unary.Natural sub, Unary.Natural super, Extent.C vert, Extent.C horiz,+ Shape.InvIndexed height, Shape.InvIndexed width) =>+ Shape.InvIndexed (Banded sub super vert horiz height width) where++ indexFromOffset (Banded (sub,super) order extent) j =+ bandedIndexFromOffset+ Shape.indexFromOffset Shape.indexFromOffset+ (integralFromProxy sub, integralFromProxy super) order+ (Extent.dimensions extent) j++ uncheckedIndexFromOffset (Banded (sub,super) order extent) j =+ bandedIndexFromOffset+ Shape.uncheckedIndexFromOffset Shape.uncheckedIndexFromOffset+ (integralFromProxy sub, integralFromProxy super) order+ (Extent.dimensions extent) j++outsideOffset :: Shape.C sh => sh -> Int -> Int+outsideOffset size k = if k<0 then k else Shape.size size + k++bandedOffset ::+ (Shape.Indexed height, Shape.Indexed width) =>+ (Int, Int) -> Order -> (height, width) ->+ BandedIndex (Shape.Index height) (Shape.Index width) -> Int+bandedOffset (kl,ku) order (height,width) ix =+ let k = kl+ku+ in case ix of+ InsideBox r c ->+ let i = Shape.uncheckedOffset height r+ j = Shape.uncheckedOffset width c+ in case order of+ RowMajor -> k*i + kl+j+ ColumnMajor -> k*j + ku+i+ VertOutsideBox r c ->+ let i = outsideOffset height r+ j = Shape.uncheckedOffset width c+ in k*j + ku+i+ HorizOutsideBox r c ->+ let i = Shape.uncheckedOffset height r+ j = outsideOffset width c+ in k*i + kl+j++bandedIndicesRowMajor ::+ (Unary.Natural sub, Unary.Natural super,+ Shape.Indexed height, Shape.Indexed width) =>+ (UnaryProxy sub, UnaryProxy super) ->+ (height, width) ->+ [(Shape.Index height, Either Int (Shape.Index width))]+bandedIndicesRowMajor (sub,super) (height,width) =+ let kl = integralFromProxy sub+ ku = integralFromProxy super+ in concat $+ zipWith (\r -> map ((,) r)) (Shape.indices height) $+ map (take (kl+1+ku)) $ tails $+ (map Left $ take kl $ iterate (1+) (-kl)) +++ (map Right $ Shape.indices width) +++ (map Left $ iterate (1+) 0)++bandedIndexFromOffset ::+ (Shape.C height, Shape.C width) =>+ (height -> Int -> row) ->+ (width -> Int -> column) ->+ (Int,Int) -> Order -> (height,width) -> Int -> BandedIndex row column+bandedIndexFromOffset+ rowFromOffset columnFromOffset (kl,ku) order (height,width) j =+ case order of+ RowMajor ->+ let n = Shape.size width+ (rb,cb) = divMod j (kl+1+ku)+ r = rowFromOffset height rb+ ci = rb+cb-kl+ in if' (ci<0) (HorizOutsideBox r ci) $+ if' (ci>=n) (HorizOutsideBox r (ci-n)) $+ InsideBox r (columnFromOffset width ci)+ ColumnMajor ->+ let m = Shape.size height+ (cb,rb) = divMod j (kl+1+ku)+ c = columnFromOffset width cb+ ri = rb+cb-ku+ in if' (ri<0) (VertOutsideBox ri c) $+ if' (ri>=m) (VertOutsideBox (ri-m) c) $+ InsideBox (rowFromOffset height ri) c+++data BandedHermitian off size =+ BandedHermitian {+ bandedHermitianOffDiagonals :: UnaryProxy off,+ bandedHermitianOrder :: Order,+ bandedHermitianSize :: size+ } deriving (Eq, Show)++type instance HeightOf (BandedHermitian off size) = size+type instance WidthOf (BandedHermitian off size) = size++instance (Unary.Natural off, NFData size) =>+ NFData (BandedHermitian off size) where+ rnf (BandedHermitian Proxy order size) = rnf (order, size)++instance (Unary.Natural off, Shape.C size) =>+ Shape.C (BandedHermitian off size) where+ size (BandedHermitian offDiag _order size) =+ (1 + integralFromProxy offDiag) * Shape.size size+ uncheckedSize (BandedHermitian offDiag _order size) =+ (1 + integralFromProxy offDiag) * Shape.uncheckedSize size++instance (Unary.Natural off, Shape.Indexed size) =>+ Shape.Indexed (BandedHermitian off size) where+ type Index (BandedHermitian off size) =+ BandedIndex (Shape.Index size) (Shape.Index size)+ indices (BandedHermitian offDiag order size) =+ case order of+ RowMajor ->+ map (\(r,c) -> either (HorizOutsideBox r) (InsideBox r) c) $+ bandedIndicesRowMajor (unary TypeNum.u0, offDiag) (size,size)+ ColumnMajor ->+ map (\(c,r) ->+ either (flip VertOutsideBox c) (flip InsideBox c) r) $+ bandedIndicesRowMajor (offDiag, unary TypeNum.u0) (size,size)++ offset shape ix =+ if Shape.inBounds shape ix+ then Shape.uncheckedOffset shape ix+ else error "BandedHermitian.offset: index outside band"++ uncheckedOffset (BandedHermitian offDiag order size) ix =+ let k = integralFromProxy offDiag+ in bandedOffset (0,k) order (size,size) ix++ inBounds (BandedHermitian offDiag order size) ix =+ let ku = integralFromProxy offDiag+ insideBand r c = Shape.inBounds (Shape.Range 0 ku) (c-r)+ in case (order,ix) of+ (_, InsideBox r c) ->+ Shape.inBounds (size,size) (r,c)+ &&+ insideBand (Shape.offset size r) (Shape.offset size c)+ (RowMajor, HorizOutsideBox r c) ->+ Shape.inBounds size r+ &&+ insideBand (Shape.offset size r) (outsideOffset size c)+ (ColumnMajor, VertOutsideBox r c) ->+ Shape.inBounds size c+ &&+ insideBand (outsideOffset size r) (Shape.offset size c)+ _ -> False++instance (Unary.Natural off, Shape.InvIndexed size) =>+ Shape.InvIndexed (BandedHermitian off size) where++ indexFromOffset (BandedHermitian offDiag order size) j =+ bandedHermitianIndexFromOffset+ Shape.indexFromOffset Shape.indexFromOffset+ (integralFromProxy offDiag) order size j++ uncheckedIndexFromOffset (BandedHermitian offDiag order size) j =+ bandedHermitianIndexFromOffset+ Shape.uncheckedIndexFromOffset Shape.uncheckedIndexFromOffset+ (integralFromProxy offDiag) order size j++bandedHermitianIndexFromOffset ::+ (Shape.C sh) =>+ (sh -> Int -> row) ->+ (sh -> Int -> column) ->+ Int -> Order -> sh -> Int -> BandedIndex row column+bandedHermitianIndexFromOffset rowFromOffset columnFromOffset k order size j =+ case order of+ RowMajor ->+ let n = Shape.size size+ (rb,cb) = divMod j (k+1)+ r = rowFromOffset size rb+ ci = rb+cb+ in if ci<n+ then InsideBox r (columnFromOffset size ci)+ else HorizOutsideBox r (ci-n)+ ColumnMajor ->+ let (cb,rb) = divMod j (k+1)+ c = columnFromOffset size cb+ ri = rb+cb-k+ in if ri>=0+ then InsideBox (rowFromOffset size ri) c+ else VertOutsideBox ri c
src/Numeric/LAPACK/Matrix/Square.hs view
@@ -1,202 +1,51 @@ module Numeric.LAPACK.Matrix.Square (- Square,- size,- toGeneral,- fromGeneral,- fromScalar,- toScalar,- fromList,- autoFromList,-- transpose,- adjoint,-- identity,- identityFrom,- diagonal,- getDiagonal,- trace,+ module Numeric.LAPACK.Matrix.Square.Basic,+ module Numeric.LAPACK.Matrix.Square.Linear, - multiply,- square,- power,+ eigenvalues,+ Eigen.schur,+ eigensystem,+ ComplexOf, ) where +import qualified Numeric.LAPACK.Matrix.Square.Eigen as Eigen+import Numeric.LAPACK.Matrix.Square.Basic+import Numeric.LAPACK.Matrix.Square.Linear -import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Vector as Vector-import qualified Numeric.LAPACK.Private as Private-import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor))-import Numeric.LAPACK.Matrix.Private (General, ZeroInt, zeroInt) import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private (zero, one)+import Numeric.LAPACK.Scalar (ComplexOf) -import qualified Numeric.LAPACK.FFI.Generic as LapackGen-import qualified Numeric.BLAS.FFI.Generic as BlasGen-import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class -import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array)) -import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Storable (Storable, peek, poke) -import System.IO.Unsafe (unsafePerformIO)--import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)--import Data.Function.HT (powerAssociative)---type Square sh = Array (MatrixShape.Square sh)--size :: Square sh a -> sh-size = MatrixShape.squareSize . Array.shape--toGeneral :: Square sh a -> General sh sh a-toGeneral (Array sh a) = Array (MatrixShape.generalFromSquare sh) a--fromGeneral :: (Eq sh) => General sh sh a -> Square sh a-fromGeneral (Array (MatrixShape.General order height width) a) =- if height==width- then Array (MatrixShape.Square order height) a- else error "Square.fromGeneral: no square shape"---fromScalar :: (Storable a) => a -> Square () a-fromScalar a =- Array.unsafeCreate (MatrixShape.Square RowMajor ()) $ flip poke a--toScalar :: (Storable a) => Square () a -> a-toScalar (Array (MatrixShape.Square _ ()) a) =- unsafePerformIO $ withForeignPtr a peek--fromList :: (Shape.C sh, Storable a) => sh -> [a] -> Square sh a-fromList sh =- Array.fromList (MatrixShape.Square RowMajor sh)--autoFromList :: (Storable a) => [a] -> Square ZeroInt a-autoFromList xs =- let n = length xs- m = round $ sqrt (fromIntegral n :: Double)- in if n == m*m- then fromList (zeroInt m) xs- else error "Square.autoFromList: no quadratic number of elements"---transpose :: Square sh a -> Square sh a-transpose = Array.mapShape MatrixShape.transposeSquare+eigenvalues ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a -> Vector sh (ComplexOf a)+eigenvalues = Eigen.values {- |-conjugate transpose--}-adjoint :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a-adjoint = transpose . Vector.conjugate---identity :: (Shape.C sh, Class.Floating a) => sh -> Square sh a-identity = identityOrder ColumnMajor--identityFrom :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a-identityFrom (Array (MatrixShape.Square order sh) _) = identityOrder order sh--identityOrder, _identityOrder ::- (Shape.C sh, Class.Floating a) => Order -> sh -> Square sh a-identityOrder order sh =- Array.unsafeCreate (MatrixShape.Square order sh) $ \aPtr ->- evalContT $ do- uploPtr <- Call.char 'A'- nPtr <- Call.cint $ Shape.size sh- alphaPtr <- Call.number zero- betaPtr <- Call.number one- liftIO $ LapackGen.laset uploPtr nPtr nPtr alphaPtr betaPtr aPtr nPtr--_identityOrder order sh =- Array.unsafeCreateWithSize (MatrixShape.Square order sh) $ \blockSize yPtr ->- evalContT $ do- nPtr <- Call.alloca- xPtr <- Call.number zero- incxPtr <- Call.cint 0- incyPtr <- Call.cint 1- liftIO $ do- poke nPtr $ fromIntegral blockSize- BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr- let n = fromIntegral $ Shape.size sh- poke nPtr n- poke xPtr one- poke incyPtr (n+1)- BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr--diagonal :: (Shape.C sh, Class.Floating a) => Vector sh a -> Square sh a-diagonal (Array sh x) =- Array.unsafeCreateWithSize (MatrixShape.Square ColumnMajor sh) $- \blockSize yPtr ->- evalContT $ do- nPtr <- Call.alloca- xPtr <- ContT $ withForeignPtr x- zPtr <- Call.number zero- incxPtr <- Call.cint 1- incyPtr <- Call.cint 1- inczPtr <- Call.cint 0- liftIO $ do- poke nPtr $ fromIntegral blockSize- BlasGen.copy nPtr zPtr inczPtr yPtr incyPtr- let n = fromIntegral $ Shape.size sh- poke nPtr n- poke incyPtr (n+1)- BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr--getDiagonal :: (Shape.C sh, Class.Floating a) => Square sh a -> Vector sh a-getDiagonal (Array (MatrixShape.Square _ sh) x) =- Array.unsafeCreateWithSize sh $ \n yPtr -> evalContT $ do- nPtr <- Call.cint n- xPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint (n+1)- incyPtr <- Call.cint 1- liftIO $ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr--trace :: (Shape.C sh, Class.Floating a) => Square sh a -> a-trace (Array (MatrixShape.Square _ sh) x) = unsafePerformIO $ do- let n = Shape.size sh- withForeignPtr x $ \xPtr -> Private.sum n xPtr (n+1)---multiply ::- (Shape.C sh, Eq sh, Class.Floating a) =>- Square sh a -> Square sh a -> Square sh a-multiply- (Array (MatrixShape.Square orderA shA) a)- (Array (MatrixShape.Square orderB shB) b) =- Array.unsafeCreate (MatrixShape.Square ColumnMajor shA) $ \cPtr -> do- Call.assert "Square.multiply: shapes mismatch" (shA == shB)- let n = Shape.size shA- Private.multiplyMatrix orderA orderB n n n a b cPtr+@(vr,d,vl) = eigensystem a@ -square :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a-square a = multiplyCommutativeUnchecked a a+Counterintuitively, @vr@ contains the right eigenvectors+and @vl@ contains the left eigenvectors as columns.+The idea is to provide a decomposition of @a@.+If @a@ is diagonalizable, then @vr@ and @vl@ are almost inverse to each other.+More precisely, @adjoint vl \<#\> vr@ is a diagonal matrix.+This is because all eigenvectors are normalized to Euclidean norm 1.+With the following scaling, the decomposition becomes perfect: -power ::- (Shape.C sh, Class.Floating a) =>- Integer -> Square sh a -> Square sh a-power n a =- powerAssociative multiplyCommutativeUnchecked (identityFrom a) a n+> let scal = Array.map recip $ takeDiagonal $ adjoint vl <#> vr+> a == vr <#> diagonal d <#> diagonal scal <#> adjoint vl -{--orderA and orderB must be equal but this is not checked.+If @a@ is non-diagonalizable then some columns of @vr@ and @vl@ are left zero+and the above property does not hold. -}-multiplyCommutativeUnchecked ::+eigensystem :: (Shape.C sh, Class.Floating a) =>- Square sh a -> Square sh a -> Square sh a-multiplyCommutativeUnchecked- (Array shape@(MatrixShape.Square order sh) a)- (Array (MatrixShape.Square _order _sh) b) =- Array.unsafeCreate shape $ \cPtr ->- let n = Shape.size sh- (at,bt) =- case order of- ColumnMajor -> (a,b)- RowMajor -> (b,a)- in Private.multiplyMatrix ColumnMajor ColumnMajor n n n at bt cPtr+ Square sh a ->+ (Square sh (ComplexOf a),+ Vector sh (ComplexOf a),+ Square sh (ComplexOf a))+eigensystem = Eigen.decompose
+ src/Numeric/LAPACK/Matrix/Square/Basic.hs view
@@ -0,0 +1,214 @@+module Numeric.LAPACK.Matrix.Square.Basic (+ Square,+ size,+ toFull,+ toGeneral,+ fromGeneral,+ fromScalar,+ toScalar,+ fromList,+ autoFromList,++ transpose,+ adjoint,++ identity,+ identityFrom,+ identityFromWidth,+ identityFromHeight,+ diagonal,+ takeDiagonal,+ trace,++ multiply,+ square,+ power,+ ) where+++import qualified Numeric.LAPACK.Matrix.Multiply as Mult+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as ExtentPriv+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor, ColumnMajor), swapOnRowMajor)+import Numeric.LAPACK.Matrix.Private+ (Full, mapExtent,+ General, argGeneral, Square, argSquare, ZeroInt, zeroInt)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (pokeCInt)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Storable (Storable, peek, poke)++import System.IO.Unsafe (unsafePerformIO)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Function.HT (powerAssociative)+++size :: Square sh a -> sh+size = MatrixShape.fullHeight . Array.shape++toGeneral :: Square sh a -> General sh sh a+toGeneral = toFull++toFull ::+ (Extent.C vert, Extent.C horiz) => Square sh a -> Full vert horiz sh sh a+toFull = mapExtent Extent.fromSquare++fromGeneral :: (Eq sh) => General sh sh a -> Square sh a+fromGeneral = mapExtent (ExtentPriv.Map ExtentPriv.squareFromGeneral)+++fromScalar :: (Storable a) => a -> Square () a+fromScalar a =+ Array.unsafeCreate (MatrixShape.square RowMajor ()) $ flip poke a++toScalar :: (Storable a) => Square () a -> a+toScalar = argSquare $ \_ () a ->+ unsafePerformIO $ withForeignPtr a peek++fromList :: (Shape.C sh, Storable a) => sh -> [a] -> Square sh a+fromList sh =+ Array.fromList (MatrixShape.square RowMajor sh)++autoFromList :: (Storable a) => [a] -> Square ZeroInt a+autoFromList xs =+ let n = length xs+ m = round $ sqrt (fromIntegral n :: Double)+ in if n == m*m+ then fromList (zeroInt m) xs+ else error "Square.autoFromList: no quadratic number of elements"+++transpose :: Square sh a -> Square sh a+transpose = Array.mapShape MatrixShape.transpose++{- |+conjugate transpose+-}+adjoint :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a+adjoint = transpose . Vector.conjugate+++identity :: (Shape.C sh, Class.Floating a) => sh -> Square sh a+identity = identityOrder ColumnMajor++identityFrom :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a+identityFrom = argSquare $ \order sh _ -> identityOrder order sh++identityFromWidth ::+ (Shape.C height, Shape.C width, Class.Floating a) =>+ General height width a -> Square width a+identityFromWidth =+ argGeneral $ \order _ width _ -> identityOrder order width++identityFromHeight ::+ (Shape.C height, Shape.C width, Class.Floating a) =>+ General height width a -> Square height a+identityFromHeight =+ argGeneral $ \order height _ _ -> identityOrder order height++identityOrder, _identityOrder ::+ (Shape.C sh, Class.Floating a) => Order -> sh -> Square sh a+identityOrder order sh =+ Array.unsafeCreate (MatrixShape.square order sh) $ \aPtr ->+ evalContT $ do+ uploPtr <- Call.char 'A'+ nPtr <- Call.cint $ Shape.size sh+ alphaPtr <- Call.number zero+ betaPtr <- Call.number one+ liftIO $ LapackGen.laset uploPtr nPtr nPtr alphaPtr betaPtr aPtr nPtr++_identityOrder order sh =+ Array.unsafeCreateWithSize (MatrixShape.square order sh) $ \blockSize yPtr ->+ evalContT $ do+ nPtr <- Call.alloca+ xPtr <- Call.number zero+ incxPtr <- Call.cint 0+ incyPtr <- Call.cint 1+ liftIO $ do+ pokeCInt nPtr blockSize+ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr+ let n = fromIntegral $ Shape.size sh+ poke nPtr n+ poke xPtr one+ poke incyPtr (n+1)+ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr++diagonal :: (Shape.C sh, Class.Floating a) => Vector sh a -> Square sh a+diagonal (Array sh x) =+ Array.unsafeCreateWithSize (MatrixShape.square ColumnMajor sh) $+ \blockSize yPtr ->+ evalContT $ do+ nPtr <- Call.alloca+ xPtr <- ContT $ withForeignPtr x+ zPtr <- Call.number zero+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ inczPtr <- Call.cint 0+ liftIO $ do+ pokeCInt nPtr blockSize+ BlasGen.copy nPtr zPtr inczPtr yPtr incyPtr+ let n = fromIntegral $ Shape.size sh+ poke nPtr n+ poke incyPtr (n+1)+ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr++takeDiagonal :: (Shape.C sh, Class.Floating a) => Square sh a -> Vector sh a+takeDiagonal = argSquare $ \_ sh x ->+ Array.unsafeCreateWithSize sh $ \n yPtr -> evalContT $ do+ nPtr <- Call.cint n+ xPtr <- ContT $ withForeignPtr x+ incxPtr <- Call.cint (n+1)+ incyPtr <- Call.cint 1+ liftIO $ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr++trace :: (Shape.C sh, Class.Floating a) => Square sh a -> a+trace = argSquare $ \_ sh x -> unsafePerformIO $ do+ let n = Shape.size sh+ withForeignPtr x $ \xPtr -> Private.sum n xPtr (n+1)+++multiply ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Square sh a -> Square sh a -> Square sh a+multiply = Mult.multiply++square :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a+square a = multiplyCommutativeUnchecked a a++power ::+ (Shape.C sh, Class.Floating a) =>+ Integer -> Square sh a -> Square sh a+power n a =+ powerAssociative multiplyCommutativeUnchecked (identityFrom a) a n++{-+orderA and orderB must be equal but this is not checked.+-}+multiplyCommutativeUnchecked ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a -> Square sh a -> Square sh a+multiplyCommutativeUnchecked+ (Array shape@(MatrixShape.Full order extent) a)+ (Array _ b) =+ Array.unsafeCreate shape $ \cPtr ->+ let n = Shape.size $ Extent.height extent+ (at,bt) = swapOnRowMajor order (a,b)+ in Private.multiplyMatrix ColumnMajor ColumnMajor n n n at bt cPtr
+ src/Numeric/LAPACK/Matrix/Square/Eigen.hs view
@@ -0,0 +1,302 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Square.Eigen (+ values,+ schur,+ decompose,+ ComplexOf,+ ) where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor), swapOnRowMajor)+import Numeric.LAPACK.Matrix.Private (Square, argSquare)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (ComplexOf, RealOf, zero)+import Numeric.LAPACK.Private+ (copyConjugate, copyToTemp, copyToColumnMajor,+ withAutoWorkspaceInfo)++import qualified Numeric.LAPACK.FFI.Complex as LapackComplex+import qualified Numeric.LAPACK.FFI.Real as LapackReal+import qualified Numeric.BLAS.FFI.Real as BlasReal+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)++import Foreign.Marshal.Array (advancePtr, peekArray)+import Foreign.C.Types (CInt, CChar)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr, nullPtr, nullFunPtr, castPtr)+import Foreign.Storable (Storable)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Complex (Complex)+++values ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a -> Vector sh (ComplexOf a)+values =+ getValues $+ Class.switchFloating+ (Values valuesAux) (Values valuesAux)+ (Values valuesAux) (Values valuesAux)++type Values_ sh a = Square sh a -> Vector sh (ComplexOf a)++newtype Values sh a = Values {getValues :: Values_ sh a}++valuesAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Values_ sh a+valuesAux = argSquare $ \_order size a ->+ Array.unsafeCreateWithSize size $ \n wPtr -> do+ let lda = n+ evalContT $ do+ jobvsPtr <- Call.char 'N'+ sortPtr <- Call.char 'N'+ aPtr <- copyToTemp (n*n) a+ ldaPtr <- Call.leadingDim lda+ sdimPtr <- Call.alloca+ let vsPtr = nullPtr+ ldvsPtr <- Call.leadingDim n+ let bworkPtr = nullPtr+ liftIO $+ withAutoWorkspaceInfo eigenMsg "gees" $ \workPtr lworkPtr infoPtr ->+ gees+ jobvsPtr sortPtr n aPtr ldaPtr sdimPtr+ wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr+++{- |+If @(q,r) = schur a@, then @a = q \<#\> r \<#\> adjoint q@,+where @q@ is unitary (orthogonal)+and @r@ is a right-upper triangular matrix for complex @a@+and a 1x1-or-2x2-block upper triangular matrix for real @a@.+With @takeDiagonal r@ you get all eigenvalues of @a@ if @a@ is complex+and the real parts of the eigenvalues if @a@ is real.+Complex conjugated eigenvalues of a real matrix @a@+are encoded as 2x2 blocks along the diagonal.+-}+schur ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a -> (Square sh a, Square sh a)+schur =+ getSchur $+ Class.switchFloating+ (Schur schurAux) (Schur schurAux)+ (Schur schurAux) (Schur schurAux)++type Schur_ sh a = Square sh a -> (Square sh a, Square sh a)++newtype Schur sh a = Schur {getSchur :: Schur_ sh a}++schurAux ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ Schur_ sh a+schurAux = argSquare $ \order size a ->+ let sh = MatrixShape.square ColumnMajor size+ in Array.unsafeCreateWithSizeAndResult sh $ \_ vsPtr ->+ ArrayIO.unsafeCreate sh $ \sPtr -> do++ let n = Shape.size size+ let lda = n+ evalContT $ do+ jobvsPtr <- Call.char 'V'+ sortPtr <- Call.char 'N'+ aPtr <- ContT $ withForeignPtr a+ liftIO $ copyToColumnMajor order n n aPtr sPtr+ ldaPtr <- Call.leadingDim lda+ sdimPtr <- Call.alloca+ wPtr <- Call.allocaArray n+ ldvsPtr <- Call.leadingDim n+ let bworkPtr = nullPtr+ liftIO $+ withAutoWorkspaceInfo eigenMsg "gees" $ \workPtr lworkPtr infoPtr ->+ gees+ jobvsPtr sortPtr n sPtr ldaPtr sdimPtr+ wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr++++type GEES_ ar a =+ Ptr CChar -> Ptr CChar -> Int -> Ptr a -> Ptr CInt ->+ Ptr CInt -> Ptr (Complex ar) -> Ptr a -> Ptr CInt ->+ Ptr a -> Ptr CInt -> Ptr Bool -> Ptr CInt -> IO ()++newtype GEES a = GEES {getGEES :: GEES_ (RealOf a) a}++gees :: Class.Floating a => GEES_ (RealOf a) a+gees =+ getGEES $+ Class.switchFloating+ (GEES geesReal) (GEES geesReal) (GEES geesComplex) (GEES geesComplex)++geesReal :: Class.Real a => GEES_ a a+geesReal+ jobvsPtr sortPtr n aPtr ldaPtr sdimPtr+ wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr =+ evalContT $ do+ let selectPtr = nullFunPtr+ nPtr <- Call.cint n+ wrPtr <- Call.allocaArray n+ wiPtr <- Call.allocaArray n+ liftIO $+ LapackReal.gees+ jobvsPtr sortPtr selectPtr nPtr aPtr ldaPtr sdimPtr+ wrPtr wiPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr+ liftIO $ zipComplex n wrPtr wiPtr wPtr++geesComplex :: Class.Real a => GEES_ a (Complex a)+geesComplex+ jobvsPtr sortPtr n aPtr ldaPtr sdimPtr+ wPtr vsPtr ldvsPtr workPtr lworkPtr bworkPtr infoPtr =+ evalContT $ do+ let selectPtr = nullFunPtr+ nPtr <- Call.cint n+ rworkPtr <- Call.allocaArray n+ liftIO $+ LapackComplex.gees+ jobvsPtr sortPtr selectPtr nPtr aPtr ldaPtr sdimPtr+ wPtr vsPtr ldvsPtr workPtr lworkPtr rworkPtr bworkPtr infoPtr++++decompose ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a ->+ (Square sh (ComplexOf a),+ Vector sh (ComplexOf a),+ Square sh (ComplexOf a))+decompose =+ getDecompose $+ Class.switchFloating+ (Decompose decomposeReal)+ (Decompose decomposeReal)+ (Decompose decomposeComplex)+ (Decompose decomposeComplex)++newtype Decompose sh a =+ Decompose {+ getDecompose ::+ Square sh a ->+ (Square sh (ComplexOf a),+ Vector sh (ComplexOf a),+ Square sh (ComplexOf a))+ }++decomposeReal ::+ (Shape.C sh, Class.Real a) =>+ Square sh a ->+ (Square sh (Complex a), Vector sh (Complex a), Square sh (Complex a))+decomposeReal = argSquare $ \order size a ->+ (\(w, (vlc,vrc)) -> (vlc, w, vrc)) $+ Array.unsafeCreateWithSizeAndResult size $ \n wPtr ->+ evalContT $ do+ jobvlPtr <- Call.char 'V'+ jobvrPtr <- Call.char 'V'+ nPtr <- Call.cint n+ aPtr <- copyToTemp (n*n) a+ ldaPtr <- Call.leadingDim n+ wrPtr <- Call.allocaArray n+ wiPtr <- Call.allocaArray n+ vlPtr <- Call.allocaArray (n*n)+ ldvlPtr <- Call.leadingDim n+ vrPtr <- Call.allocaArray (n*n)+ ldvrPtr <- Call.leadingDim n+ liftIO $ withAutoWorkspaceInfo eigenMsg "geev" $+ LapackReal.geev+ jobvlPtr jobvrPtr nPtr aPtr ldaPtr+ wrPtr wiPtr vlPtr ldvlPtr vrPtr ldvrPtr+ liftIO $ zipComplex n wrPtr wiPtr wPtr+ liftIO $ createArrayPair order (MatrixShape.square ColumnMajor size) $+ \vlcPtr vrcPtr -> do+ eigenvectorsToComplex n wiPtr vlPtr vlcPtr+ eigenvectorsToComplex n wiPtr vrPtr vrcPtr++eigenvectorsToComplex ::+ (Eq a, Class.Real a) =>+ Int -> Ptr a -> Ptr a -> Ptr (Complex a) -> IO ()+eigenvectorsToComplex n wiPtr vPtr vcPtr = evalContT $ do+ nPtr <- Call.cint n+ zeroPtr <- Call.real zero+ inc0Ptr <- Call.cint 0+ inc1Ptr <- Call.cint 1+ inc2Ptr <- Call.cint 2+ liftIO $ do+ let go _ _ [] = return ()+ go xPtr yPtr (False:wi) = do+ let yrPtr = castPtr yPtr+ let yiPtr = advancePtr yrPtr 1+ BlasReal.copy nPtr xPtr inc1Ptr yrPtr inc2Ptr+ BlasReal.copy nPtr zeroPtr inc0Ptr yiPtr inc2Ptr+ go (advancePtr xPtr n) (advancePtr yPtr n) wi+ go xPtr yPtr (True:True:wi) = do+ let xrPtr = xPtr+ let xiPtr = advancePtr xPtr n+ let yrPtr = castPtr yPtr+ let yiPtr = advancePtr yrPtr 1+ let y1Ptr = advancePtr yPtr n+ BlasReal.copy nPtr xrPtr inc1Ptr yrPtr inc2Ptr+ BlasReal.copy nPtr xiPtr inc1Ptr yiPtr inc2Ptr+ copyConjugate nPtr yPtr inc1Ptr y1Ptr inc1Ptr+ go (advancePtr xPtr (2*n)) (advancePtr yPtr (2*n)) wi+ go _xPtr _yPtr wi =+ error $ "eigenvectorToComplex: invalid non-real pattern " ++ show wi+ go vPtr vcPtr . map (zero/=) =<< peekArray n wiPtr++decomposeComplex ::+ (Shape.C sh, Class.Real a) =>+ Square sh (Complex a) ->+ (Square sh (Complex a), Vector sh (Complex a), Square sh (Complex a))+decomposeComplex = argSquare $ \order size a ->+ (\(w, (vlc,vrc)) -> (vlc, w, vrc)) $+ Array.unsafeCreateWithSizeAndResult size $ \n wPtr ->+ evalContT $ do+ jobvlPtr <- Call.char 'V'+ jobvrPtr <- Call.char 'V'+ nPtr <- Call.cint n+ aPtr <- copyToTemp (n*n) a+ ldaPtr <- Call.leadingDim n+ ldvlPtr <- Call.leadingDim n+ ldvrPtr <- Call.leadingDim n+ rworkPtr <- Call.allocaArray (2*n)++ liftIO $ createArrayPair order (MatrixShape.square ColumnMajor size) $+ \vlPtr vrPtr ->++ withAutoWorkspaceInfo eigenMsg "geev" $ \workPtr lworkPtr infoPtr ->+ LapackComplex.geev+ jobvlPtr jobvrPtr nPtr aPtr ldaPtr+ wPtr vlPtr ldvlPtr vrPtr ldvrPtr+ workPtr lworkPtr rworkPtr infoPtr+++zipComplex ::+ (Class.Real a) => Int -> Ptr a -> Ptr a -> Ptr (Complex a) -> IO ()+zipComplex n vr vi vc =+ evalContT $ do+ nPtr <- Call.cint n+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 2+ let yPtr = castPtr vc+ liftIO $ BlasReal.copy nPtr vr incxPtr yPtr incyPtr+ liftIO $ BlasReal.copy nPtr vi incxPtr (advancePtr yPtr 1) incyPtr++createArrayPair ::+ (Shape.C sh, Storable a) =>+ Order -> sh -> (Ptr a -> Ptr a -> IO ()) ->+ IO (Array sh a, Array sh a)+createArrayPair order sh act =+ fmap (swapOnRowMajor order) $+ ArrayIO.unsafeCreateWithSizeAndResult sh $ \_ vrcPtr ->+ ArrayIO.unsafeCreate sh $ \vlcPtr -> act vlcPtr vrcPtr+++eigenMsg :: String+eigenMsg = "only eigenvalues starting with the %d-th one converged"
+ src/Numeric/LAPACK/Matrix/Square/Linear.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Matrix.Square.Linear (+ solve,+ inverse,+ determinant,+ ) where++import Numeric.LAPACK.Matrix.Private (Full, Square, argSquare)++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Split as Split+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Linear.Private+ (solver, withDeterminantInfo, withInfo, diagonalMsg)+import Numeric.LAPACK.Matrix.Shape.Private (transposeFromOrder)+import Numeric.LAPACK.Private+ (withAutoWorkspaceInfo, copyBlock, copyToTemp, copyToColumnMajor)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import System.IO.Unsafe (unsafePerformIO)++import Foreign.Marshal.Array (peekArray)+import Foreign.ForeignPtr (withForeignPtr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (when)+++solve, _solve ::+ (Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Square sh a -> Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solve =+ argSquare $ \orderA shA a ->+ solver "Square.solve" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ transPtr <- Call.char $ transposeFromOrder orderA+ aPtr <- copyToTemp (n*n) a+ ldaPtr <- Call.leadingDim n+ ipivPtr <- Call.allocaArray n+ liftIO $ do+ withInfo "getrf" $+ LapackGen.getrf nPtr nPtr aPtr ldaPtr ipivPtr+ withInfo "getrs" $+ LapackGen.getrs transPtr nPtr nrhsPtr+ aPtr ldaPtr ipivPtr xPtr ldxPtr++_solve =+ argSquare $ \orderA shA a ->+ solver "Square.solve" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ aPtr <- ContT $ withForeignPtr a+ atmpPtr <- Call.allocaArray (n*n)+ ldaPtr <- Call.leadingDim n+ ipivPtr <- Call.allocaArray n+ liftIO $ do+ copyToColumnMajor orderA n n aPtr atmpPtr+ withInfo "gesv" $+ LapackGen.gesv nPtr nrhsPtr atmpPtr ldaPtr ipivPtr xPtr ldxPtr+++inverse :: (Shape.C sh, Class.Floating a) => Square sh a -> Square sh a+inverse (Array shape@(MatrixShape.Full _order extent) a) =+ Array.unsafeCreateWithSize shape $ \blockSize bPtr -> do+ let n = Shape.size $ Extent.squareSize extent+ evalContT $ do+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ ldbPtr <- Call.leadingDim n+ ipivPtr <- Call.allocaArray n+ liftIO $ when (n>0) $ do+ copyBlock blockSize aPtr bPtr+ withInfo "getrf" $ LapackGen.getrf nPtr nPtr bPtr ldbPtr ipivPtr+ withAutoWorkspaceInfo diagonalMsg "getri" $+ LapackGen.getri nPtr bPtr ldbPtr ipivPtr+++determinant :: (Shape.C sh, Class.Floating a) => Square sh a -> a+determinant = argSquare $ \_order sh a -> unsafePerformIO $ do+ let n = Shape.size sh+ evalContT $ do+ nPtr <- Call.cint n+ aPtr <- copyToTemp (n*n) a+ ldaPtr <- Call.leadingDim n+ ipivPtr <- Call.allocaArray n+ liftIO $ withDeterminantInfo "getrf"+ (LapackGen.getrf nPtr nPtr aPtr ldaPtr ipivPtr)+ (do+ det <- Private.product n aPtr (n+1)+ ipiv <- peekArray n ipivPtr+ return $ if Split.oddPermutation ipiv then -det else det)
+ src/Numeric/LAPACK/Matrix/Symmetric/Private.hs view
@@ -0,0 +1,158 @@+module Numeric.LAPACK.Matrix.Symmetric.Private where++import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Triangular.Private+ (diagonalPointerPairs, columnMajorPointers, rowMajorPointers,+ forPointers, pack, unpackToTemp, copyTriangleToTemp)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor), uploFromOrder, triangleSize)+import Numeric.LAPACK.Matrix.Private+ (Full, Conjugation(NonConjugated, Conjugated))+import Numeric.LAPACK.Linear.Private (solver, withDeterminantInfo, withInfo)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (copyBlock, copyToTemp, copyCondConjugate)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Shape as Shape++import Foreign.Marshal.Array (advancePtr)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable, peek)++import qualified System.IO.Lazy as LazyIO++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Applicative ((<$>))+++unpack :: Class.Floating a =>+ Conjugation -> Order -> Int -> Ptr a -> Ptr a -> IO ()+unpack conj order n packedPtr fullPtr = evalContT $ do+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint n+ liftIO $ case order of+ RowMajor ->+ forPointers (rowMajorPointers n fullPtr packedPtr) $+ \nPtr (dstPtr,srcPtr) -> do+ copyCondConjugate (conj==Conjugated)+ nPtr srcPtr incxPtr dstPtr incyPtr+ BlasGen.copy nPtr srcPtr incxPtr dstPtr incxPtr+ ColumnMajor ->+ forPointers (columnMajorPointers n fullPtr packedPtr) $+ \nPtr ((dstRowPtr,dstColumnPtr),srcPtr) -> do+ copyCondConjugate (conj==Conjugated)+ nPtr srcPtr incxPtr dstRowPtr incyPtr+ BlasGen.copy nPtr srcPtr incxPtr dstColumnPtr incxPtr+++square ::+ (Class.Floating a) =>+ Conjugation -> Order -> Int -> ForeignPtr a -> Ptr a -> IO ()+square conj order n a bpPtr =+ evalContT $ do+ sidePtr <- Call.char 'L'+ uploPtr <- Call.char 'U'+ nPtr <- Call.cint n+ ldPtr <- Call.leadingDim n+ aPtr <- unpackToTemp (unpack conj order) n a+ bPtr <- Call.allocaArray (n*n)+ alphaPtr <- Call.number one+ betaPtr <- Call.number zero+ liftIO $ do+ (if conj==Conjugated then BlasGen.hemm else BlasGen.symm)+ sidePtr uploPtr+ nPtr nPtr alphaPtr aPtr ldPtr+ aPtr ldPtr betaPtr bPtr ldPtr+ pack order n bPtr bpPtr+++solve ::+ (Extent.C vert, Extent.C horiz,+ Shape.C width, Shape.C height, Eq height, Class.Floating a) =>+ String -> Conjugation -> Order -> height -> ForeignPtr a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+solve name conj order sh a =+ solver name sh $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder order+ apPtr <- copyTriangleToTemp conj order (triangleSize n) a+ ipivPtr <- Call.allocaArray n+ liftIO $+ let (lapackName,slv) =+ case conj of+ Conjugated -> ("hpsv", LapackGen.hpsv)+ NonConjugated -> ("spsv", LapackGen.spsv)+ in withInfo lapackName $+ slv uploPtr nPtr nrhsPtr apPtr ipivPtr xPtr ldxPtr+++inverse ::+ Class.Floating a =>+ Conjugation -> Order -> Int -> ForeignPtr a -> Int -> Ptr a -> IO ()+inverse conj order n a triSize bPtr = evalContT $ do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ ipivPtr <- Call.allocaArray n+ workPtr <- Call.allocaArray n+ liftIO $ do+ copyBlock triSize aPtr bPtr+ case conj of+ Conjugated -> do+ withInfo "hptrf" $ LapackGen.hptrf uploPtr nPtr bPtr ipivPtr+ withInfo "hptri" $ LapackGen.hptri uploPtr nPtr bPtr ipivPtr workPtr+ NonConjugated -> do+ withInfo "sptrf" $ LapackGen.sptrf uploPtr nPtr bPtr ipivPtr+ withInfo "sptri" $ LapackGen.sptri uploPtr nPtr bPtr ipivPtr workPtr+++blockDiagonalPointers ::+ (Storable a) =>+ Order -> [(Ptr CInt, Ptr a)] -> LazyIO.T [(Ptr a, Maybe (Ptr a, Ptr a))]+blockDiagonalPointers order =+ let go ((ipiv0Ptr,a0Ptr):ptrs0) = do+ ipiv <- LazyIO.interleave $ peek ipiv0Ptr+ (ext,ptrTuples) <-+ if ipiv >= 0+ then (,) Nothing <$> go ptrs0+ else+ case ptrs0 of+ [] -> error "Symmetric.determinant: incomplete 2x2 block"+ (_ipiv1Ptr,a1Ptr):ptrs1 ->+ let bPtr =+ case order of+ ColumnMajor -> advancePtr a1Ptr (-1)+ RowMajor -> advancePtr a0Ptr 1+ in (,) (Just (a1Ptr,bPtr)) <$> go ptrs1+ return $ (a0Ptr,ext) : ptrTuples+ go [] = return []+ in go++determinant ::+ (Class.Floating a, Class.Floating ar) =>+ Conjugation -> ((Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar) ->+ Order -> Int -> ForeignPtr a -> IO ar+determinant conj peekBlockDeterminant order n a = evalContT $ do+ uploPtr <- Call.char $ uploFromOrder order+ nPtr <- Call.cint n+ aPtr <- copyToTemp (triangleSize n) a+ ipivPtr <- Call.allocaArray n+ let (name,trf) =+ case conj of+ Conjugated -> ("hptrf", LapackGen.hptrf)+ NonConjugated -> ("sptrf", LapackGen.sptrf)+ liftIO $ withDeterminantInfo name+ (trf uploPtr nPtr aPtr ipivPtr)+ (((return $!) =<<) $+ LazyIO.run+ (fmap product $+ mapM (LazyIO.interleave . peekBlockDeterminant) =<<+ blockDiagonalPointers order+ (diagonalPointerPairs order n ipivPtr aPtr)))
src/Numeric/LAPACK/Matrix/Triangular.hs view
@@ -1,315 +1,58 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-} module Numeric.LAPACK.Matrix.Triangular (- Triangular, MatrixShape.Uplo(..),- Upper, Lower,- fromList, autoFromList,- lowerFromList, autoLowerFromList,- upperFromList, autoUpperFromList,- identity,- diagonal,- getDiagonal,- transposeUp, transposeDown,- adjointUp, adjointDown,-- toSquare,+ module Numeric.LAPACK.Matrix.Triangular.Basic,+ module Numeric.LAPACK.Matrix.Triangular.Linear,+ size, - multiplyVectorLeft,- multiplyVectorRight,- square,- multiply,- multiplySquareLeft,- multiplyGeneralLeft,- multiplySquareRight,- multiplyGeneralRight,+ eigenvalues,+ eigensystem, ) where +import qualified Numeric.LAPACK.Matrix.Triangular.Eigen as Eigen+import Numeric.LAPACK.Matrix.Triangular.Basic+import Numeric.LAPACK.Matrix.Triangular.Linear+ import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Matrix.Triangular.Private- (diagonalPointers, pack, unpack, unpackZero, unpackToTemp)-import Numeric.LAPACK.Matrix.Shape.Private- (Order(RowMajor,ColumnMajor),- flipOrder, transposeFromOrder, uploFromOrder, uploOrder)-import Numeric.LAPACK.Matrix.Square (Square)-import Numeric.LAPACK.Matrix.Private (General, ZeroInt, zeroInt)+import Numeric.LAPACK.Matrix.Shape.Private (NonUnit) import Numeric.LAPACK.Vector (Vector)-import Numeric.LAPACK.Private (fill, zero, one, copyBlock) -import qualified Numeric.BLAS.FFI.Generic as BlasGen-import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class -import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Storable as Array import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array)) -import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr)-import Foreign.Storable (Storable, poke, peek) -import Control.Monad.Trans.Cont (ContT(ContT), evalContT)-import Control.Monad.IO.Class (liftIO)--import Data.Foldable (forM_)---type Triangular uplo sh = Array (MatrixShape.Triangular uplo sh)--type Lower sh = Array (MatrixShape.LowerTriangular sh)-type Upper sh = Array (MatrixShape.UpperTriangular sh)--transposeUp :: Lower sh a -> Upper sh a-transposeUp (Array sh a) =- Array (MatrixShape.triangularTransposeUp sh) a--transposeDown :: Upper sh a -> Lower sh a-transposeDown (Array sh a) =- Array (MatrixShape.triangularTransposeDown sh) a--adjointUp :: (Shape.C sh, Class.Floating a) => Lower sh a -> Upper sh a-adjointUp = Vector.conjugate . transposeUp--adjointDown :: (Shape.C sh, Class.Floating a) => Upper sh a -> Lower sh a-adjointDown = Vector.conjugate . transposeDown---fromList ::- (MatrixShape.Uplo uplo, Shape.C sh, Storable a) =>- Order -> sh -> [a] -> Triangular uplo sh a-fromList order sh =- Array.fromList (MatrixShape.Triangular MatrixShape.autoUplo order sh)--lowerFromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Lower sh a-lowerFromList = fromList--upperFromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Upper sh a-upperFromList = fromList---autoFromList ::- (MatrixShape.Uplo uplo, Storable a) =>- Order -> [a] -> Triangular uplo ZeroInt a-autoFromList order xs =- fromList order- (zeroInt $ MatrixShape.triangleExtent "Triangular.autoFromList" $- length xs)- xs--autoLowerFromList :: (Storable a) => Order -> [a] -> Lower ZeroInt a-autoLowerFromList = autoFromList--autoUpperFromList :: (Storable a) => Order -> [a] -> Upper ZeroInt a-autoUpperFromList = autoFromList---toSquare ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a -> Square sh a-toSquare (Array (MatrixShape.Triangular uplo order sh) a) =- Array.unsafeCreate (MatrixShape.Square order sh) $ \bPtr ->- withForeignPtr a $ \aPtr ->- unpackZero (uploOrder uplo order) (Shape.size sh) aPtr bPtr---identity ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Order -> sh -> Triangular uplo sh a-identity order sh =- let (realOrder, uplo) = autoUploOrder order- in Array.unsafeCreate (MatrixShape.Triangular uplo order sh) $ \aPtr -> do- let n = Shape.size sh- fill zero (MatrixShape.triangleSize n) aPtr- forM_ (diagonalPointers realOrder n aPtr aPtr) $ flip poke one . snd--diagonal ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Order -> Vector sh a -> Triangular uplo sh a-diagonal order (Array sh x) =- let (realOrder, uplo) = autoUploOrder order- in Array.unsafeCreate (MatrixShape.Triangular uplo order sh) $ \aPtr -> do- let n = Shape.size sh- fill zero (MatrixShape.triangleSize n) aPtr- withForeignPtr x $ \xPtr ->- forM_ (diagonalPointers realOrder n xPtr aPtr) $- \(srcPtr,dstPtr) -> poke dstPtr =<< peek srcPtr--getDiagonal ::- (MatrixShape.Uplo uplo, Shape.C sh, Class.Floating a) =>- Triangular uplo sh a -> Vector sh a-getDiagonal (Array (MatrixShape.Triangular uplo order sh) a) =- Array.unsafeCreate sh $ \xPtr -> do- withForeignPtr a $ \aPtr ->- mapM_- (\(dstPtr,srcPtr) -> poke dstPtr =<< peek srcPtr)- (diagonalPointers (uploOrder uplo order) (Shape.size sh) xPtr aPtr)---multiplyVectorLeft, multiplyVectorRight ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Triangular uplo sh a -> Vector sh a -> Vector sh a-multiplyVectorLeft = multiplyVector True-multiplyVectorRight = multiplyVector False--multiplyVector ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Bool -> Triangular uplo sh a -> Vector sh a -> Vector sh a-multiplyVector transp- (Array (MatrixShape.Triangular uplo order shA) a) (Array shX x) =- Array.unsafeCreate shX $ \yPtr -> do- Call.assert "Triangular.multiplyVector: width shapes mismatch" (shA == shX)- let n = Shape.size shA- evalContT $ do- uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo order- transPtr <-- Call.char $ transposeFromOrder $- (if transp then flipOrder else id) order- diagPtr <- Call.char 'N'- nPtr <- Call.cint n- aPtr <- ContT $ withForeignPtr a- xPtr <- ContT $ withForeignPtr x- incyPtr <- Call.cint 1- liftIO $ do- copyBlock n xPtr yPtr- BlasGen.tpmv uploPtr transPtr diagPtr nPtr aPtr yPtr incyPtr+size :: Triangular lo diag up sh a -> sh+size = MatrixShape.triangularSize . Array.shape -square ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Triangular uplo sh a -> Triangular uplo sh a-square- (Array shape@(MatrixShape.Triangular uplo order sh) a) =- Array.unsafeCreate shape $ \bpPtr -> do- let n = Shape.size sh- evalContT $ do- sidePtr <- Call.char 'L'- let realOrder = uploOrder uplo order- uploPtr <- Call.char $ uploFromOrder realOrder- transPtr <- Call.char 'N'- diagPtr <- Call.char 'N'- nPtr <- Call.cint n- let ldPtr = nPtr- aPtr <- unpackToTemp (unpack realOrder) n a- bPtr <- unpackToTemp (unpackZero realOrder) n a- alphaPtr <- Call.number one- liftIO $ do- BlasGen.trmm sidePtr uploPtr transPtr diagPtr- nPtr nPtr alphaPtr aPtr ldPtr bPtr ldPtr- pack realOrder n bPtr bpPtr--multiply ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Triangular uplo sh a -> Triangular uplo sh a -> Triangular uplo sh a-multiply- (Array (MatrixShape.Triangular uploA orderA shA) a)- (Array shapeB@(MatrixShape.Triangular uploB orderB shB) b) =- Array.unsafeCreate shapeB $ \cpPtr -> do- Call.assert "Triangular.multiply: width shapes mismatch" (shA == shB)- let n = Shape.size shA- evalContT $ do- let (side,trans) =- case orderB of- ColumnMajor -> ('L', orderA)- RowMajor -> ('R', flipOrder orderA)- sidePtr <- Call.char side- let realOrderA = uploOrder uploA orderA- let realOrderB = uploOrder uploB orderB- uploPtr <- Call.char $ uploFromOrder realOrderA- transPtr <- Call.char $ transposeFromOrder trans- diagPtr <- Call.char 'N'- nPtr <- Call.cint n- let ldPtr = nPtr- aPtr <- unpackToTemp (unpack realOrderA) n a- bPtr <- unpackToTemp (unpackZero realOrderB) n b- alphaPtr <- Call.number one- liftIO $ do- BlasGen.trmm sidePtr uploPtr transPtr diagPtr- nPtr nPtr alphaPtr aPtr ldPtr bPtr ldPtr- pack realOrderB n bPtr cpPtr+eigenvalues ::+ (MatrixShape.DiagUpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Vector sh a+eigenvalues = Eigen.values -multiplySquareLeft ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Square sh a -> Triangular uplo sh a -> Square sh a-multiplySquareLeft- (Array shapeB@(MatrixShape.Square orderB shB) b)- (Array (MatrixShape.Triangular uploA orderA shA) a) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Triangular.multiplySquareLeft: shapes mismatch" (shA == shB)- let n = Shape.size shB- MatrixShape.caseUplo uploA- (multiplyAux MatrixShape.Upper)- (multiplyAux MatrixShape.Lower)- (flipOrder orderA) n a (flipOrder orderB) n b cPtr--multiplyGeneralLeft ::- (MatrixShape.Uplo uplo,- Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- General height width a -> Triangular uplo width a -> General height width a-multiplyGeneralLeft- (Array shapeB@(MatrixShape.General orderB height width) b)- (Array (MatrixShape.Triangular uploA orderA shA) a) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Triangular.multiplyGeneralLeft: shapes mismatch" (shA == width)- MatrixShape.caseUplo uploA- (multiplyAux MatrixShape.Upper)- (multiplyAux MatrixShape.Lower)- (flipOrder orderA) (Shape.size width) a- (flipOrder orderB) (Shape.size height) b cPtr--multiplySquareRight ::- (MatrixShape.Uplo uplo, Shape.C sh, Eq sh, Class.Floating a) =>- Triangular uplo sh a -> Square sh a -> Square sh a-multiplySquareRight- (Array (MatrixShape.Triangular uploA orderA shA) a)- (Array shapeB@(MatrixShape.Square orderB shB) b) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Triangular.multiplySquareRight: shapes mismatch" (shA == shB)- let n = Shape.size shB- multiplyAux uploA orderA n a orderB n b cPtr--multiplyGeneralRight ::- (MatrixShape.Uplo uplo,- Shape.C height, Eq height, Shape.C width, Class.Floating a) =>- Triangular uplo height a -> General height width a -> General height width a-multiplyGeneralRight- (Array (MatrixShape.Triangular uploA orderA shA) a)- (Array shapeB@(MatrixShape.General orderB height width) b) =- Array.unsafeCreate shapeB $ \cPtr -> do- Call.assert "Triangular.multiplyGeneralRight: shapes mismatch"- (shA == height)- multiplyAux- uploA orderA (Shape.size height) a orderB (Shape.size width) b cPtr+{- |+@(vr,d,vlAdj) = eigensystem a@ -multiplyAux ::- (MatrixShape.Uplo uplo, Class.Floating a) =>- uplo ->- Order -> Int -> ForeignPtr a ->- Order -> Int -> ForeignPtr a -> Ptr a -> IO ()-multiplyAux uploA orderA m0 a orderB n0 b cPtr =- evalContT $ do- let (side,trans,(m,n)) =- case orderB of- ColumnMajor -> ('L', orderA, (m0,n0))- RowMajor -> ('R', flipOrder orderA, (n0,m0))- sidePtr <- Call.char side- let realOrderA = uploOrder uploA orderA- uploPtr <- Call.char $ uploFromOrder realOrderA- transPtr <- Call.char $ transposeFromOrder trans- diagPtr <- Call.char 'N'- mPtr <- Call.cint m- nPtr <- Call.cint n- alphaPtr <- Call.number one- aPtr <- unpackToTemp (unpack realOrderA) m0 a- ldaPtr <- Call.cint m0- bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint m- liftIO $ do- copyBlock (m0*n0) bPtr cPtr- BlasGen.trmm sidePtr uploPtr transPtr diagPtr- mPtr nPtr alphaPtr aPtr ldaPtr cPtr ldbPtr+Counterintuitively, @vr@ contains the right eigenvectors as columns+and @vlAdj@ contains the left conjugated eigenvectors as rows.+The idea is to provide a decomposition of @a@.+If @a@ is diagonalizable, then @vr@ and @vlAdj@+are almost inverse to each other.+More precisely, @vlAdj \<#\> vr@ is a diagonal matrix.+This is because the eigenvectors are not normalized.+With the following scaling, the decomposition becomes perfect: +> let scal = Array.map recip $ takeDiagonal $ vlAdj <#> vr+> a == vr <#> diagonal d <#> diagonal scal <#> vlAdj -autoUploOrder :: MatrixShape.Uplo uplo => Order -> (Order, uplo)-autoUploOrder order =- case MatrixShape.autoUplo of- uplo -> (uploOrder uplo order, uplo)+If @a@ is non-diagonalizable+then some columns of @vr@ and corresponding rows of @vlAdj@ are left zero+and the above property does not hold.+-}+eigensystem ::+ (MatrixShape.DiagUpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo NonUnit up sh a ->+ (Triangular lo NonUnit up sh a, Vector sh a, Triangular lo NonUnit up sh a)+eigensystem = Eigen.decompose
+ src/Numeric/LAPACK/Matrix/Triangular/Basic.hs view
@@ -0,0 +1,548 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+module Numeric.LAPACK.Matrix.Triangular.Basic (+ Triangular, MatrixShape.UpLo,+ Upper, UnitUpper,+ Lower, UnitLower,+ Symmetric, Diagonal,+ fromList, autoFromList,+ lowerFromList, autoLowerFromList,+ upperFromList, autoUpperFromList,+ symmetricFromList, autoSymmetricFromList,+ diagonalFromList, autoDiagonalFromList,+ relaxUnitDiagonal, strictNonUnitDiagonal,+ asDiagonal, asLower, asUpper, asSymmetric,+ forceUnitDiagonal, forceNonUnitDiagonal,+ identity,+ diagonal,+ takeDiagonal,+ transpose,+ adjoint,++ toSquare,+ takeUpper,+ takeLower,++ Tri.PowerDiag,+ multiplyVector,+ square, squareGeneric,+ multiply,+ multiplyFull,+ ) where++import qualified Numeric.LAPACK.Matrix.Symmetric.Private as Symmetric+import qualified Numeric.LAPACK.Matrix.Triangular.Private as Tri+import qualified Numeric.LAPACK.Matrix.Basic as Basic+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Triangular.Private+ (Triangular, FlexDiagonal, diagonalPointers, diagonalPointerPairs,+ pack, packRect, unpack, unpackZero, unpackToTemp)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor,ColumnMajor),+ flipOrder, transposeFromOrder, uploFromOrder, uploOrder,+ Unit(Unit), NonUnit(NonUnit), charFromTriDiag)+import Numeric.LAPACK.Matrix.Private+ (Full, Square, ZeroInt, zeroInt, Conjugation(NonConjugated))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (fill, copyBlock)++import qualified Numeric.LAPACK.FFI.Complex as LapackComplex+import qualified Numeric.BLAS.FFI.Real as BlasReal+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.C.Types (CChar, CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable, poke, peek)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Foldable (forM_)+++type Lower sh = FlexLower NonUnit sh+type Upper sh = FlexUpper NonUnit sh+type Symmetric sh = Array (MatrixShape.Symmetric sh)+type Diagonal sh = FlexDiagonal NonUnit sh++type FlexLower diag sh = Array (MatrixShape.LowerTriangular diag sh)+type FlexUpper diag sh = Array (MatrixShape.UpperTriangular diag sh)+type FlexSymmetric diag sh = Array (MatrixShape.FlexSymmetric diag sh)++type UnitLower sh = Array (MatrixShape.LowerTriangular Unit sh)+type UnitUpper sh = Array (MatrixShape.UpperTriangular Unit sh)++transpose ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag) =>+ Triangular lo diag up sh a -> Triangular up diag lo sh a+transpose (Array sh a) =+ Array (MatrixShape.triangularTranspose sh) a++adjoint ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ MatrixShape.TriDiag diag, Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular up diag lo sh a+adjoint = Vector.conjugate . transpose+++fromList ::+ (MatrixShape.Content lo, MatrixShape.Content up, Shape.C sh, Storable a) =>+ Order -> sh -> [a] -> Triangular lo NonUnit up sh a+fromList order sh =+ Array.fromList (MatrixShape.Triangular NonUnit MatrixShape.autoUplo order sh)++lowerFromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Lower sh a+lowerFromList = fromList++upperFromList :: (Shape.C sh, Storable a) => Order -> sh -> [a] -> Upper sh a+upperFromList = fromList++symmetricFromList ::+ (Shape.C sh, Storable a) => Order -> sh -> [a] -> Symmetric sh a+symmetricFromList = fromList++diagonalFromList ::+ (Shape.C sh, Storable a) => Order -> sh -> [a] -> Diagonal sh a+diagonalFromList = fromList+++autoFromList ::+ (MatrixShape.Content lo, MatrixShape.Content up, Storable a) =>+ Order -> [a] -> Triangular lo NonUnit up ZeroInt a+autoFromList order xs =+ let n = length xs+ triSize = MatrixShape.triangleExtent "Triangular.autoFromList" n+ uplo = MatrixShape.autoUplo+ size = MatrixShape.caseDiagUpLoSym uplo n triSize triSize triSize+ in Array.fromList+ (MatrixShape.Triangular+ MatrixShape.autoDiag uplo order (zeroInt size))+ xs++autoLowerFromList :: (Storable a) => Order -> [a] -> Lower ZeroInt a+autoLowerFromList = autoFromList++autoUpperFromList :: (Storable a) => Order -> [a] -> Upper ZeroInt a+autoUpperFromList = autoFromList++autoSymmetricFromList :: (Storable a) => Order -> [a] -> Symmetric ZeroInt a+autoSymmetricFromList = autoFromList++autoDiagonalFromList :: (Storable a) => Order -> [a] -> Diagonal ZeroInt a+autoDiagonalFromList = autoFromList+++asDiagonal :: FlexDiagonal diag sh a -> FlexDiagonal diag sh a+asDiagonal = id++asLower :: FlexLower diag sh a -> FlexLower diag sh a+asLower = id++asUpper :: FlexUpper diag sh a -> FlexUpper diag sh a+asUpper = id++asSymmetric :: FlexSymmetric diag sh a -> FlexSymmetric diag sh a+asSymmetric = id++forceUnitDiagonal :: Triangular lo Unit up sh a -> Triangular lo Unit up sh a+forceUnitDiagonal = id++forceNonUnitDiagonal ::+ Triangular lo NonUnit up sh a -> Triangular lo NonUnit up sh a+forceNonUnitDiagonal = id+++toSquare ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Square sh a+toSquare (Array (MatrixShape.Triangular _diag uplo order sh) a) =+ Array.unsafeCreateWithSize (MatrixShape.square order sh) $ \size bPtr ->+ let n = Shape.size sh+ in withForeignPtr a $ \aPtr ->+ MatrixShape.caseDiagUpLoSym uplo+ (do+ fill zero size bPtr+ evalContT $ do+ nPtr <- Call.cint n+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint (n+1)+ liftIO $ BlasGen.copy nPtr aPtr incxPtr bPtr incyPtr)+ (unpackZero order n aPtr bPtr)+ (unpackZero (flipOrder order) n aPtr bPtr)+ (Symmetric.unpack NonConjugated order n aPtr bPtr)++takeLower ::+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ Full Extent.Small horiz height width a -> Lower height a+takeLower =+ Tri.takeLower (MatrixShape.NonUnit, const $ const $ const $ return ())++takeUpper ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert Extent.Small height width a -> Upper width a+takeUpper (Array (MatrixShape.Full order extent) a) =+ let (height,width) = Extent.dimensions extent+ m = Shape.size height+ n = Shape.size width+ k = case order of RowMajor -> n; ColumnMajor -> m+ in Array.unsafeCreate+ (MatrixShape.Triangular MatrixShape.NonUnit+ MatrixShape.upper order width) $ \bPtr ->+ withForeignPtr a $ \aPtr -> packRect order n k aPtr bPtr+++identity ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ Shape.C sh, Class.Floating a) =>+ Order -> sh -> Triangular lo Unit up sh a+identity order sh =+ let (realOrder, uplo) = autoUploOrder order+ in Array.unsafeCreateWithSize (MatrixShape.Triangular Unit uplo order sh) $+ \size aPtr -> do+ let n = Shape.size sh+ let fillTriangle = do+ fill zero size aPtr+ mapM_ (flip poke one) (diagonalPointers realOrder n aPtr)+ MatrixShape.caseDiagUpLoSym uplo+ (fill one n aPtr)+ fillTriangle+ fillTriangle+ fillTriangle++diagonal, diagonalAux ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ Shape.C sh, Class.Floating a) =>+ Order -> Vector sh a -> Triangular lo NonUnit up sh a+diagonal order x@(Array sh xPtr) =+ let uplo = MatrixShape.autoUplo+ in MatrixShape.caseDiagUpLoSym uplo+ (Array (MatrixShape.Triangular NonUnit uplo order sh) xPtr)+ (diagonalAux order x)+ (diagonalAux order x)+ (diagonalAux order x)++diagonalAux order (Array sh x) =+ let (realOrder, uplo) = autoUploOrder order+ in Array.unsafeCreateWithSize+ (MatrixShape.Triangular NonUnit uplo order sh) $+ \size aPtr -> do+ let n = Shape.size sh+ fill zero size aPtr+ withForeignPtr x $ \xPtr ->+ forM_ (diagonalPointerPairs realOrder n xPtr aPtr) $+ \(srcPtr,dstPtr) -> poke dstPtr =<< peek srcPtr+++takeDiagonal, takeDiagonalAux ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Vector sh a+takeDiagonal a@(Array (MatrixShape.Triangular _diag uplo _order sh) aPtr) =+ MatrixShape.caseDiagUpLoSym uplo+ (Array sh aPtr)+ (takeDiagonalAux a)+ (takeDiagonalAux a)+ (takeDiagonalAux a)++takeDiagonalAux (Array (MatrixShape.Triangular _diag uplo order sh) a) =+ Array.unsafeCreate sh $ \xPtr ->+ withForeignPtr a $ \aPtr ->+ mapM_+ (\(dstPtr,srcPtr) -> poke dstPtr =<< peek srcPtr)+ (diagonalPointerPairs (uploOrder uplo order) (Shape.size sh) xPtr aPtr)++relaxUnitDiagonal ::+ (MatrixShape.TriDiag diag) =>+ Triangular lo Unit up sh a -> Triangular lo diag up sh a+relaxUnitDiagonal = Array.mapShape MatrixShape.relaxUnitDiagonal++strictNonUnitDiagonal ::+ (MatrixShape.TriDiag diag) =>+ Triangular lo diag up sh a -> Triangular lo NonUnit up sh a+strictNonUnitDiagonal = Array.mapShape MatrixShape.strictNonUnitDiagonal+++multiplyVector ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Vector sh a -> Vector sh a+multiplyVector =+ Tri.getMultiplyRight $+ MatrixShape.switchDiagUpLoSym+ (Tri.MultiplyRight $+ Tri.multiplyDiagonal+ "multiplyVector.diagonal: sizes mismatch"+ Array.shape+ (Vector.mul . takeDiagonal))+ (Tri.MultiplyRight multiplyVectorTriangular)+ (Tri.MultiplyRight multiplyVectorTriangular)+ (Tri.MultiplyRight multiplyVectorTriangular)++multiplyVectorTriangular ::+ (MatrixShape.UpLoSym lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Vector sh a -> Vector sh a+multiplyVectorTriangular+ (Array (MatrixShape.Triangular diag uplo order shA) a) (Array shX x) =+ Array.unsafeCreate shX $ \yPtr -> do+ Call.assert "Triangular.multiplyVector: width shapes mismatch" (shA == shX)+ let n = Shape.size shA+ evalContT $ do+ uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo order+ transPtr <- Call.char $ transposeFromOrder order+ diagPtr <- Call.char $ charFromTriDiag diag+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ xPtr <- ContT $ withForeignPtr x+ alphaPtr <- Call.number one+ betaPtr <- Call.number zero+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ let runTPMV = do+ copyBlock n xPtr yPtr+ BlasGen.tpmv uploPtr transPtr diagPtr nPtr aPtr yPtr incyPtr+ liftIO $+ MatrixShape.caseUpLoSym uplo+ runTPMV+ runTPMV+ (spmv uploPtr nPtr alphaPtr aPtr xPtr incxPtr betaPtr yPtr incyPtr)+++newtype SPMV a =+ SPMV {+ getSPMV ::+ Ptr CChar -> Ptr CInt -> Ptr a -> Ptr a ->+ Ptr a -> Ptr CInt -> Ptr a -> Ptr a -> Ptr CInt -> IO ()+ }++spmv :: Class.Floating a =>+ Ptr CChar -> Ptr CInt -> Ptr a -> Ptr a ->+ Ptr a -> Ptr CInt -> Ptr a -> Ptr a -> Ptr CInt -> IO ()+spmv =+ getSPMV $+ Class.switchFloating+ (SPMV BlasReal.spmv) (SPMV BlasReal.spmv)+ (SPMV LapackComplex.spmv) (SPMV LapackComplex.spmv)+++square ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular lo diag up sh a+square =+ Tri.getMap $+ MatrixShape.switchDiagUpLo+ (Tri.Map squareDiagonal)+ (Tri.Map squareTriangular)+ (Tri.Map squareTriangular)+++{- |+Include symmetric matrices.+However, symmetric matrices do not preserve unit diagonals.+-}+squareGeneric ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a ->+ Triangular lo (Tri.PowerDiag lo up diag) up sh a+squareGeneric =+ Tri.getPower $+ MatrixShape.switchDiagUpLoSym+ (Tri.Power squareDiagonal)+ (Tri.Power squareTriangular)+ (Tri.Power squareTriangular)+ (Tri.Power $ squareSymmetric . strictNonUnitDiagonal)+++squareDiagonal ::+ (MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ FlexDiagonal diag sh a -> FlexDiagonal diag sh a+squareDiagonal =+ getMapDiag $+ MatrixShape.switchTriDiag (MapDiag id) (MapDiag $ \a -> Vector.mul a a)++newtype MapDiag lo up sh a diag =+ MapDiag {+ getMapDiag ::+ Triangular lo diag up sh a ->+ Triangular lo diag up sh a+ }++squareTriangular ::+ (MatrixShape.UpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular lo diag up sh a+squareTriangular+ (Array shape@(MatrixShape.Triangular diag uplo order sh) a) =+ Array.unsafeCreate shape $ \bpPtr -> do+ let n = Shape.size sh+ evalContT $ do+ sidePtr <- Call.char 'L'+ let realOrder = uploOrder uplo order+ uploPtr <- Call.char $ uploFromOrder realOrder+ transPtr <- Call.char 'N'+ diagPtr <- Call.char $ charFromTriDiag diag+ nPtr <- Call.cint n+ ldPtr <- Call.leadingDim n+ aPtr <- unpackToTemp (unpack realOrder) n a+ bPtr <- unpackToTemp (unpackZero realOrder) n a+ alphaPtr <- Call.number one+ liftIO $ do+ BlasGen.trmm sidePtr uploPtr transPtr diagPtr+ nPtr nPtr alphaPtr aPtr ldPtr bPtr ldPtr+ pack realOrder n bPtr bpPtr++squareSymmetric ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Symmetric sh a -> Symmetric sh a+squareSymmetric (Array shape@(MatrixShape.Triangular _diag _uplo order sh) a) =+ Array.unsafeCreate shape $+ Symmetric.square NonConjugated order (Shape.size sh) a+++multiply ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular lo diag up sh a ->+ Triangular lo diag up sh a+multiply =+ getMultiply $+ MatrixShape.switchDiagUpLo+ (Multiply $+ Tri.multiplyDiagonal+ "multiply.diagonal: sizes mismatch"+ (MatrixShape.triangularSize . Array.shape)+ (\a b ->+ Array.mapShape+ (MatrixShape.Triangular+ MatrixShape.autoDiag MatrixShape.autoUplo+ (MatrixShape.triangularOrder $ Array.shape b)) $+ Vector.mul (takeDiagonal a) (takeDiagonal b)))+ (Multiply multiplyTriangular)+ (Multiply multiplyTriangular)++newtype Multiply diag sh a lo up =+ Multiply {+ getMultiply ::+ Triangular lo diag up sh a ->+ Triangular lo diag up sh a -> Triangular lo diag up sh a+ }++multiplyTriangular ::+ (MatrixShape.UpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Eq sh, Class.Floating a) =>+ Triangular lo diag up sh a ->+ Triangular lo diag up sh a -> Triangular lo diag up sh a+multiplyTriangular+ (Array (MatrixShape.Triangular diag uploA orderA shA) a)+ (Array shapeB@(MatrixShape.Triangular _diag uploB orderB shB) b) =+ Array.unsafeCreate shapeB $ \cpPtr -> do+ Call.assert "Triangular.multiply: width shapes mismatch" (shA == shB)+ let n = Shape.size shA+ evalContT $ do+ let (side,trans) =+ case orderB of+ ColumnMajor -> ('L', orderA)+ RowMajor -> ('R', flipOrder orderA)+ sidePtr <- Call.char side+ let realOrderA = uploOrder uploA orderA+ let realOrderB = uploOrder uploB orderB+ uploPtr <- Call.char $ uploFromOrder realOrderA+ transPtr <- Call.char $ transposeFromOrder trans+ diagPtr <- Call.char $ charFromTriDiag diag+ nPtr <- Call.cint n+ ldPtr <- Call.leadingDim n+ aPtr <- unpackToTemp (unpack realOrderA) n a+ bPtr <- unpackToTemp (unpackZero realOrderB) n b+ alphaPtr <- Call.number one+ liftIO $ do+ BlasGen.trmm sidePtr uploPtr transPtr diagPtr+ nPtr nPtr alphaPtr aPtr ldPtr bPtr ldPtr+ pack realOrderB n bPtr cpPtr+++multiplyFull ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width,+ Class.Floating a) =>+ Triangular lo diag up height a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+multiplyFull =+ Tri.getMultiplyRight $+ MatrixShape.switchDiagUpLoSym+ (Tri.MultiplyRight $+ Tri.multiplyDiagonal+ "multiplyFull.diagonal: sizes mismatch"+ (MatrixShape.fullHeight . Array.shape)+ (Basic.scaleRows . takeDiagonal))+ (Tri.MultiplyRight multiplyFullTriangular)+ (Tri.MultiplyRight multiplyFullTriangular)+ (Tri.MultiplyRight multiplyFullTriangular)++multiplyFullTriangular ::+ (MatrixShape.UpLoSym lo up, MatrixShape.TriDiag diag,+ Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width,+ Class.Floating a) =>+ Triangular lo diag up height a ->+ Full vert horiz height width a ->+ Full vert horiz height width a+multiplyFullTriangular+ (Array (MatrixShape.Triangular diag uploA orderA shA) a)+ (Array shapeB@(MatrixShape.Full orderB extentB) b) =+ Array.unsafeCreateWithSize shapeB $ \size cPtr -> do+ let (height,width) = Extent.dimensions extentB+ Call.assert "Triangular.multiplyFull: shapes mismatch" (shA == height)+ let m0 = Shape.size height+ let n0 = Shape.size width+ evalContT $ do+ let (side,trans,(m,n)) =+ case orderB of+ ColumnMajor -> ('L', orderA, (m0,n0))+ RowMajor -> ('R', flipOrder orderA, (n0,m0))+ sidePtr <- Call.char side+ let realOrderA = uploOrder uploA orderA+ uploPtr <- Call.char $ uploFromOrder realOrderA+ transPtr <- Call.char $ transposeFromOrder trans+ diagPtr <- Call.char $ charFromTriDiag diag+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ alphaPtr <- Call.number one+ aPtr <- unpackToTemp (unpack realOrderA) m0 a+ ldaPtr <- Call.leadingDim m0+ betaPtr <- Call.number zero+ bPtr <- ContT $ withForeignPtr b+ ldbPtr <- Call.leadingDim m+ let runTRMM = do+ copyBlock size bPtr cPtr+ BlasGen.trmm sidePtr uploPtr transPtr diagPtr+ mPtr nPtr alphaPtr aPtr ldaPtr cPtr ldbPtr+ liftIO $+ MatrixShape.caseUpLoSym uploA+ runTRMM+ runTRMM+ (BlasGen.symm sidePtr uploPtr+ mPtr nPtr alphaPtr aPtr ldaPtr bPtr ldbPtr betaPtr cPtr ldbPtr)+++autoUploOrder ::+ (MatrixShape.Content lo, MatrixShape.Content up) => Order -> (Order, (lo,up))+autoUploOrder order =+ case MatrixShape.autoUplo of+ uplo -> (uploOrder uplo order, uplo)
+ src/Numeric/LAPACK/Matrix/Triangular/Eigen.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+module Numeric.LAPACK.Matrix.Triangular.Eigen (+ values,+ decompose,+ ) where++import qualified Numeric.LAPACK.Matrix.Triangular.Basic as Triangular+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import Numeric.LAPACK.Matrix.Triangular.Private+ (unpackZero, pack, unpackToTemp, fillTriangle,+ forPointers, rowMajorPointers)+import Numeric.LAPACK.Matrix.Triangular.Basic (Triangular)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(ColumnMajor,RowMajor), caseLoUp, uploOrder,+ NonUnit(NonUnit), triangleSize)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (zero)+import Numeric.LAPACK.Private (lacgv, withInfo, errorCodeMsg)++import qualified Numeric.LAPACK.FFI.Complex as LapackComplex+import qualified Numeric.LAPACK.FFI.Real as LapackReal+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.C.Types (CInt, CChar)+import Foreign.Ptr (Ptr, nullPtr)++import Control.Monad.Trans.Cont (evalContT)+import Control.Monad.IO.Class (liftIO)++import Data.Complex (Complex)+import Data.Tuple.HT (swap)+++values ::+ (MatrixShape.DiagUpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Vector sh a+values = Triangular.takeDiagonal+++decompose ::+ (MatrixShape.DiagUpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo NonUnit up sh a ->+ (Triangular lo NonUnit up sh a, Vector sh a, Triangular lo NonUnit up sh a)+decompose a =+ let (vr,vl) =+ flip getDecompose a $+ MatrixShape.switchDiagUpLo+ (Decompose $+ (\eye -> (eye, Triangular.transpose eye)) .+ Triangular.relaxUnitDiagonal .+ Triangular.identity ColumnMajor .+ MatrixShape.triangularSize . Array.shape)+ (Decompose decomposeTriangular)+ (Decompose decomposeTriangular)+ in (vr, values a, vl)++newtype Decompose sh a lo up =+ Decompose {+ getDecompose ::+ Triangular lo NonUnit up sh a ->+ (Triangular lo NonUnit up sh a, Triangular lo NonUnit up sh a)+ }++decomposeTriangular ::+ (MatrixShape.UpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo NonUnit up sh a ->+ (Triangular lo NonUnit up sh a, Triangular lo NonUnit up sh a)+decomposeTriangular (Array (MatrixShape.Triangular _diag uplo order sh) a) =+ let triShape ord =+ MatrixShape.Triangular NonUnit uplo (uploOrder uplo ord) sh+ n = Shape.size sh+ n2 = n*n+ triSize = triangleSize n++ in caseLoUp uplo id swap $+ Array.unsafeCreateWithSizeAndResult (triShape RowMajor) $ \_ vlpPtr ->+ ArrayIO.unsafeCreate (triShape ColumnMajor) $ \vrpPtr ->++ evalContT $ do+ sidePtr <- Call.char 'B'+ howManyPtr <- Call.char 'A'+ let selectPtr = nullPtr+ let unpk =+ case uploOrder uplo order of+ ColumnMajor -> unpackZero ColumnMajor+ RowMajor -> unpackZeroRowMajor+ aPtr <- unpackToTemp unpk n a+ ldaPtr <- Call.leadingDim n+ vlPtr <- Call.allocaArray n2+ vrPtr <- Call.allocaArray n2+ mmPtr <- Call.cint n+ mPtr <- Call.alloca+ liftIO $ withInfo errorCodeMsg "trevc" $+ trevc sidePtr howManyPtr selectPtr n+ aPtr ldaPtr vlPtr ldaPtr vrPtr ldaPtr mmPtr mPtr+ sizePtr <- Call.cint triSize+ incPtr <- Call.cint 1+ liftIO $ do+ pack ColumnMajor n vrPtr vrpPtr+ pack RowMajor n vlPtr vlpPtr+ lacgv sizePtr vlpPtr incPtr+++unpackZeroRowMajor :: Class.Floating a => Int -> Ptr a -> Ptr a -> IO ()+unpackZeroRowMajor n packedPtr fullPtr = do+ fillTriangle zero RowMajor n fullPtr+ unpackRowMajor n packedPtr fullPtr++unpackRowMajor :: Class.Floating a => Int -> Ptr a -> Ptr a -> IO ()+unpackRowMajor n packedPtr fullPtr = evalContT $ do+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint n+ liftIO $+ forPointers (rowMajorPointers n fullPtr packedPtr) $+ \nPtr (dstPtr,srcPtr) ->+ BlasGen.copy nPtr srcPtr incxPtr dstPtr incyPtr+++type TREVC_ a =+ Ptr CChar -> Ptr CChar -> Ptr Bool ->+ Int -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt ->+ Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ()++newtype TREVC a = TREVC {getTREVC :: TREVC_ a}++trevc :: Class.Floating a => TREVC_ a+trevc =+ getTREVC $+ Class.switchFloating+ (TREVC trevcReal) (TREVC trevcReal)+ (TREVC trevcComplex) (TREVC trevcComplex)++trevcReal :: Class.Real a => TREVC_ a+trevcReal sidePtr howmnyPtr selectPtr n+ tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray (3*n)+ liftIO $+ LapackReal.trevc sidePtr howmnyPtr selectPtr nPtr+ tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr workPtr infoPtr++trevcComplex :: Class.Real a => TREVC_ (Complex a)+trevcComplex sidePtr howmnyPtr selectPtr n+ tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr infoPtr =+ evalContT $ do+ nPtr <- Call.cint n+ workPtr <- Call.allocaArray (2*n)+ rworkPtr <- Call.allocaArray n+ liftIO $+ LapackComplex.trevc sidePtr howmnyPtr selectPtr nPtr+ tPtr ldtPtr vlPtr ldvlPtr vrPtr ldvrPtr mmPtr mPtr+ workPtr rworkPtr infoPtr
+ src/Numeric/LAPACK/Matrix/Triangular/Linear.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+module Numeric.LAPACK.Matrix.Triangular.Linear (+ solve,+ inverse,+ inverseGeneric,+ determinant,+ ) where++import qualified Numeric.LAPACK.Matrix.Banded.Linear as BandedLin+import qualified Numeric.LAPACK.Matrix.Banded.Basic as Banded+import qualified Numeric.LAPACK.Matrix.Symmetric.Private as Symmetric+import qualified Numeric.LAPACK.Matrix.Triangular.Private as Tri+import Numeric.LAPACK.Linear.Private (solver, withInfo)+import Numeric.LAPACK.Matrix.Triangular.Basic+ (Triangular, Symmetric, PowerDiag, takeDiagonal, strictNonUnitDiagonal)+import Numeric.LAPACK.Matrix.Private (Full)++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import Numeric.LAPACK.Matrix.Shape.Private+ (transposeFromOrder, uploFromOrder, uploOrder,+ charFromTriDiag, triangleSize)+import Numeric.LAPACK.Matrix.Private (Conjugation(NonConjugated))+import Numeric.LAPACK.Private (copyBlock, copyToTemp)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import System.IO.Unsafe (unsafePerformIO)++import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (peek)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++solve ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Triangular lo diag up sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solve =+ Tri.getMultiplyRight $+ MatrixShape.switchDiagUpLoSym+ (Tri.MultiplyRight $+ Tri.multiplyDiagonal+ "solve.diagonal: sizes mismatch"+ (MatrixShape.fullHeight . Array.shape)+ (BandedLin.solve . Banded.diagonal . takeDiagonal))+ (Tri.MultiplyRight solveTriangular)+ (Tri.MultiplyRight solveTriangular)+ (Tri.MultiplyRight $ solveSymmetric . strictNonUnitDiagonal)++solveTriangular ::+ (MatrixShape.UpLo lo up, MatrixShape.TriDiag diag,+ Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Triangular lo diag up sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solveTriangular (Array (MatrixShape.Triangular diag uplo orderA shA) a) =+ solver "Triangular.solve" shA $ \n nPtr nrhsPtr xPtr ldxPtr -> do+ uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo orderA+ transPtr <- Call.char $ transposeFromOrder orderA+ diagPtr <- Call.char $ charFromTriDiag diag+ apPtr <- copyToTemp (triangleSize n) a+ liftIO $+ withInfo "tptrs" $+ LapackGen.tptrs uploPtr transPtr diagPtr+ nPtr nrhsPtr apPtr xPtr ldxPtr++solveSymmetric ::+ (Extent.C vert, Extent.C horiz,+ Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>+ Symmetric sh a ->+ Full vert horiz sh nrhs a -> Full vert horiz sh nrhs a+solveSymmetric (Array (MatrixShape.Triangular _diag _uplo orderA shA) a) =+ Symmetric.solve "Symmetric.solve" NonConjugated orderA shA a+++inverse ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular lo diag up sh a+inverse =+ Tri.getMap $+ MatrixShape.switchDiagUpLo+ (Tri.Map inverseDiagonal)+ (Tri.Map inverseTriangular)+ (Tri.Map inverseTriangular)++inverseGeneric ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a ->+ Triangular lo (PowerDiag lo up diag) up sh a+inverseGeneric =+ Tri.getPower $+ MatrixShape.switchDiagUpLoSym+ (Tri.Power inverseDiagonal)+ (Tri.Power inverseTriangular)+ (Tri.Power inverseTriangular)+ (Tri.Power $ inverseSymmetric . strictNonUnitDiagonal)++inverseDiagonal ::+ (MatrixShape.TriDiag diag, Shape.C sh, Class.Floating a) =>+ Tri.FlexDiagonal diag sh a -> Tri.FlexDiagonal diag sh a+inverseDiagonal = Tri.caseTriDiagArray id (Array.map recip)++inverseTriangular ::+ (MatrixShape.UpLo lo up, MatrixShape.TriDiag diag,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> Triangular lo diag up sh a+inverseTriangular (Array shape@(MatrixShape.Triangular diag uplo order sh) a) =+ Array.unsafeCreateWithSize shape $ \triSize bPtr ->+ evalContT $ do+ uploPtr <- Call.char $ uploFromOrder $ uploOrder uplo order+ diagPtr <- Call.char $ charFromTriDiag diag+ nPtr <- Call.cint $ Shape.size sh+ aPtr <- ContT $ withForeignPtr a+ liftIO $ do+ copyBlock triSize aPtr bPtr+ withInfo "tptri" $ LapackGen.tptri uploPtr diagPtr nPtr bPtr++inverseSymmetric ::+ (Shape.C sh, Class.Floating a) => Symmetric sh a -> Symmetric sh a+inverseSymmetric (Array shape@(MatrixShape.Triangular _diag _uplo order sh) a) =+ Array.unsafeCreateWithSize shape $+ Symmetric.inverse NonConjugated order (Shape.size sh) a+++determinant ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> a+determinant =+ Tri.getMultiplyRight $+ MatrixShape.switchDiagUpLoSym+ (Tri.MultiplyRight determinantTriangular)+ (Tri.MultiplyRight determinantTriangular)+ (Tri.MultiplyRight determinantTriangular)+ (Tri.MultiplyRight $ determinantSymmetric . strictNonUnitDiagonal)++determinantTriangular ::+ (MatrixShape.DiagUpLo lo up, Shape.C sh, Class.Floating a) =>+ Triangular lo diag up sh a -> a+determinantTriangular = product . Array.toList . takeDiagonal++determinantSymmetric ::+ (Shape.C sh, Class.Floating a) => Symmetric sh a -> a+determinantSymmetric (Array (MatrixShape.Triangular _diag _uplo order sh) a) =+ unsafePerformIO $+ Symmetric.determinant NonConjugated+ peekBlockDeterminant order (Shape.size sh) a++peekBlockDeterminant ::+ (Class.Floating a) => (Ptr a, Maybe (Ptr a, Ptr a)) -> IO a+peekBlockDeterminant (a0Ptr,ext) = do+ a0 <- peek a0Ptr+ case ext of+ Nothing -> return a0+ Just (a1Ptr,bPtr) -> do+ a1 <- peek a1Ptr+ b <- peek bPtr+ return (a0*a1 - b*b)
src/Numeric/LAPACK/Matrix/Triangular/Private.hs view
@@ -1,19 +1,31 @@+{-# LANGUAGE TypeFamilies #-} module Numeric.LAPACK.Matrix.Triangular.Private where +import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent import Numeric.LAPACK.Matrix.Shape.Private- (Order(RowMajor,ColumnMajor), flipOrder, uploFromOrder, triangleSize)-import Numeric.LAPACK.Private (pointerSeq, copyToTemp, lacgv, fill, zero)+ (Order(RowMajor,ColumnMajor), flipOrder, uploFromOrder,+ Empty, Filled, NonUnit)+import Numeric.LAPACK.Matrix.Private (Full, Conjugation(Conjugated))+import Numeric.LAPACK.Scalar (zero)+import Numeric.LAPACK.Private+ (pointerSeq, copyBlock, copyCondConjugateToTemp,+ pokeCInt, fill, withInfo, errorCodeMsg) import qualified Numeric.LAPACK.FFI.Generic as LapackGen import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class +import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))+ import Foreign.Marshal.Alloc (alloca) import Foreign.Marshal.Array (advancePtr) import Foreign.C.Types (CInt) import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr)-import Foreign.Storable (Storable, poke)+import Foreign.Storable (Storable) import Control.Monad.Trans.Cont (ContT(ContT), evalContT) import Control.Monad.IO.Class (liftIO)@@ -21,16 +33,20 @@ import Data.Foldable (forM_) -diagonalPointers ::- (Storable a, Storable ar) =>- Order -> Int -> Ptr ar -> Ptr a -> [(Ptr ar, Ptr a)]-diagonalPointers order n xPtr aPtr =- take n $ zip (pointerSeq 1 xPtr) $ scanl advancePtr aPtr $+diagonalPointers :: (Storable a) => Order -> Int -> Ptr a -> [Ptr a]+diagonalPointers order n aPtr =+ take n $ scanl advancePtr aPtr $ case order of RowMajor -> iterate pred n ColumnMajor -> iterate succ 2 +diagonalPointerPairs ::+ (Storable a, Storable b) =>+ Order -> Int -> Ptr a -> Ptr b -> [(Ptr a, Ptr b)]+diagonalPointerPairs order n aPtr bPtr =+ zip (pointerSeq 1 aPtr) $ diagonalPointers order n bPtr + columnMajorPointers :: (Storable a) => Int -> Ptr a -> Ptr a -> [(Int, ((Ptr a, Ptr a), Ptr a))] columnMajorPointers n fullPtr packedPtr =@@ -52,23 +68,15 @@ forPointers xs act = alloca $ \nPtr -> forM_ xs $ \(d,ptrs) -> do- poke nPtr $ fromIntegral d+ pokeCInt nPtr d act nPtr ptrs copyTriangleToTemp :: Class.Floating a =>- Order -> Int -> ForeignPtr a -> ContT r IO (Ptr a)-copyTriangleToTemp order n a = do- let aSize = triangleSize n- apPtr <- copyToTemp aSize a- liftIO $ evalContT $ do- aSizePtr <- Call.cint aSize- incPtr <- Call.cint 1- case order of- RowMajor -> liftIO $ lacgv aSizePtr apPtr incPtr- ColumnMajor -> return ()- return apPtr+ Conjugation -> Order -> Int -> ForeignPtr a -> ContT r IO (Ptr a)+copyTriangleToTemp conj order =+ copyCondConjugateToTemp (order==RowMajor && conj==Conjugated) unpackToTemp ::@@ -87,16 +95,21 @@ evalContT $ do uploPtr <- Call.char $ uploFromOrder order nPtr <- Call.cint n- ldaPtr <- Call.cint n- liftIO $ withInfo $ LapackGen.tpttr uploPtr nPtr packedPtr fullPtr ldaPtr+ ldaPtr <- Call.leadingDim n+ liftIO $ withInfo errorCodeMsg "tpttr" $+ LapackGen.tpttr uploPtr nPtr packedPtr fullPtr ldaPtr pack :: Class.Floating a => Order -> Int -> Ptr a -> Ptr a -> IO ()-pack order n fullPtr packedPtr =+pack order n = packRect order n n++packRect :: Class.Floating a => Order -> Int -> Int -> Ptr a -> Ptr a -> IO ()+packRect order n ld fullPtr packedPtr = evalContT $ do uploPtr <- Call.char $ uploFromOrder order nPtr <- Call.cint n- ldaPtr <- Call.cint n- liftIO $ withInfo $ LapackGen.trttp uploPtr nPtr fullPtr ldaPtr packedPtr+ ldaPtr <- Call.leadingDim ld+ liftIO $ withInfo errorCodeMsg "trttp" $+ LapackGen.trttp uploPtr nPtr fullPtr ldaPtr packedPtr unpackZero, _unpackZero ::@@ -117,5 +130,88 @@ liftIO $ LapackGen.laset uploPtr nPtr nPtr zPtr zPtr aPtr nPtr -withInfo :: (Ptr CInt -> IO ()) -> IO ()-withInfo = alloca+type Triangular lo diag up sh = Array (MatrixShape.Triangular lo diag up sh)++type FlexDiagonal diag sh =+ Triangular MatrixShape.Empty diag MatrixShape.Empty sh++newtype MultiplyRight diag sh a b lo up =+ MultiplyRight {getMultiplyRight :: Triangular lo diag up sh a -> b}++newtype Map diag sh a lo up =+ Map {getMap :: Triangular lo diag up sh a -> Triangular lo diag up sh a}++newtype Power diag sh a lo up =+ Power {+ getPower ::+ Triangular lo diag up sh a ->+ Triangular lo (PowerDiag lo up diag) up sh a+ }++type family PowerDiag lo up diag+type instance PowerDiag Empty up diag = diag+type instance PowerDiag Filled Empty diag = diag+type instance PowerDiag Filled Filled diag = NonUnit++caseTriDiagArray ::+ (MatrixShape.TriDiag diag) =>+ (Triangular lo diag up sh a -> b) ->+ (Triangular lo diag up sh a -> b) ->+ (Triangular lo diag up sh a -> b)+caseTriDiagArray fu fn a =+ MatrixShape.caseTriDiag+ (MatrixShape.triangularDiag $ Array.shape a)+ (fu a) (fn a)++multiplyDiagonal ::+ (Eq sh, MatrixShape.TriDiag diag) =>+ String ->+ (b -> sh) ->+ (Triangular lo diag up sh a -> b -> b) ->+ (Triangular lo diag up sh a -> b -> b)+multiplyDiagonal msg shape =+ caseTriDiagArray+ (\a b ->+ if MatrixShape.triangularSize (Array.shape a) == shape b+ then b+ else error ("Triangular." ++ msg))+++fromBanded ::+ (Class.Floating a) =>+ Int -> Order -> Int -> ForeignPtr a -> Int -> Ptr a -> IO ()+fromBanded k order n a bSize bPtr =+ withForeignPtr a $ \aPtr -> do+ fill zero bSize bPtr+ let lda = k+1+ let pointers =+ zip [0..] $ zip (pointerSeq lda aPtr) $+ diagonalPointers order n bPtr+ case order of+ ColumnMajor ->+ forM_ pointers $ \(i,(xPtr,yPtr)) ->+ let j = min i k+ in copyBlock (j+1) (advancePtr xPtr (k-j)) (advancePtr yPtr (-j))+ RowMajor ->+ forM_ pointers $ \(i,(xPtr,yPtr)) ->+ copyBlock (min lda (n-i)) xPtr yPtr+++type FlexLower diag sh = Array (MatrixShape.LowerTriangular diag sh)++takeLower ::+ (MatrixShape.TriDiag diag,+ Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ (diag, Order -> Int -> Ptr a -> IO ()) ->+ Full Extent.Small horiz height width a -> FlexLower diag height a+takeLower (diag, fillDiag) (Array (MatrixShape.Full order extent) a) =+ let (height,width) = Extent.dimensions extent+ m = Shape.size height+ n = Shape.size width+ k = case order of RowMajor -> n; ColumnMajor -> m+ in Array.unsafeCreate+ (MatrixShape.Triangular diag MatrixShape.lower order height) $ \lPtr ->+ withForeignPtr a $ \aPtr -> do+ let dstOrder = flipOrder order+ packRect dstOrder m k aPtr lPtr+ fillDiag dstOrder m lPtr
src/Numeric/LAPACK/Orthogonal.hs view
@@ -2,34 +2,34 @@ module Numeric.LAPACK.Orthogonal ( leastSquares, minimumNorm,- leastSquaresMinimumNorm,+ leastSquaresMinimumNormRCond, pseudoInverseRCond, - Householder,- householder,- householderDecompose,- householderDeterminant, determinant,- householderExtractQ,- householderExtractR,- orthogonalComplement,+ determinantAbsolute,+ complement,++ householder, ) where -import qualified Numeric.LAPACK.Matrix.Square as Square-import Numeric.LAPACK.Matrix- (General, ZeroInt, zeroInt, transpose, identity, dropColumns)-import Numeric.LAPACK.Matrix.Square (Square)+import qualified Numeric.LAPACK.Orthogonal.Private as HH +import qualified Numeric.LAPACK.Matrix.Square.Basic as Square+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Matrix.Extent.Kind as EK+import Numeric.LAPACK.Matrix.Square.Basic (Square)+import Numeric.LAPACK.Matrix.Private (Full, Tall, ZeroInt, zeroInt)+import Numeric.LAPACK.Matrix (transpose, dropColumns)+ import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Private as Private-import Numeric.LAPACK.Matrix.Shape.Private- (Order(RowMajor, ColumnMajor), transposeFromOrder)-import Numeric.LAPACK.Vector (Vector)+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor,ColumnMajor))+import Numeric.LAPACK.Scalar (RealOf, zero, absolute) import Numeric.LAPACK.Private- (RealOf, zero, fill,- copySubMatrix, copyBlock, copyToTemp,- copyToColumnMajor, copyToSubColumnMajor,- withAutoWorkspaceInfo, allocArray, allocHigherArray)+ (lacgv, peekCInt,+ copySubMatrix, copyToTemp, copyToColumnMajor, copyToSubColumnMajor,+ withAutoWorkspaceInfo, rankMsg, errorCodeMsg, createHigherArray) import qualified Numeric.LAPACK.FFI.Generic as LapackGen import qualified Numeric.LAPACK.FFI.Complex as LapackComplex@@ -43,15 +43,13 @@ import System.IO.Unsafe (unsafePerformIO) -import Foreign.Marshal.Array (advancePtr)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Marshal.Array (pokeArray)+import Foreign.C.Types (CInt, CChar)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr)-import Foreign.Storable (peek) import Control.Monad.Trans.Cont (ContT(ContT), evalContT) import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>)) import Data.Complex (Complex) import Data.Tuple.HT (mapSnd)@@ -64,34 +62,39 @@ Precondition: @a@ must have full rank and @height a >= width a@. -} leastSquares ::- (Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>- General height width a -> General height nrhs a -> General width nrhs a+ (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- (Array shapeA@(MatrixShape.General orderA heightA widthA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor widthA widthB) $- \xPtr -> do- Call.assert "leastSquares: height shapes mismatch" (heightA == heightB)- Call.assert "leastSquares: height of 'a' must be at least the width"- (Shape.size heightA >= Shape.size widthA)+ (Array shapeA@(MatrixShape.Full orderA extentA) a)+ (Array shapeB@(MatrixShape.Full orderB extentB) b) =++ case Extent.fuse (Extent.generalizeWide $ Extent.transpose extentA) extentB of+ Nothing -> error "leastSquares: height shapes mismatch"+ Just extent ->+ Array.unsafeCreate (MatrixShape.Full ColumnMajor extent) $ \xPtr -> do++ let widthA = Extent.width extentA+ let (height,widthB) = Extent.dimensions extentB let (m,n) = MatrixShape.dimensions shapeA let lda = m let nrhs = Shape.size widthB- let ldb = Shape.size heightB+ let ldb = Shape.size height let ldx = Shape.size widthA evalContT $ do- transPtr <- Call.char $ transposeFromOrder orderA mPtr <- Call.cint m nPtr <- Call.cint n nrhsPtr <- Call.cint nrhs- aPtr <- copyToTemp (Shape.size shapeA) a- ldaPtr <- Call.cint lda+ (transPtr,aPtr) <- transposeA orderA (m*n) a+ ldaPtr <- Call.leadingDim lda bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb- let bSize = Shape.size (heightB,widthB)+ ldbPtr <- Call.leadingDim ldb+ let bSize = Shape.size shapeB btmpPtr <- Call.allocaArray bSize liftIO $ copyToColumnMajor orderB ldb nrhs bPtr btmpPtr- liftIO $ withAutoWorkspaceInfo "gels" $+ liftIO $ withAutoWorkspaceInfo rankMsg "gels" $ LapackGen.gels transPtr mPtr nPtr nrhsPtr aPtr ldaPtr btmpPtr ldbPtr liftIO $ copySubMatrix ldx nrhs ldb btmpPtr ldx xPtr@@ -104,74 +107,126 @@ Precondition: @a@ must have full rank and @height a <= width a@. -} minimumNorm ::- (Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>- General height width a -> General height nrhs a -> General width nrhs a+ (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- (Array shapeA@(MatrixShape.General orderA heightA widthA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- Array.unsafeCreate (MatrixShape.General ColumnMajor widthA widthB) $- \xPtr -> do- Call.assert "minimumNorm: height shapes mismatch" (heightA == heightB)- Call.assert "minimumNorm: width of 'a' must be at least the height"- (Shape.size widthA >= Shape.size heightA)+ (Array shapeA@(MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =++ case Extent.fuse (Extent.generalizeTall $ Extent.transpose extentA) extentB of+ Nothing -> error "minimumNorm: height shapes mismatch"+ Just extent ->+ Array.unsafeCreate (MatrixShape.Full ColumnMajor extent) $ \xPtr -> do++ let widthA = Extent.width extentA+ let (height,widthB) = Extent.dimensions extentB let (m,n) = MatrixShape.dimensions shapeA let lda = m let nrhs = Shape.size widthB- let ldb = Shape.size heightB+ let ldb = Shape.size height let ldx = Shape.size widthA evalContT $ do- transPtr <- Call.char $ transposeFromOrder orderA mPtr <- Call.cint m nPtr <- Call.cint n nrhsPtr <- Call.cint nrhs- aPtr <- copyToTemp (Shape.size shapeA) a- ldaPtr <- Call.cint lda+ (transPtr,aPtr) <- transposeA orderA (m*n) a+ ldaPtr <- Call.leadingDim lda bPtr <- ContT $ withForeignPtr b- ldxPtr <- Call.cint ldx+ ldxPtr <- Call.leadingDim ldx liftIO $ copyToSubColumnMajor orderB ldb nrhs bPtr ldx xPtr- liftIO $ withAutoWorkspaceInfo "gels" $+ liftIO $ withAutoWorkspaceInfo rankMsg "gels" $ LapackGen.gels transPtr mPtr nPtr nrhsPtr aPtr ldaPtr xPtr ldxPtr ++transposeA ::+ Class.Floating a =>+ Order -> Int -> ForeignPtr a -> ContT r IO (Ptr CChar, Ptr a)+transposeA order size a = do+ aPtr <- copyToTemp size a+ trans <-+ case order of+ RowMajor -> do+ sizePtr <- Call.cint size+ incPtr <- Call.cint 1+ liftIO $ lacgv sizePtr aPtr incPtr+ return $ HH.invChar a+ ColumnMajor -> return 'N'+ transPtr <- Call.char trans+ return (transPtr, aPtr)++ {- |-If @x = leastSquaresMinimumNorm a b@+If @x = leastSquaresMinimumNormRCond rcond a b@ then @x@ is the vector with minimum @Vector.norm2 x@ that minimizes @Vector.norm2 (multiply a x `sub` b)@. Matrix @a@ can have any rank but you must specify the reciprocal condition of the rank-truncated matrix. -}-leastSquaresMinimumNorm ::- (Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>+leastSquaresMinimumNormRCond ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) => RealOf a ->- General height width a -> General height nrhs a ->- (Int, General width nrhs a)-leastSquaresMinimumNorm rcond- (Array (MatrixShape.General orderA heightA widthA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- unsafePerformIO $ do- Call.assert "leastSquaresMinimumNorm: height shapes mismatch"- (heightA == heightB)- let shapeX = MatrixShape.General ColumnMajor widthA widthB- let m = Shape.size heightA- let n = Shape.size widthA- let nrhs = Shape.size widthB+ Full horiz vert height width a ->+ Full vert horiz height nrhs a ->+ (Int, Full vert horiz width nrhs a)+leastSquaresMinimumNormRCond rcond+ (Array (MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ case Extent.fuse (Extent.transpose extentA) extentB of+ Nothing -> error "leastSquaresMinimumNormRCond: height shapes mismatch"+ Just extent ->+ let widthA = Extent.width extentA+ (height,widthB) = Extent.dimensions extentB+ shapeX = MatrixShape.Full ColumnMajor extent+ m = Shape.size height+ n = Shape.size widthA+ nrhs = Shape.size widthB+ in if m == 0+ then (0, Vector.constant shapeX zero)+ else+ if nrhs == 0+ then+ (fst $ unsafePerformIO $+ case Vector.constant height zero of+ Array _ b1 ->+ leastSquaresMinimumNormIO rcond+ (MatrixShape.general ColumnMajor widthA ())+ orderA a orderB b1 m n 1,+ Vector.constant shapeX zero)+ else+ unsafePerformIO $+ leastSquaresMinimumNormIO rcond shapeX+ orderA a orderB b m n nrhs++leastSquaresMinimumNormIO ::+ (Shape.C sh, Class.Floating a) =>+ RealOf a -> sh ->+ Order -> ForeignPtr a ->+ Order -> ForeignPtr a ->+ Int -> Int -> Int -> IO (Int, Array sh a)+leastSquaresMinimumNormIO rcond shapeX orderA a orderB b m n nrhs =+ createHigherArray shapeX m n nrhs $ \(tmpPtr,ldtmp) -> do+ let aSize = m*n let lda = m evalContT $ do aPtr <- ContT $ withForeignPtr a atmpPtr <- Call.allocaArray aSize liftIO $ copyToColumnMajor orderA m n aPtr atmpPtr- ldaPtr <- Call.cint lda- (x,(tmpPtr,ldtmp)) <- allocHigherArray shapeX m n nrhs- ldtmpPtr <- Call.cint ldtmp+ ldaPtr <- Call.leadingDim lda+ ldtmpPtr <- Call.leadingDim ldtmp bPtr <- ContT $ withForeignPtr b liftIO $ copyToSubColumnMajor orderB m nrhs bPtr ldtmp tmpPtr jpvtPtr <- Call.allocaArray n+ liftIO $ pokeArray jpvtPtr (replicate n 0) rankPtr <- Call.alloca gelsy m n nrhs atmpPtr ldaPtr tmpPtr ldtmpPtr jpvtPtr rcond rankPtr- rank <- liftIO $ fromIntegral <$> peek rankPtr- return (rank, x)+ liftIO $ peekCInt rankPtr type GELSY_ r ar a =@@ -195,7 +250,7 @@ nPtr <- Call.cint n nrhsPtr <- Call.cint nrhs rcondPtr <- Call.real rcond- liftIO $ withAutoWorkspaceInfo "gelsy" $+ liftIO $ withAutoWorkspaceInfo errorCodeMsg "gelsy" $ LapackReal.gelsy mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr jpvtPtr rcondPtr rankPtr @@ -206,167 +261,85 @@ nrhsPtr <- Call.cint nrhs rcondPtr <- Call.real rcond rworkPtr <- Call.allocaArray (2*n)- liftIO $ withAutoWorkspaceInfo "gelsy" $ \workPtr lworkPtr infoPtr ->+ liftIO $+ withAutoWorkspaceInfo errorCodeMsg "gelsy" $ \workPtr lworkPtr infoPtr -> LapackComplex.gelsy mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr jpvtPtr rcondPtr rankPtr workPtr lworkPtr rworkPtr infoPtr pseudoInverseRCond ::- (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>- RealOf a -> General height width a -> (Int, General width height a)+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ RealOf a ->+ Full vert horiz height width a ->+ (Int, Full horiz vert width height a) pseudoInverseRCond rcond a =- let (MatrixShape.General _ height width) = Array.shape a- in if Shape.size height < Shape.size width- then leastSquaresMinimumNorm rcond a $ identity height- else mapSnd transpose $- leastSquaresMinimumNorm rcond (transpose a) $- identity width+ case Matrix.caseTallWide a of+ Left _ ->+ mapSnd transpose $+ leastSquaresMinimumNormRCond rcond (transpose a) $+ Square.toFull $ Square.identity $+ MatrixShape.fullWidth $ Array.shape a+ Right _ ->+ leastSquaresMinimumNormRCond rcond a $+ Square.toFull $ Square.identity $+ MatrixShape.fullHeight $ Array.shape a -type Householder height width = Array (MatrixShape.Householder height width)- {- @(q,r) = householder a@ means that @q@ is unitary and @r@ is upper triangular and @a = multiply q r@. -} householder ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- General height width a ->- (Square height a, General height width a)+ (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 a =- let hh = householderDecompose a- in (householderExtractQ hh, householderExtractR $ snd hh)+ let hh = HH.fromMatrix a+ in (HH.extractQ hh, HH.extractR hh) -householderDecompose ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a -> (Vector width a, Householder height width a)-householderDecompose (Array shape@(MatrixShape.General order height width) a) =- unsafePerformIO $ do - let (m,n) = MatrixShape.dimensions shape- let lda = m- let mn = min m n- evalContT $ do- mPtr <- Call.cint m- nPtr <- Call.cint n- aPtr <- ContT $ withForeignPtr a- ldaPtr <- Call.cint lda- (qr,qrPtr) <- allocArray $ MatrixShape.Householder order height width- liftIO $ copyBlock (m*n) aPtr qrPtr- (tau,tauPtr) <- allocArray width- liftIO $ fill zero (n-mn) (advancePtr tauPtr mn)- liftIO $- case order of- RowMajor ->- withAutoWorkspaceInfo "gelqf" $- LapackGen.gelqf mPtr nPtr qrPtr ldaPtr tauPtr- ColumnMajor ->- withAutoWorkspaceInfo "geqrf" $- LapackGen.geqrf mPtr nPtr qrPtr ldaPtr tauPtr- return (tau, qr)--householderDeterminant ::- (Shape.C height, Shape.C width, Class.Floating a) =>- Householder height width a -> a-householderDeterminant- (Array (MatrixShape.Householder order height width) a) =- let m = Shape.size height- n = Shape.size width- k = case order of RowMajor -> n; ColumnMajor -> m- in unsafePerformIO $- withForeignPtr a $ \aPtr ->- Private.product (min m n) aPtr (k+1)-+determinant :: (Shape.C sh, Class.Floating a) => Square sh a -> a+determinant = HH.determinant . HH.fromMatrix {-|-Generalized determinant - works also for non-square matrices.-In contrast to the square root of the Gramian determinant-it has the proper sign.+Gramian determinant -+works also for non-square matrices, but is sensitive to transposition.++> determinantAbsolute a = sqrt (Herm.determinant (Herm.covariance a)) -}-determinant ::- (Shape.C height, Shape.C width, Eq a, Class.Floating a) =>- General height width a -> a-determinant a =- let (tau,hh) = householderDecompose a- in foldl (\x _ -> negate x)- (householderDeterminant hh)- (takeWhile (/=zero) $ Array.toList tau)+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 =+ absolute .+ either (HH.determinantR . HH.fromMatrix) (const zero) .+ Matrix.caseTallWide -householderExtractQ ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- (Vector width a, Householder height width a) -> Square height a-householderExtractQ- (Array widthTau tau,- Array (MatrixShape.Householder order height width) qr) =-- Array.unsafeCreate (MatrixShape.Square order height) $ \qPtr -> do-- Call.assert "householderExtractQ: width shapes mismatch" (widthTau == width)-- let m = Shape.size height- let k = min m $ Shape.size width- let lda = m- evalContT $ do- mPtr <- Call.cint m- kPtr <- Call.cint k- qrPtr <- ContT $ withForeignPtr qr- ldaPtr <- Call.cint lda- tauPtr <- ContT $ withForeignPtr tau- liftIO $- case order of- RowMajor -> do- copySubMatrix k m k qrPtr lda qPtr- withAutoWorkspaceInfo "unglq" $- LapackGen.unglq mPtr mPtr kPtr qPtr ldaPtr tauPtr- ColumnMajor -> do- copyBlock (m*k) qrPtr qPtr- withAutoWorkspaceInfo "ungqr" $- LapackGen.ungqr mPtr mPtr kPtr qPtr ldaPtr tauPtr--householderExtractR ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- Householder height width a -> General height width a-householderExtractR- (Array (MatrixShape.Householder order height width) qr) =-- Array.unsafeCreate (MatrixShape.General order height width) $- \rPtr -> do-- let (uplo, (m,n)) =- case order of- RowMajor -> ('L', (Shape.size width, Shape.size height))- ColumnMajor -> ('U', (Shape.size height, Shape.size width))- fill zero (m*n) rPtr- evalContT $ do- uploPtr <- Call.char uplo- mPtr <- Call.cint m- nPtr <- Call.cint n- qrPtr <- ContT $ withForeignPtr qr- ldqrPtr <- Call.cint m- ldrPtr <- Call.cint m- liftIO $ LapackGen.lacpy uploPtr mPtr nPtr qrPtr ldqrPtr rPtr ldrPtr- {- | For an m-by-n-matrix @a@ with m>=n this function computes an m-by-(m-n)-matrix @b@-such that @Matrix.multiply (transpose b) a@ is a zero matrix.+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@. -}-orthogonalComplement ::- (Shape.C height, Shape.C width, Eq width, Class.Floating a) =>- General height width a -> General height ZeroInt a-orthogonalComplement a =- dropColumns (Shape.size $ MatrixShape.generalWidth $ Array.shape a) $- Array.mapShape zeroIntWidth $- Square.toGeneral $ householderExtractQ $ householderDecompose a+complement ::+ (Shape.C height, Shape.C width, Class.Floating a) =>+ Tall height width a -> Tall height ZeroInt a+complement a =+ dropColumns (Shape.size $ MatrixShape.fullWidth $ Array.shape a) $+ Array.mapShape zeroIntWidth $ Square.toFull $+ HH.extractQ $ HH.fromMatrix $ Matrix.fromFull a zeroIntWidth :: (Shape.C width) =>- MatrixShape.General height width -> MatrixShape.General height ZeroInt-zeroIntWidth (MatrixShape.General order height width) =- MatrixShape.General order height (zeroInt $ Shape.size width)+ MatrixShape.Tall height width -> MatrixShape.Tall height ZeroInt+zeroIntWidth (MatrixShape.Full order (Extent.Extent o (EK.Tall height width))) =+ MatrixShape.Full order+ (Extent.Extent o (EK.Tall height (zeroInt $ Shape.size width)))
+ src/Numeric/LAPACK/Orthogonal/Householder.hs view
@@ -0,0 +1,30 @@+module Numeric.LAPACK.Orthogonal.Householder (+ Householder,+ General,+ Tall,+ Wide,+ Square,+ mapExtent,+ fromMatrix,+ determinant,+ determinantAbsolute,+ leastSquares,+ minimumNorm,++ Matrix.Transposition(..),+ Matrix.Conjugation(..),+ Matrix.Inversion(..),+ extractQ,+ extractR,+ multiplyQ,++ tallExtractQ,+ tallExtractR,+ tallMultiplyQ,+ tallMultiplyQAdjoint,+ tallMultiplyR,+ tallSolveR,+ ) where++import qualified Numeric.LAPACK.Matrix.Private as Matrix+import Numeric.LAPACK.Orthogonal.Private
+ src/Numeric/LAPACK/Orthogonal/Private.hs view
@@ -0,0 +1,427 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Orthogonal.Private where++import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as ExtentPriv+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import qualified Numeric.LAPACK.Split as Split+import Numeric.LAPACK.Matrix.Triangular.Basic (Upper)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor, ColumnMajor), sideSwapFromOrder)+import Numeric.LAPACK.Matrix.Extent.Private (Extent)+import Numeric.LAPACK.Matrix.Private+ (Full, ZeroInt, zeroInt,+ Transposition(NonTransposed, Transposed),+ Conjugation(NonConjugated, Conjugated),+ Inversion(NonInverted, Inverted), flipInversion)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Format (Format(format))+import Numeric.LAPACK.Scalar (RealOf, zero, isZero, absolute, conjugate)+import Numeric.LAPACK.Private+ (fill, copySubMatrix, copyBlock, conjugateToTemp,+ withAutoWorkspaceInfo, errorCodeMsg)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO+import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import Foreign.Marshal.Array (advancePtr)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (when)+import Control.Applicative (Const(Const,getConst), liftA3)++import qualified Data.List as List+++data Householder vert horiz height width a =+ Householder {+ tau_ :: Vector ZeroInt a,+ split_ ::+ Array+ (MatrixShape.Split MatrixShape.Reflector vert horiz height width) a+ } deriving (Show)++type General = Householder Extent.Big Extent.Big+type Tall = Householder Extent.Big Extent.Small+type Wide = Householder Extent.Small Extent.Big+type Square sh = Householder Extent.Small Extent.Small sh sh+++extent_ ::+ Householder vert horiz height width a ->+ Extent vert horiz height width+extent_ = MatrixShape.splitExtent . Array.shape . split_++mapExtent ::+ (Extent.C vertA, Extent.C horizA) =>+ (Extent.C vertB, Extent.C horizB) =>+ Extent.Map vertA horizA vertB horizB height width ->+ Householder vertA horizA height width a ->+ Householder vertB horizB height width a+mapExtent f (Householder tau split) =+ Householder tau $ Array.mapShape (MatrixShape.splitMapExtent f) split++caseTallWide ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width) =>+ Householder vert horiz height width a ->+ Either (Tall height width a) (Wide height width a)+caseTallWide (Householder tau (Array shape a)) =+ either+ (Left . Householder tau . flip Array a)+ (Right . Householder tau . flip Array a) $+ MatrixShape.caseTallWideSplit shape+++instance+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Format (Householder vert horiz height width a) where+ format fmt (Householder tau m) = format fmt (tau, m)++fromMatrix ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Full vert horiz height width a ->+ Householder vert horiz height width a+fromMatrix (Array shape@(MatrixShape.Full order extent) a) =+ let (m,n) = MatrixShape.dimensions shape+ in uncurry Householder $+ Array.unsafeCreateWithSizeAndResult (zeroInt $ min m n) $ \_ tauPtr ->+ ArrayIO.unsafeCreate+ (MatrixShape.Split MatrixShape.Reflector order extent) $ \qrPtr ->++ evalContT $ do+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim m+ liftIO $ do+ copyBlock (m*n) aPtr qrPtr+ case order of+ RowMajor ->+ withAutoWorkspaceInfo errorCodeMsg "gelqf" $+ LapackGen.gelqf mPtr nPtr qrPtr ldaPtr tauPtr+ ColumnMajor ->+ withAutoWorkspaceInfo errorCodeMsg "geqrf" $+ LapackGen.geqrf mPtr nPtr qrPtr ldaPtr tauPtr++determinantR ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Householder vert Extent.Small height width a -> a+determinantR = Split.determinantR . split_++{-+For complex numbers LAPACK uses not exactly reflections,+i.e. the determinants of the primitive transformations are not necessarily -1.++It holds: det(I-tau*v*v^H) = 1-tau*v^H*v+ because of https://en.wikipedia.org/wiki/Sylvester's_determinant_theorem+ simple proof from: https://en.wikipedia.org/wiki/Matrix_determinant_lemma+ I 0 . I+u*vt u . I 0 = I+u*vt u . I 0 = I u+ vt 1 0 1 -vt 1 vt+vt*u*vt vt*u+1 -vt 1 0 vt*u+1++We already know:+ v^H*v is real and greater or equal to 1, because v[i] = 1,+ and determinant has absolute value 1.++Let k = v^H*v.+For which real k lies 1-tau*k on the unit circle?++ (1-taur*k)^2 + (taui*k)^2 = 1+ 1-2*taur*k+(taur^2+taui^2)*k^2 = 1+ (taur^2 + taui^2)*k^2 - 2*taur*k = 0 (k/=0)+ (taur^2 + taui^2)*k - 2*taur = 0+ k = 2*taur / (taur^2 + taui^2)++ 1-tau*k+ = (taur^2 + taui^2 - tau*2*taur) / (taur^2 + taui^2)+ = (taur^2 + taui^2 - 2*(taur+i*taui)*taur) / (taur^2 + taui^2)+ = (-taur^2 + taui^2 - 2*(i*taui)*taur) / (taur^2 + taui^2)+ = -(taur + i*taui)^2 / (taur^2 + taui^2)+-}+determinant ::+ (Shape.C sh, Class.Floating a) =>+ Square sh a -> a+determinant (Householder tau split) =+ List.foldl' (*) (Split.determinantR split) $+ (case MatrixShape.splitOrder $ Array.shape split of+ RowMajor -> map conjugate+ ColumnMajor -> id) $+ map (negate.(^(2::Int)).signum) $+ filter (not . isZero) $ Array.toList tau++determinantAbsolute ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Householder vert horiz height width a -> RealOf a+determinantAbsolute =+ absolute . either determinantR (const zero) . caseTallWide+++leastSquares ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Shape.C nrhs,+ Class.Floating a) =>+ Householder horiz Extent.Small height width a ->+ Full vert horiz height nrhs a ->+ Full vert horiz width nrhs a+leastSquares qr =+ tallSolveR NonTransposed NonConjugated qr . tallMultiplyQAdjoint qr++{- |+@+HH.minimumNorm (HH.fromMatrix a) b+==+Ortho.minimumNorm (adjoint a) b+@+-}+minimumNorm ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Shape.C nrhs,+ Class.Floating a) =>+ Householder vert Extent.Small width height a ->+ Full vert horiz height nrhs a ->+ Full vert horiz width nrhs a+minimumNorm qr = tallMultiplyQ qr . tallSolveR Transposed Conjugated qr++-- cf. Matrix.takeRows+takeRows ::+ (Extent.C vert, Extent.C horiz,+ Eq fuse, Shape.C fuse, Shape.C height, Shape.C width, Class.Floating a) =>+ Extent Extent.Small horiz height fuse ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+takeRows extentA (Array (MatrixShape.Full order extentB) b) =+ case Extent.fuse (ExtentPriv.generalizeWide extentA) extentB of+ Nothing -> error "Householder.takeRows: heights mismatch"+ Just extentC ->+ Array.unsafeCreateWithSize (MatrixShape.Full order extentC) $+ \blockSize cPtr ->+ withForeignPtr b $ \bPtr ->+ case order of+ RowMajor -> copyBlock blockSize bPtr cPtr+ ColumnMajor ->+ let n = Shape.size $ Extent.width extentB+ mb = Shape.size $ Extent.height extentB+ mc = Shape.size $ Extent.height extentC+ in copySubMatrix mc n mb bPtr mc cPtr++addRows ::+ (Extent.C vert, Extent.C horiz,+ Eq fuse, Shape.C fuse, Shape.C height, Shape.C width, Class.Floating a) =>+ Extent vert Extent.Small height fuse ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+addRows extentA (Array shapeB@(MatrixShape.Full order extentB) b) =+ case Extent.fuse (ExtentPriv.generalizeTall extentA) extentB of+ Nothing -> error "Householder.addRows: heights mismatch"+ Just extentC ->+ Array.unsafeCreateWithSize (MatrixShape.Full order extentC) $+ \cSize cPtr ->+ withForeignPtr b $ \bPtr ->+ case order of+ RowMajor -> do+ let bSize = Shape.size shapeB+ copyBlock bSize bPtr cPtr+ fill zero (cSize - bSize) (advancePtr cPtr bSize)+ ColumnMajor -> do+ let n = Shape.size $ Extent.width extentB+ mb = Shape.size $ Extent.height extentB+ mc = Shape.size $ Extent.height extentC+ copySubMatrix mb n mb bPtr mc cPtr+ evalContT $ do+ uploPtr <- Call.char 'A'+ mPtr <- Call.cint (mc-mb)+ nPtr <- Call.cint n+ ldcPtr <- Call.leadingDim mc+ zPtr <- Call.number zero+ liftIO $+ LapackGen.laset uploPtr mPtr nPtr zPtr zPtr+ (advancePtr cPtr mb) ldcPtr+++extractQ ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Householder vert horiz height width a -> Matrix.Square height a+extractQ+ (Householder tau (Array (MatrixShape.Split _ order extent) qr)) =+ extractQAux tau (Extent.width extent) order+ (Extent.square $ Extent.height extent) qr++tallExtractQ ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Householder vert Extent.Small height width a ->+ Full vert Extent.Small height width a+tallExtractQ+ (Householder tau (Array (MatrixShape.Split _ order extent) qr)) =+ extractQAux tau (Extent.width extent) order extent qr+++extractQAux ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C widthQR,+ Class.Floating a) =>+ Vector ZeroInt a -> widthQR ->+ Order -> Extent vert horiz height width -> ForeignPtr a ->+ Full vert horiz height width a+extractQAux (Array widthTau tau) widthQR order extent qr =+ Array.unsafeCreate (MatrixShape.Full order extent) $ \qPtr -> do++ let (height,width) = Extent.dimensions extent+ let m = Shape.size height+ let n = Shape.size width+ let k = Shape.size widthTau+ evalContT $ do+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ kPtr <- Call.cint k+ qrPtr <- ContT $ withForeignPtr qr+ tauPtr <- ContT $ withForeignPtr tau+ case order of+ RowMajor -> do+ ldaPtr <- Call.leadingDim n+ liftIO $ do+ copySubMatrix k m (Shape.size widthQR) qrPtr n qPtr+ withAutoWorkspaceInfo errorCodeMsg "unglq" $+ LapackGen.unglq nPtr mPtr kPtr qPtr ldaPtr tauPtr+ ColumnMajor -> do+ ldaPtr <- Call.leadingDim m+ liftIO $ do+ copyBlock (m*k) qrPtr qPtr+ withAutoWorkspaceInfo errorCodeMsg "ungqr" $+ LapackGen.ungqr mPtr nPtr kPtr qPtr ldaPtr tauPtr+++tallMultiplyQ ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Shape.C fuse, Eq fuse,+ Class.Floating a) =>+ Householder vert Extent.Small height fuse a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+tallMultiplyQ qr = multiplyQ NonInverted qr . addRows (extent_ qr)++tallMultiplyQAdjoint ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Shape.C fuse, Eq fuse, Class.Floating a) =>+ Householder horiz Extent.Small fuse height a ->+ Full vert horiz fuse width a ->+ Full vert horiz height width a+tallMultiplyQAdjoint qr =+ takeRows (Extent.transpose $ extent_ qr) . multiplyQ Inverted qr+++multiplyQ ::+ (Extent.C vertA, Extent.C horizA, Shape.C widthA,+ Extent.C vertB, Extent.C horizB, Shape.C widthB,+ Shape.C height, Eq height, Class.Floating a) =>+ Inversion ->+ Householder vertA horizA height widthA a ->+ Full vertB horizB height widthB a ->+ Full vertB horizB height widthB a+multiplyQ inverted+ (Householder+ (Array widthTau tau)+ (Array shapeA@(MatrixShape.Split _ orderA extentA) qr))+ (Array shapeB@(MatrixShape.Full orderB extentB) b) =++ Array.unsafeCreateWithSize shapeB $ \cSize cPtr -> do++ let (heightA,widthA) = Extent.dimensions extentA+ let (height,width) = Extent.dimensions extentB+ Call.assert "Householder.multiplyQ: height shapes mismatch"+ (heightA == height)++ let (side,(m,n)) =+ sideSwapFromOrder orderB (Shape.size height, Shape.size width)++ evalContT $ do+ sidePtr <- Call.char side+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ let k = Shape.size widthTau+ kPtr <- Call.cint k+ (transPtr,qrPtr,tauPtr) <-+ if orderA==orderB+ then+ liftA3 (,,)+ (Call.char $ transposeFromInversion qr inverted)+ (ContT $ withForeignPtr qr)+ (ContT $ withForeignPtr tau)+ else+ liftA3 (,,)+ (Call.char $+ transposeFromInversion qr $ flipInversion inverted)+ (conjugateToTemp (Shape.size shapeA) qr)+ (conjugateToTemp k tau)+ bPtr <- ContT $ withForeignPtr b+ ldcPtr <- Call.leadingDim m+ liftIO $ copyBlock cSize bPtr cPtr+ case orderA of+ ColumnMajor -> do+ ldaPtr <- Call.leadingDim $ Shape.size heightA+ liftIO $ withAutoWorkspaceInfo errorCodeMsg "unmqr" $+ LapackGen.unmqr sidePtr transPtr+ mPtr nPtr kPtr qrPtr ldaPtr tauPtr cPtr ldcPtr+ RowMajor -> do+ ldaPtr <- Call.leadingDim $ Shape.size widthA+ -- work-around for https://github.com/Reference-LAPACK/lapack/issues/260+ liftIO $ when (k>0) $+ withAutoWorkspaceInfo errorCodeMsg "unmlq" $+ LapackGen.unmlq sidePtr transPtr+ mPtr nPtr kPtr qrPtr ldaPtr tauPtr cPtr ldcPtr++transposeFromInversion :: (Class.Floating a) => f a -> Inversion -> Char+transposeFromInversion qr Inverted = invChar qr+transposeFromInversion _ NonInverted = 'N'++invChar :: (Class.Floating a) => f a -> Char+invChar f = getConst $ asFuncTypeOf f inverseChar++asFuncTypeOf :: f a -> g a -> g a+asFuncTypeOf = const id++inverseChar :: (Class.Floating a) => Const Char a+inverseChar =+ Class.switchFloating (Const 'T') (Const 'T') (Const 'C') (Const 'C')+++extractR ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Householder vert horiz height width a ->+ Full vert horiz height width a+extractR = Split.extractTriangle (Right MatrixShape.Triangle) . split_++tallExtractR ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Householder vert Extent.Small height width a -> Upper width a+tallExtractR = Split.tallExtractR . split_++tallMultiplyR ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz, Shape.C height, Eq height,+ Shape.C heightA, Shape.C widthB, Class.Floating a) =>+ Transposition ->+ Householder vertA Extent.Small heightA height a ->+ Full vert horiz height widthB a ->+ Full vert horiz height widthB a+tallMultiplyR transposed = Split.tallMultiplyR transposed . split_++tallSolveR ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Shape.C nrhs, Class.Floating a) =>+ Transposition -> Conjugation ->+ Householder vertA Extent.Small height width a ->+ Full vert horiz width nrhs a -> Full vert horiz width nrhs a+tallSolveR transposed conjugated =+ Split.tallSolveR transposed conjugated . split_
+ src/Numeric/LAPACK/Permutation.hs view
@@ -0,0 +1,15 @@+module Numeric.LAPACK.Permutation (+ Permutation,+ Matrix.Inversion(..),+ fromPivots,+ toPivots,+ toMatrix,+ determinant,+ numberFromSign,+ transpose,+ multiply,+ apply,+ ) where++import Numeric.LAPACK.Permutation.Private+import qualified Numeric.LAPACK.Matrix.Private as Matrix
+ src/Numeric/LAPACK/Permutation/Private.hs view
@@ -0,0 +1,193 @@+module Numeric.LAPACK.Permutation.Private where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Split as Split+import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor))+import Numeric.LAPACK.Matrix.Private+ (Full, Square, ZeroInt, Inversion(NonInverted, Inverted))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Format (Format(format))+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (fill, pointerSeq, copyBlock, copyToTemp)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import qualified Text.PrettyPrint.Boxes as TextBox++import qualified Foreign.Marshal.Array.Guarded as ForeignArray+import Foreign.Marshal.Array (advancePtr, copyArray)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable, poke, peek, pokeElemOff, peekElemOff)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+import Control.Monad (forM_)+import Control.Applicative ((<$>))++import Data.Bool.HT (if')+++newtype Permutation sh = Permutation (Vector sh CInt)+ deriving (Show)++instance (Shape.C sh) => Format (Permutation sh) where+ format _fmt (Permutation perm) =+ let n = Shape.size $ Array.shape perm+ in TextBox.vcat TextBox.top $+ map (TextBox.hsep 1 TextBox.right . map TextBox.char) $+ map (\k -> (replicate (k-1) '.' ++ '1' : replicate (n-k) '.')) $+ map fromIntegral $ Array.toList perm+++{-+We could use laswp if it would be available for CInt elements.+-}+{- |+The pivot array must be at most as long as @Shape.size sh@.+-}+fromPivots :: (Shape.C sh) =>+ Inversion -> sh -> Vector ZeroInt CInt -> Permutation sh+fromPivots inverted sh (Array (Shape.ZeroBased numIPiv) ipiv) =+ Permutation $+ if' (numIPiv > Shape.size sh)+ (error "Permutation.fromPivots: too many pivots") $+ Array.unsafeCreateWithSize sh $ \n permPtr ->+ withForeignPtr ipiv $ \ipivPtr -> do+ sequence_ $ take n $ zipWith poke (pointerSeq 1 permPtr) (iterate (1+) 1)+ let is =+ case inverted of+ Inverted -> tail $ iterate (subtract 1) numIPiv+ NonInverted -> iterate (1+) 0+ forM_ (take numIPiv is) $ \i ->+ swapElem permPtr i =<< peek1 ipivPtr i++swapElem :: (Storable a) => Ptr a -> Int -> Int -> IO ()+swapElem ptr i j = swap (advancePtr ptr i) (advancePtr ptr j)++swap :: (Storable a) => Ptr a -> Ptr a -> IO ()+swap ptr0 ptr1 = do+ a <- peek ptr0+ poke ptr0 =<< peek ptr1+ poke ptr1 a+++toPivots :: (Shape.C sh) => Inversion -> Permutation sh -> Vector sh CInt+toPivots inverted (Permutation (Array sh perm)) =+ Array.unsafeCreateWithSize sh $ \n invPtr ->+ withForeignPtr perm $ \perm0Ptr ->+ ForeignArray.alloca n $ \permPtr -> do+ case inverted of+ Inverted -> do+ copyArray permPtr perm0Ptr n+ transposeIO n permPtr invPtr+ NonInverted -> do+ copyArray invPtr perm0Ptr n+ transposeIO n perm0Ptr permPtr+ forM_ (take n $ iterate (1+) 0) $ \i -> do+ j <- peek1 invPtr i+ k <- peek1 permPtr i+ poke1 permPtr j k+ poke1 invPtr k j+++data Sign = Negative | Positive+ deriving (Eq, Show)++{-+We could also count the cycles of even number. This might be a little faster.+-}+determinant :: (Shape.C sh) => Permutation sh -> Sign+determinant =+ (\oddp -> if oddp then Negative else Positive) .+ Split.oddPermutation . Array.toList . toPivots NonInverted++numberFromSign :: (Class.Floating a) => Sign -> a+numberFromSign s =+ case s of+ Negative -> -1+ Positive -> 1+++transpose :: (Shape.C sh) => Permutation sh -> Permutation sh+transpose (Permutation (Array shape perm)) =+ Permutation $+ Array.unsafeCreateWithSize shape $ \n dstPtr ->+ withForeignPtr perm $ \srcPtr ->+ transposeIO n srcPtr dstPtr++transposeIO :: Int -> Ptr CInt -> Ptr CInt -> IO ()+transposeIO n srcPtr dstPtr =+ forM_ (take n $ iterate (1+) 0) $ \i -> do+ j <- peek1 srcPtr i+ poke1 dstPtr j i+++multiply :: (Shape.C sh, Eq sh) =>+ Permutation sh -> Permutation sh -> Permutation sh+multiply (Permutation (Array shape permA)) (Permutation (Array shapeB permB)) =+ if shape /= shapeB+ then error "Permutation.multiply: sizes mismatch"+ else+ Permutation $+ Array.unsafeCreateWithSize shape $ \n cPtr ->+ withForeignPtr permA $ \aPtr ->+ withForeignPtr permB $ \bPtr ->+ forM_ (take n $ iterate (1+) 0) $ \i ->+ poke1 cPtr i =<< peek1 bPtr =<< peek1 aPtr i+++toMatrix :: (Shape.C sh, Class.Floating a) => Permutation sh -> Square sh a+toMatrix (Permutation (Array shape perm)) =+ Array.unsafeCreate (MatrixShape.square RowMajor shape) $ \aPtr ->+ withForeignPtr perm $ \permPtr -> do+ let n = Shape.size shape+ fill zero (n*n) aPtr+ forM_ (take n $ zip (iterate (1+) 0) (pointerSeq n aPtr)) $+ \(k,rowPtr) -> do+ i <- peek1 permPtr k+ pokeElemOff rowPtr i one+++peek1 :: Ptr CInt -> Int -> IO Int+peek1 ptr i = subtract 1 . fromIntegral <$> peekElemOff ptr i++poke1 :: Ptr CInt -> Int -> Int -> IO ()+poke1 ptr i j = pokeElemOff ptr i (fromIntegral (j+1))+++apply ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Class.Floating a) =>+ Bool -> Permutation height ->+ Full vert horiz height width a ->+ Full vert horiz height width a+apply inverted+ (Permutation (Array shapeP perm))+ (Array shape@(MatrixShape.Full order extent) a) =++ Array.unsafeCreateWithSize shape $ \blockSize bPtr -> do++ let (height,width) = Extent.dimensions extent+ Call.assert "Permutation.apply: heights mismatch" (height == shapeP)+ let m = Shape.size height+ let n = Shape.size width+ evalContT $ do+ fwdPtr <- Call.bool $ not inverted+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ kPtr <- copyToTemp n perm+ aPtr <- ContT $ withForeignPtr a+ liftIO $ do+ copyBlock blockSize aPtr bPtr+ case order of+ RowMajor -> LapackGen.lapmt fwdPtr nPtr mPtr bPtr mPtr kPtr+ ColumnMajor -> LapackGen.lapmr fwdPtr mPtr nPtr bPtr nPtr kPtr
src/Numeric/LAPACK/Private.hs view
@@ -3,6 +3,7 @@ import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor, ColumnMajor), transposeFromOrder)+import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip)) import qualified Numeric.LAPACK.FFI.Generic as LapackGen import qualified Numeric.LAPACK.FFI.Complex as LapackComplex@@ -10,56 +11,35 @@ import qualified Numeric.BLAS.FFI.Generic as BlasGen import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class+import Numeric.LAPACK.Scalar (zero, one, isZero) -import Foreign.Marshal.Array (advancePtr)+import qualified Foreign.Marshal.Utils as Marshal+import qualified Foreign.C.String as CStr+import Foreign.Marshal.Array (copyArray, advancePtr) import Foreign.Marshal.Alloc (alloca)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, mallocForeignPtrArray)+import Foreign.C.Types (CChar, CInt)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr) import Foreign.Storable (Storable, poke, peek) import Text.Printf (printf) -import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.Trans.Cont (ContT(ContT), evalContT, runContT) import Control.Monad.IO.Class (liftIO)-import Control.Monad (foldM)+import Control.Monad (when, foldM) import Control.Applicative ((<$>)) -import Data.Functor.Identity (Identity(Identity, runIdentity))-+import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO import qualified Data.Array.Comfort.Shape as Shape-import Data.Array.Comfort.Storable.Internal (Array(Array))+import Data.Array.Comfort.Storable (Array) import qualified Data.Complex as Complex-import Data.Complex (Complex((:+)))+import Data.Complex (Complex)+import Data.Tuple.HT (swap) import Prelude hiding (sum) -type family RealOf x--type instance RealOf Float = Float-type instance RealOf Double = Double-type instance RealOf (Complex a) = a---type ComplexOf x = Complex (RealOf x)---zero, one, minusOne :: Class.Floating a => a-zero =- runIdentity $- Class.switchFloating (Identity 0) (Identity 0) (Identity 0) (Identity 0)-one =- runIdentity $- Class.switchFloating (Identity 1) (Identity 1) (Identity 1) (Identity 1)-minusOne =- runIdentity $- Class.switchFloating- (Identity (-1)) (Identity (-1)) (Identity (-1)) (Identity (-1))--- fill :: (Class.Floating a) => a -> Int -> Ptr a -> IO () fill a n dstPtr = evalContT $ do nPtr <- Call.cint n@@ -76,27 +56,93 @@ incyPtr <- Call.cint 1 liftIO $ BlasGen.copy nPtr srcPtr incxPtr dstPtr incyPtr -copyToTemp :: (Class.Floating a) => Int -> ForeignPtr a -> ContT r IO (Ptr a)+copyToTemp :: (Storable a) => Int -> ForeignPtr a -> ContT r IO (Ptr a) copyToTemp n fptr = do ptr <- ContT $ withForeignPtr fptr tmpPtr <- Call.allocaArray n- liftIO $ copyBlock n ptr tmpPtr+ liftIO $ copyArray tmpPtr ptr n return tmpPtr {- |+Make a temporary copy only for complex matrices.+-}+conjugateToTemp ::+ (Class.Floating a) => Int -> ForeignPtr a -> ContT r IO (Ptr a)+conjugateToTemp n =+ runCopyToTemp $+ Class.switchFloating+ (CopyToTemp $ ContT . withForeignPtr)+ (CopyToTemp $ ContT . withForeignPtr)+ (CopyToTemp $ complexConjugateToTemp n)+ (CopyToTemp $ complexConjugateToTemp n)++newtype CopyToTemp r a =+ CopyToTemp {runCopyToTemp :: ForeignPtr a -> ContT r IO (Ptr a)}++complexConjugateToTemp ::+ Class.Real a =>+ Int -> ForeignPtr (Complex a) -> ContT r IO (Ptr (Complex a))+complexConjugateToTemp n x = do+ nPtr <- Call.cint n+ xPtr <- copyToTemp n x+ incxPtr <- Call.cint 1+ liftIO $ LapackComplex.lacgv nPtr xPtr incxPtr+ return xPtr+++copyConjugate ::+ (Class.Floating a) =>+ Ptr CInt -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt -> IO ()+copyConjugate nPtr xPtr incxPtr yPtr incyPtr = do+ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr+ lacgv nPtr yPtr incyPtr++copyCondConjugate ::+ (Class.Floating a) =>+ Bool -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt -> IO ()+copyCondConjugate conj nPtr xPtr incxPtr yPtr incyPtr = do+ BlasGen.copy nPtr xPtr incxPtr yPtr incyPtr+ when conj $ lacgv nPtr yPtr incyPtr++condConjugateToTemp ::+ (Class.Floating a) =>+ Bool -> Int -> ForeignPtr a -> ContT r IO (Ptr a)+condConjugateToTemp conj n x =+ if conj then conjugateToTemp n x else ContT $ withForeignPtr x++copyCondConjugateToTemp ::+ (Class.Floating a) =>+ Bool -> Int -> ForeignPtr a -> ContT r IO (Ptr a)+copyCondConjugateToTemp conj n a = do+ bPtr <- Call.allocaArray n+ liftIO $ evalContT $ do+ aPtr <- ContT $ withForeignPtr a+ sizePtr <- Call.cint n+ incPtr <- Call.cint 1+ liftIO $ copyCondConjugate conj sizePtr aPtr incPtr bPtr incPtr+ return bPtr++++{- | In ColumnMajor: Copy a m-by-n-matrix with lda>=m and ldb>=m. -} copySubMatrix :: (Class.Floating a) => Int -> Int -> Int -> Ptr a -> Int -> Ptr a -> IO ()-copySubMatrix m n lda aPtr ldb bPtr = evalContT $ do- uploPtr <- Call.char 'A'+copySubMatrix = copySubTrapezoid 'A'++copySubTrapezoid ::+ (Class.Floating a) =>+ Char -> Int -> Int -> Int -> Ptr a -> Int -> Ptr a -> IO ()+copySubTrapezoid side m n lda aPtr ldb bPtr = evalContT $ do+ uploPtr <- Call.char side mPtr <- Call.cint m nPtr <- Call.cint n- ldaPtr <- Call.cint lda- ldbPtr <- Call.cint ldb+ ldaPtr <- Call.leadingDim lda+ ldbPtr <- Call.leadingDim ldb liftIO $ LapackGen.lacpy uploPtr mPtr nPtr aPtr ldaPtr bPtr ldbPtr copyTransposed ::@@ -140,26 +186,19 @@ pointerSeq k ptr = iterate (flip advancePtr k) ptr -allocArray :: (Shape.C sh, Storable a) => sh -> ContT r IO (Array sh a, Ptr a)-allocArray sh = do- fptr <- liftIO $ mallocForeignPtrArray $ Shape.size sh- ptr <- ContT $ withForeignPtr fptr- return (Array sh fptr, ptr)---allocHigherArray ::+createHigherArray :: (Shape.C sh, Class.Floating a) =>- sh -> Int -> Int -> Int -> ContT r IO (Array sh a, (Ptr a, Int))-allocHigherArray shapeX m n nrhs = do- (x,xPtr) <- allocArray shapeX+ sh -> Int -> Int -> Int ->+ ((Ptr a, Int) -> IO rank) -> IO (rank, Array sh a)+createHigherArray shapeX m n nrhs act =+ fmap swap $ ArrayIO.unsafeCreateWithSizeAndResult shapeX $ \ _ xPtr -> if m>n- then do- tmpPtr <- Call.allocaArray (m*nrhs)- ContT $ \act -> do- r <- act (x,(tmpPtr,m))+ then+ runContT (Call.allocaArray (m*nrhs)) $ \tmpPtr -> do+ r <- act (tmpPtr,m) copySubMatrix n nrhs m tmpPtr n xPtr return r- else return (x,(xPtr,n))+ else act (xPtr,n) @@ -193,17 +232,17 @@ onePtr <- Call.number one zeroincPtr <- Call.cint 0 aPtr <- Call.allocaArray n- ldaPtr <- Call.cint 1+ ldaPtr <- Call.leadingDim 1 incxPtr <- Call.cint incx betaPtr <- Call.number zero yPtr <- Call.alloca incyPtr <- Call.cint 1- liftIO $ BlasGen.copy nPtr onePtr zeroincPtr aPtr incyPtr- liftIO $- BlasGen.gemv+ liftIO $ do+ BlasGen.copy nPtr onePtr zeroincPtr aPtr incyPtr+ gemv transPtr mPtr nPtr alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr- liftIO $ peek yPtr+ peek yPtr product :: Class.Floating a => Int -> Ptr a -> Int -> IO a@@ -224,6 +263,51 @@ (LACGV LapackComplex.lacgv) +{-+Work around an inconsistency of BLAS.+In case of a zero-column matrix+BLAS's gemv and gbmv do not initialize the target vector.+In contrast, these work-arounds do.+-}+{-# INLINE gemv #-}+gemv ::+ (Class.Floating a) =>+ Ptr CChar -> Ptr CInt -> Ptr CInt ->+ Ptr a -> Ptr a -> Ptr CInt ->+ Ptr a -> Ptr CInt -> Ptr a -> Ptr a -> Ptr CInt -> IO ()+gemv transPtr mPtr nPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr = do+ initializeMV transPtr mPtr nPtr betaPtr yPtr incyPtr+ BlasGen.gemv transPtr mPtr nPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr++{-# INLINE gbmv #-}+gbmv ::+ (Class.Floating a) =>+ Ptr CChar -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt ->+ Ptr a -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt ->+ Ptr a -> Ptr a -> Ptr CInt -> IO ()+gbmv transPtr mPtr nPtr klPtr kuPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr = do+ initializeMV transPtr mPtr nPtr betaPtr yPtr incyPtr+ BlasGen.gbmv transPtr mPtr nPtr klPtr kuPtr+ alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr++initializeMV ::+ Class.Floating a =>+ Ptr CChar -> Ptr CInt -> Ptr CInt -> Ptr a -> Ptr a -> Ptr CInt -> IO ()+initializeMV transPtr mPtr nPtr betaPtr yPtr incyPtr = do+ trans <- peek transPtr+ let (mtPtr,ntPtr) =+ if trans == CStr.castCharToCChar 'N'+ then (mPtr,nPtr) else (nPtr,mPtr)+ n <- peek ntPtr+ beta <- peek betaPtr+ when (n == 0 && isZero beta) $+ Marshal.with 0 $ \incbPtr ->+ BlasGen.copy mtPtr betaPtr incbPtr yPtr incyPtr++ multiplyMatrix :: (Class.Floating a) => Order -> Order -> Int -> Int -> Int ->@@ -240,11 +324,11 @@ kPtr <- Call.cint k alphaPtr <- Call.number one aPtr <- ContT $ withForeignPtr a- ldaPtr <- Call.cint lda+ ldaPtr <- Call.leadingDim lda bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint ldb+ ldbPtr <- Call.leadingDim ldb betaPtr <- Call.number zero- ldcPtr <- Call.cint ldc+ ldcPtr <- Call.leadingDim ldc liftIO $ BlasGen.gemm transaPtr transbPtr mPtr nPtr kPtr alphaPtr aPtr ldaPtr@@ -254,16 +338,11 @@ withAutoWorkspaceInfo :: (Class.Floating a) =>- String -> (Ptr a -> Ptr CInt -> Ptr CInt -> IO ()) -> IO ()-withAutoWorkspaceInfo name computation = evalContT $ do- infoPtr <- Call.alloca- liftIO $ withAutoWorkspace $ \workPtr lworkPtr ->+ String -> String -> (Ptr a -> Ptr CInt -> Ptr CInt -> IO ()) -> IO ()+withAutoWorkspaceInfo msg name computation =+ withInfo msg name $ \infoPtr ->+ withAutoWorkspace $ \workPtr lworkPtr -> computation workPtr lworkPtr infoPtr- info <- liftIO $ fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $ printf "%s: deficient rank %d" name info withAutoWorkspace :: (Class.Floating a) =>@@ -272,42 +351,48 @@ lworkPtr <- Call.cint (-1) lwork <- liftIO $ alloca $ \workPtr -> do computation workPtr lworkPtr- ceilingSize <$> peek workPtr+ max 1 . ceilingSize <$> peek workPtr workPtr <- Call.allocaArray lwork- liftIO $ poke lworkPtr $ fromIntegral lwork+ liftIO $ pokeCInt lworkPtr lwork liftIO $ computation workPtr lworkPtr +withInfo :: String -> String -> (Ptr CInt -> IO ()) -> IO ()+withInfo msg name computation = alloca $ \infoPtr -> do+ computation infoPtr+ info <- peekCInt infoPtr+ case compare info (0::Int) of+ EQ -> return ()+ LT -> error $ printf argMsg name (-info)+ GT -> error $ name ++ ": " ++ printf msg info -newtype FromReal a = FromReal {getFromReal :: RealOf a -> a}+argMsg :: String+argMsg = "%s: illegal value in %d-th argument" -fromReal :: (Class.Floating a) => RealOf a -> a-fromReal =- getFromReal $- Class.switchFloating- (FromReal id)- (FromReal id)- (FromReal (:+0))- (FromReal (:+0))+errorCodeMsg :: String+errorCodeMsg = "unknown error code %d" -newtype RealPart a = RealPart {getRealPart :: a -> RealOf a}+rankMsg :: String+rankMsg = "deficient rank %d" -realPart :: (Class.Floating a) => a -> RealOf a-realPart =- getRealPart $- Class.switchFloating- (RealPart id)- (RealPart id)- (RealPart Complex.realPart)- (RealPart Complex.realPart)+definiteMsg :: String+definiteMsg = "minor of order %d not positive definite" +eigenMsg :: String+eigenMsg = "%d off-diagonal elements not converging" -newtype FuncArg b a = FuncArg {runFuncArg :: a -> b} +pokeCInt :: Ptr CInt -> Int -> IO ()+pokeCInt ptr = poke ptr . fromIntegral++peekCInt :: Ptr CInt -> IO Int+peekCInt ptr = fromIntegral <$> peek ptr++ ceilingSize :: (Class.Floating a) => a -> Int ceilingSize =- runFuncArg $+ getFlip $ Class.switchFloating- (FuncArg ceiling)- (FuncArg ceiling)- (FuncArg $ ceiling . Complex.realPart)- (FuncArg $ ceiling . Complex.realPart)+ (Flip ceiling)+ (Flip ceiling)+ (Flip $ ceiling . Complex.realPart)+ (Flip $ ceiling . Complex.realPart)
+ src/Numeric/LAPACK/Scalar.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.Scalar (+ RealOf,+ ComplexOf,+ zero,+ one,+ minusOne,+ isZero,+ selectReal,+ selectFloating,++ fromReal,+ absolute,+ absoluteSquared,+ norm1,+ realPart,+ conjugate,+ ) where++import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip))++import qualified Numeric.Netlib.Class as Class++import Data.Functor.Identity (Identity(Identity, runIdentity))++import qualified Data.Complex as Complex+import Data.Complex (Complex((:+)))+import Data.Monoid (Endo(Endo,appEndo))+++type family RealOf x++type instance RealOf Float = Float+type instance RealOf Double = Double+type instance RealOf (Complex a) = a+++type ComplexOf x = Complex (RealOf x)+++-- move to netlib-carray:Utility or netlib-ffi:Class+zero, one, minusOne :: Class.Floating a => a+zero = selectFloating 0 0 0 0+one = selectFloating 1 1 1 1+minusOne = selectFloating (-1) (-1) (-1) (-1)++selectReal :: (Class.Real a) => Float -> Double -> a+selectReal rf rd =+ runIdentity $ Class.switchReal (Identity rf) (Identity rd)++selectFloating ::+ (Class.Floating a) =>+ Float -> Double -> Complex Float -> Complex Double -> a+selectFloating rf rd cf cd =+ runIdentity $+ Class.switchFloating+ (Identity rf) (Identity rd) (Identity cf) (Identity cd)+++isZero :: Class.Floating a => a -> Bool+isZero =+ getFlip $+ Class.switchFloating+ (Flip (0==)) (Flip (0==))+ (Flip (0==)) (Flip (0==))+++newtype FromReal a = FromReal {getFromReal :: RealOf a -> a}++fromReal :: (Class.Floating a) => RealOf a -> a+fromReal =+ getFromReal $+ Class.switchFloating+ (FromReal id)+ (FromReal id)+ (FromReal (:+0))+ (FromReal (:+0))++newtype ToReal a = ToReal {getToReal :: a -> RealOf a}++realPart :: (Class.Floating a) => a -> RealOf a+realPart =+ getToReal $+ Class.switchFloating+ (ToReal id)+ (ToReal id)+ (ToReal Complex.realPart)+ (ToReal Complex.realPart)++absolute :: (Class.Floating a) => a -> RealOf a+absolute =+ getToReal $+ Class.switchFloating+ (ToReal abs)+ (ToReal abs)+ (ToReal Complex.magnitude)+ (ToReal Complex.magnitude)+++norm1 :: (Class.Floating a) => a -> RealOf a+norm1 =+ getToReal $+ Class.switchFloating+ (ToReal abs)+ (ToReal abs)+ (ToReal norm1Complex)+ (ToReal norm1Complex)++norm1Complex :: (Class.Real a) => Complex a -> a+norm1Complex (r:+i) = abs r + abs i+++absoluteSquared :: (Class.Floating a) => a -> RealOf a+absoluteSquared =+ getToReal $+ Class.switchFloating+ (ToReal absoluteSquaredReal)+ (ToReal absoluteSquaredReal)+ (ToReal absoluteSquaredComplex)+ (ToReal absoluteSquaredComplex)++absoluteSquaredReal :: (Class.Real a) => a -> a+absoluteSquaredReal a = a*a++absoluteSquaredComplex :: (Class.Real a) => Complex a -> a+absoluteSquaredComplex (r:+i) = r*r+i*i+++conjugate :: (Class.Floating a) => a -> a+conjugate =+ appEndo $+ Class.switchFloating+ (Endo id) (Endo id) (Endo Complex.conjugate) (Endo Complex.conjugate)
+ src/Numeric/LAPACK/ShapeStatic.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE TypeFamilies #-}+module Numeric.LAPACK.ShapeStatic where++import Numeric.LAPACK.Matrix.Shape.Private (UnaryProxy)++import qualified Data.FixedLength as FL++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)++import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num (integralFromProxy)+import Type.Base.Proxy (Proxy(Proxy))++import Foreign.Storable (Storable)++import Text.Printf (printf)+++{- |+'ZeroBased' denotes a range starting at zero and has a certain length.+-}+newtype ZeroBased n = ZeroBased {zeroBasedSize :: UnaryProxy n}+ deriving (Eq, Show)++instance (Unary.Natural n) => Shape.C (ZeroBased n) where+ size = Shape.uncheckedSize+ uncheckedSize (ZeroBased len) = integralFromProxy len++instance (Unary.Natural n) => Shape.Indexed (ZeroBased n) where+ type Index (ZeroBased n) = FL.Index n+ indices _len = FL.toList FL.indices+ offset = Shape.uncheckedOffset+ uncheckedOffset _len = fromIntegral . FL.numFromIndex+ inBounds _len _ix = True++instance (Unary.Natural n) => Shape.InvIndexed (ZeroBased n) where+ -- could be implemented using new fixed-length-0.2.1:FL.indexFromNum+ indexFromOffset len k =+ case (0<=k, drop k $ Shape.indices len) of+ (True, i:_) -> i+ _ -> -- cf. comfort-array:Shape.errorIndexFromOffset+ error $+ printf "indexFromOffset (ShapeStatic.ZeroBased): index %d out of range" k+++vector :: (Unary.Natural n, Storable a) => FL.T n a -> Array (ZeroBased n) a+vector = Array.fromList (ZeroBased Proxy) . FL.toList
src/Numeric/LAPACK/Singular.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE TypeFamilies #-} module Numeric.LAPACK.Singular ( values,+ valuesTall,+ valuesWide, decompose,- decomposeNarrow,- decomposeSquat,+ decomposeTall,+ decomposeWide, determinantAbsolute, leastSquaresMinimumNormRCond, pseudoInverseRCond,@@ -11,15 +13,22 @@ ) where import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Square.Basic as Square+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent import qualified Numeric.LAPACK.Matrix as Matrix import qualified Numeric.LAPACK.Vector as Vector-import Numeric.LAPACK.Matrix.Square (Square)-import Numeric.LAPACK.Matrix.Shape.Private (Order(RowMajor,ColumnMajor))-import Numeric.LAPACK.Matrix.Private (General, ZeroInt, zeroInt)+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Hermitian.Private+ (TakeDiagonal(..), Determinant(..))+import Numeric.LAPACK.Matrix.Extent.Private (Extent)+import Numeric.LAPACK.Matrix.Square.Basic (Square)+import Numeric.LAPACK.Matrix.Shape.Private (Order(ColumnMajor), swapOnRowMajor)+import Numeric.LAPACK.Matrix (scaleRowsReal)+import Numeric.LAPACK.Matrix.Private (Full, General, ZeroInt, zeroInt) import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, zero) import Numeric.LAPACK.Private- (RealOf, withAutoWorkspace, fromReal, allocArray, allocHigherArray,+ (withAutoWorkspace, peekCInt, createHigherArray, copyToTemp, copyToColumnMajor, copyToSubColumnMajor) import qualified Numeric.LAPACK.FFI.Complex as LapackComplex@@ -27,49 +36,68 @@ import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class +import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape import Data.Array.Comfort.Storable.Internal (Array(Array)) import System.IO.Unsafe (unsafePerformIO) -import Foreign.Marshal.Array (allocaArray)-import Foreign.Marshal.Alloc (alloca)+import qualified Foreign.Marshal.Array.Guarded as ForeignArray+import qualified Foreign.Marshal.Utils as Marshal import Foreign.C.Types (CInt, CChar)-import Foreign.ForeignPtr (withForeignPtr)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr, nullPtr)-import Foreign.Storable (Storable, peek)+import Foreign.Storable (Storable) import Control.Monad.Trans.Cont (evalContT) import Control.Monad.IO.Class (liftIO)-import Control.Applicative ((<$>)) -import Text.Printf (printf)- import Data.Complex (Complex)+import Data.Tuple.HT (mapSnd)+import Data.Bool.HT (if') values :: (Shape.C height, Shape.C width, Class.Floating a) => General height width a -> Vector ZeroInt (RealOf a) values =- getValues $- Class.switchFloating- (Values valuesAux) (Values valuesAux)- (Values valuesAux) (Values valuesAux)+ valuesGen $ \extent ->+ zeroInt $+ min+ (Shape.size $ Extent.height extent)+ (Shape.size $ Extent.width extent) -type Values_ height width a =- General height width a -> Vector ZeroInt (RealOf a)+valuesTall ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Full vert Extent.Small height width a -> Vector width (RealOf a)+valuesTall = valuesGen Extent.width -newtype Values height width a = Values {getValues :: Values_ height width a}+valuesWide ::+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ Full Extent.Small horiz height width a -> Vector height (RealOf a)+valuesWide = valuesTall . Matrix.transpose +valuesGen ::+ (Extent.C vert, Extent.C horiz, Shape.C width, Shape.C height,+ Shape.C shape, Class.Floating a) =>+ (Extent vert horiz height width -> shape) ->+ Full vert horiz height width a -> Vector shape (RealOf a)+valuesGen resultShape =+ runTakeDiagonal $+ Class.switchFloating+ (TakeDiagonal $ valuesAux resultShape)+ (TakeDiagonal $ valuesAux resultShape)+ (TakeDiagonal $ valuesAux resultShape)+ (TakeDiagonal $ valuesAux resultShape)+ valuesAux ::- (Shape.C height, Shape.C width,- Class.Floating a, RealOf a ~ ar, Storable ar) =>- Values_ height width a-valuesAux (Array shape@(MatrixShape.General _order height width) a) =- Array.unsafeCreateWithSize- (zeroInt $ min (Shape.size height) (Shape.size width)) $ \mn sPtr -> do+ (Extent.C vert, Extent.C horiz, Shape.C width, Shape.C height,+ Shape.C shape, Class.Floating a, RealOf a ~ ar, Storable ar) =>+ (Extent vert horiz height width -> shape) ->+ Full vert horiz height width a -> Vector shape ar+valuesAux resultShape (Array shape@(MatrixShape.Full _order extent) a) =+ Array.unsafeCreateWithSize (resultShape extent) $ \mn sPtr -> do let (m,n) = MatrixShape.dimensions shape let lda = m evalContT $ do@@ -78,11 +106,11 @@ mPtr <- Call.cint m nPtr <- Call.cint n aPtr <- copyToTemp (m*n) a- ldaPtr <- Call.cint lda+ ldaPtr <- Call.leadingDim lda let uPtr = nullPtr let vtPtr = nullPtr- lduPtr <- Call.cint m- ldvtPtr <- Call.cint n+ lduPtr <- Call.leadingDim m+ ldvtPtr <- Call.leadingDim n liftIO $ withInfo "gesvd" $ \infoPtr -> gesvd jobuPtr jobvtPtr mPtr nPtr@@ -93,23 +121,21 @@ (Shape.C height, Shape.C width, Class.Floating a) => General height width a -> RealOf a determinantAbsolute =- getDeterminantAbsolute $+ getDeterminant $ Class.switchFloating- (DeterminantAbsolute determinantAbsoluteAux)- (DeterminantAbsolute determinantAbsoluteAux)- (DeterminantAbsolute determinantAbsoluteAux)- (DeterminantAbsolute determinantAbsoluteAux)--newtype DeterminantAbsolute f a =- DeterminantAbsolute {- getDeterminantAbsolute :: f a -> RealOf a- }+ (Determinant determinantAbsoluteAux)+ (Determinant determinantAbsoluteAux)+ (Determinant determinantAbsoluteAux)+ (Determinant determinantAbsoluteAux) determinantAbsoluteAux :: (Shape.C height, Shape.C width,- Class.Floating a, RealOf a ~ ar, Class.Floating ar) =>+ Class.Floating a, RealOf a ~ ar, Class.Real ar) => General height width a -> ar-determinantAbsoluteAux = Vector.product . values+determinantAbsoluteAux =+ either (Vector.product . valuesTall) (const zero)+ .+ Matrix.caseTallWide decompose ::@@ -125,56 +151,61 @@ (Decompose decomposeAux) newtype Decompose m f v g a =- Decompose {- getDecompose :: m a -> (f a, v (RealOf a), g a)- }+ Decompose {getDecompose :: m a -> (f a, v (RealOf a), g a)} decomposeAux :: (Shape.C height, Shape.C width, Class.Floating a, RealOf a ~ ar, Storable ar) => General height width a -> (Square height a, Vector ZeroInt ar, Square width a)-decomposeAux (Array (MatrixShape.General order height width) a) =- unsafePerformIO $ evalContT $ do- (u,uPtr0) <- allocArray (MatrixShape.Square order height)- (vt,vtPtr0) <- allocArray (MatrixShape.Square order width)- let ((m,n),(uPtr,vtPtr)) =- case order of- RowMajor ->- ((Shape.size width, Shape.size height), (vtPtr0,uPtr0))- ColumnMajor ->- ((Shape.size height, Shape.size width), (uPtr0,vtPtr0))- let mn = min m n+decomposeAux arr@(Array shape@(MatrixShape.Full order extent) a) =++ let (height,width) = Extent.dimensions extent+ (m,n) = MatrixShape.dimensions shape+ mn = min m n++ in (if' (mn==0)+ (Square.identityFromHeight arr,+ Vector.autoFromList [],+ Square.identityFromWidth arr)) $+ (\(u,(s,vt)) -> (u,s,vt)) $+ Array.unsafeCreateWithSizeAndResult (MatrixShape.square order height) $+ \ _ uPtr0 ->+ ArrayIO.unsafeCreateWithSizeAndResult (zeroInt mn) $ \ _ sPtr ->+ ArrayIO.unsafeCreate (MatrixShape.square order width) $ \vtPtr0 ->++ evalContT $ do+ let (uPtr,vtPtr) = swapOnRowMajor order (uPtr0,vtPtr0) let lda = m jobuPtr <- Call.char 'A' jobvtPtr <- Call.char 'A' mPtr <- Call.cint m nPtr <- Call.cint n aPtr <- copyToTemp (m*n) a- ldaPtr <- Call.cint lda- (s,sPtr) <- allocArray (zeroInt mn)- lduPtr <- Call.cint m- ldvtPtr <- Call.cint n+ ldaPtr <- Call.leadingDim lda+ lduPtr <- Call.leadingDim m+ ldvtPtr <- Call.leadingDim n liftIO $ withInfo "gesvd" $ \infoPtr -> gesvd jobuPtr jobvtPtr mPtr nPtr aPtr ldaPtr sPtr uPtr lduPtr vtPtr ldvtPtr mn infoPtr- return (u, s, vt) -decomposeSquat ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a ->- (Square height a, Vector height (RealOf a), General height width a)-decomposeSquat a =- let (u,s,vt) = decomposeNarrow $ Matrix.transpose a+decomposeWide ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Full Extent.Small vert height width a ->+ (Square height a, Vector height (RealOf a),+ Full Extent.Small vert height width a)+decomposeWide a =+ let (u,s,vt) = decomposeTall $ Matrix.transpose a in (Square.transpose vt, s, Matrix.transpose u) -decomposeNarrow ::- (Shape.C height, Shape.C width, Class.Floating a) =>- General height width a ->- (General height width a, Vector width (RealOf a), Square width a)-decomposeNarrow =+decomposeTall ::+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ Full horiz Extent.Small height width a ->+ (Full horiz Extent.Small height width a,+ Vector width (RealOf a), Square width a)+decomposeTall = getDecompose $ Class.switchFloating (Decompose decomposeThin)@@ -183,23 +214,22 @@ (Decompose decomposeThin) decomposeThin ::- (Shape.C height, Shape.C width,+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a, RealOf a ~ ar, Storable ar) =>- General height width a ->- (General height width a, Vector width ar, Square width a)-decomposeThin (Array (MatrixShape.General order height width) a) =- unsafePerformIO $ do- Call.assert "Singular.decomposeThin: matrix is wider than high"- (Shape.size height >= Shape.size width)- evalContT $ do- (u,uPtr0) <- allocArray (MatrixShape.General order height width)- (vt,vtPtr0) <- allocArray (MatrixShape.Square order width)- let ((m,n),(uPtr,vtPtr)) =- case order of- RowMajor ->- ((Shape.size width, Shape.size height), (vtPtr0,uPtr0))- ColumnMajor ->- ((Shape.size height, Shape.size width), (uPtr0,vtPtr0))+ Full horiz Extent.Small height width a ->+ (Full horiz Extent.Small height width a, Vector width ar, Square width a)+decomposeThin (Array (MatrixShape.Full order extent) a) =+ let (height,width) = Extent.dimensions extent+ in (\(u,(s,vt)) -> (u,s,vt)) $+ Array.unsafeCreateWithSizeAndResult (MatrixShape.Full order extent) $+ \ _ uPtr0 ->+ ArrayIO.unsafeCreateWithSizeAndResult width $ \ _ sPtr ->+ ArrayIO.unsafeCreate (MatrixShape.square order width) $ \vtPtr0 ->++ evalContT $ do+ let ((m,uPtr),(n,vtPtr)) =+ swapOnRowMajor order+ ((Shape.size height, uPtr0), (Shape.size width, vtPtr0)) let mn = min m n let lda = m jobuPtr <- Call.char 'S'@@ -207,15 +237,13 @@ mPtr <- Call.cint m nPtr <- Call.cint n aPtr <- copyToTemp (m*n) a- ldaPtr <- Call.cint lda- (s,sPtr) <- allocArray width- lduPtr <- Call.cint m- ldvtPtr <- Call.cint mn+ ldaPtr <- Call.leadingDim lda+ lduPtr <- Call.leadingDim m+ ldvtPtr <- Call.leadingDim mn liftIO $ withInfo "gesvd" $ \infoPtr -> gesvd jobuPtr jobvtPtr mPtr nPtr aPtr ldaPtr sPtr uPtr lduPtr vtPtr ldvtPtr mn infoPtr- return (u, s, vt) type GESVD_ ar a =@@ -245,7 +273,7 @@ gesvdComplex :: (Class.Real a) => GESVD_ a (Complex a) gesvdComplex jobuPtr jobvtPtr mPtr nPtr aPtr ldaPtr sPtr uPtr lduPtr vtPtr ldvtPtr mn infoPtr =- allocaArray (5*mn) $ \rworkPtr ->+ ForeignArray.alloca (5*mn) $ \rworkPtr -> withAutoWorkspace $ \workPtr lworkPtr -> LapackComplex.gesvd jobuPtr jobvtPtr mPtr nPtr aPtr ldaPtr sPtr uPtr lduPtr vtPtr ldvtPtr@@ -253,38 +281,50 @@ leastSquaresMinimumNormRCond ::- (Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>- RealOf a -> General height width a -> General height nrhs a ->- (Int, General width nrhs a)-leastSquaresMinimumNormRCond =- getLeastSquaresMinimumNormRCond $- Class.switchFloating- (LeastSquaresMinimumNormRCond leastSquaresMinimumNormRCondAux)- (LeastSquaresMinimumNormRCond leastSquaresMinimumNormRCondAux)- (LeastSquaresMinimumNormRCond leastSquaresMinimumNormRCondAux)- (LeastSquaresMinimumNormRCond leastSquaresMinimumNormRCondAux)+ (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 rcond+ (Array (MatrixShape.Full orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =+ case Extent.fuse (Extent.transpose extentA) extentB of+ Nothing -> error "leastSquaresMinimumNorm: height shapes mismatch"+ Just extent ->+ let widthA = Extent.width extentA+ (height,widthB) = Extent.dimensions extentB+ shapeX = MatrixShape.Full ColumnMajor extent+ m = Shape.size height+ n = Shape.size widthA+ nrhs = Shape.size widthB+ in if m == 0+ then (0, Vector.constant shapeX zero)+ else+ if nrhs == 0+ then+ (fst $ unsafePerformIO $+ case Vector.constant height zero of+ Array _ b1 ->+ leastSquaresMinimumNormIO rcond+ (MatrixShape.general ColumnMajor widthA ())+ orderA a orderB b1 m n 1,+ Vector.constant shapeX zero)+ else+ unsafePerformIO $+ leastSquaresMinimumNormIO rcond shapeX+ orderA a orderB b m n nrhs -newtype LeastSquaresMinimumNormRCond f g h a =- LeastSquaresMinimumNormRCond {- getLeastSquaresMinimumNormRCond ::- RealOf a -> f a -> g a -> (Int, h a)- }+leastSquaresMinimumNormIO ::+ (Shape.C sh, Class.Floating a) =>+ RealOf a -> sh ->+ Order -> ForeignPtr a ->+ Order -> ForeignPtr a ->+ Int -> Int -> Int -> IO (Int, Array sh a)+leastSquaresMinimumNormIO rcond shapeX orderA a orderB b m n nrhs =+ createHigherArray shapeX m n nrhs $ \(tmpPtr,ldtmp) -> do -leastSquaresMinimumNormRCondAux ::- (Shape.C height, Eq height, Shape.C width, Shape.C nrhs,- Class.Floating a, RealOf a ~ ar, Class.Floating ar) =>- ar -> General height width a -> General height nrhs a ->- (Int, General width nrhs a)-leastSquaresMinimumNormRCondAux rcond- (Array (MatrixShape.General orderA heightA widthA) a)- (Array (MatrixShape.General orderB heightB widthB) b) =- unsafePerformIO $ do- Call.assert "leastSquaresMinimumNorm: height shapes mismatch"- (heightA == heightB)- let shapeX = MatrixShape.General ColumnMajor widthA widthB- let m = Shape.size heightA- let n = Shape.size widthA- let nrhs = Shape.size widthB let mn = min m n let aSize = m*n let lda = m@@ -295,28 +335,24 @@ aPtr <- Call.allocaArray aSize liftIO $ withForeignPtr a $ \asrcPtr -> copyToColumnMajor orderA m n asrcPtr aPtr- ldaPtr <- Call.cint lda- (x,(tmpPtr,ldtmp)) <- allocHigherArray shapeX m n nrhs- ldtmpPtr <- Call.cint ldtmp+ ldaPtr <- Call.leadingDim lda+ ldtmpPtr <- Call.leadingDim ldtmp liftIO $ withForeignPtr b $ \bPtr -> copyToSubColumnMajor orderB m nrhs bPtr ldtmp tmpPtr - sPtr <- Call.allocaArray mn- rcondPtr <- Call.number rcond rankPtr <- Call.alloca liftIO $ withInfo "gelss" $ \infoPtr ->- gelss mPtr nPtr nrhsPtr aPtr ldaPtr tmpPtr ldtmpPtr sPtr rcondPtr+ gelss mPtr nPtr nrhsPtr aPtr ldaPtr tmpPtr ldtmpPtr rcond rankPtr mn infoPtr - rank <- liftIO $ fromIntegral <$> peek rankPtr- return (rank, x)+ liftIO $ peekCInt rankPtr type GELSS_ ar a = Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr a -> Ptr CInt ->- Ptr ar -> Ptr ar -> Ptr CInt -> Int -> Ptr CInt -> IO ()+ ar -> Ptr CInt -> Int -> Ptr CInt -> IO () newtype GELSS a = GELSS {getGELSS :: GELSS_ (RealOf a) a} @@ -330,17 +366,21 @@ (GELSS gelssComplex) gelssReal :: (Class.Real a) => GELSS_ a a-gelssReal mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr sPtr rcondPtr- rankPtr _mn infoPtr =+gelssReal mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr rcond+ rankPtr mn infoPtr =+ Marshal.with rcond $ \rcondPtr ->+ ForeignArray.alloca mn $ \sPtr -> withAutoWorkspace $ \workPtr lworkPtr -> LapackReal.gelss mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr sPtr rcondPtr rankPtr workPtr lworkPtr infoPtr gelssComplex :: (Class.Real a) => GELSS_ a (Complex a)-gelssComplex mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr sPtr rcondPtr+gelssComplex mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr rcond rankPtr mn infoPtr =- allocaArray (5*mn) $ \rworkPtr ->+ Marshal.with rcond $ \rcondPtr ->+ ForeignArray.alloca mn $ \sPtr ->+ ForeignArray.alloca (5*mn) $ \rworkPtr -> withAutoWorkspace $ \workPtr lworkPtr -> LapackComplex.gelss mPtr nPtr nrhsPtr aPtr ldaPtr bPtr ldbPtr sPtr rcondPtr@@ -348,8 +388,11 @@ pseudoInverseRCond ::- (Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>- RealOf a -> General height width a -> (Int, General width height a)+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a) =>+ RealOf a ->+ Full vert horiz height width a ->+ (Int, Full horiz vert width height a) pseudoInverseRCond = getPseudoInverseRCond $ Class.switchFloating@@ -364,43 +407,70 @@ } pseudoInverseRCondAux ::- (Shape.C height, Eq height, Shape.C width, Eq width,+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>- RealOf a -> General height width a -> (Int, General width height a)-pseudoInverseRCondAux rcond a =- let (MatrixShape.General _ height width) = Array.shape a- in if Shape.size height < Shape.size width- then- let (u,s,vt) = decomposeSquat a- (rank,recipS) = recipSigma rcond s- in (rank,- Matrix.multiply (Matrix.adjoint vt) $- Matrix.scaleRows recipS $- Square.toGeneral $ Square.adjoint u)- else- let (u,s,vt) = decomposeNarrow a- (rank,recipS) = recipSigma rcond s- in (rank,- Matrix.multiply (Square.toGeneral $ Square.adjoint vt) $- Matrix.scaleRows recipS $ Matrix.adjoint u)+ ar ->+ Full vert horiz height width a ->+ (Int, Full horiz vert width height a)+pseudoInverseRCondAux rcond =+ getPseudoInverseExtent $+ Extent.switchTagPair+ (PseudoInverseExtent $ pseudoInverseRCondWide rcond)+ (PseudoInverseExtent $ pseudoInverseRCondWide rcond)+ (PseudoInverseExtent $ pseudoInverseRCondTall rcond)+ (PseudoInverseExtent $+ either+ (mapSnd Matrix.fromFull . pseudoInverseRCondTall rcond)+ (mapSnd Matrix.fromFull . pseudoInverseRCondWide rcond)+ .+ Matrix.caseTallWide) +newtype PseudoInverseExtent height width a vert horiz =+ PseudoInverseExtent {+ getPseudoInverseExtent ::+ Full vert horiz height width a ->+ (Int, Full horiz vert width height a)+ }++pseudoInverseRCondWide ::+ (Extent.C horiz, Shape.C height, Eq height, Shape.C width, Eq width,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ RealOf a ->+ Full Extent.Small horiz height width a ->+ (Int, Full horiz Extent.Small width height a)+pseudoInverseRCondWide rcond a =+ let (u,s,vt) = decomposeWide a+ (rank,recipS) = recipSigma rcond s+ in (rank,+ Matrix.multiply (Matrix.adjoint vt) $+ scaleRowsReal recipS $ Square.toFull $ Square.adjoint u)++pseudoInverseRCondTall ::+ (Extent.C vert, Shape.C height, Eq height, Shape.C width, Eq width,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ RealOf a ->+ Full vert Extent.Small height width a ->+ (Int, Full Extent.Small vert width height a)+pseudoInverseRCondTall rcond a =+ let (u,s,vt) = decomposeTall a+ (rank,recipS) = recipSigma rcond s+ in (rank,+ Matrix.multiply (Square.toFull $ Square.adjoint vt) $+ scaleRowsReal recipS $ Matrix.adjoint u)++ recipSigma ::- (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>- ar -> Array sh ar -> (Int, Array sh a)+ (Shape.C sh, Class.Real a) => a -> Array sh a -> (Int, Array sh a) recipSigma rcond sigmas = case Array.toList sigmas of- [] -> (0, Array.map fromReal sigmas)+ [] -> (0, sigmas)+ 0:_ -> (0, sigmas) xs@(x:_) -> let smin = x * rcond in (length (takeWhile (>=smin) xs),- Array.map (\s -> if s>=smin then fromReal (recip s) else 0) sigmas)+ Array.map (\s -> if s>=smin then recip s else 0) sigmas) withInfo :: String -> (Ptr CInt -> IO ()) -> IO ()-withInfo name computation = alloca $ \infoPtr -> do- computation infoPtr- info <- fromIntegral <$> peek infoPtr- case compare info (0::Int) of- EQ -> return ()- LT -> error $ printf "%s: illegal value in %d-th argument" name (-info)- GT -> error $ printf "%s: %d superdiagonals did not converge" name info+withInfo = Private.withInfo "%d superdiagonals did not converge"
+ src/Numeric/LAPACK/Split.hs view
@@ -0,0 +1,244 @@+module Numeric.LAPACK.Split where++import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape+import qualified Numeric.LAPACK.Matrix.Triangular.Private as TriPriv+import qualified Numeric.LAPACK.Matrix.Triangular.Basic as Tri+import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Matrix.Extent.Private as Extent+import qualified Numeric.LAPACK.Private as Private+import Numeric.LAPACK.Matrix.Triangular.Private (diagonalPointers)+import Numeric.LAPACK.Matrix.Triangular.Basic (UnitLower, Upper)+import Numeric.LAPACK.Matrix.Shape.Private+ (Order(RowMajor, ColumnMajor), transposeFromOrder,+ swapOnRowMajor, sideSwapFromOrder,+ Triangle, uploFromOrder, flipOrder)+import Numeric.LAPACK.Matrix.Private+ (Full, Transposition, transposeOrder,+ Conjugation(NonConjugated, Conjugated))+import Numeric.LAPACK.Linear.Private (solver, withInfo)+import Numeric.LAPACK.Scalar (zero, one)+import Numeric.LAPACK.Private (copyBlock, conjugateToTemp)++import qualified Numeric.LAPACK.FFI.Generic as LapackGen+import qualified Numeric.BLAS.FFI.Generic as BlasGen+import qualified Numeric.Netlib.Utility as Call+import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable.Internal as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable.Internal (Array(Array))++import System.IO.Unsafe (unsafePerformIO)++import Foreign.C.Types (CInt, CChar)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable (poke)++import Control.Monad.Trans.Cont (ContT(ContT), evalContT)+import Control.Monad.IO.Class (liftIO)+++type Split lower vert horiz height width =+ Array (MatrixShape.Split lower vert horiz height width)+++determinantR ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Split lower vert Extent.Small height width a -> a+determinantR (Array (MatrixShape.Split _ order extent) a) =+ let (height,width) = Extent.dimensions extent+ m = Shape.size height+ n = Shape.size width+ k = case order of RowMajor -> n; ColumnMajor -> m+ in unsafePerformIO $+ withForeignPtr a $ \aPtr ->+ Private.product (min m n) aPtr (k+1)++oddPermutation :: [CInt] -> Bool+oddPermutation = not . null . dropEven . filter id . zipWith (/=) [1..]++dropEven :: [a] -> [a]+dropEven (_:_:xs) = dropEven xs+dropEven xs = xs+++extractTriangle ::+ (Extent.C vert, Extent.C horiz, Shape.C height, Shape.C width,+ Class.Floating a) =>+ Either lower Triangle ->+ Split lower vert horiz height width a ->+ Full vert horiz height width a+extractTriangle part (Array (MatrixShape.Split _ order extent) qr) =++ Array.unsafeCreate (MatrixShape.Full order extent) $ \rPtr -> do++ let (height,width) = Extent.dimensions extent+ let ((loup,m), (uplo,n)) =+ swapOnRowMajor order+ (('L', Shape.size height), ('U', Shape.size width))+ evalContT $ do+ loupPtr <- Call.char loup+ uploPtr <- Call.char uplo+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ qrPtr <- ContT $ withForeignPtr qr+ ldqrPtr <- Call.leadingDim m+ ldrPtr <- Call.leadingDim m+ zeroPtr <- Call.number zero+ onePtr <- Call.number one+ liftIO $+ case part of+ Left _ -> do+ LapackGen.lacpy loupPtr mPtr nPtr qrPtr ldqrPtr rPtr ldrPtr+ LapackGen.laset uploPtr mPtr nPtr zeroPtr onePtr rPtr ldrPtr+ Right _ -> do+ LapackGen.laset loupPtr mPtr nPtr zeroPtr zeroPtr rPtr ldrPtr+ LapackGen.lacpy uploPtr mPtr nPtr qrPtr ldqrPtr rPtr ldrPtr+++wideExtractL ::+ (Extent.C horiz, Shape.C height, Shape.C width, Class.Floating a) =>+ Split lower Extent.Small horiz height width a -> UnitLower height a+wideExtractL =+ TriPriv.takeLower+ (MatrixShape.Unit,+ \order m lPtr -> mapM_ (flip poke one) $ diagonalPointers order m lPtr)+ .+ toFull++tallExtractR ::+ (Extent.C vert, Shape.C height, Shape.C width, Class.Floating a) =>+ Split lower vert Extent.Small height width a -> Upper width a+tallExtractR = Tri.takeUpper . toFull++toFull ::+ Split lower vert horiz height width a ->+ Full vert horiz height width a+toFull =+ Array.mapShape+ (\(MatrixShape.Split _ order extent) -> MatrixShape.Full order extent)+++wideMultiplyL ::+ (Extent.C horizA, Extent.C vert, Extent.C horiz, Shape.C height, Eq height,+ Shape.C widthA, Shape.C widthB, Class.Floating a) =>+ Transposition ->+ Split Triangle Extent.Small horizA height widthA a ->+ Full vert horiz height widthB a ->+ Full vert horiz height widthB a+wideMultiplyL transposed a b =+ if MatrixShape.splitHeight (Array.shape a) == Matrix.height b+ then multiplyTriangular ('L','U') 'U' transposed a b+ else error "wideMultiplyL: height shapes mismatch"++tallMultiplyR ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz, Shape.C height, Eq height,+ Shape.C heightA, Shape.C widthB, Class.Floating a) =>+ Transposition ->+ Split lower vertA Extent.Small heightA height a ->+ Full vert horiz height widthB a ->+ Full vert horiz height widthB a+tallMultiplyR transposed a b =+ if MatrixShape.splitWidth (Array.shape a) == Matrix.height b+ then multiplyTriangular ('U','L') 'N' transposed a b+ else error "wideMultiplyR: height shapes mismatch"++multiplyTriangular ::+ (Extent.C vertA, Extent.C horizA, Extent.C vertB, Extent.C horizB,+ Shape.C heightA, Shape.C widthA, Shape.C heightB, Shape.C widthB,+ Class.Floating a) =>+ (Char,Char) -> Char -> Transposition ->+ Split lower vertA horizA heightA widthA a ->+ Full vertB horizB heightB widthB a ->+ Full vertB horizB heightB widthB a+multiplyTriangular (normalPart,transposedPart) diag transposed+ (Array (MatrixShape.Split _ orderA extentA) a)+ (Array (MatrixShape.Full orderB extentB) b) =++ Array.unsafeCreate (MatrixShape.Full orderB extentB) $ \cPtr -> do++ let (heightA,widthA) = Extent.dimensions extentA+ let (heightB,widthB) = Extent.dimensions extentB+ let transOrderB = transposeOrder transposed orderB+ let ((uplo, transa), lda) =+ case orderA of+ RowMajor ->+ ((transposedPart, flipOrder transOrderB), Shape.size widthA)+ ColumnMajor ->+ ((normalPart, transOrderB), Shape.size heightA)+ let (side,(m,n)) =+ sideSwapFromOrder orderB (Shape.size heightB, Shape.size widthB)+ evalContT $ do+ sidePtr <- Call.char side+ uploPtr <- Call.char uplo+ transaPtr <- Call.char $ transposeFromOrder transa+ diagPtr <- Call.char diag+ mPtr <- Call.cint m+ nPtr <- Call.cint n+ aPtr <- ContT $ withForeignPtr a+ ldaPtr <- Call.leadingDim lda+ bPtr <- ContT $ withForeignPtr b+ ldcPtr <- Call.leadingDim m+ alphaPtr <- Call.number one+ liftIO $ do+ copyBlock (m*n) bPtr cPtr+ BlasGen.trmm sidePtr uploPtr transaPtr diagPtr+ mPtr nPtr alphaPtr aPtr ldaPtr cPtr ldcPtr+++wideSolveL ::+ (Extent.C horizA, Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Shape.C nrhs, Class.Floating a) =>+ Transposition -> Conjugation ->+ Split Triangle Extent.Small horizA height width a ->+ Full vert horiz height nrhs a -> Full vert horiz height nrhs a+wideSolveL transposed conjugated+ (Array (MatrixShape.Split _ orderA extentA) a) =+ let heightA = Extent.height extentA+ in solver "Split.wideSolveL" heightA $ \n nPtr nrhsPtr xPtr ldxPtr -> do++ uploPtr <- Call.char $ uploFromOrder $ flipOrder orderA+ diagPtr <- Call.char 'U'+ let m = Shape.size heightA+ solveTriangular transposed conjugated orderA m n a+ uploPtr diagPtr nPtr nrhsPtr xPtr ldxPtr++tallSolveR ::+ (Extent.C vertA, Extent.C vert, Extent.C horiz,+ Shape.C height, Shape.C width, Eq width, Shape.C nrhs, Class.Floating a) =>+ Transposition -> Conjugation ->+ Split lower vertA Extent.Small height width a ->+ Full vert horiz width nrhs a -> Full vert horiz width nrhs a+tallSolveR transposed conjugated+ (Array (MatrixShape.Split _ orderA extentA) a) =+ let (heightA,widthA) = Extent.dimensions extentA+ in solver "Split.tallSolveR" widthA $ \n nPtr nrhsPtr xPtr ldxPtr -> do++ uploPtr <- Call.char $ uploFromOrder orderA+ diagPtr <- Call.char 'N'+ let m = Shape.size heightA+ solveTriangular transposed conjugated orderA m n a+ uploPtr diagPtr nPtr nrhsPtr xPtr ldxPtr++solveTriangular ::+ Class.Floating a =>+ Transposition -> Conjugation ->+ Order -> Int -> Int -> ForeignPtr a ->+ Ptr CChar -> Ptr CChar -> Ptr CInt -> Ptr CInt ->+ Ptr a -> Ptr CInt -> ContT r IO ()+solveTriangular transposed conjugated orderA m n a+ uploPtr diagPtr nPtr nrhsPtr xPtr ldxPtr = do+ let (trans, getA) =+ case (transposeOrder transposed orderA, conjugated) of+ (RowMajor, NonConjugated) -> ('T', ContT $ withForeignPtr a)+ (RowMajor, Conjugated) -> ('C', ContT $ withForeignPtr a)+ (ColumnMajor, NonConjugated) -> ('N', ContT $ withForeignPtr a)+ (ColumnMajor, Conjugated) -> ('N', conjugateToTemp (m*n) a)+ transPtr <- Call.char trans+ aPtr <- getA+ ldaPtr <- Call.leadingDim $ case orderA of ColumnMajor -> m; RowMajor -> n+ liftIO $+ withInfo "trtrs" $+ LapackGen.trtrs uploPtr transPtr diagPtr+ nPtr nrhsPtr aPtr ldaPtr xPtr ldxPtr
src/Numeric/LAPACK/Vector.hs view
@@ -1,29 +1,49 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} module Numeric.LAPACK.Vector ( Vector,+ RealOf,+ ComplexOf,+ toList, fromList, autoFromList,+ append, take, drop,+ takeLeft, takeRight, constant,- dot,+ unit,+ dot, inner, sum, absSum, norm1, norm2,+ normInf,+ normInf1, argAbsMaximum, argAbs1Maximum, product,- scale,- add, sub ,+ scale, scaleReal,+ add, sub, mac, mul,- outer,+ conjugate,+ fromReal,+ toComplex,+ realPart,+ complexFromReal,+ complexToRealPart,+ complexToImaginaryPart,+ zipComplex,+ unzipComplex,+ random, RandomDistribution(..), ) where -import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape-import qualified Numeric.LAPACK.Matrix.Private as Matrix+import qualified Numeric.LAPACK.Scalar as Scalar import qualified Numeric.LAPACK.Private as Private-import Numeric.LAPACK.Private (RealOf, zero, one, minusOne, fill)+import Numeric.LAPACK.Matrix.Private (ZeroInt)+import Numeric.LAPACK.Scalar (ComplexOf, RealOf, zero, one, minusOne, absolute)+import Numeric.LAPACK.Private (fill, copyConjugate) import qualified Numeric.LAPACK.FFI.Generic as LapackGen import qualified Numeric.LAPACK.FFI.Complex as LapackComplex@@ -33,8 +53,9 @@ import qualified Numeric.Netlib.Utility as Call import qualified Numeric.Netlib.Class as Class +import Foreign.Marshal.Array (copyArray, advancePtr) import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr)+import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (Storable, peek, peekElemOff, pokeElemOff) import Foreign.C.Types (CInt) @@ -42,22 +63,27 @@ import Control.Monad.Trans.Cont (ContT(ContT), evalContT) import Control.Monad.IO.Class (liftIO)-import Control.Applicative (Const(Const,getConst), (<$>))+import Control.Applicative (Const(Const,getConst), liftA3, (<$>)) import qualified Data.Array.Comfort.Storable.Internal as Array import qualified Data.Array.Comfort.Shape as Shape import Data.Array.Comfort.Storable.Internal (Array(Array))+import Data.Array.Comfort.Shape ((:+:)((:+:))) import Data.Complex (Complex)+import Data.Tuple.HT (mapFst, uncurry3) import Data.Word (Word64) import Data.Bits (shiftR, (.&.)) -import Prelude hiding (sum, product)+import Prelude hiding (sum, product, take, drop) type Vector = Array +toList :: (Shape.C sh, Storable a) => Vector sh a -> [a]+toList = Array.toList+ fromList :: (Shape.C sh, Storable a) => sh -> [a] -> Vector sh a fromList = Array.fromList @@ -68,9 +94,63 @@ constant :: (Shape.C sh, Class.Floating a) => sh -> a -> Vector sh a constant sh a = Array.unsafeCreateWithSize sh $ fill a +unit ::+ (Shape.Indexed sh, Class.Floating a) =>+ sh -> Shape.Index sh -> Vector sh a+unit sh ix = Array.unsafeCreateWithSize sh $ \n xPtr -> do+ fill zero n xPtr+ pokeElemOff xPtr (Shape.offset sh ix) one ++append ::+ (Shape.C shx, Shape.C shy, Storable a) =>+ Vector shx a -> Vector shy a -> Vector (shx:+:shy) a+append (Array shX x) (Array shY y) =+ Array.unsafeCreate (shX:+:shY) $ \zPtr ->+ evalContT $ do+ xPtr <- ContT $ withForeignPtr x+ yPtr <- ContT $ withForeignPtr y+ let sizeX = Shape.size shX+ let sizeY = Shape.size shY+ liftIO $ do+ copyArray zPtr xPtr sizeX+ copyArray (advancePtr zPtr sizeX) yPtr sizeY++take, drop :: (Storable a) => Int -> Vector ZeroInt a -> Vector ZeroInt a+take n = takeLeft . split n+drop n = takeRight . split n++split :: (Storable a) => Int -> Vector ZeroInt a -> Vector (ZeroInt:+:ZeroInt) a+split n =+ Array.mapShape+ (\(Shape.ZeroBased m) ->+ if n<0+ then error "Vector.split: negative number of elements"+ else+ let k = min n m+ in Shape.ZeroBased k :+: Shape.ZeroBased (m-k))++takeLeft ::+ (Shape.C sh0, Shape.C sh1, Storable a) =>+ Vector (sh0:+:sh1) a -> Vector sh0 a+takeLeft (Array (sh0 :+: _sh1) x) =+ Array.unsafeCreateWithSize sh0 $ \k yPtr ->+ withForeignPtr x $ \xPtr -> copyArray yPtr xPtr k++takeRight ::+ (Shape.C sh0, Shape.C sh1, Storable a) =>+ Vector (sh0:+:sh1) a -> Vector sh1 a+takeRight (Array (sh0:+:sh1) x) =+ Array.unsafeCreateWithSize sh1 $ \k yPtr ->+ withForeignPtr x $ \xPtr ->+ copyArray yPtr (advancePtr xPtr (Shape.size sh0)) k++ newtype Dot sh a = Dot {runDot :: Vector sh a -> Vector sh a -> a} +{- |+> dot x y = Matrix.toScalar (singleRow x <#> singleColumn y)+-} dot :: (Shape.C sh, Eq sh, Class.Floating a) => Vector sh a -> Vector sh a -> a@@ -79,18 +159,30 @@ Class.switchFloating (Dot dotReal) (Dot dotReal)- (Dot dotComplex)- (Dot dotComplex)+ (Dot $ dotComplex 'T')+ (Dot $ dotComplex 'T') +{- |+> inner x y = dot (conjugate x) y+-}+inner ::+ (Shape.C sh, Eq sh, Class.Floating a) =>+ Vector sh a -> Vector sh a -> a+inner =+ runDot $+ Class.switchFloating+ (Dot dotReal)+ (Dot dotReal)+ (Dot $ dotComplex 'C')+ (Dot $ dotComplex 'C')+ dotReal :: (Shape.C sh, Eq sh, Class.Real a) => Vector sh a -> Vector sh a -> a-dotReal (Array shX x) (Array shY y) = unsafePerformIO $ do+dotReal arrX@(Array shX _x) (Array shY y) = unsafePerformIO $ do Call.assert "dot: shapes mismatch" (shX == shY) evalContT $ do- nPtr <- Call.cint $ Shape.size shX- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1+ (nPtr, sxPtr, incxPtr) <- vectorArgs arrX syPtr <- ContT $ withForeignPtr y incyPtr <- Call.cint 1 liftIO $ BlasReal.dot nPtr sxPtr incxPtr syPtr incyPtr@@ -101,23 +193,24 @@ -} dotComplex :: (Shape.C sh, Eq sh, Class.Real a) =>- Vector sh (Complex a) -> Vector sh (Complex a) -> Complex a-dotComplex (Array shX x) (Array shY y) = unsafePerformIO $ do+ Char -> Vector sh (Complex a) -> Vector sh (Complex a) -> Complex a+dotComplex trans (Array shX x) (Array shY y) = unsafePerformIO $ do Call.assert "dot: shapes mismatch" (shX == shY) evalContT $ do- transPtr <- Call.char 'N'- mPtr <- Call.cint 1- nPtr <- Call.cint $ Shape.size shX+ let m = Shape.size shX+ transPtr <- Call.char trans+ mPtr <- Call.cint m+ nPtr <- Call.cint 1 alphaPtr <- Call.number one xPtr <- ContT $ withForeignPtr x- ldxPtr <- Call.cint 1+ ldxPtr <- Call.leadingDim m yPtr <- ContT $ withForeignPtr y incyPtr <- Call.cint 1 betaPtr <- Call.number zero zPtr <- Call.alloca inczPtr <- Call.cint 1 liftIO $- BlasGen.gemv+ Private.gemv transPtr mPtr nPtr alphaPtr xPtr ldxPtr yPtr incyPtr betaPtr zPtr inczPtr liftIO $ peek zPtr@@ -127,12 +220,8 @@ withForeignPtr x $ \xPtr -> Private.sum (Shape.size sh) xPtr 1 norm1 :: (Shape.C sh, Class.Floating a) => Vector sh a -> RealOf a-norm1 (Array sh x) = unsafePerformIO $- evalContT $ do- nPtr <- Call.cint $ Shape.size sh- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ csum1 nPtr sxPtr incxPtr+norm1 arr = unsafePerformIO $+ evalContT $ liftIO . uncurry3 csum1 =<< vectorArgs arr csum1 :: Class.Floating a => Ptr CInt -> Ptr a -> Ptr CInt -> IO (RealOf a) csum1 =@@ -149,12 +238,8 @@ For real numbers it is equivalent to 'norm1'. -} absSum :: (Shape.C sh, Class.Floating a) => Vector sh a -> RealOf a-absSum (Array sh x) = unsafePerformIO $- evalContT $ do- nPtr <- Call.cint $ Shape.size sh- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ asum nPtr sxPtr incxPtr+absSum arr = unsafePerformIO $+ evalContT $ liftIO . uncurry3 asum =<< vectorArgs arr asum :: Class.Floating a => Ptr CInt -> Ptr a -> Ptr CInt -> IO (RealOf a) asum =@@ -168,12 +253,8 @@ Euclidean norm of a vector or Frobenius norm of a matrix. -} norm2 :: (Shape.C sh, Class.Floating a) => Vector sh a -> RealOf a-norm2 (Array sh x) = unsafePerformIO $- evalContT $ do- nPtr <- Call.cint $ Shape.size sh- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ nrm2 nPtr sxPtr incxPtr+norm2 arr = unsafePerformIO $+ evalContT $ liftIO . uncurry3 nrm2 =<< vectorArgs arr nrm2 :: Class.Floating a => Ptr CInt -> Ptr a -> Ptr CInt -> IO (RealOf a) nrm2 =@@ -185,22 +266,45 @@ newtype Norm a = Norm {getNorm :: Ptr CInt -> Ptr a -> Ptr CInt -> IO (RealOf a)} ++normInf :: (Shape.C sh, Class.Floating a) => Vector sh a -> RealOf a+normInf arr = unsafePerformIO $+ evalContT $ do+ (nPtr, sxPtr, incxPtr) <- vectorArgs arr+ liftIO $+ fmap (absolute . maybe zero snd) $+ peekElemOff1 sxPtr =<< absMax nPtr sxPtr incxPtr+ {- |+Computes (almost) the infinity norm of the vector.+For complex numbers every element is replaced+by the sum of the absolute component values first.+-}+normInf1 :: (Shape.C sh, Class.Floating a) => Vector sh a -> RealOf a+normInf1 arr = unsafePerformIO $+ evalContT $ do+ (nPtr, sxPtr, incxPtr) <- vectorArgs arr+ liftIO $+ fmap (Scalar.norm1 . maybe zero snd) $+ peekElemOff1 sxPtr =<< BlasGen.iamax nPtr sxPtr incxPtr+++{- | Returns the index and value of the element with the maximal absolute value. Caution: It actually returns the value of the element, not its absolute value! -} argAbsMaximum ::- (Shape.C sh, Class.Floating a) =>+ (Shape.InvIndexed sh, Class.Floating a) => Vector sh a -> (Shape.Index sh, a)-argAbsMaximum (Array sh x) = unsafePerformIO $+argAbsMaximum arr = unsafePerformIO $ evalContT $ do- nPtr <- Call.cint $ Shape.size sh- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ do- k <- fromIntegral . subtract 1 <$> absMax nPtr sxPtr incxPtr- xmax <- peekElemOff sxPtr k- return (Shape.indices sh !! k, xmax)+ (nPtr, sxPtr, incxPtr) <- vectorArgs arr+ liftIO $+ fmap+ (maybe+ (error "Vector.argAbsMaximum: empty vector")+ (mapFst (Shape.uncheckedIndexFromOffset $ Array.shape arr))) $+ peekElemOff1 sxPtr =<< absMax nPtr sxPtr incxPtr newtype ArgMaximum a = ArgMaximum {runArgMaximum :: Ptr CInt -> Ptr a -> Ptr CInt -> IO CInt}@@ -222,19 +326,35 @@ Caution: It actually returns the value of the element, not its absolute value! -} argAbs1Maximum ::- (Shape.C sh, Class.Floating a) =>+ (Shape.InvIndexed sh, Class.Floating a) => Vector sh a -> (Shape.Index sh, a)-argAbs1Maximum (Array sh x) = unsafePerformIO $+argAbs1Maximum arr = unsafePerformIO $ evalContT $ do- nPtr <- Call.cint $ Shape.size sh- sxPtr <- ContT $ withForeignPtr x- incxPtr <- Call.cint 1- liftIO $ do- k <- fromIntegral . subtract 1 <$> BlasGen.iamax nPtr sxPtr incxPtr- xmax <- peekElemOff sxPtr k- return (Shape.indices sh !! k, xmax)+ (nPtr, sxPtr, incxPtr) <- vectorArgs arr+ liftIO $+ fmap+ (maybe+ (error "Vector.argAbs1Maximum: empty vector")+ (mapFst (Shape.uncheckedIndexFromOffset $ Array.shape arr))) $+ peekElemOff1 sxPtr =<< BlasGen.iamax nPtr sxPtr incxPtr +vectorArgs ::+ (Shape.C sh) => Array sh a -> ContT r IO (Ptr CInt, Ptr a, Ptr CInt)+vectorArgs (Array sh x) =+ liftA3 (,,)+ (Call.cint $ Shape.size sh)+ (ContT $ withForeignPtr x)+ (Call.cint 1) +peekElemOff1 :: (Storable a) => Ptr a -> CInt -> IO (Maybe (Int, a))+peekElemOff1 ptr k1 =+ let k1i = fromIntegral k1+ ki = k1i-1+ in if k1i == 0+ then return Nothing+ else Just . (,) ki <$> peekElemOff ptr ki++ product :: (Shape.C sh, Class.Floating a) => Vector sh a -> a product (Array sh x) = unsafePerformIO $ withForeignPtr x $ \xPtr -> Private.product (Shape.size sh) xPtr 1@@ -264,16 +384,48 @@ nPtr <- Call.cint n alphaPtr <- Call.number one aPtr <- Call.number a- ldaPtr <- Call.cint m+ ldaPtr <- Call.leadingDim m bPtr <- ContT $ withForeignPtr b- ldbPtr <- Call.cint k+ ldbPtr <- Call.leadingDim k betaPtr <- Call.number zero- ldcPtr <- Call.cint m+ ldcPtr <- Call.leadingDim m liftIO $ BlasGen.gemm transaPtr transbPtr mPtr nPtr kPtr alphaPtr aPtr ldaPtr bPtr ldbPtr betaPtr cPtr ldcPtr ++scaleReal ::+ (Shape.C sh, Class.Floating a) =>+ RealOf a -> Vector sh a -> Vector sh a+scaleReal =+ getScaleReal $+ Class.switchFloating+ (ScaleReal scale)+ (ScaleReal scale)+ (ScaleReal scaleRealComplex)+ (ScaleReal scaleRealComplex)++newtype ScaleReal f a = ScaleReal {getScaleReal :: RealOf a -> f a -> f a}++scaleRealComplex ::+ (Shape.C sh, Class.Real a) =>+ a -> Vector sh (Complex a) -> Vector sh (Complex a)+scaleRealComplex alpha (Array sh x) =+ Array.unsafeCreateWithSize sh $ \n cyPtr ->+ evalContT $ do+ alphaPtr <- Call.number alpha+ n2Ptr <- Call.cint (2*n)+ cxPtr <- ContT $ withForeignPtr x+ let sxPtr = castPtr cxPtr+ let syPtr = castPtr cyPtr+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 1+ liftIO $ do+ BlasReal.copy n2Ptr sxPtr incxPtr syPtr incyPtr+ BlasReal.scal n2Ptr alphaPtr syPtr incyPtr++ add, sub :: (Shape.C sh, Eq sh, Class.Floating a) => Vector sh a -> Vector sh a -> Vector sh a@@ -305,50 +457,22 @@ Call.assert "mul: shapes mismatch" (shA == shX) evalContT $ do transPtr <- Call.char 'N'- mPtr <- Call.cint n nPtr <- Call.cint n klPtr <- Call.cint 0 kuPtr <- Call.cint 0 alphaPtr <- Call.number one aPtr <- ContT $ withForeignPtr a- ldaPtr <- Call.cint 1+ ldaPtr <- Call.leadingDim 1 xPtr <- ContT $ withForeignPtr x incxPtr <- Call.cint 1 betaPtr <- Call.number zero incyPtr <- Call.cint 1 liftIO $ BlasGen.gbmv transPtr- mPtr nPtr klPtr kuPtr alphaPtr aPtr ldaPtr+ nPtr nPtr klPtr kuPtr alphaPtr aPtr ldaPtr xPtr incxPtr betaPtr yPtr incyPtr -outer ::- (Shape.C shx, Eq shx, Shape.C shy, Eq shy, Class.Floating a) =>- Vector shx a -> Vector shy a -> Matrix.General shx shy a-outer (Array shX x) (Array shY y) =- Array.unsafeCreate (MatrixShape.General MatrixShape.ColumnMajor shX shY) $- \cPtr -> do- let m = Shape.size shX- let n = Shape.size shY- evalContT $ do- transaPtr <- Call.char 'N'- transbPtr <- Call.char 'N'- mPtr <- Call.cint m- nPtr <- Call.cint n- kPtr <- Call.cint 1- alphaPtr <- Call.number one- aPtr <- ContT $ withForeignPtr x- ldaPtr <- Call.cint m- bPtr <- ContT $ withForeignPtr y- ldbPtr <- Call.cint 1- betaPtr <- Call.number zero- ldcPtr <- Call.cint m- liftIO $- BlasGen.gemm- transaPtr transbPtr mPtr nPtr kPtr alphaPtr- aPtr ldaPtr bPtr ldbPtr betaPtr cPtr ldcPtr-- newtype Conjugate sh a = Conjugate {getConjugate :: Vector sh a -> Vector sh a} conjugate ::@@ -371,9 +495,101 @@ sxPtr <- ContT $ withForeignPtr x incxPtr <- Call.cint 1 incyPtr <- Call.cint 1+ liftIO $ copyConjugate nPtr sxPtr incxPtr syPtr incyPtr+++fromReal ::+ (Shape.C sh, Class.Floating a) => Vector sh (RealOf a) -> Vector sh a+fromReal =+ getFromReal $+ Class.switchFloating+ (FromReal id)+ (FromReal id)+ (FromReal complexFromReal)+ (FromReal complexFromReal)++newtype FromReal f a = FromReal {getFromReal :: f (RealOf a) -> f a}++toComplex ::+ (Shape.C sh, Class.Floating a) => Vector sh a -> Vector sh (ComplexOf a)+toComplex =+ getToComplex $+ Class.switchFloating+ (ToComplex complexFromReal)+ (ToComplex complexFromReal)+ (ToComplex id)+ (ToComplex id)++newtype ToComplex f a = ToComplex {getToComplex :: f a -> f (ComplexOf a)}++complexFromReal ::+ (Shape.C sh, Class.Real a) => Vector sh a -> Vector sh (Complex a)+complexFromReal (Array sh x) =+ Array.unsafeCreateWithSize sh $ \n yPtr ->+ case castPtr yPtr of+ yrPtr -> evalContT $ do+ nPtr <- Call.cint n+ xPtr <- ContT $ withForeignPtr x+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 2+ inczPtr <- Call.cint 0+ zPtr <- Call.number zero+ liftIO $ do+ BlasGen.copy nPtr xPtr incxPtr yrPtr incyPtr+ BlasGen.copy nPtr zPtr inczPtr (advancePtr yrPtr 1) incyPtr+++realPart ::+ (Shape.C sh, Class.Floating a) => Vector sh a -> Vector sh (RealOf a)+realPart =+ getToReal $+ Class.switchFloating+ (ToReal id)+ (ToReal id)+ (ToReal complexToRealPart)+ (ToReal complexToRealPart)++newtype ToReal f a = ToReal {getToReal :: f a -> f (RealOf a)}+++zipComplex ::+ (Shape.C sh, Eq sh, Class.Real a) =>+ Vector sh a -> Vector sh a -> Vector sh (Complex a)+zipComplex (Array shr xr) (Array shi xi) =+ Array.unsafeCreateWithSize shr $ \n yPtr -> evalContT $ do+ liftIO $ Call.assert "zipComplex: shapes mismatch" (shr==shi)+ nPtr <- Call.cint n+ xrPtr <- ContT $ withForeignPtr xr+ xiPtr <- ContT $ withForeignPtr xi+ let yrPtr = castPtr yPtr+ incxPtr <- Call.cint 1+ incyPtr <- Call.cint 2 liftIO $ do- BlasGen.copy nPtr sxPtr incxPtr syPtr incyPtr- LapackComplex.lacgv nPtr syPtr incyPtr+ BlasGen.copy nPtr xrPtr incxPtr yrPtr incyPtr+ BlasGen.copy nPtr xiPtr incxPtr (advancePtr yrPtr 1) incyPtr+++complexToRealPart, complexToImaginaryPart ::+ (Shape.C sh, Class.Real a) => Vector sh (Complex a) -> Vector sh a+complexToRealPart = complexToPart 0+complexToImaginaryPart = complexToPart 1++complexToPart ::+ (Shape.C sh, Class.Real a) => Int -> Vector sh (Complex a) -> Vector sh a+complexToPart offset (Array sh x) =+ Array.unsafeCreateWithSize sh $ \n yPtr -> evalContT $ do+ nPtr <- Call.cint n+ xPtr <- ContT $ withForeignPtr x+ incxPtr <- Call.cint 2+ incyPtr <- Call.cint 1+ liftIO $+ BlasGen.copy nPtr+ (advancePtr (castPtr xPtr) offset) incxPtr yPtr incyPtr++unzipComplex ::+ (Shape.C sh, Class.Real a) =>+ Vector sh (Complex a) -> (Vector sh a, Vector sh a)+unzipComplex x = (complexToRealPart x, complexToImaginaryPart x) data RandomDistribution =
+ src/Numeric/LAPACK/Wrapper.hs view
@@ -0,0 +1,4 @@+module Numeric.LAPACK.Wrapper where++-- cf. Data.Bifunctor.Flip+newtype Flip f b a = Flip {getFlip :: f a b}
+ test/Main.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE TypeFamilies #-}+module Main where++import qualified Test.Vector as Vector+import qualified Test.Matrix as Matrix+import qualified Test.Square as Square+import qualified Test.Triangular as Triangular+import qualified Test.Hermitian as Hermitian+import qualified Test.Banded as Banded+import qualified Test.BandedHermitian as BandedHermitian+import qualified Test.Orthogonal as Orthogonal+import qualified Test.Singular as Singular+import qualified Test.Shape as Shape+import qualified Test.Permutation as Permutation+import Test.Format ()+import Test.Utility (Tagged(Tagged), prefix)++import qualified Test.QuickCheck as QC++import Numeric.LAPACK.Scalar (RealOf)++import qualified Numeric.Netlib.Class as Class++import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.List as List+import Data.Complex (Complex)+import Data.Tuple.HT (mapSnd)+++testsVar ::+ (Show a, Show ar,+ Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar, RealOf ar ~ ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ prefix "Vector" Vector.testsVar +++ prefix "Matrix" Matrix.testsVar +++ prefix "Square" Square.testsVar +++ prefix "Triangular" Triangular.testsVar +++ prefix "Hermitian" Hermitian.testsVar +++ prefix "Banded" Banded.testsVar +++ prefix "BandedHermitian" BandedHermitian.testsVar +++ prefix "Orthogonal" Orthogonal.testsVar +++ prefix "Singular" Singular.testsVar +++ []++tagTests ::+ String -> Proxy tag ->+ [(String, Tagged tag QC.Property)] -> [(String, QC.Property)]+tagTests typeName Proxy =+ map (\(name, Tagged prop) -> (name++"."++typeName, prop))++tests :: [(String, QC.Property)]+tests =+ concat $ List.transpose $+ (tagTests "Float" (Proxy :: Proxy Float) testsVar) :+ (tagTests "Double" (Proxy :: Proxy Double) testsVar) :+ (tagTests "ComplexFloat" (Proxy :: Proxy (Complex Float)) testsVar) :+ (tagTests "ComplexDouble" (Proxy :: Proxy (Complex Double)) testsVar) :+ []++simpleTests :: [(String, QC.Property)]+simpleTests =+ prefix "Shape" Shape.tests +++ prefix "Permutation" Permutation.tests +++ []++main :: IO ()+main =+ mapM_ (\(name,act) -> putStr (name ++ ": ") >> act) $++ map (mapSnd (QC.quickCheckWith (QC.stdArgs {QC.maxSuccess=200}))) tests+ +++ map (mapSnd QC.quickCheck) simpleTests
+ test/Test/Banded.hs view
@@ -0,0 +1,266 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE GADTs #-}+module Test.Banded (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Banded.Utility+ (Square(Square), genSquare, genSquareCond,+ offDiagonals, offDiagonalNats)+import Test.Generator ((<.*|>), (<|*.>), (<.*.>), (<|*|>), (<|\|>))+import Test.Utility+ (approx, approxArray, approxMatrix,+ genOrder, genArray, Tagged, equalListWith)++import qualified Numeric.LAPACK.Matrix.Banded as Banded+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix (ZeroInt, (<#>), (<#), (#>))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, absolute)++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary, (:+:))++import qualified Data.Array.Comfort.Shape as Shape++import Foreign.Storable (Storable)++import Control.Applicative ((<$>))++import qualified Test.QuickCheck as QC+++data Banded height width a =+ forall sub super.+ (Unary.Natural sub, Unary.Natural super) =>+ Banded (Banded.General sub super height width a)++instance+ (Show width, Show height, Show a,+ Shape.C width, Shape.C height, Storable a) =>+ Show (Banded height width a) where+ showsPrec p (Banded a) = showsPrec p a+++genBanded ::+ (Class.Floating a) => Gen.Matrix a Int Int (Banded ZeroInt ZeroInt a)+genBanded =+ flip Gen.mapGenDim Gen.matrixDims $ \maxElem maxDim (height,width) -> do+ order <- genOrder+ kl <- QC.choose (0, toInteger maxDim)+ ku <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural kl $ \sub ->+ Unary.reifyNatural ku $ \super ->+ fmap Banded $ genArray maxElem $+ MatrixShape.bandedGeneral (unary sub, unary super) order height width++multiplyFullIdentity ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Banded ZeroInt ZeroInt a -> Bool+multiplyFullIdentity (Banded m) =+ let a = Banded.toFull m+ in approxArray a $+ Banded.multiplyFull m $ Square.toGeneral $ Square.identityFromWidth a+++multiplyVectorDot ::+ (Class.Floating a, Eq a) =>+ (Vector ZeroInt a,+ Banded ZeroInt ZeroInt a,+ Vector ZeroInt a) ->+ Bool+multiplyVectorDot (x, Banded m, y) =+ Vector.dot x (m#>y) == Vector.dot (x<#m) y+++multiplyFullAny ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a) ->+ Bool+multiplyFullAny (Banded a, b) =+ approxArray+ (Banded.multiplyFull a b)+ (Matrix.multiply (Banded.toFull a) b)++multiplyFullColumns ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a) ->+ Bool+multiplyFullColumns (Banded a, b) =+ equalListWith approxArray+ (Matrix.toColumns (Banded.multiplyFull a b))+ (map (Banded.multiplyVector a) (Matrix.toColumns b))+++multiplyFullAssoc ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a) ->+ Bool+multiplyFullAssoc (Banded a, b, c) =+ approxArray+ (Matrix.multiply (Banded.multiplyFull a b) c)+ (Banded.multiplyFull a (Matrix.multiply b c))+++addOffDiagonals ::+ (Unary.Natural subA, Unary.Natural superA,+ Unary.Natural subB, Unary.Natural superB) =>+ Banded.General subA superA heightA widthA a ->+ Banded.General subB superB heightB widthB a ->+ (Proof.Nat (subA :+: subB), Proof.Nat (superA :+: superB))+addOffDiagonals a b =+ fst $ MatrixShape.addOffDiagonals (offDiagonals a) (offDiagonals b)++multiplyBanded ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Banded ZeroInt ZeroInt a) ->+ Bool+multiplyBanded (Banded a, Banded b) =+ case addOffDiagonals a b of+ (Proof.Nat, Proof.Nat) ->+ approxArray+ (Banded.toFull (Banded.multiply a b))+ (Banded.multiplyFull a (Banded.toFull b))++multiplyBandedVectorAssoc ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Banded ZeroInt ZeroInt a,+ Vector ZeroInt a) ->+ Bool+multiplyBandedVectorAssoc (Banded a, Banded b, x) =+ case addOffDiagonals a b of+ (Proof.Nat, Proof.Nat) ->+ approxArray (a #> b #> x) (Banded.multiply a b #> x)+++multiplyBandedAssoc ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Banded ZeroInt ZeroInt a,+ Banded ZeroInt ZeroInt a,+ Banded ZeroInt ZeroInt a) ->+ Bool+multiplyBandedAssoc (Banded a, Banded b, Banded c) =+ let ab = Banded.multiply a b+ bc = Banded.multiply b c+ (subA,superA) = offDiagonalNats a+ (subB,superB) = offDiagonalNats b+ (subC,superC) = offDiagonalNats c+ in case (addOffDiagonals a b, addOffDiagonals b c) of+ ((Proof.Nat, Proof.Nat), (Proof.Nat, Proof.Nat)) ->+ case ((addOffDiagonals ab c, addOffDiagonals a bc),+ (Proof.addAssoc subA subB subC,+ Proof.addAssoc superA superB superC)) of+ (((Proof.Nat, Proof.Nat), (Proof.Nat, Proof.Nat)),+ (Proof.AddAssoc, Proof.AddAssoc)) ->+ approxArray (Banded.multiply a bc) (Banded.multiply ab c)+++data Upper size a =+ forall super. (Unary.Natural super) => Upper (Banded.Upper super size a)++instance+ (Show size, Show a, Shape.C size, Storable a) =>+ Show (Upper size a) where+ showsPrec p (Upper a) = showsPrec p a++genUpper :: (Class.Floating a) => Gen.Matrix a Int Int (Upper ZeroInt a)+genUpper = flip Gen.mapGenDim Gen.squareDim $ \maxElem maxDim size -> do+ order <- genOrder+ ku <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural ku $ \super ->+ fmap Upper $ genArray maxElem $+ MatrixShape.bandedSquare (unary TypeNum.u0, unary super) order size++multiplyUpperVector ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Upper ZeroInt a, Vector ZeroInt a) -> Bool+multiplyUpperVector (Upper m, x) =+ approxArray (m#>x) (Banded.toUpperTriangular m #> x)++multiplyLowerVector ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Upper ZeroInt a, Vector ZeroInt a) -> Bool+multiplyLowerVector (Upper up, x) =+ let lo = Banded.transpose up+ in approxArray (lo#>x) (Banded.toLowerTriangular lo #> x)+++determinant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+determinant (Square a) =+ approx 0.5 (Banded.determinant a) (Square.determinant $ Banded.toFull a)+++invertible ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+invertible (Square a) = absolute (Banded.determinant a) > 0.1++multiplySolve ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Square ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+multiplySolve (Square a, b) =+ approxMatrix 1e-2 (a <#> Banded.solve a b) b++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 10 5)+++testsVar ::+ (Show a, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("multiplyFullIdentity",+ checkForAll genBanded multiplyFullIdentity) :+ ("multiplyFullAny",+ checkForAll ((,) <$> genBanded <|*|> Gen.matrix) multiplyFullAny) :+ ("multiplyVectorDot",+ checkForAll+ ((,,) <$> Gen.vector <.*|> genBanded <.*.> Gen.vector)+ multiplyVectorDot) :+ ("multiplyFullColumns",+ checkForAll ((,) <$> genBanded <|*|> Gen.matrix) multiplyFullColumns) :+ ("multiplyFullAssoc",+ checkForAll+ ((,,) <$> genBanded <|*|> Gen.matrix <|*|> Gen.matrix)+ multiplyFullAssoc) :+ ("multiplyBanded",+ checkForAll ((,) <$> genBanded <|*|> genBanded) multiplyBanded) :+ ("multiplyBandedVectorAssoc",+ checkForAll+ ((,,) <$> genBanded <|*|> genBanded <|*.> Gen.vector)+ multiplyBandedVectorAssoc) :+ ("multiplyBandedAssoc",+ checkForAll+ ((,,) <$> genBanded <|*|> genBanded <|*|> genBanded)+ multiplyBandedAssoc) :+ ("multiplyUpperVector",+ checkForAll ((,) <$> genUpper <|*.> Gen.vector) multiplyUpperVector) :+ ("multiplyLowerVector",+ checkForAll ((,) <$> genUpper <|*.> Gen.vector) multiplyLowerVector) :+ ("determinant",+ checkForAll genSquare determinant) :+ ("multiplySolve",+ checkForAll+ ((,) <$> genSquareCond invertible <|\|> Gen.matrix) multiplySolve) :+ []
+ test/Test/Banded/Utility.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE ExistentialQuantification #-}+module Test.Banded.Utility where++import qualified Test.Generator as Gen+import Test.Utility (genOrder, genArray)++import qualified Numeric.LAPACK.Matrix.Banded as Banded+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import Numeric.LAPACK.Matrix.Shape (UnaryProxy)+import Numeric.LAPACK.Matrix (ZeroInt)++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary)+import Type.Base.Proxy (Proxy(Proxy))++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape++import Foreign.Storable (Storable)++import Data.Tuple.HT (mapPair)++import qualified Test.QuickCheck as QC+++-- cf. MatrixShape.Private+natFromProxy :: (Unary.Natural n) => UnaryProxy n -> Proof.Nat n+natFromProxy Proxy = Proof.Nat++offDiagonals ::+ Banded.Banded sub super vert horiz height width a ->+ (UnaryProxy sub, UnaryProxy super)+offDiagonals = MatrixShape.bandedOffDiagonals . Array.shape++offDiagonalNats ::+ (Unary.Natural sub, Unary.Natural super) =>+ Banded.Banded sub super vert horiz height width a ->+ (Proof.Nat sub, Proof.Nat super)+offDiagonalNats = mapPair (natFromProxy, natFromProxy) . offDiagonals+++data Square size a =+ forall sub super.+ (Unary.Natural sub, Unary.Natural super) =>+ Square (Banded.Square sub super size a)++instance+ (Show size, Show a, Shape.C size, Storable a) =>+ Show (Square size a) where+ showsPrec p (Square a) = showsPrec p a++genSquare :: (Class.Floating a) => Gen.Matrix a Int Int (Square ZeroInt a)+genSquare = genSquareCond (const True)++genSquareCond ::+ (Class.Floating a) =>+ (Square ZeroInt a -> Bool) ->+ Gen.Matrix a Int Int (Square ZeroInt a)+genSquareCond cond =+ flip Gen.mapGenDim Gen.squareDim $ \maxElem maxDim size -> do+ order <- genOrder+ kl <- QC.choose (0, toInteger maxDim)+ ku <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural kl $ \sub ->+ Unary.reifyNatural ku $ \super ->+ (fmap Square $+ genArray maxElem $+ MatrixShape.bandedSquare (unary sub, unary super) order size)+ `QC.suchThat`+ cond
+ test/Test/BandedHermitian.hs view
@@ -0,0 +1,411 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE GADTs #-}+module Test.BandedHermitian (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Banded.Utility+ (Square(Square), genSquare, natFromProxy, offDiagonalNats)+import Test.Generator ((<.*|>), (<|*.>), (<.*.>), (<|*|>), (<|\|>))+import Test.Utility+ (approxReal, approxArray, approxRealArrayTol, approxMatrix,+ genOrder, genArray, Tagged, equalListWith)++import qualified Numeric.LAPACK.Matrix.BandedHermitianPositiveDefinite+ as BandedHermitianPD+import qualified Numeric.LAPACK.Matrix.BandedHermitian as BandedHermitian+import qualified Numeric.LAPACK.Matrix.Banded as Banded+import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.ShapeStatic as ShapeStatic+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt, (<#>), (<#), (#>))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, fromReal, absolute, selectReal)++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Proof as Proof+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary)++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape++import Foreign.Storable (Storable)++import Control.Applicative (liftA2, (<$>))++import qualified Data.List.HT as ListHT+import Data.Traversable (for)+import Data.Tuple.HT (mapSnd)++import qualified Test.QuickCheck as QC+++data BandedHermitian size a =+ forall offDiag.+ (Unary.Natural offDiag) =>+ BandedHermitian (BandedHermitian.BandedHermitian offDiag size a)++instance+ (Show size, Show a, Shape.C size, Storable a) =>+ Show (BandedHermitian size a) where+ showsPrec p (BandedHermitian a) = showsPrec p a+++{-+Non-real elements on the diagonal.+-}+_genBandedHermitian ::+ (Class.Floating a) => Gen.Matrix a Int Int (BandedHermitian ZeroInt a)+_genBandedHermitian =+ flip Gen.mapGenDim Gen.squareDim $ \maxElem maxDim size -> do+ order <- genOrder+ k <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural k $ \numOff ->+ fmap BandedHermitian $ genArray maxElem $+ MatrixShape.bandedHermitian (unary numOff) order size++genBandedHermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int (BandedHermitian ZeroInt a)+genBandedHermitian =+ flip Gen.mapGenDim Gen.squareDim $ \maxElem maxDim size -> do+ order <- genOrder+ k <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural k $ \numOff -> do+ let shape = MatrixShape.bandedHermitian (unary numOff) order size+ BandedHermitian . Array.fromList shape <$>+ (for (Shape.indices shape) $ \ix ->+ let real =+ case ix of+ MatrixShape.InsideBox r c -> r==c+ MatrixShape.VertOutsideBox _ _ -> False+ MatrixShape.HorizOutsideBox _ _ -> False+ in if real+ then fromReal <$> Util.genReal maxElem+ else Util.genElement maxElem)++++convertToFull ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+convertToFull (BandedHermitian a) =+ approxArray+ (Hermitian.toSquare $ BandedHermitian.toHermitian a)+ (Banded.toFull $ BandedHermitian.toBanded a)++takeDiagonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+takeDiagonal (BandedHermitian a) =+ approxRealArrayTol 1e-5+ (Hermitian.takeDiagonal $ BandedHermitian.toHermitian a)+ (BandedHermitian.takeDiagonal a)++covariance ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+covariance (Square a) =+ let (sub,super) = offDiagonalNats a+ in case (Proof.addNat sub super, Proof.addComm sub super) of+ (Proof.Nat, Proof.AddComm) ->+ approxArray+ (BandedHermitian.toBanded $ BandedHermitian.covariance a)+ (Banded.adjoint a <#> a)++++type StaticVector1 n = Vector (ShapeStatic.ZeroBased (Unary.Succ n))++data SumRank1 size a =+ forall offDiag.+ (Unary.Natural offDiag) =>+ SumRank1 size [(RealOf a, (Shape.Index size, StaticVector1 offDiag a))]++instance+ (Show size, Show (Shape.Index size), Show a, Show (RealOf a),+ Shape.C size, Storable a) =>+ Show (SumRank1 size a) where+ showsPrec p (SumRank1 sh a) = showsPrec p (sh,a)++genScaledVectors ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Vector a Int (SumRank1 ZeroInt a)+genScaledVectors =+ flip Gen.mapGen Gen.vectorDim $ \maxElem size@(Shape.ZeroBased n) -> do+ k <- QC.choose (0, n-1)+ Unary.reifyNatural (toInteger k) $ \numOff ->+ fmap (SumRank1 size) $+ if n==0+ then return []+ else+ QC.listOf $+ liftA2 (,) (Util.genReal maxElem) $+ liftA2 (,) (QC.choose (0,n-k-1))+ (Util.genArray maxElem+ (ShapeStatic.ZeroBased $ unary $ Unary.succ numOff))++sumRank1 ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> SumRank1 ZeroInt a -> Bool+sumRank1 order (SumRank1 sh xs) =+ approxArray+ (BandedHermitian.toHermitian $ BandedHermitian.sumRank1 order sh xs)+ (Hermitian.sumRank1 order sh $+ map (mapSnd (uncurry $ displace sh)) xs)++displace ::+ (Shape.C sh, Class.Floating a) =>+ ZeroInt -> Int -> Vector sh a -> Vector ZeroInt a+displace (Shape.ZeroBased n) k a =+ Array.mapShape (zeroInt . Shape.size) $+ Vector.constant (zeroInt k) 0+ `Vector.append`+ a+ `Vector.append`+ Vector.constant (zeroInt $ max 0 $ n - k - Shape.size (Array.shape a)) 0+++multiplyIdentity ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian.Transposition -> Matrix.General ZeroInt ZeroInt a -> Bool+multiplyIdentity trans m =+ approxArray m+ (BandedHermitian.multiplyFull trans+ (BandedHermitian.identity (Matrix.height m)) m)++multiplyDiagonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian.Transposition ->+ (Vector ZeroInt ar, Matrix.General ZeroInt ZeroInt a) -> Bool+multiplyDiagonal trans (d,m) =+ approxArray+ (Matrix.scaleRowsReal d m)+ (BandedHermitian.multiplyFull trans (BandedHermitian.diagonal d) m)++multiplyFullIdentity ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+multiplyFullIdentity (BandedHermitian m) =+ let a = Banded.toFull $ BandedHermitian.toBanded m+ in approxArray a $+ BandedHermitian.multiplyFull BandedHermitian.NonTransposed m $+ Square.identityFrom a+++multiplyHermitianVector ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian.Transposition ->+ (BandedHermitian ZeroInt a, Vector ZeroInt a) ->+ Bool+multiplyHermitianVector trans (BandedHermitian m, x) =+ approxArray+ (BandedHermitian.multiplyVector trans m x)+ (Hermitian.multiplyVector trans (BandedHermitian.toHermitian m) x)++multiplyVectorDot ::+ (Class.Floating a, Eq a) =>+ (Vector ZeroInt a, BandedHermitian ZeroInt a, Vector ZeroInt a) -> Bool+multiplyVectorDot (x, BandedHermitian m, y) =+ Vector.dot x (m#>y) == Vector.dot (x<#m) y+++multiplyFullAny ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian.Transposition ->+ (BandedHermitian ZeroInt a,+ Matrix.General ZeroInt ZeroInt a) ->+ Bool+multiplyFullAny trans (BandedHermitian a, b) =+ approxArray+ (BandedHermitian.multiplyFull trans a b)+ (Hermitian.multiplyFull trans (BandedHermitian.toHermitian a) b)++multiplyFullColumns ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian.Transposition ->+ (BandedHermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+multiplyFullColumns trans (BandedHermitian a, b) =+ equalListWith approxArray+ (Matrix.toColumns (BandedHermitian.multiplyFull trans a b))+ (map (BandedHermitian.multiplyVector trans a) (Matrix.toColumns b))+++multiplyFullAssoc ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian.Transposition ->+ (BandedHermitian ZeroInt a,+ Matrix.General ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a) ->+ Bool+multiplyFullAssoc trans (BandedHermitian a, b, c) =+ approxArray+ (Matrix.multiply (BandedHermitian.multiplyFull trans a b) c)+ (BandedHermitian.multiplyFull trans a (Matrix.multiply b c))++++genBandedHPD ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int (BandedHermitian ZeroInt a)+genBandedHPD = flip Gen.mapGenDim Gen.squareDim $ \maxElem maxDim size -> do+ order <- genOrder+ kl <- QC.choose (0, toInteger maxDim)+ ku <- QC.choose (0, toInteger maxDim)+ Unary.reifyNatural kl $ \subU ->+ Unary.reifyNatural ku $ \superU ->+ let sub = unary subU; subP = natFromProxy sub+ super = unary superU; superP = natFromProxy super+ in case (Proof.addNat subP superP, Proof.addComm subP superP) of+ (Proof.Nat, Proof.AddComm) ->+ fmap (BandedHermitian . BandedHermitian.covariance) $+ (genArray maxElem $+ MatrixShape.bandedSquare (sub, super) order size)+ `QC.suchThat`+ (\a -> absolute (Banded.determinant a) > 0.1)+++determinant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+determinant (BandedHermitian a) =+ let detB = BandedHermitianPD.determinant a+ detS = Hermitian.determinant $ BandedHermitian.toHermitian a+ in approxReal (selectReal 1 1e-3 * max 1 (abs detB + abs detS)) detB detS+++multiplySolve ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (BandedHermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+multiplySolve (BandedHermitian a, b) =+ approxMatrix (selectReal 10 1e-3) (a <#> BandedHermitianPD.solve a b) b++solveDecomposed ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (BandedHermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solveDecomposed (BandedHermitian a, b) =+ approxMatrix (selectReal 1e-3 1e-7)+ (BandedHermitianPD.solve a b)+ (BandedHermitianPD.solveDecomposed (BandedHermitianPD.decompose a) b)++++eigenvaluesDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+eigenvaluesDeterminant (BandedHermitian a) =+ let det = BandedHermitianPD.determinant a+ prod = Vector.product $ BandedHermitian.eigenvalues a+ in approxReal ((det+prod) * selectReal 0.5 1e-6) det prod++eigensystem ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+eigensystem (BandedHermitian a) =+ let (q,d) = BandedHermitian.eigensystem a+ in approxMatrix 1e-4+ (Banded.toFull $ BandedHermitian.toBanded a)+ (q <#> Matrix.scaleRowsReal d (Square.adjoint q))++eigenvaluesHermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> Bool+eigenvaluesHermitian (BandedHermitian a) =+ approxRealArrayTol (selectReal 1e-3 1e-5)+ (BandedHermitian.eigenvalues a)+ (Hermitian.eigenvalues $ BandedHermitian.toHermitian a)++eigensystemHermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ BandedHermitian ZeroInt a -> QC.Property+eigensystemHermitian (BandedHermitian a) =+ let (q0,d0) = BandedHermitian.eigensystem a+ (q1,d1) = Hermitian.eigensystem $ BandedHermitian.toHermitian a+ unit = Matrix.adjoint q0 <#> q1+ tol = selectReal 1e-4 1e-7+ in not (or (ListHT.mapAdjacent (approxReal 0.1) (Array.toList d0)))+ QC.==>+ approxRealArrayTol tol d0 d1+ &&+ and+ (zipWith+ (\(r,c) x -> approxReal tol (absolute x) $ if r==c then 1 else 0)+ (Shape.indices $ Array.shape unit) (Array.toList unit))++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 6 5)++checkForAllExtra ::+ (Show a, Show b, QC.Testable test, Gen.Required required) =>+ QC.Gen a -> Gen.T tag required actual b ->+ (a -> b -> test) -> Tagged tag QC.Property+checkForAllExtra = Gen.withExtra checkForAll+++testsVar ::+ (Show a, Show ar,+ Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("convertToFull",+ checkForAll genBandedHermitian convertToFull) :+ ("takeDiagonal",+ checkForAll genBandedHermitian takeDiagonal) :+ ("sumRank1",+ checkForAllExtra genOrder genScaledVectors sumRank1) :+ ("covariance",+ checkForAll genSquare covariance) :+ ("multiplyIdentity",+ checkForAllExtra QC.arbitraryBoundedEnum Gen.matrix multiplyIdentity) :+ ("multiplyDiagonal",+ checkForAllExtra QC.arbitraryBoundedEnum+ ((,) <$> Gen.vectorReal <.*|> Gen.matrix) multiplyDiagonal) :+ ("multiplyFullIdentity",+ checkForAll genBandedHermitian multiplyFullIdentity) :+ ("multiplyFullAny",+ checkForAllExtra QC.arbitraryBoundedEnum+ ((,) <$> genBandedHermitian <|*|> Gen.matrix) multiplyFullAny) :+ ("multiplyHermitianVector",+ checkForAllExtra QC.arbitraryBoundedEnum+ ((,) <$> genBandedHermitian <|*.> Gen.vector)+ multiplyHermitianVector) :+ ("multiplyVectorDot",+ checkForAll+ ((,,) <$> Gen.vector <.*|> genBandedHermitian <.*.> Gen.vector)+ multiplyVectorDot) :+ ("multiplyFullColumns",+ checkForAllExtra QC.arbitraryBoundedEnum+ ((,) <$> genBandedHermitian <|*|> Gen.matrix) multiplyFullColumns) :+ ("multiplyFullAssoc",+ checkForAllExtra QC.arbitraryBoundedEnum+ ((,,) <$> genBandedHermitian <|*|> Gen.matrix <|*|> Gen.matrix)+ multiplyFullAssoc) :++ ("determinant",+ checkForAll genBandedHPD determinant) :+ ("multiplySolve",+ checkForAll ((,) <$> genBandedHPD <|\|> Gen.matrix) multiplySolve) :+ ("solveDecomposed",+ checkForAll ((,) <$> genBandedHPD <|\|> Gen.matrix) solveDecomposed) :++ ("eigenvaluesDeterminant",+ checkForAll genBandedHPD eigenvaluesDeterminant) :+ ("eigensystem",+ checkForAll genBandedHermitian eigensystem) :+ ("eigenvaluesHermitian",+ checkForAll genBandedHermitian eigenvaluesHermitian) :+ ("eigensystemHermitian",+ checkForAll genBandedHermitian eigensystemHermitian) :+ []
+ test/Test/Format.hs view
@@ -0,0 +1,153 @@+{-# LANGUAGE Rank2Types #-}+module Test.Format where++import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.BandedHermitian as BandedHermitian+import qualified Numeric.LAPACK.Matrix.Banded as Banded+import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian+import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.Permutation as Perm+import Numeric.LAPACK.Matrix.Shape (Order(RowMajor, ColumnMajor), UnaryProxy)+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt)+import Numeric.LAPACK.Format (Format, (##))++import qualified Numeric.Netlib.Class as Class++import qualified Type.Data.Num.Unary.Literal as TypeNum+import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary)++import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)++import Data.Complex as Cplx (Complex((:+)))+++vector :: (Class.Floating a) => Vector.Vector ZeroInt a+vector = Vector.random Vector.UniformBoxPM1 (zeroInt 4) 419++general :: (Class.Floating a) => Order -> Matrix.General ZeroInt ZeroInt a+general order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.general order (zeroInt 3) (zeroInt 4)) 420++split ::+ (Eq lower, Shape.C height, Shape.C width, Class.Floating a) =>+ lower -> height -> width -> Order ->+ Array (MatrixShape.SplitGeneral lower height width) a+split lowerPart height width order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.splitGeneral lowerPart order height width) 420++hermitian :: (Class.Floating a) => Order -> Hermitian.Hermitian ZeroInt a+hermitian order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.hermitian order (zeroInt 4)) 421++diagonal :: (Class.Floating a) => Order -> Triangular.Diagonal ZeroInt a+diagonal order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.diagonal order (zeroInt 4)) 422++lowerTriangular ::+ (Class.Floating a) => Order -> Triangular.Lower ZeroInt a+lowerTriangular order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.lowerTriangular order (zeroInt 4)) 423++upperTriangular ::+ (Class.Floating a) => Order -> Triangular.Upper ZeroInt a+upperTriangular order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.upperTriangular order (zeroInt 4)) 424++symmetric :: (Class.Floating a) => Order -> Triangular.Symmetric ZeroInt a+symmetric order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.symmetric order (zeroInt 4)) 425+++bandedHermitian ::+ (Unary.Natural offDiag, Class.Floating a) =>+ UnaryProxy offDiag -> Order ->+ BandedHermitian.BandedHermitian offDiag ZeroInt a+bandedHermitian numOff order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.bandedHermitian numOff order (zeroInt 4)) 426++banded ::+ (Unary.Natural sub, Unary.Natural super,+ Shape.C height, Shape.C width, Class.Floating a) =>+ (UnaryProxy sub, UnaryProxy super) -> height -> width -> Order ->+ Banded.General sub super height width a+banded offDiag height width order =+ Vector.random Vector.UniformBoxPM1+ (MatrixShape.bandedGeneral offDiag order height width) 427+++permutation :: Perm.Permutation ZeroInt+permutation =+ Perm.fromPivots Perm.NonInverted (zeroInt 5) $+ Vector.fromList (zeroInt 5) [3,2,4,5,5]+++fmt :: String+fmt = "%.4g"++printFormatted :: Format a => a -> IO ()+printFormatted x = putStrLn "" >> (x ## fmt)++printVectorFloat :: (Format (f Float)) => f Float -> IO ()+printVectorFloat = printFormatted++printVectorComplex ::+ (Format (f (Complex Float))) => f (Complex Float) -> IO ()+printVectorComplex = printFormatted++printVectorWithOrder ::+ Format (f Float) =>+ Format (f (Complex Float)) =>+ (forall a. (Class.Floating a) => Order -> f a) -> IO ()+printVectorWithOrder f = do+ printFormatted $ floatVector $ f RowMajor+ printFormatted $ floatVector $ f ColumnMajor+ printFormatted $ complexVector $ f RowMajor+ printFormatted $ complexVector $ f ColumnMajor++floatVector :: f Float -> f Float+floatVector = id++complexVector :: f (Complex Float) -> f (Complex Float)+complexVector = id++main :: IO ()+main = do+ printFormatted (pi :: Float)+ printFormatted permutation+ printVectorFloat $ sin (1:+1)+ printVectorFloat vector+ printVectorComplex vector+ printVectorWithOrder general+ printVectorWithOrder $ split MatrixShape.Reflector (zeroInt 4) (zeroInt 3)+ printVectorWithOrder $ split MatrixShape.Reflector (zeroInt 3) (zeroInt 4)+ printVectorWithOrder $ split MatrixShape.Triangle (zeroInt 4) (zeroInt 3)+ printVectorWithOrder hermitian+ printVectorWithOrder diagonal+ printVectorWithOrder lowerTriangular+ printVectorWithOrder upperTriangular+ printVectorWithOrder symmetric+ printVectorWithOrder $ bandedHermitian $ unary TypeNum.u0+ printVectorWithOrder $ bandedHermitian $ unary TypeNum.u1+ printVectorWithOrder $ bandedHermitian $ unary TypeNum.u2+ printVectorWithOrder $+ banded (unary TypeNum.u0, unary TypeNum.u0) (zeroInt 4) (zeroInt 3)+ printVectorWithOrder $+ banded (unary TypeNum.u0, unary TypeNum.u2) (zeroInt 4) (zeroInt 3)+ printVectorWithOrder $+ banded (unary TypeNum.u2, unary TypeNum.u0) (zeroInt 4) (zeroInt 3)+ printVectorWithOrder $+ banded (unary TypeNum.u1, unary TypeNum.u2) (zeroInt 4) (zeroInt 3)+ printVectorWithOrder $+ banded (unary TypeNum.u1, unary TypeNum.u2) (zeroInt 3) (zeroInt 4)
+ test/Test/Generator.hs view
@@ -0,0 +1,497 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+module Test.Generator where++import qualified Test.Utility as Util+import Test.Utility (Match(Match,Mismatch))++import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Hermitian (Hermitian)+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt)+import Numeric.LAPACK.Scalar (RealOf, fromReal, one)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)+import Data.Array.Comfort.Shape ((:+:)((:+:)))++import qualified Control.Monad.Trans.RWS as MRWS+import qualified Control.Monad.Trans.Class as MT+import qualified Control.Functor.HT as FuncHT+import Control.Applicative (liftA2, (<$>))++import Data.Traversable (for)+import Data.Tuple.HT (mapFst, mapSnd, mapPair, swap)++import qualified Test.QuickCheck as QC++++{- |+@Cons generator@ with @generator maxElem maxDim fixedDims@.+@generator@ constructs an array with possibly fixed height or width+and returns its actual dimensions.+Non-fixed dimensions will be choosen arbitrarily from the range @(0,maxDim)@.+Elements are choosen from the range @(-maxElem,maxElem)@.+-}+newtype T tag required actual array = Cons (required -> ExtGen (array,actual))++instance Functor (T tag required actual) where+ fmap f (Cons gen) = Cons $ \fixed -> mapFst f <$> gen fixed++type ExtGen = MRWS.RWST (Integer,Int,MatchMode) Match () QC.Gen++data MatchMode = DontForceMatch | ForceMatch+ deriving (Eq, Show)++class Required required where nothingRequired :: required+instance Required () where nothingRequired = ()+instance Required (Maybe a) where nothingRequired = Nothing+instance (Required a, Required b) => Required (a,b) where+ nothingRequired = (nothingRequired,nothingRequired)++run ::+ (Required required) =>+ T tag required actual array -> Integer -> Int ->+ Util.TaggedGen tag (array, Match)+run (Cons gen) maxElem maxDim =+ Util.Tagged $ do+ forceMatch <- QC.elements [DontForceMatch, ForceMatch]+ ((array, _actualDim), match) <-+ MRWS.evalRWST (gen nothingRequired) (maxElem, maxDim, forceMatch) ()+ return (array, match)++withExtra ::+ (T tag required actual (a,b) -> ((a,b) -> c) -> io) ->+ QC.Gen a -> T tag required actual b -> (a -> b -> c) -> io+withExtra checkForAll genA genB test =+ checkForAll (mapGen (\_ b -> flip (,) b <$> genA) genB) (uncurry test)+++mapGen ::+ (Integer -> a -> QC.Gen b) ->+ T tag required actual a -> T tag required actual b+mapGen f (Cons gen) =+ Cons $ \fixed -> do+ (maxElem, _maxDim, _match) <- MRWS.ask+ MT.lift . FuncHT.mapFst (f maxElem) =<< gen fixed++mapGenDim ::+ (Integer -> Int -> a -> QC.Gen b) ->+ T tag required actual a -> T tag required actual b+mapGenDim f (Cons gen) =+ Cons $ \fixed -> do+ (maxElem, maxDim, _match) <- MRWS.ask+ MT.lift . FuncHT.mapFst (f maxElem maxDim) =<< gen fixed+++chooseDimMin :: Int -> ExtGen Int+chooseDimMin k = do+ (_maxElem, maxDim, _match) <- MRWS.ask+ MT.lift $ QC.choose (k,maxDim)+++class Dim dim where chooseDim :: ExtGen dim+instance Dim Int where chooseDim = chooseDimMin 0+instance (Dim dimA, Dim dimB) => Dim (dimA:+:dimB) where+ chooseDim = liftA2 (:+:) chooseDim chooseDim+++matchDim :: (Dim i, Eq i) => i -> ExtGen i+matchDim size = do+ (_maxElem, _maxDim, match) <- MRWS.ask+ case match of+ ForceMatch -> return size+ DontForceMatch -> do+ newSize <- chooseDim+ MRWS.tell $ if newSize==size then Match else Mismatch+ return newSize+++type Scalar tag = T tag () ()++scalar :: (Class.Floating a) => Scalar a a+scalar =+ Cons $ \ _fixed -> do+ (maxElem, _maxDim, _match) <- MRWS.ask+ MT.lift $ flip (,) () <$> Util.genElement maxElem++(<.*.>) ::+ Vector tag size (a -> b) ->+ Vector tag size a ->+ Scalar tag b+(<.*.>) (Cons genA) (Cons genB) =+ Cons $ \() -> do+ (f,size) <- genA Nothing+ (a,_) <- genB $ Just size+ return (f a, ())+++type Vector tag size = T tag (Maybe size) size++vectorDim :: (Class.Floating a) => Vector a Int ZeroInt+vectorDim =+ Cons $ \ fixed -> do+ dims <- maybe chooseDim return fixed+ return (zeroInt dims, dims)++vector :: (Class.Floating a) => Vector a Int (Vector.Vector ZeroInt a)+vector = mapGen Util.genArray vectorDim++vectorReal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Vector a Int (Vector.Vector ZeroInt ar)+vectorReal = mapGen Util.genArray vectorDim++(<.*|>) ::+ (Dim height, Eq height) =>+ Vector tag height (a -> b) ->+ Matrix tag height width a ->+ Vector tag width b+(<.*|>) (Cons genA) (Cons genB) =+ Cons $ \fixed -> do+ (a,(height,width)) <- genB $ Right <$> fixed+ (f,_) <- genA . Just =<< matchDim height+ return (f a, width)++(<|*.>) ::+ (Dim width, Eq width) =>+ Matrix tag height width (a -> b) ->+ Vector tag width a ->+ Vector tag height b+(<|*.>) (Cons genA) (Cons genB) =+ Cons $ \fixed -> do+ (f,(height,width)) <- genA $ Left <$> fixed+ (a,_) <- genB . Just =<< matchDim width+ return (f a, height)++(<.=.>) ::+ (Dim size, Eq size) =>+ Vector tag size (a -> b) ->+ Vector tag size a ->+ Vector tag size b+(<.=.>) (Cons genA) (Cons genB) =+ Cons $ \fixed -> do+ (f,size) <- genA fixed+ (a,_) <- genB . Just =<< matchDim size+ return (f a, size)+++type Matrix tag height width =+ T tag (Maybe (Either height width)) (height,width)++matrixDims ::+ (Class.Floating a) => Matrix a Int Int (ZeroInt, ZeroInt)+matrixDims =+ Cons $ \ fixed -> do+ dims <-+ case fixed of+ Nothing -> liftA2 (,) chooseDim chooseDim+ Just (Left h) -> (,) h <$> chooseDim+ Just (Right w) -> flip (,) w <$> chooseDim+ return (mapPair (zeroInt,zeroInt) dims, dims)++matrix ::+ (Class.Floating a) => Matrix a Int Int (Matrix.General ZeroInt ZeroInt a)+matrix =+ flip mapGen matrixDims $ \maxElem dims -> do+ order <- Util.genOrder+ Util.genArray maxElem $ uncurry (MatrixShape.general order) dims+++squareDim :: (Class.Floating a) => Matrix a Int Int ZeroInt+squareDim =+ Cons $ \ fixed -> do+ size <-+ case fixed of+ Nothing -> chooseDim+ Just (Left h) -> return h+ Just (Right w) -> return w+ return (zeroInt size, (size,size))++squareShaped ::+ (Shape.C sh, Class.Floating a) =>+ (MatrixShape.Order -> ZeroInt -> sh) -> Matrix a Int Int (Array sh a)+squareShaped shape =+ flip mapGen squareDim $ \maxElem size -> do+ order <- Util.genOrder+ Util.genArray maxElem $ shape order size++square :: (Class.Floating a) => Matrix a Int Int (Square.Square ZeroInt a)+square = squareShaped MatrixShape.square++squareCond ::+ (Class.Floating a) =>+ (Square.Square ZeroInt a -> Bool) ->+ Matrix a Int Int (Square.Square ZeroInt a)+squareCond cond =+ flip mapGen squareDim $ \maxElem size -> do+ order <- Util.genOrder+ Util.genArray maxElem (MatrixShape.square order size)+ `QC.suchThat`+ cond++invertible ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix a Int Int (Square.Square ZeroInt a)+invertible = squareCond Util.invertible++diagonal ::+ (Class.Floating a) => Matrix a Int Int (Triangular.Diagonal ZeroInt a)+diagonal = squareShaped MatrixShape.diagonal++identity ::+ (MatrixShape.Content lo, MatrixShape.Content up, Class.Floating a) =>+ Matrix a Int Int (Triangular.Triangular lo MatrixShape.Unit up ZeroInt a)+identity =+ flip mapGen squareDim $ \ _maxElem size -> do+ order <- Util.genOrder+ return $ Triangular.identity order size++triangularCond ::+ (MatrixShape.Content up, MatrixShape.Content lo, MatrixShape.TriDiag diag,+ Class.Floating a) =>+ (Triangular.Triangular lo diag up ZeroInt a -> Bool) ->+ Matrix a Int Int (Triangular.Triangular lo diag up ZeroInt a)+triangularCond cond =+ flip mapGen squareDim $ \maxElem size -> do+ order <- Util.genOrder+ genTriangularArray maxElem+ (MatrixShape.Triangular+ MatrixShape.autoDiag MatrixShape.autoUplo order size)+ `QC.suchThat`+ cond++triangular ::+ (MatrixShape.Content up, MatrixShape.Content lo, MatrixShape.TriDiag diag,+ Class.Floating a) =>+ Matrix a Int Int (Triangular.Triangular lo diag up ZeroInt a)+triangular = triangularCond (const True)+++newtype GenTriangularDiag lo up a diag =+ GenTriangularDiag {+ runGenTriangularDiag ::+ MatrixShape.Triangular lo diag up ZeroInt ->+ QC.Gen (Triangular.Triangular lo diag up ZeroInt a)+ }++genTriangularArray ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a) =>+ Integer ->+ MatrixShape.Triangular lo diag up ZeroInt ->+ QC.Gen (Triangular.Triangular lo diag up ZeroInt a)+genTriangularArray maxElem =+ runGenTriangularDiag $+ MatrixShape.switchTriDiag+ (GenTriangularDiag $ \shape ->+ Array.fromList shape <$>+ (for (Shape.indices shape) $ \(r,c) ->+ if r==c+ then return one+ else Util.genElement maxElem))+ (GenTriangularDiag $ Util.genArray maxElem)+++tallDims :: (Class.Floating a) => Matrix a Int Int (ZeroInt, ZeroInt)+tallDims =+ Cons $ \ fixed -> do+ dims <-+ case fixed of+ Nothing -> do+ h <- chooseDim+ w <- MT.lift $ QC.choose (0,h)+ return (h,w)+ Just (Left h) -> do+ w <- MT.lift $ QC.choose (0,h)+ return (h,w)+ Just (Right w) -> do+ h <- chooseDimMin w+ return (h,w)+ return (mapPair (zeroInt,zeroInt) dims, dims)++tall ::+ (Class.Floating a) =>+ Matrix a Int Int (Matrix.Tall ZeroInt ZeroInt a)+tall =+ flip mapGen tallDims $ \maxElem dims -> do+ order <- Util.genOrder+ Util.genArray maxElem $ uncurry (MatrixShape.tall order) dims++fullRankTall ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix a Int Int (Matrix.Tall ZeroInt ZeroInt a)+fullRankTall =+ flip mapGen tallDims $ \maxElem dims -> do+ order <- Util.genOrder+ Util.genArray maxElem (uncurry (MatrixShape.tall order) dims)+ `QC.suchThat` Util.fullRankTall+++wideDims :: (Class.Floating a) => Matrix a Int Int (ZeroInt, ZeroInt)+wideDims =+ Cons $ \ fixed -> do+ dims <-+ case fixed of+ Nothing -> do+ w <- chooseDim+ h <- MT.lift $ QC.choose (0,w)+ return (h,w)+ Just (Left h) -> do+ w <- chooseDimMin h+ return (h,w)+ Just (Right w) -> do+ h <- MT.lift $ QC.choose (0,w)+ return (h,w)+ return (mapPair (zeroInt,zeroInt) dims, dims)++wide ::+ (Class.Floating a) =>+ Matrix a Int Int (Matrix.Wide ZeroInt ZeroInt a)+wide =+ flip mapGen wideDims $ \maxElem dims -> do+ order <- Util.genOrder+ Util.genArray maxElem $ uncurry (MatrixShape.wide order) dims++fullRankWide ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix a Int Int (Matrix.Wide ZeroInt ZeroInt a)+fullRankWide =+ flip mapGen wideDims $ \maxElem dims -> do+ order <- Util.genOrder+ fmap Matrix.transpose $+ Util.genArray maxElem (uncurry (MatrixShape.tall order) (swap dims))+ `QC.suchThat` Util.fullRankTall+++hermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix a Int Int (Hermitian ZeroInt a)+hermitian = hermitianCond (const True)++hermitianCond ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a -> Bool) ->+ Matrix a Int Int (Hermitian ZeroInt a)+hermitianCond cond =+ flip mapGen squareDim $ \maxElem size -> do+ order <- Util.genOrder+ let shape = MatrixShape.hermitian order size+ (Array.fromList shape <$>+ (for (Shape.indices shape) $ \(r,c) ->+ if r==c+ then fromReal <$> Util.genReal maxElem+ else Util.genElement maxElem))+ `QC.suchThat` cond+++{-+There cannot be a pure/point function.+-}+(<|*|>) ::+ (Dim fuse, Eq fuse) =>+ Matrix tag height fuse (a -> b) ->+ Matrix tag fuse width a ->+ Matrix tag height width b+(<|*|>) (Cons genA) (Cons genB) =+ Cons $ \fixed ->+ case fixed of+ Just (Right width) -> do+ (a,(fuse,_)) <- genB $ Just $ Right width+ (f,(height,_)) <- genA . Just . Right =<< matchDim fuse+ return (f a, (height,width))+ Just (Left height) -> do+ (f,(_,fuse)) <- genA $ Just $ Left height+ (a,(_,width)) <- genB . Just . Left =<< matchDim fuse+ return (f a, (height,width))+ Nothing -> do+ (f,(height,fuse)) <- genA Nothing+ (a,(_,width)) <- genB . Just . Left =<< matchDim fuse+ return (f a, (height,width))++transpose ::+ Matrix tag height width a ->+ Matrix tag width height a+transpose (Cons gen) =+ Cons $ fmap (mapSnd swap) . gen . fmap (either Right Left)++(<|\|>) ::+ (Dim height, Eq height) =>+ Matrix tag height width (a -> b) ->+ Matrix tag height nrhs a ->+ Matrix tag width nrhs b+(<|\|>) a b = transpose a <|*|> b++(<***>) ::+ Vector tag height (a -> b) ->+ Vector tag width a ->+ Matrix tag height width b+(<***>) (Cons genA) (Cons genB) =+ Cons $ \fixed -> do+ (f,height) <- genA $ either Just (const Nothing) =<< fixed+ (a,width) <- genB $ either (const Nothing) Just =<< fixed+ return (f a, (height,width))+++{-+We need this type because the test stackRowsColumnsCommutative+requires to fix both height and width of the bottom right matrix.++Conversely, we cannot use the type e.g. for Square matrices,+because Square does not allow independent choice of height and width.+-}+type Matrix2 tag height width =+ T tag (Maybe height, Maybe width) (height,width)++matrix2Dims :: (Class.Floating a) => Matrix2 a Int Int (ZeroInt, ZeroInt)+matrix2Dims =+ Cons $ \ (fixedHeight,fixedWidth) -> do+ let maybeChooseDim = maybe chooseDim return+ dims <-+ liftA2 (,) (maybeChooseDim fixedHeight) (maybeChooseDim fixedWidth)+ return (mapPair (zeroInt,zeroInt) dims, dims)++matrix2 ::+ (Class.Floating a) => Matrix2 a Int Int (Matrix.General ZeroInt ZeroInt a)+matrix2 =+ flip mapGen matrix2Dims $ \maxElem dims -> do+ order <- Util.genOrder+ Util.genArray maxElem $ uncurry (MatrixShape.general order) dims++(<===>) ::+ (Dim width, Eq width) =>+ Matrix2 tag heightA width (a -> b) ->+ Matrix2 tag heightB width a ->+ Matrix2 tag (heightA:+:heightB) width b+(<===>) (Cons genA) (Cons genB) =+ Cons $ \(fixedHeight,fixedWidth) -> do+ (f,(heightA,width)) <-+ genA ((\(heightA:+:_) -> heightA) <$> fixedHeight, fixedWidth)+ matchingWidth <- matchDim width+ (a,(heightB,_)) <-+ genB ((\(_:+:heightB) -> heightB) <$> fixedHeight, Just matchingWidth)+ return (f a, (heightA:+:heightB, width))++(<|||>) ::+ (Dim height, Eq height) =>+ Matrix2 tag height widthA (a -> b) ->+ Matrix2 tag height widthB a ->+ Matrix2 tag height (widthA:+:widthB) b+(<|||>) (Cons genA) (Cons genB) =+ Cons $ \(fixedHeight,fixedWidth) -> do+ (f,(height,widthA)) <-+ genA (fixedHeight, (\(widthA:+:_) -> widthA) <$> fixedWidth)+ matchingHeight <- matchDim height+ (a,(_,widthB)) <-+ genB (Just matchingHeight, (\(_:+:widthB) -> widthB) <$> fixedWidth)+ return (f a, (height, widthA:+:widthB))+++infixl 4 <.*.>, <.*|>, <|*.>, <|*|>, <|\|>, <***>, <.=.>, <===>, <|||>
+ test/Test/Hermitian.hs view
@@ -0,0 +1,373 @@+{-# LANGUAGE TypeFamilies #-}+module Test.Hermitian (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<.*|>), (<|*.>), (<|*|>), (<|\|>))+import Test.Utility+ (approx, approxReal, approxArray, approxArrayTol, approxMatrix,+ Tagged, genOrder)++import qualified Numeric.LAPACK.Orthogonal.Householder as HH+import qualified Numeric.LAPACK.Matrix.HermitianPositiveDefinite as HermitianPD+import qualified Numeric.LAPACK.Matrix.Hermitian as Hermitian+import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Hermitian (Hermitian)+import Numeric.LAPACK.Matrix.Square (Square)+import Numeric.LAPACK.Matrix.Shape (Order)+import Numeric.LAPACK.Matrix (General, ZeroInt, zeroInt, (<#), (<#>), (#>))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, fromReal, selectReal)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape++import Control.Applicative (liftA2, (<$>))++import qualified Data.NonEmpty.Class as NonEmptyC+import qualified Data.NonEmpty as NonEmpty++import qualified Test.QuickCheck as QC+++covariance ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+covariance x =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $ Hermitian.covariance x)+ (Matrix.adjoint x <#> x)+++outer ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> Vector ZeroInt a -> Bool+outer order x =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $ Hermitian.outer order x)+ (Matrix.outer order x x)+++genScaledVectors ::+ (NonEmptyC.Gen f, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Vector a Int (ZeroInt, f (ar, Vector ZeroInt a))+genScaledVectors =+ flip Gen.mapGen Gen.vectorDim $ \maxElem size ->+ fmap ((,) size) $+ NonEmptyC.genOf $+ liftA2 (,) (Util.genReal maxElem) (Util.genArray maxElem size)++sumRank1 ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> (ZeroInt, [(ar, Vector ZeroInt a)]) -> Bool+sumRank1 order (sh,xs) =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $ Hermitian.sumRank1 order sh xs)+ (foldl Vector.add (Vector.constant (MatrixShape.general order sh sh) 0) $+ fmap (rank1 order) xs)++sumRank1NonEmpty ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> NonEmpty.T [] (ar, Vector ZeroInt a) -> Bool+sumRank1NonEmpty order xs =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $+ Hermitian.sumRank1NonEmpty order xs)+ (NonEmpty.foldl1 Vector.add $ fmap (rank1 order) xs)++rank1 ::+ (Eq size, Shape.C size, Class.Floating a) =>+ Order -> (RealOf a, Vector size a) -> Matrix.General size size a+rank1 order (r,x) = Vector.scaleReal r $ Matrix.outer order x x+++genScaledVectorPairs ::+ (NonEmptyC.Gen f, Class.Floating a) =>+ Gen.Vector a Int (ZeroInt, f (a, (Vector ZeroInt a, Vector ZeroInt a)))+genScaledVectorPairs =+ flip Gen.mapGen Gen.vectorDim $ \maxElem size ->+ fmap ((,) size) $+ NonEmptyC.genOf $+ liftA2 (,) (Util.genElement maxElem) $+ liftA2 (,) (Util.genArray maxElem size) (Util.genArray maxElem size)++sumRank2 ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> (ZeroInt, [(a, (Vector ZeroInt a, Vector ZeroInt a))]) -> Bool+sumRank2 order (sh,xys) =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $ Hermitian.sumRank2 order sh xys)+ (foldl Vector.add (Vector.constant (MatrixShape.general order sh sh) 0) $+ fmap (rank2 order) xys)++sumRank2NonEmpty ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Order -> NonEmpty.T [] (a, (Vector ZeroInt a, Vector ZeroInt a)) -> Bool+sumRank2NonEmpty order xys =+ approxArray+ (Matrix.fromFull $ Hermitian.toSquare $+ Hermitian.sumRank2NonEmpty order xys)+ (NonEmpty.foldl1 Vector.add $ fmap (rank2 order) xys)++rank2 ::+ (Eq size, Shape.C size, Class.Floating a) =>+ Order -> (a, (Vector size a, Vector size a)) -> Matrix.General size size a+rank2 order (a,(x,y)) =+ let ax = Vector.scale a x+ in Vector.add+ (Matrix.outer order ax y)+ (Matrix.outer order y ax)+++addAdjoint ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+addAdjoint x =+ approxArray+ (Hermitian.toSquare $ Hermitian.addAdjoint x)+ (Matrix.add (Matrix.adjoint x) x)+++multiplySquare ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+multiplySquare a =+ approxArray (Hermitian.toSquare $ Hermitian.square a) (a <#> a)++squareSquare ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+squareSquare a =+ approxArray+ (Hermitian.toSquare $ Hermitian.square a)+ (Square.square $ Hermitian.toSquare a)++{-+multiplyPower ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Int, Hermitian ZeroInt a) -> Bool+multiplyPower (n,a) =+ let b = Hermitian.power (fromIntegral n) a+ c = nest n (Hermitian.multiply a) $ Hermitian.identityFrom a+ in approxArrayTol (1e-6 * (Vector.normInf1 b + Vector.normInf1 c)) b c+-}+++multiplyVectorLeft ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Vector ZeroInt a, Hermitian ZeroInt a) -> Bool+multiplyVectorLeft (x,a) =+ approxArray (x <# Hermitian.toSquare a) (x <# a)++multiplyVectorRight ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a, Vector ZeroInt a) -> Bool+multiplyVectorRight (a,x) =+ approxArray (Hermitian.toSquare a #> x) (a #> x)+++multiplyLeft ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (General ZeroInt ZeroInt a, Hermitian ZeroInt a) -> Bool+multiplyLeft (a,b) =+ approxMatrix 1e-5 (a <#> Hermitian.toSquare b) (a <#> b)++multiplyRight ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a, General ZeroInt ZeroInt a) -> Bool+multiplyRight (a,b) =+ approxArray (Hermitian.toSquare a <#> b) (a <#> b)+++determinant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+determinant a =+ approx+ (selectReal 1e-1 1e-5)+ (fromReal $ Hermitian.determinant a)+ (Square.determinant $ Hermitian.toSquare a)++choleskyQR ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> QC.Property+choleskyQR a =+ let qr = HH.fromMatrix a+ r = HH.tallExtractR qr+ in HH.determinantAbsolute qr > 0.1+ QC.==>+ approxArrayTol 1e-1+ (Matrix.scaleRows (Array.map signum $ Triangular.takeDiagonal r) $+ Triangular.toSquare r)+ (Triangular.toSquare $+ HermitianPD.decompose $ Hermitian.covariance $ Matrix.fromFull a)+++invertible ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian sh a -> Bool+invertible a = abs (Hermitian.determinant a) > 0.1++inverse ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+inverse a =+ approxArrayTol+ (selectReal 1 1e-5)+ (Hermitian.toSquare $ Hermitian.inverse a)+ (Square.inverse $ Hermitian.toSquare a)+++solve ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solve (a, b) =+ approxMatrix (selectReal 1 1e-5)+ (Hermitian.solve a b)+ (Square.solve (Hermitian.toSquare a) b)++++genPositiveDefinite ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int (Hermitian ZeroInt a)+genPositiveDefinite =+ flip Gen.mapGenDim Gen.squareDim $+ \maxElem maxDim width@(Shape.ZeroBased w) -> do+ height <- zeroInt <$> QC.choose (w,maxDim)+ order <- Util.genOrder+ Hermitian.covariance . Matrix.fromFull <$>+ Util.genArray maxElem (MatrixShape.tall order height width)+ `QC.suchThat` Util.fullRankTall++determinantPD ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+determinantPD a =+ approxReal (selectReal 100 1e-4)+ (Hermitian.determinant a)+ (HermitianPD.determinant a)++inversePD ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+inversePD a =+ approxArrayTol (selectReal 1000 1e-4)+ (Hermitian.inverse a)+ (HermitianPD.inverse a)++solvePD ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solvePD (a,b) =+ approxArrayTol (selectReal 1000 1e-4)+ (Hermitian.solve a b)+ (HermitianPD.solve a b)++solveDecomposedPD ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Hermitian ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solveDecomposedPD (a,b) =+ approxArrayTol (selectReal 1e-1 1e-6)+ (HermitianPD.solve a b)+ (HermitianPD.solveDecomposed (HermitianPD.decompose a) b)++++eigenvaluesDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+eigenvaluesDeterminant a =+ approxReal+ (selectReal 1e-1 1e-5)+ (Hermitian.determinant a)+ (Vector.product $ Hermitian.eigenvalues a)++eigensystem ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Hermitian ZeroInt a -> Bool+eigensystem a =+ let (q,d) = Hermitian.eigensystem a+ in approxMatrix 1e-4+ (Hermitian.toSquare a)+ (q <#> Matrix.scaleRowsReal d (Square.adjoint q))++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 3 5)++checkForAllExtra ::+ (Show a, Show b, QC.Testable test, Gen.Required required) =>+ QC.Gen a -> Gen.T tag required actual b ->+ (a -> b -> test) -> Tagged tag QC.Property+checkForAllExtra = Gen.withExtra checkForAll+++testsVar ::+ (Show a, Show ar, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("covariance",+ checkForAll Gen.matrix covariance) :+ ("outer",+ checkForAllExtra genOrder Gen.vector outer) :+ ("sumRank1",+ checkForAllExtra genOrder genScaledVectors sumRank1) :+ ("sumRank1NonEmpty",+ checkForAllExtra genOrder (snd <$> genScaledVectors) sumRank1NonEmpty) :+ ("sumRank2",+ checkForAllExtra genOrder genScaledVectorPairs sumRank2) :+ ("sumRank2NonEmpty",+ checkForAllExtra genOrder+ (snd <$> genScaledVectorPairs) sumRank2NonEmpty) :+ ("addAdjoint",+ checkForAll Gen.square addAdjoint) :+ ("multiplySquare",+ checkForAll Gen.hermitian multiplySquare) :+ ("squareSquare",+ checkForAll Gen.hermitian squareSquare) :++ ("multiplyVectorLeft",+ checkForAll ((,) <$> Gen.vector <.*|> Gen.hermitian) multiplyVectorLeft) :+ ("multiplyVectorRight",+ checkForAll ((,) <$> Gen.hermitian <|*.> Gen.vector) multiplyVectorRight) :+ ("multiplyLeft",+ checkForAll ((,) <$> Gen.matrix <|*|> Gen.hermitian) multiplyLeft) :+ ("multiplyRight",+ checkForAll ((,) <$> Gen.hermitian <|*|> Gen.matrix) multiplyRight) :++ ("determinant",+ checkForAll Gen.hermitian determinant) :+ ("choleskyQR",+ checkForAll Gen.tall choleskyQR) :++ ("inverse",+ checkForAll (Gen.hermitianCond invertible) inverse) :+ ("solve",+ checkForAll+ ((,) <$> Gen.hermitianCond invertible <|\|> Gen.matrix) solve) :++ ("determinantPD",+ checkForAll genPositiveDefinite determinantPD) :+ ("inversePD",+ checkForAll genPositiveDefinite inversePD) :+ ("solvePD",+ checkForAll ((,) <$> genPositiveDefinite <|\|> Gen.matrix) solvePD) :+ ("solveDecomposedPD",+ checkForAll+ ((,) <$> genPositiveDefinite <|\|> Gen.matrix) solveDecomposedPD) :++ ("eigenvaluesDeterminant",+ checkForAll Gen.hermitian eigenvaluesDeterminant) :+ ("eigensystem",+ checkForAll Gen.hermitian eigensystem) :+ []
+ test/Test/Matrix.hs view
@@ -0,0 +1,503 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+module Test.Matrix (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<|*|>), (<|*.>), (<.*.>), (<***>), (<|||>), (<===>))+import Test.Utility+ (approx, approxArray, approxMatrix,+ genOrder, Tagged(Tagged), TaggedGen)++import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix+ (General, ZeroInt, zeroInt, (#>), (<#>), (|||), (===))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, conjugate)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)+import Data.Array.Comfort.Shape ((:+:))++import Control.Applicative (liftA2, (<$>))++import Data.Tuple.HT (mapPair, swap)+import Data.Eq.HT (equating)++import qualified Test.QuickCheck as QC+++genArray ::+ (Shape.C shape, Class.Floating a) => shape -> QC.Gen (Array shape a)+genArray = Util.genArray 10++equalArray ::+ (Shape.C shape, Eq shape, Class.Floating a) =>+ Array shape a -> Array shape a -> Bool+equalArray x y =+ if Array.shape x == Array.shape y+ then equalArrayBody x y+ else error "equalArray: shapes mismatch"++equalArrayBody ::+ (Shape.C shape, Class.Floating a) =>+ Array shape a -> Array shape a -> Bool+equalArrayBody =+ getEqualArray $+ Class.switchFloating+ (EqualArray $ equating Array.toList)+ (EqualArray $ equating Array.toList)+ (EqualArray $ equating Array.toList)+ (EqualArray $ equating Array.toList)++newtype EqualArray f a = EqualArray {getEqualArray :: f a -> f a -> Bool}+++dotProduct ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Vector ZeroInt a, Vector ZeroInt a) -> Bool+dotProduct (x,y) =+ approx 1e-5+ (Vector.dot x y)+ (Matrix.toScalar $+ Matrix.singleRow MatrixShape.RowMajor x <#>+ Matrix.singleColumn MatrixShape.ColumnMajor y)++innerDot ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Vector ZeroInt a, Vector ZeroInt a) -> Bool+innerDot (x,y) =+ approx 1e-5 (Vector.inner x y) (Vector.dot (Vector.conjugate x) y)++tensorProductTranspose ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+tensorProductTranspose order (x,y) =+ approxArray+ (Matrix.transpose (Matrix.tensorProduct order x y))+ (Matrix.tensorProduct (MatrixShape.flipOrder order) y x)++outerTranspose ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+outerTranspose order (x,y) =+ approxArray+ (Matrix.transpose (Matrix.outer order x y))+ (Matrix.outer (MatrixShape.flipOrder order)+ (Vector.conjugate y) (Vector.conjugate x))++tensorProduct ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+tensorProduct order (x,y) =+ approxArray+ (Matrix.tensorProduct order x y)+ (Matrix.singleColumn order x <#> Matrix.singleRow order y)++tensorProductMul ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular.Diagonal ZeroInt a,+ Matrix.General ZeroInt ZeroInt a,+ Triangular.Diagonal ZeroInt a) ->+ Bool+tensorProductMul (x,m,y) =+ let xmy = x <#> m <#> y+ in approxArray xmy+ (Vector.mul m+ (Matrix.tensorProduct (MatrixShape.fullOrder $ Array.shape xmy)+ (Triangular.takeDiagonal x) (Triangular.takeDiagonal y)))++outerTensorProduct ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+outerTensorProduct order (x,y) =+ approxArray+ (Matrix.outer order x y)+ (Matrix.tensorProduct order x $ Vector.conjugate y)++genScaledVectorPairs ::+ (Class.Floating a) =>+ Gen.Matrix a Int Int+ ((ZeroInt, ZeroInt), [(a, (Vector ZeroInt a, Vector ZeroInt a))])+genScaledVectorPairs =+ flip Gen.mapGen Gen.matrixDims $ \maxElem size@(height,width) ->+ fmap ((,) size) $+ QC.listOf $+ liftA2 (,) (Util.genElement maxElem) $+ liftA2 (,) (Util.genArray maxElem height) (Util.genArray maxElem width)++sumRank1 ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order ->+ ((ZeroInt,ZeroInt), [(a, (Vector ZeroInt a, Vector ZeroInt a))]) -> Bool+sumRank1 order (size,xys) =+ approxArray+ (case order of+ MatrixShape.ColumnMajor -> Matrix.sumRank1 size xys+ MatrixShape.RowMajor ->+ Matrix.adjoint $+ Matrix.sumRank1 (swap size) $ map (mapPair (conjugate, swap)) xys)+ (foldl Vector.add+ (Vector.constant (uncurry (MatrixShape.general order) size) 0)+ (map (\(a,(x,y)) -> Matrix.outer order (Vector.scale a x) y) xys))+++outerTrace ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+outerTrace order (x,y) =+ approx 1e-5+ (Vector.inner y x)+ (Square.trace $ Square.fromGeneral $ Matrix.outer order x y)++outerInner ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a, Vector ZeroInt a) -> Bool+outerInner order (x,y,z) =+ approxArray (Matrix.outer order x y #> z) (Vector.scale (Vector.inner y z) x)+++tensorTrace ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> (Vector ZeroInt a, Vector ZeroInt a) -> Bool+tensorTrace order (x,y) =+ approx 1e-5 (Vector.dot y x)+ (Square.trace $ Square.fromGeneral $ Matrix.tensorProduct order x y)++tensorDot ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order ->+ (Vector ZeroInt a, Vector ZeroInt a, Vector ZeroInt a) -> Bool+tensorDot order (x,y,z) =+ approxArray+ (Matrix.tensorProduct order x y #> z) (Vector.scale (Vector.dot y z) x)+++genZeroColumns ::+ (Class.Floating a) => TaggedGen a (Matrix.Tall ZeroInt ZeroInt a)+genZeroColumns = Tagged $ do+ height <- zeroInt <$> QC.choose (0,5)+ order <- genOrder+ genArray (MatrixShape.tall order height (zeroInt 0))+++reverseNoRows :: (Class.Floating a) => Matrix.Wide ZeroInt ZeroInt a -> Bool+reverseNoRows x =+ equalArray x $ Matrix.reverseRows x++reverseNoColumns :: (Class.Floating a) => Matrix.Tall ZeroInt ZeroInt a -> Bool+reverseNoColumns x =+ equalArray x $ Matrix.reverseColumns x++++genMatrix2EqHeight ::+ (Class.Floating a) =>+ Gen.Matrix2 a Int (Int:+:Int)+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a)+genMatrix2EqHeight = (,) <$> Gen.matrix2 <|||> Gen.matrix2++genMatrix2EqWidth ::+ (Class.Floating a) =>+ Gen.Matrix2 a (Int:+:Int) Int+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a)+genMatrix2EqWidth = (,) <$> Gen.matrix2 <===> Gen.matrix2++reverseRows :: (Class.Floating a) => General ZeroInt ZeroInt a -> Bool+reverseRows x =+ equalArray x $ Matrix.reverseRows (Matrix.reverseRows x)++reverseColumns :: (Class.Floating a) => General ZeroInt ZeroInt a -> Bool+reverseColumns x =+ equalArray x $ Matrix.reverseColumns (Matrix.reverseColumns x)+++mapHeight ::+ (heightA -> heightB) ->+ MatrixShape.General heightA width ->+ MatrixShape.General heightB width+mapHeight f shape =+ MatrixShape.general+ (MatrixShape.fullOrder shape)+ (f $ MatrixShape.fullHeight shape)+ (MatrixShape.fullWidth shape)++mapWidth ::+ (widthA -> widthB) ->+ MatrixShape.General height widthA ->+ MatrixShape.General height widthB+mapWidth f shape =+ MatrixShape.general+ (MatrixShape.fullOrder shape)+ (MatrixShape.fullHeight shape)+ (f $ MatrixShape.fullWidth shape)++zeroIntHeight ::+ (Shape.C height, Shape.C width) =>+ General height width a -> General ZeroInt width a+zeroIntHeight = Array.mapShape (mapHeight (zeroInt . Shape.size))++zeroIntWidth ::+ (Shape.C height, Shape.C width) =>+ General height width a -> General height ZeroInt a+zeroIntWidth = Array.mapShape (mapWidth (zeroInt . Shape.size))++reverseRowsStack ::+ (Class.Floating a) =>+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a) -> Bool+reverseRowsStack (x,y) =+ equalArray+ (Matrix.reverseRows $ zeroIntHeight $ x===y)+ (zeroIntHeight $ Matrix.reverseRows y === Matrix.reverseRows x)++reverseColumnsStack ::+ (Class.Floating a) =>+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a) -> Bool+reverseColumnsStack (x,y) =+ equalArray+ (Matrix.reverseColumns $ zeroIntWidth $ x|||y)+ (zeroIntWidth $ Matrix.reverseColumns y ||| Matrix.reverseColumns x)+++data Cut = Take | Drop deriving (Show, Eq, Ord, Enum, Bounded)+data Slice = Row | Column deriving (Show, Eq, Ord, Enum, Bounded)++cut ::+ (Class.Floating a) =>+ Cut -> Slice -> Int ->+ General ZeroInt ZeroInt a -> General ZeroInt ZeroInt a+cut Take Row = Matrix.takeRows+cut Take Column = Matrix.takeColumns+cut Drop Row = Matrix.dropRows+cut Drop Column = Matrix.dropColumns++cutCommutative ::+ (Class.Floating a) =>+ ((Cut,Slice),(Int,Int)) -> General ZeroInt ZeroInt a -> Bool+cutCommutative (kind,(k,j)) x =+ let cutK = uncurry cut kind k+ cutJ = uncurry cut kind j+ in equalArray (cutK $ cutJ x) (cutJ $ cutK x)++cutRowColumnCommutative ::+ (Class.Floating a) =>+ ((Cut,Int),(Cut,Int)) -> General ZeroInt ZeroInt a -> Bool+cutRowColumnCommutative ((cutR,k),(cutC,j)) x =+ let cutRows = cut cutR Row k+ cutColumns = cut cutC Column j+ in equalArray (cutRows $ cutColumns x) (cutColumns $ cutRows x)+++takeEqually ::+ (Class.Floating a) => Int -> General ZeroInt ZeroInt a -> Bool+takeEqually k x =+ equalArray+ (Matrix.takeEqually k x)+ (Matrix.takeRows k (Matrix.takeColumns k x))++dropEqually ::+ (Class.Floating a) => Int -> General ZeroInt ZeroInt a -> Bool+dropEqually k x =+ equalArray+ (Matrix.dropEqually k x)+ (Matrix.dropRows k (Matrix.dropColumns k x))+++stackSplitRows ::+ (Class.Floating a) => Int -> General ZeroInt ZeroInt a -> Bool+stackSplitRows k x =+ equalArray x+ (zeroIntHeight $ Matrix.takeRows k x === Matrix.dropRows k x)++stackSplitColumns ::+ (Class.Floating a) => Int -> General ZeroInt ZeroInt a -> Bool+stackSplitColumns k x =+ equalArray x+ (zeroIntWidth $ Matrix.takeColumns k x ||| Matrix.dropColumns k x)+++takeStackRows, dropStackRows ::+ (Class.Floating a) =>+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a) -> Bool+takeStackRows (x,y) =+ equalArray+ (Matrix.toRowMajor x)+ (Matrix.toRowMajor $ Matrix.takeRows (Shape.size $ Matrix.height x) $+ zeroIntHeight $ x===y)+dropStackRows (x,y) =+ equalArray+ (Matrix.toRowMajor y)+ (Matrix.toRowMajor $ Matrix.dropRows (Shape.size $ Matrix.height x) $+ zeroIntHeight $ x===y)++takeStackColumns, dropStackColumns ::+ (Class.Floating a) =>+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a) -> Bool+takeStackColumns (x,y) =+ equalArray+ (Matrix.toRowMajor x)+ (Matrix.toRowMajor $ Matrix.takeColumns (Shape.size $ Matrix.width x) $+ zeroIntWidth $ x|||y)+dropStackColumns (x,y) =+ equalArray+ (Matrix.toRowMajor y)+ (Matrix.toRowMajor $ Matrix.dropColumns (Shape.size $ Matrix.width x) $+ zeroIntWidth $ x|||y)++stackRowsAssociative, stackColumnsAssociative ::+ (Class.Floating a) =>+ (General ZeroInt ZeroInt a,+ General ZeroInt ZeroInt a,+ General ZeroInt ZeroInt a) -> Bool+stackRowsAssociative (x,y,z) =+ equalArray+ (zeroIntHeight ((x===y)===z))+ (zeroIntHeight (x===(y===z)))+stackColumnsAssociative (x,y,z) =+ equalArray+ (zeroIntWidth ((x|||y)|||z))+ (zeroIntWidth (x|||(y|||z)))++stackRowsColumnsCommutative ::+ (Class.Floating a) =>+ ((General ZeroInt ZeroInt a, General ZeroInt ZeroInt a),+ (General ZeroInt ZeroInt a, General ZeroInt ZeroInt a)) -> Bool+stackRowsColumnsCommutative ((x,y),(z,w)) =+ equalArray+ (Matrix.toRowMajor $ (x|||y)===(z|||w))+ (Matrix.toRowMajor $ (x===z)|||(y===w))+++multiplyDiagonalMatrix ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular.Diagonal ZeroInt a, General ZeroInt ZeroInt a) -> Bool+multiplyDiagonalMatrix (x,y) =+ approxArray (x <#> y) (Triangular.toSquare x <#> y)++multiplyMatrixDiagonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (General ZeroInt ZeroInt a, Triangular.Diagonal ZeroInt a) -> Bool+multiplyMatrixDiagonal (x,y) =+ approxMatrix 1e-5 (x <#> y) (x <#> Triangular.toSquare y)++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 10 5)++checkForAllExtra ::+ (Show a, Show b, QC.Testable test, Gen.Required required) =>+ QC.Gen a -> Gen.T tag required actual b ->+ (a -> b -> test) -> Tagged tag QC.Property+checkForAllExtra = Gen.withExtra checkForAll+++testsVar ::+ (Show a, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("dotProduct",+ checkForAll ((,) <$> Gen.vector <.*.> Gen.vector) dotProduct) :+ ("innerDot",+ checkForAll ((,) <$> Gen.vector <.*.> Gen.vector) innerDot) :+ ("tensorProductTranspose",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <***> Gen.vector) tensorProductTranspose) :+ ("outerTranspose",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <***> Gen.vector) outerTranspose) :+ ("tensorProduct",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <***> Gen.vector) tensorProduct) :+ ("tensorProductMul",+ checkForAll ((,,) <$> Gen.diagonal <|*|> Gen.matrix <|*|> Gen.diagonal)+ tensorProductMul) :+ ("outerTensorProduct",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <***> Gen.vector) outerTensorProduct) :+ ("sumRank1",+ checkForAllExtra genOrder genScaledVectorPairs sumRank1) :++ ("outerTrace",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <.*.> Gen.vector) outerTrace) :+ ("outerInner",+ checkForAllExtra genOrder+ ((,,) <$> Gen.vector <***> Gen.vector <|*.> Gen.vector) outerInner) :+ ("tensorTrace",+ checkForAllExtra genOrder+ ((,) <$> Gen.vector <.*.> Gen.vector) tensorTrace) :+ ("tensorDot",+ checkForAllExtra genOrder+ ((,,) <$> Gen.vector <***> Gen.vector <|*.> Gen.vector) tensorDot) :++ ("reverseNoRows",+ Util.checkForAllPlain+ (fmap Matrix.transpose <$> genZeroColumns) reverseNoRows) :+ ("reverseNoColumns",+ Util.checkForAllPlain genZeroColumns reverseNoColumns) :+ ("reverseRows",+ checkForAll Gen.matrix reverseRows) :+ ("reverseColumns",+ checkForAll Gen.matrix reverseColumns) :+ ("reverseRowsStack",+ checkForAll genMatrix2EqWidth reverseRowsStack) :+ ("reverseColumnsStack",+ checkForAll genMatrix2EqHeight reverseColumnsStack) :+ ("cutCommutative",+ checkForAllExtra+ (liftA2 (,)+ (liftA2 (,) QC.arbitraryBoundedEnum QC.arbitraryBoundedEnum)+ (liftA2 (,) (QC.choose (0,5)) (QC.choose (0,5))))+ Gen.matrix cutCommutative) :+ ("cutRowColumnCommutative",+ checkForAllExtra+ (liftA2 (,)+ (liftA2 (,) QC.arbitraryBoundedEnum (QC.choose (0,5)))+ (liftA2 (,) QC.arbitraryBoundedEnum (QC.choose (0,5))))+ Gen.matrix cutRowColumnCommutative) :+ ("takeEqually",+ checkForAllExtra (QC.choose (0,5)) Gen.matrix takeEqually) :+ ("dropEqually",+ checkForAllExtra (QC.choose (0,5)) Gen.matrix dropEqually) :+ ("stackSplitRows",+ checkForAllExtra (QC.choose (0,5)) Gen.matrix stackSplitRows) :+ ("stackSplitColumns",+ checkForAllExtra (QC.choose (0,5)) Gen.matrix stackSplitColumns) :+ ("takeStackRows",+ checkForAll genMatrix2EqWidth takeStackRows) :+ ("dropStackRows",+ checkForAll genMatrix2EqWidth dropStackRows) :+ ("takeStackColumns",+ checkForAll genMatrix2EqHeight takeStackColumns) :+ ("dropStackColumns",+ checkForAll genMatrix2EqHeight dropStackColumns) :+ ("stackRowsAssociative",+ checkForAll+ ((,,) <$> Gen.matrix2 <===> Gen.matrix2 <===> Gen.matrix2)+ stackRowsAssociative) :+ ("stackColumnsAssociative",+ checkForAll+ ((,,) <$> Gen.matrix2 <|||> Gen.matrix2 <|||> Gen.matrix2)+ stackColumnsAssociative) :+ ("stackRowsColumnsCommutative",+ checkForAll+ ((,) <$> genMatrix2EqHeight <===> genMatrix2EqHeight)+ stackRowsColumnsCommutative) :++ ("multiplyDiagonalMatrix",+ checkForAll+ ((,) <$> Gen.diagonal <|*|> Gen.matrix) multiplyDiagonalMatrix) :+ ("multiplyMatrixDiagonal",+ checkForAll+ ((,) <$> Gen.matrix <|*|> Gen.diagonal) multiplyMatrixDiagonal) :+ []
+ test/Test/Orthogonal.hs view
@@ -0,0 +1,415 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+module Test.Orthogonal (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<|*|>), (<|\|>))+import Test.Utility+ (approx, approxReal, approxArrayTol, approxMatrix, isIdentity, Tagged)++import qualified Numeric.LAPACK.Orthogonal.Householder as HH+import qualified Numeric.LAPACK.Orthogonal as Ortho+import qualified Numeric.LAPACK.Matrix.Hermitian as Herm+import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Square (Square)+import Numeric.LAPACK.Matrix (General, ZeroInt, (<#>))+import Numeric.LAPACK.Scalar (RealOf, absolute, selectReal)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)++import Control.Applicative (liftA2, (<$>))++import qualified Test.QuickCheck as QC+++pseudoInverseProjection ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+pseudoInverseProjection a =+ let ainv = snd $ Ortho.pseudoInverseRCond 1e-5 a+ tol = selectReal 1e-1 1e-5+ in approxArrayTol tol a (a <#> ainv <#> a) &&+ approxArrayTol tol ainv (ainv <#> a <#> ainv)++pseudoInverseHermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+pseudoInverseHermitian a =+ let ainv = snd $ Ortho.pseudoInverseRCond 1e-5 a+ tol = selectReal 1e-2 1e-5+ aainv = a <#> ainv+ ainva = ainv <#> a+ in approxMatrix tol aainv (Matrix.adjoint aainv) &&+ approxMatrix tol ainva (Matrix.adjoint ainva)++pseudoInverseFactored ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a,+ Matrix.Wide ZeroInt ZeroInt a) -> Bool+pseudoInverseFactored (a,b) =+ let pinv x = snd $ Ortho.pseudoInverseRCond 1e-5 x+ in approxMatrix (selectReal 1e-1 1e-5)+ (pinv (a <#> b)) (pinv b <#> pinv a)++pseudoInverseInverse ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+pseudoInverseInverse a =+ approxMatrix (selectReal 1e-1 1e-5)+ (Matrix.inverse a)+ (snd $ Ortho.pseudoInverseRCond 1e-5 a)+++determinant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+determinant a =+ let detSquare = Square.determinant a+ detOrtho = Ortho.determinant a+ in approx+ (1e-3 * max 1 (max (absolute detSquare) (absolute detOrtho)))+ detSquare detOrtho++determinantAbsolute ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+determinantAbsolute a =+ let det = absolute $ Ortho.determinant a+ detAbs = Ortho.determinantAbsolute a+ in approxReal (1e-5 * max 1 (max det detAbs)) det detAbs++gramianDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+gramianDeterminant a =+ let cov = Herm.covariance a+ Shape.ZeroBased n = Matrix.width a+ estimate = (Vector.sum (Herm.takeDiagonal cov) / fromIntegral n) ^ n+ in approxReal (1e-5 * max 1 estimate)+ (Herm.determinant cov)+ (Ortho.determinantAbsolute a ^ (2::Int))+++multiplyDeterminantRight ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (General ZeroInt ZeroInt a, Square ZeroInt a) -> Bool+multiplyDeterminantRight (a,b) =+ let detA = Ortho.determinantAbsolute a+ detB = absolute $ Ortho.determinant b+ in approxReal+ (selectReal 1e-1 1e-5 * max 1 detA * max 1 detB)+ (Ortho.determinantAbsolute (a<#>b))+ (detA * detB)++multiplyDeterminantLeft ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Square ZeroInt a, General ZeroInt ZeroInt a) -> Bool+multiplyDeterminantLeft (a,b) =+ let detA = absolute $ Ortho.determinant a+ detB = Ortho.determinantAbsolute b+ in approxReal+ (selectReal 1e-1 1e-5 * max 1 detA * max 1 detB)+ (Ortho.determinantAbsolute (a<#>b))+ (detA * detB)+++genFullRankTallRHS ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int+ (Matrix.Tall ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a)+genFullRankTallRHS = (,) <$> Gen.fullRankTall <|\|> Gen.matrix+++normalEquationLeastSquares ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+normalEquationLeastSquares (a, b) =+ approxArrayTol+ (selectReal 10 1e-3)+ (Ortho.leastSquares a b)+ (Herm.solve (Herm.covariance $ Matrix.fromFull a) $+ Matrix.adjoint a <#> b)++specializedLeastSquares ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+specializedLeastSquares (a, b) =+ approxArrayTol+ (selectReal 1e-1 1e-5)+ (Ortho.leastSquares a b)+ (snd $ Ortho.leastSquaresMinimumNormRCond 1e-5 (Matrix.fromFull a) b)++householderLeastSquares ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+householderLeastSquares (a, b) =+ approxArrayTol+ (selectReal 1e-1 1e-5)+ (Ortho.leastSquares a b)+ (HH.leastSquares (HH.fromMatrix a) b)++++genFullRankWideRHS ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int+ (Matrix.Wide ZeroInt ZeroInt a,+ Matrix.General ZeroInt ZeroInt a)+genFullRankWideRHS = (,) <$> Gen.fullRankWide <|\|> Gen.matrix+++normalEquationMinimumNorm ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Wide ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+normalEquationMinimumNorm (a, b) =+ approxArrayTol+ (selectReal 10 1e-3)+ (Ortho.minimumNorm a b)+ (Matrix.adjoint a <#>+ Herm.solve (Herm.covariance $ Matrix.fromFull $ Matrix.adjoint a) b)++specializedMinimumNorm ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Wide ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+specializedMinimumNorm (a, b) =+ approxArrayTol+ (selectReal 1e-1 1e-5)+ (Ortho.minimumNorm a b)+ (snd $ Ortho.leastSquaresMinimumNormRCond 1e-5 (Matrix.fromFull a) b)++householderMinimumNorm ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Wide ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+householderMinimumNorm (a, b) =+ approxArrayTol+ (selectReal 1e-1 1e-5)+ (Ortho.minimumNorm a b)+ (HH.minimumNorm (HH.fromMatrix $ Matrix.adjoint a) b)+++complementDimension ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> Bool+complementDimension a =+ let b = Matrix.fromFull a Matrix.||| Matrix.fromFull (Ortho.complement a)+ in Shape.size (Matrix.height b) == Shape.size (Matrix.width b)++complementBiorthogonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> Bool+complementBiorthogonal a =+ all (approx 1e-3 0) $+ Array.toList $ Matrix.adjoint a <#> Ortho.complement a++complementOrthogonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> Bool+complementOrthogonal =+ isIdentity (selectReal 1e-3 1e-7) .+ Herm.toSquare . Herm.covariance . Matrix.fromFull . Ortho.complement+++householderReconstruction ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.General ZeroInt ZeroInt a -> Bool+householderReconstruction a =+ approxArrayTol (selectReal 1e-3 1e-7)+ a (uncurry (<#>) (Ortho.householder a))++householderDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+householderDeterminant a =+ let detOrtho = Ortho.determinant a+ detHH = HH.determinant $ HH.fromMatrix a+ in approx 1e-5 detOrtho detHH+++maybeConjugate ::+ (Shape.C sh, Class.Floating a) =>+ HH.Conjugation -> Array sh a -> Array sh a+maybeConjugate HH.NonConjugated = id+maybeConjugate HH.Conjugated = Vector.conjugate++maybeTranspose ::+ (Shape.C size, Class.Floating a, MatrixShape.TriDiag diag,+ MatrixShape.Content lo, MatrixShape.Content up) =>+ Herm.Transposition ->+ Triangular.Triangular up diag lo size a -> Square size a+maybeTranspose HH.NonTransposed = Triangular.toSquare+maybeTranspose HH.Transposed = Triangular.toSquare . Triangular.transpose++maybeAdjoint ::+ (Shape.C size, Class.Floating a) =>+ HH.Inversion -> Square size a -> Square size a+maybeAdjoint HH.NonInverted = id+maybeAdjoint HH.Inverted = Matrix.adjoint++householderSolveRR ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (HH.Transposition, HH.Conjugation) ->+ Matrix.Tall ZeroInt ZeroInt a -> Bool+householderSolveRR (trans,conj) a =+ let qr = HH.fromMatrix a+ in isIdentity (selectReal 1e-3 1e-7) $+ HH.tallSolveR trans conj qr $+ maybeTranspose trans $ maybeConjugate conj $ HH.tallExtractR qr+++householderMultiplyR ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ HH.Transposition ->+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) ->+ Bool+householderMultiplyR trans (a,b) =+ let qr = HH.fromMatrix a+ r = HH.tallExtractR qr+ in approxArrayTol+ (selectReal 1e-3 1e-7)+ (HH.tallMultiplyR trans qr b)+ (case trans of+ HH.NonTransposed -> r <#> b+ HH.Transposed -> Triangular.transpose r <#> b)+++householderQOrthogonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.General ZeroInt ZeroInt a -> Bool+householderQOrthogonal a =+ let q = HH.extractQ $ HH.fromMatrix a+ in isIdentity (selectReal 1e-3 1e-7) $ Matrix.adjoint q <#> q+++householderMultiplyQ ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ HH.Inversion ->+ (Matrix.General ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) ->+ Bool+householderMultiplyQ inv (a,b) =+ let qr = HH.fromMatrix a+ in approxArrayTol+ (selectReal 1e-3 1e-7)+ (maybeAdjoint inv (HH.extractQ qr) <#> b)+ (HH.multiplyQ inv qr b)+++householderTallQOrthogonal ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> Bool+householderTallQOrthogonal =+ isIdentity (selectReal 1e-3 1e-7) .+ Herm.toSquare . Herm.covariance . Matrix.fromFull .+ HH.tallExtractQ . HH.fromMatrix++householderTallMultiplyQ ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+householderTallMultiplyQ (a,b) =+ let qr = HH.fromMatrix a+ in approxArrayTol+ (selectReal 1e-3 1e-7)+ (HH.tallExtractQ qr <#> b)+ (HH.tallMultiplyQ qr b)++householderTallMultiplyQAdjoint ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.Tall ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+householderTallMultiplyQAdjoint (a,b) =+ let qr = HH.fromMatrix a+ in approxArrayTol+ (selectReal 1e-3 1e-7)+ (Matrix.adjoint (HH.tallExtractQ qr) <#> b)+ (HH.tallMultiplyQAdjoint qr b)++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 3 5)+++testsVar ::+ (Show a, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("pseudoInverseProjection",+ checkForAll Gen.matrix pseudoInverseProjection) :+ ("pseudoInverseHermitian",+ checkForAll Gen.matrix pseudoInverseHermitian) :+ ("pseudoInverseFactored",+ checkForAll+ ((,) <$> Gen.fullRankTall <|*|> Gen.fullRankWide)+ pseudoInverseFactored) :+ ("pseudoInverseInverse",+ checkForAll Gen.invertible pseudoInverseInverse) :++ ("determinant",+ checkForAll Gen.square determinant) :+ ("determinantAbsolute",+ checkForAll Gen.square determinantAbsolute) :+ ("gramianDeterminant",+ checkForAll Gen.matrix gramianDeterminant) :+ ("multiplyDeterminantRight",+ checkForAll+ ((,) <$> Gen.matrix <|*|> Gen.square) multiplyDeterminantRight) :+ ("multiplyDeterminantLeft",+ checkForAll+ ((,) <$> (fst . Ortho.householder <$> Gen.square) <|*|> Gen.matrix)+ multiplyDeterminantLeft) :+ ("normalEquationLeastSquares",+ checkForAll genFullRankTallRHS normalEquationLeastSquares) :+ ("normalEquationMinimumNorm",+ checkForAll genFullRankWideRHS normalEquationMinimumNorm) :+ ("specializedLeastSquares",+ checkForAll genFullRankTallRHS specializedLeastSquares) :+ ("specializedMinimumNorm",+ checkForAll genFullRankWideRHS specializedMinimumNorm) :++ ("complementDimension",+ checkForAll Gen.tall complementDimension) :+ ("complementBiorthogonal",+ checkForAll Gen.tall complementBiorthogonal) :+ ("complementOrthogonal",+ checkForAll Gen.tall complementOrthogonal) :++ ("householderReconstruction",+ checkForAll Gen.matrix householderReconstruction) :+ ("householderDeterminant",+ checkForAll Gen.square householderDeterminant) :+ ("householderLeastSquares",+ checkForAll genFullRankTallRHS householderLeastSquares) :+ ("householderMinimumNorm",+ checkForAll genFullRankWideRHS householderMinimumNorm) :+ ("householderSolveRR",+ Gen.withExtra checkForAll+ (liftA2 (,) QC.arbitraryBoundedEnum QC.arbitraryBoundedEnum)+ Gen.fullRankTall householderSolveRR) :+ ("householderMultiplyR",+ Gen.withExtra checkForAll+ QC.arbitraryBoundedEnum ((,) <$> Gen.tall <|*|> Gen.matrix)+ householderMultiplyR) :+ ("householderQOrthogonal",+ checkForAll Gen.matrix householderQOrthogonal) :+ ("householderMultiplyQ",+ Gen.withExtra checkForAll+ QC.arbitraryBoundedEnum ((,) <$> Gen.matrix <|\|> Gen.matrix)+ householderMultiplyQ) :+ ("householderTallQOrthogonal",+ checkForAll Gen.tall householderTallQOrthogonal) :+ ("householderTallMultiplyQ",+ checkForAll ((,) <$> Gen.tall <|*|> Gen.matrix) householderTallMultiplyQ) :+ ("householderTallMultiplyQAdjoint",+ checkForAll+ ((,) <$> Gen.tall <|\|> Gen.matrix) householderTallMultiplyQAdjoint) :+ []
+ test/Test/Permutation.hs view
@@ -0,0 +1,40 @@+module Test.Permutation where++import qualified Numeric.LAPACK.Permutation as Perm+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Permutation (Inversion(Inverted, NonInverted))+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt)+import Numeric.LAPACK.Vector (Vector)++import qualified Data.Array.Comfort.Storable as Array+import Data.Array.Comfort.Storable (Array)++import Foreign.C.Types (CInt)++import Control.Monad (forM)++import qualified Test.QuickCheck as QC+++genPivots :: QC.Gen (Vector ZeroInt CInt)+genPivots = do+ nat <- QC.arbitrary+ let n = length nat+ let nc = fromIntegral n+ fmap (Vector.fromList (zeroInt n)) $+ forM (zip [1..] nat) $ \(i,()) -> QC.choose (i,nc)+++permutationPivots :: Bool -> Array ZeroInt CInt -> Bool+permutationPivots dir xs =+ let inv = if dir then Inverted else NonInverted+ in Array.toList (Perm.toPivots inv (Perm.fromPivots inv (Array.shape xs) xs))+ ==+ Array.toList xs+++tests :: [(String, QC.Property)]+tests =+ ("permutationPivots",+ QC.property $ QC.forAll genPivots . permutationPivots) :+ []
+ test/Test/Shape.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ExistentialQuantification #-}+module Test.Shape where++import Test.Utility (genOrder, prefix)++import qualified Data.Array.Comfort.Shape.Test as ShapeTest+import qualified Data.Array.Comfort.Shape as Shape++import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt)++import qualified Type.Data.Num.Unary as Unary+import Type.Data.Num.Unary (unary)++import Control.Applicative ((<$>))++import qualified Test.QuickCheck as QC+++genGeneral :: QC.Gen (MatrixShape.General ZeroInt ZeroInt)+genGeneral = do+ order <- genOrder+ m <- QC.choose (0,10)+ n <- QC.choose (0,10)+ return $ MatrixShape.general order (zeroInt m) (zeroInt n)++genTall :: QC.Gen (MatrixShape.Tall ZeroInt ZeroInt)+genTall = do+ order <- genOrder+ m <- QC.choose (0,10)+ n <- QC.choose (0,m)+ return $ MatrixShape.tall order (zeroInt m) (zeroInt n)++genWide :: QC.Gen (MatrixShape.Wide ZeroInt ZeroInt)+genWide = do+ order <- genOrder+ m <- QC.choose (0,10)+ n <- QC.choose (m,10)+ return $ MatrixShape.wide order (zeroInt m) (zeroInt n)++genSquare :: QC.Gen (MatrixShape.Square ZeroInt)+genSquare = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.square order (zeroInt n)+++genHermitian :: QC.Gen (MatrixShape.Hermitian ZeroInt)+genHermitian = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.hermitian order (zeroInt n)++genDiagonal :: QC.Gen (MatrixShape.Diagonal ZeroInt)+genDiagonal = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.diagonal order (zeroInt n)++genLowerTriangular ::+ QC.Gen (MatrixShape.LowerTriangular MatrixShape.NonUnit ZeroInt)+genLowerTriangular = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.lowerTriangular order (zeroInt n)++genUpperTriangular ::+ QC.Gen (MatrixShape.UpperTriangular MatrixShape.NonUnit ZeroInt)+genUpperTriangular = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.upperTriangular order (zeroInt n)++genSymmetric :: QC.Gen (MatrixShape.Symmetric ZeroInt)+genSymmetric = do+ order <- genOrder+ n <- QC.choose (0,10)+ return $ MatrixShape.symmetric order (zeroInt n)+++data Banded vert horiz height width =+ forall sub super.+ (Unary.Natural sub, Unary.Natural super) =>+ Banded (MatrixShape.Banded sub super vert horiz height width)++instance+ (Extent.C horiz, Extent.C vert,+ Show height, Show width, Shape.C height, Shape.C width) =>+ Show (Banded vert horiz height width) where+ showsPrec p (Banded sh) = showsPrec p sh++instance+ (Extent.C horiz, Extent.C vert, Shape.C height, Shape.C width) =>+ Shape.C (Banded vert horiz height width) where+ size (Banded sh) = Shape.size sh+ uncheckedSize (Banded sh) = Shape.uncheckedSize sh++instance+ (Extent.C horiz, Extent.C vert,+ Shape.Indexed height, Shape.Indexed width) =>+ Shape.Indexed (Banded vert horiz height width) where+ type Index (Banded vert horiz height width) =+ MatrixShape.BandedIndex (Shape.Index height) (Shape.Index width)+ indices (Banded sh) = Shape.indices sh+ offset (Banded sh) = Shape.offset sh+ uncheckedOffset (Banded sh) = Shape.uncheckedOffset sh+ inBounds (Banded sh) = Shape.inBounds sh++ sizeOffset (Banded sh) = Shape.sizeOffset sh+ uncheckedSizeOffset (Banded sh) = Shape.uncheckedSizeOffset sh++instance+ (Extent.C horiz, Extent.C vert,+ Shape.InvIndexed height, Shape.InvIndexed width) =>+ Shape.InvIndexed (Banded vert horiz height width) where++ indexFromOffset (Banded sh) = Shape.indexFromOffset sh+ uncheckedIndexFromOffset (Banded sh) = Shape.uncheckedIndexFromOffset sh+++genBanded ::+ MatrixShape.Full vert horiz height width ->+ QC.Gen (Banded vert horiz height width)+genBanded sh = do+ kl <- QC.choose (0,10)+ ku <- QC.choose (0,10)+ Unary.reifyNatural kl $ \sub ->+ Unary.reifyNatural ku $ \super ->+ return $ Banded $ MatrixShape.bandedFromFull (unary sub, unary super) sh+++data BandedHermitian size =+ forall offDiag.+ (Unary.Natural offDiag) =>+ BandedHermitian (MatrixShape.BandedHermitian offDiag size)++instance (Show size, Shape.C size) => Show (BandedHermitian size) where+ showsPrec p (BandedHermitian sh) = showsPrec p sh++instance (Shape.C size) => Shape.C (BandedHermitian size) where+ size (BandedHermitian sh) = Shape.size sh+ uncheckedSize (BandedHermitian sh) = Shape.uncheckedSize sh++instance (Shape.Indexed size) => Shape.Indexed (BandedHermitian size) where+ type Index (BandedHermitian size) =+ MatrixShape.BandedIndex (Shape.Index size) (Shape.Index size)+ indices (BandedHermitian sh) = Shape.indices sh+ offset (BandedHermitian sh) = Shape.offset sh+ uncheckedOffset (BandedHermitian sh) = Shape.uncheckedOffset sh+ inBounds (BandedHermitian sh) = Shape.inBounds sh++ sizeOffset (BandedHermitian sh) = Shape.sizeOffset sh+ uncheckedSizeOffset (BandedHermitian sh) = Shape.uncheckedSizeOffset sh++instance+ (Shape.InvIndexed size) => Shape.InvIndexed (BandedHermitian size) where++ indexFromOffset (BandedHermitian sh) =+ Shape.indexFromOffset sh+ uncheckedIndexFromOffset (BandedHermitian sh) =+ Shape.uncheckedIndexFromOffset sh+++genBandedHermitian :: QC.Gen (BandedHermitian ZeroInt)+genBandedHermitian = do+ order <- genOrder+ n <- QC.choose (0,10)+ k <- QC.choose (0,10)+ Unary.reifyNatural k $ \numOff ->+ return $ BandedHermitian $+ MatrixShape.bandedHermitian (unary numOff) order (zeroInt n)+++tests :: [(String, QC.Property)]+tests =+ prefix "General" (ShapeTest.tests genGeneral) +++ prefix "Tall" (ShapeTest.tests genTall) +++ prefix "Wide" (ShapeTest.tests genWide) +++ prefix "Square" (ShapeTest.tests genSquare) ++++ prefix "Split.Reflector.General"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Reflector <$> genGeneral) +++ prefix "Split.Reflector.Tall"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Reflector <$> genTall) +++ prefix "Split.Reflector.Wide"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Reflector <$> genWide) +++ prefix "Split.Reflector.Square"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Reflector <$> genSquare) +++ prefix "Split.Triangle.General"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Triangle <$> genGeneral) +++ prefix "Split.Triangle.Tall"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Triangle <$> genTall) +++ prefix "Split.Triangle.Wide"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Triangle <$> genWide) +++ prefix "Split.Triangle.Square"+ (ShapeTest.tests $+ MatrixShape.splitFromFull MatrixShape.Triangle <$> genSquare) ++++ prefix "Hermitian" (ShapeTest.tests genHermitian) +++ prefix "Diagonal" (ShapeTest.tests genDiagonal) +++ prefix "LowerTriangular" (ShapeTest.tests genLowerTriangular) +++ prefix "UpperTriangular" (ShapeTest.tests genUpperTriangular) +++ prefix "Symmetric" (ShapeTest.tests genSymmetric) ++++ prefix "Banded.General" (ShapeTest.tests $ genBanded =<< genGeneral) +++ prefix "Banded.Tall" (ShapeTest.tests $ genBanded =<< genTall) +++ prefix "Banded.Wide" (ShapeTest.tests $ genBanded =<< genWide) +++ prefix "Banded.Square" (ShapeTest.tests $ genBanded =<< genSquare) +++ prefix "BandedHermitian" (ShapeTest.tests genBandedHermitian) +++ []
+ test/Test/Singular.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE TypeFamilies #-}+module Test.Singular (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<|\|>))+import Test.Utility+ (approxReal, approxArrayTol, approxMatrix, isIdentity, Tagged)++import qualified Numeric.LAPACK.Singular as Singular+import qualified Numeric.LAPACK.Orthogonal as Ortho+import qualified Numeric.LAPACK.Matrix.Hermitian as Herm+import qualified Numeric.LAPACK.Matrix as Matrix+import Numeric.LAPACK.Matrix (General, ZeroInt, (<#>))+import Numeric.LAPACK.Scalar (RealOf, selectReal)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape++import Control.Applicative ((<$>))++import qualified Test.QuickCheck as QC+++pseudoInverseOrtho ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+pseudoInverseOrtho a =+ let (no,invo) = Ortho.pseudoInverseRCond 1e-5 a+ (ns,invs) = Singular.pseudoInverseRCond 1e-5 a+ tol = selectReal 1e-2 1e-5+ in no==ns && approxMatrix tol invo invs++pseudoInverseProjection ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+pseudoInverseProjection a =+ let ainv = snd $ Singular.pseudoInverseRCond 1e-5 a+ tol = selectReal 1e-1 1e-5+ in approxArrayTol tol a (a <#> ainv <#> a) &&+ approxArrayTol tol ainv (ainv <#> a <#> ainv)++pseudoInverseHermitian ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+pseudoInverseHermitian a =+ let ainv = snd $ Singular.pseudoInverseRCond 1e-5 a+ tol = selectReal 1e-2 1e-5+ aainv = a <#> ainv+ ainva = ainv <#> a+ in approxMatrix tol aainv (Matrix.adjoint aainv) &&+ approxMatrix tol ainva (Matrix.adjoint ainva)+++determinantAbsolute ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ General ZeroInt ZeroInt a -> Bool+determinantAbsolute a =+ let detOrtho = Ortho.determinantAbsolute a+ detSing = Singular.determinantAbsolute a+ in approxReal+ (selectReal 1e-3 1e-5 * max 1 (max detOrtho detSing))+ detOrtho detSing+++leastSquaresMinimumNorm ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Matrix.General ZeroInt ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+leastSquaresMinimumNorm (a,b) =+ let (no,xo) = Ortho.leastSquaresMinimumNormRCond 1e-5 a b+ (ns,xs) = Singular.leastSquaresMinimumNormRCond 1e-5 a b+ in no==ns &&+ approxMatrix (selectReal 10 1e-3) xo xs+++decompose ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.General ZeroInt ZeroInt a -> Bool+decompose a =+ let (u,s,vt) = Singular.decompose a+ mn = Shape.size $ Array.shape s+ in approxArrayTol 1e-3 a+ (Matrix.takeColumns mn (Matrix.generalizeWide u) <#>+ Matrix.scaleRowsReal s (Matrix.takeRows mn (Matrix.generalizeTall vt)))+ &&+ isIdentity 1e-3 (Matrix.adjoint u <#> u)+ &&+ isIdentity 1e-3 (Matrix.adjoint vt <#> vt)++decomposeTall ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall ZeroInt ZeroInt a -> Bool+decomposeTall a =+ let (u,s,vt) = Singular.decomposeTall a+ in approxArrayTol 1e-3 a (u <#> Matrix.scaleRowsReal s vt)+ &&+ isIdentity 1e-3 (Herm.toSquare $ Herm.covariance $ Matrix.fromFull u)+ &&+ isIdentity 1e-3 (Matrix.adjoint vt <#> vt)++decomposeWide ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Wide ZeroInt ZeroInt a -> Bool+decomposeWide a =+ let (u,s,vt) = Singular.decomposeWide a+ in approxArrayTol 1e-3 a (u <#> Matrix.scaleRowsReal s vt)+ &&+ isIdentity 1e-3 (Matrix.adjoint u <#> u)+ &&+ isIdentity 1e-3+ (Herm.toSquare $ Herm.covariance $+ Matrix.fromFull $ Matrix.transpose vt)++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 3 5)++testsVar ::+ (Show a, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("pseudoInverseOrtho",+ checkForAll Gen.matrix pseudoInverseOrtho) :+ ("pseudoInverseProjection",+ checkForAll Gen.matrix pseudoInverseProjection) :+ ("pseudoInverseHermitian",+ checkForAll Gen.matrix pseudoInverseHermitian) :+ ("determinantAbsolute",+ checkForAll Gen.matrix determinantAbsolute) :+ ("leastSquaresMinimumNorm",+ checkForAll ((,) <$> Gen.matrix <|\|> Gen.matrix) leastSquaresMinimumNorm) :+ ("decompose",+ checkForAll Gen.matrix decompose) :+ ("decomposeTall",+ checkForAll Gen.tall decomposeTall) :+ ("decomposeWide",+ checkForAll Gen.wide decomposeWide) :+ []
+ test/Test/Square.hs view
@@ -0,0 +1,170 @@+{-# LANGUAGE TypeFamilies #-}+module Test.Square (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<|*|>), (<|\|>))+import Test.Utility (approx, approxArray, approxArrayTol, approxMatrix, Tagged)++import qualified Numeric.LAPACK.Matrix.Triangular as Tri+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Square (Square)+import Numeric.LAPACK.Matrix (ZeroInt, (<#>))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, absolute, selectReal)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array++import Control.Applicative ((<$>))++import Data.Function.HT (nest)++import qualified Test.QuickCheck as QC+++multiplySquare ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+multiplySquare a =+ approxArray (Square.square a) (Square.multiply a a)++multiplyPower ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Int -> Square ZeroInt a -> Bool+multiplyPower n a =+ let b = Square.power (fromIntegral n) a+ c = nest n (Square.multiply a) $ Square.identityFrom a+ in approxArrayTol (1e-6 * (Vector.normInf1 b + Vector.normInf1 c)) b c+++determinantSingleton ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ a -> Bool+determinantSingleton a =+ approx 1e-5 a (Square.determinant $ Square.autoFromList [a])++determinantTranspose ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+determinantTranspose a =+ approx 1e-5+ (Square.determinant a) (Square.determinant $ Square.transpose a)+++multiplyDeterminant ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Square ZeroInt a, Square ZeroInt a) -> Bool+multiplyDeterminant (a,b) =+ let detA = Square.determinant a+ detB = Square.determinant b+ in approx+ (1e-2 * max 1 (absolute detA) * max 1 (absolute detB))+ (Square.determinant (a<#>b))+ (detA * detB)++multiplyInverse ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+multiplyInverse a =+ let eye = Square.inverse a <#> a+ in approxArrayTol 1e-4 eye (Square.identityFrom eye)+++multiplySolve ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Square ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+multiplySolve (a, b) =+ approxMatrix 1e-2 (a <#> Square.solve a b) b++schur ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+schur a =+ let (q,r) = Square.schur a+ in approxMatrix 1e-4 a (q <#> r <#> Square.adjoint q)+++diagonal :: (Class.Floating a) => Vector ZeroInt a -> Tri.Diagonal ZeroInt a+diagonal = Tri.diagonal MatrixShape.ColumnMajor++genDiagonalizable ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Gen.Matrix a Int Int (Square ZeroInt a)+genDiagonalizable = flip Gen.mapGen Gen.invertible $ \ _maxElem a -> do+ d <- Util.genDistinct 3 10 (Square.size a)+ return $ Square.solve a $ diagonal d <#> a+++eigensystem ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+eigensystem a =+ let (vr,d,vl) = Square.eigensystem a+ scal = Array.map recip $ Square.takeDiagonal $ Square.adjoint vl <#> vr+ in approxMatrix (selectReal 1e-1 1e-5)+ (Vector.toComplex a)+ (vr <#> diagonal d <#> diagonal scal <#> Square.adjoint vl)++eigensystemLeft ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+eigensystemLeft a =+ let (_vr,d,vl) = Square.eigensystem a+ vlAdj = Square.adjoint vl+ in approxMatrix (selectReal 1e-1 1e-5)+ (Vector.toComplex a)+ (Square.solve vlAdj $ diagonal d <#> vlAdj)++eigensystemRight ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square ZeroInt a -> Bool+eigensystemRight a =+ let (vr,d,_vl) = Square.eigensystem a+ solveLeft b m =+ Matrix.transpose $+ Square.solve (Matrix.transpose m) (Matrix.transpose b)+ in approxMatrix (selectReal 1e-1 1e-5)+ (Vector.toComplex a)+ (solveLeft (vr <#> diagonal d) vr)++++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 3 5)+++testsVar ::+ (Show a, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("multiplySquare",+ checkForAll Gen.square multiplySquare) :+ ("multiplyPower",+ Gen.withExtra checkForAll (QC.choose (0,10)) Gen.square multiplyPower) :+ ("multiplyInverse",+ checkForAll Gen.invertible multiplyInverse) :+ ("determinantSingleton",+ checkForAll Gen.scalar determinantSingleton) :+ ("determinantTranspose",+ checkForAll Gen.square determinantTranspose) :+ ("multiplyDeterminant",+ checkForAll ((,) <$> Gen.square <|*|> Gen.square) multiplyDeterminant) :+ ("multiplySolve",+ checkForAll ((,) <$> Gen.invertible <|\|> Gen.matrix) multiplySolve) :++ ("schur",+ checkForAll Gen.square schur) :+ ("eigensystem",+ checkForAll genDiagonalizable eigensystem) :+ ("eigensystemLeft",+ checkForAll genDiagonalizable eigensystemLeft) :+ ("eigensystemRight",+ checkForAll genDiagonalizable eigensystemRight) :+ []
+ test/Test/Triangular.hs view
@@ -0,0 +1,404 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE Rank2Types #-}+module Test.Triangular (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Generator ((<.*|>), (<|*.>), (<|*|>), (<|\|>))+import Test.Utility (approx, approxArray, approxArrayTol, approxMatrix, Tagged)++import qualified Numeric.LAPACK.Matrix.Triangular as Triangular+import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Shape as MatrixShape+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import Numeric.LAPACK.Matrix.Triangular (Triangular)+import Numeric.LAPACK.Matrix (General, ZeroInt, (<#), (<#>), (#>))+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, selectReal, absolute)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable ((!))++import Control.Applicative ((<$>))++import Data.Traversable (for)+import Data.Tuple.HT (mapFst)++import qualified Test.QuickCheck as QC+++multiplyIdentityVector ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Vector ZeroInt a) -> Bool+multiplyIdentityVector (eye,a) =+ approxArray a (Triangular.multiplyVector eye a)++multiplyIdentityFull ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, General ZeroInt ZeroInt a) ->+ Bool+multiplyIdentityFull (eye,a) =+ approxArray a (Triangular.multiplyFull eye a)++multiplyIdentity ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Eq lo, Eq diag, Eq up,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Triangular lo diag up ZeroInt a) ->+ Bool+multiplyIdentity (eye,a) =+ approxArray a (Triangular.multiply eye a)++multiplyVector ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Vector ZeroInt a) -> Bool+multiplyVector (a,x) =+ approxArray+ (Triangular.toSquare a #> x)+ (Triangular.multiplyVector a x)++multiply ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Triangular lo diag up ZeroInt a) ->+ Bool+multiply (a,b) =+ approxArray+ (Triangular.toSquare a <#> Triangular.toSquare b)+ (Triangular.toSquare $ Triangular.multiply a b)++multiplyFull ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, General ZeroInt ZeroInt a) ->+ Bool+multiplyFull (a,b) =+ approxArray+ (Triangular.toSquare a <#> b)+ (Triangular.multiplyFull a b)++multiplySquare ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+multiplySquare a =+ approxArray+ (Triangular.toSquare $ Triangular.square a)+ (Triangular.multiplyFull a $ Triangular.toSquare a)++squareSquare ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+squareSquare a =+ approxArray+ (Triangular.toSquare $ Triangular.square a)+ (Square.square $ Triangular.toSquare a)+++multiplyVectorLeft ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Vector ZeroInt a, Triangular lo diag up ZeroInt a) -> Bool+multiplyVectorLeft (x,a) =+ approxArray (x <# Triangular.toSquare a) (x <# a)++multiplyVectorRight ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Vector ZeroInt a) -> Bool+multiplyVectorRight (a,x) =+ approxArray (Triangular.toSquare a #> x) (a #> x)+++multiplyLeft ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (General ZeroInt ZeroInt a, Triangular lo diag up ZeroInt a) -> Bool+multiplyLeft (a,b) =+ approxMatrix 1e-5 (a <#> Triangular.toSquare b) (a <#> b)++multiplyRight ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, General ZeroInt ZeroInt a) -> Bool+multiplyRight (a,b) =+ approxArray (Triangular.toSquare a <#> b) (a <#> b)++++determinant ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+determinant a =+ approx+ (selectReal 1e-1 1e-5)+ (Triangular.determinant a)+ (Square.determinant $ Triangular.toSquare a)+++invertible ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up sh a -> Bool+invertible a = absolute (Triangular.determinant a) > 0.1++genInvertible ::+ (MatrixShape.Content up, MatrixShape.Content lo, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ GenTriangular lo diag up a+genInvertible = Gen.triangularCond invertible++inverse ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+inverse a =+ approxArrayTol+ (selectReal 1 1e-5)+ (Triangular.toSquare $ Triangular.inverse a)+ (Square.inverse $ Triangular.toSquare a)++inverseGeneric ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+inverseGeneric a =+ approxArrayTol+ (selectReal 1 1e-5)+ (Triangular.toSquare $ Triangular.inverseGeneric a)+ (Square.inverse $ Triangular.toSquare a)+++solve ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solve (a, b) =+ approxMatrix (selectReal 1 1e-5)+ (Triangular.solve a b)+ (Square.solve (Triangular.toSquare a) b)++solveIdentity ::+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Triangular lo diag up ZeroInt a, Matrix.General ZeroInt ZeroInt a) -> Bool+solveIdentity (eye, a) =+ approxMatrix (selectReal 1e-3 1e-5)+ a (Triangular.solve eye a)++++eigenvaluesDeterminant ::+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Triangular lo diag up ZeroInt a -> Bool+eigenvaluesDeterminant a =+ approx+ (selectReal 1e-1 1e-5)+ (Triangular.determinant a)+ (Vector.product $ Triangular.eigenvalues a)+++genDiagonalizable ::+ (MatrixShape.Content lo, MatrixShape.Content up,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ GenTriangular lo MatrixShape.NonUnit up a+genDiagonalizable =+ flip Gen.mapGen Gen.squareDim $ \maxElem size -> do+ order <- Util.genOrder+ d <- Util.genDistinct 3 10 size+ let shape =+ MatrixShape.Triangular+ MatrixShape.NonUnit MatrixShape.autoUplo order size+ Array.fromList shape <$>+ (for (Shape.indices shape) $ \(r,c) ->+ if r==c+ then return (d!r)+ else Util.genElement maxElem)++eigensystem ::+ (MatrixShape.DiagUpLo lo up, Eq lo, Eq up,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ MatrixShape.Order -> Triangular lo MatrixShape.NonUnit up ZeroInt a -> Bool+eigensystem order a =+ let (vr,d,vl) = Triangular.eigensystem a+ scal = Triangular.takeDiagonal $ Triangular.multiply vl vr+ in approxMatrix+ (selectReal 1e-3 1e-5)+ (Triangular.toSquare a)+ (Triangular.toSquare $+ vr+ `Triangular.multiply`+ Triangular.diagonal order (Vector.mul d $ Array.map recip scal)+ `Triangular.multiply`+ vl)+++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 3 5)++checkForAllExtra ::+ (Show a, Show b, QC.Testable test, Gen.Required required) =>+ QC.Gen a -> Gen.T tag required actual b ->+ (a -> b -> test) -> Tagged tag QC.Property+checkForAllExtra = Gen.withExtra checkForAll+++type GenTriangular lo diag up a =+ Gen.Matrix a Int Int (Triangular lo diag up ZeroInt a)+++addSuperName :: String -> [(String, a)] -> [(String, a)]+addSuperName superName = map (mapFst ((superName++) . ("."++)))++checkAnyFlexDiag ::+ (MatrixShape.TriDiag diag) =>+ String ->+ (forall lo up.+ (MatrixShape.Content lo, MatrixShape.Content up,+ Eq lo, Eq up, Show lo, Show up) =>+ GenTriangular lo diag up a ->+ Tagged a QC.Property) ->+ (forall lo up.+ (MatrixShape.Content lo, MatrixShape.Content up,+ Eq lo, Eq up, Show lo, Show up) =>+ GenTriangular lo diag up a) ->+ [(String, Tagged a QC.Property)]+checkAnyFlexDiag name checker gen =+ (checkDiagUpLoFlexDiag name checker gen ++) $+ addSuperName name $+ ("Symmetric", checker (Triangular.asSymmetric <$> gen)) :+ []++checkAny ::+ String ->+ (forall lo up diag.+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Eq lo, Eq up, Show lo, Show up, Show diag) =>+ GenTriangular lo diag up a ->+ Tagged a QC.Property) ->+ (forall lo up diag.+ (MatrixShape.Content lo, MatrixShape.Content up, MatrixShape.TriDiag diag,+ Eq lo, Eq up, Show lo, Show up, Show diag) =>+ GenTriangular lo diag up a) ->+ [(String, Tagged a QC.Property)]+checkAny name checker gen =+ checkAnyFlexDiag (name++".Unit") checker+ (Triangular.forceUnitDiagonal <$> gen) +++ checkAnyFlexDiag (name++".NonUnit") checker+ (Triangular.forceNonUnitDiagonal <$> gen)+++checkDiagUpLoFlexDiag ::+ (MatrixShape.TriDiag diag) =>+ String ->+ (forall lo up.+ (MatrixShape.DiagUpLo lo up, Eq lo, Eq up, Show lo, Show up) =>+ GenTriangular lo diag up a ->+ Tagged a QC.Property) ->+ (forall lo up.+ (MatrixShape.DiagUpLo lo up, Eq lo, Eq up, Show lo, Show up) =>+ GenTriangular lo diag up a) ->+ [(String, Tagged a QC.Property)]+checkDiagUpLoFlexDiag name checker gen =+ addSuperName name $+ ("Diagonal", checker (Triangular.asDiagonal <$> gen)) :+ ("Lower", checker (Triangular.asLower <$> gen)) :+ ("Upper", checker (Triangular.asUpper <$> gen)) :+ []++checkDiagUpLo ::+ String ->+ (forall lo up diag.+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Eq lo, Eq diag, Eq up, Show lo, Show diag, Show up) =>+ GenTriangular lo diag up a -> Tagged a QC.Property) ->+ (forall lo up diag.+ (MatrixShape.DiagUpLo lo up, MatrixShape.TriDiag diag,+ Eq lo, Eq diag, Eq up, Show lo, Show diag, Show up) =>+ GenTriangular lo diag up a) ->+ [(String, Tagged a QC.Property)]+checkDiagUpLo name checker gen =+ checkDiagUpLoFlexDiag (name++".Unit") checker+ (Triangular.forceUnitDiagonal <$> gen) +++ checkDiagUpLoFlexDiag (name++".NonUnit") checker+ (Triangular.forceNonUnitDiagonal <$> gen)+++testsVar ::+ (Show a, Show ar, Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ checkAny "multiplyIdentityVector"+ (\gen -> checkForAll ((,) <$> gen <|*.> Gen.vector) multiplyIdentityVector)+ (Triangular.relaxUnitDiagonal <$> Gen.identity) +++ checkAny "multiplyIdentityFull"+ (\gen -> checkForAll ((,) <$> gen <|*|> Gen.matrix) multiplyIdentityFull)+ (Triangular.relaxUnitDiagonal <$> Gen.identity) +++ checkDiagUpLo "multiplyIdentity"+ (\gen -> checkForAll ((,) <$> gen <|*|> Gen.triangular) multiplyIdentity)+ (Triangular.relaxUnitDiagonal <$> Gen.identity) +++ checkAny "multiplyVector"+ (\gen -> checkForAll ((,) <$> gen <|*.> Gen.vector) multiplyVector)+ Gen.triangular +++ checkAny "multiplyFull"+ (\gen -> checkForAll ((,) <$> gen <|*|> Gen.matrix) multiplyFull)+ Gen.triangular +++ checkAny "multiplyVectorLeft"+ (\gen -> checkForAll ((,) <$> Gen.vector <.*|> gen) multiplyVectorLeft)+ Gen.triangular +++ checkAny "multiplyVectorRight"+ (\gen -> checkForAll ((,) <$> gen <|*.> Gen.vector) multiplyVectorRight)+ Gen.triangular +++ checkAny "multiplyLeft"+ (\gen -> checkForAll ((,) <$> Gen.matrix <|*|> gen) multiplyLeft)+ Gen.triangular +++ checkAny "multiplyRight"+ (\gen -> checkForAll ((,) <$> gen <|*|> Gen.matrix) multiplyRight)+ Gen.triangular ++++ checkDiagUpLo "multiply"+ (\gen -> checkForAll ((,) <$> gen <|*|> gen) multiply)+ Gen.triangular +++ checkDiagUpLo "multiplySquare"+ (\gen -> checkForAll gen multiplySquare)+ Gen.triangular +++ checkDiagUpLo "squareSquare"+ (\gen -> checkForAll gen squareSquare)+ Gen.triangular ++++ checkAny "determinant"+ (\gen -> checkForAll gen determinant)+ Gen.triangular +++ checkAny "solve"+ (\gen -> checkForAll ((,) <$> gen <|\|> Gen.matrix) solve)+ genInvertible +++ checkAny "solveIdentity"+ (\gen -> checkForAll ((,) <$> gen <|\|> Gen.matrix) solveIdentity)+ (Triangular.relaxUnitDiagonal <$> Gen.identity) +++ checkDiagUpLo "inverse"+ (\gen -> checkForAll gen inverse)+ genInvertible +++ checkAny "inverseGeneric"+ (\gen -> checkForAll gen inverseGeneric)+ genInvertible ++++ checkDiagUpLo "eigenvaluesDeterminant"+ (\gen -> checkForAll gen eigenvaluesDeterminant)+ Gen.triangular +++ checkDiagUpLoFlexDiag "eigensystem"+ (\gen -> checkForAllExtra Util.genOrder gen eigensystem)+ genDiagonalizable +++ []
+ test/Test/Utility.hs view
@@ -0,0 +1,205 @@+{-# LANGUAGE TypeFamilies #-}+module Test.Utility where++import qualified Numeric.LAPACK.Matrix.Square as Square+import qualified Numeric.LAPACK.Matrix.Extent as Extent+import qualified Numeric.LAPACK.Matrix as Matrix+import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.Orthogonal as Ortho+import Numeric.LAPACK.Matrix.Square (Square)+import Numeric.LAPACK.Matrix.Shape (Order(RowMajor,ColumnMajor))+import Numeric.LAPACK.Matrix (ZeroInt)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf, absolute)++import qualified Numeric.Netlib.Class as Class++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable (Array)++import qualified Control.Monad.Trans.State as MS+import Control.Monad (replicateM)+import Control.Applicative (Applicative, liftA2, pure, (<*>), (<$>))++import qualified Data.List.HT as ListHT+import qualified Data.Complex as Complex+import Data.Complex (Complex((:+)))+import Data.Monoid (Monoid(mempty,mappend))+import Data.Semigroup (Semigroup((<>)))++import qualified Test.QuickCheck as QC+import Test.ChasingBottoms.IsBottom (isBottom)+++equalListWith :: (a -> a -> Bool) -> [a] -> [a] -> Bool+equalListWith eq xs ys =+ and $ ListHT.takeWhileJust $+ zipWith+ (\mx my ->+ case (mx,my) of+ (Nothing,Nothing) -> Nothing+ (Just x, Just y) -> Just $ eq x y+ _ -> Just False)+ (map Just xs ++ repeat Nothing)+ (map Just ys ++ repeat Nothing)+++approx ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) => ar -> a -> a -> Bool+approx tol x y = absolute (x-y) <= tol++approxReal :: (Class.Real a) => a -> a -> a -> Bool+approxReal tol x y = abs (x-y) <= tol+++approxArrayTol ::+ (Shape.C shape, Eq shape, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ ar -> Array shape a -> Array shape a -> Bool+approxArrayTol tol x y =+ if Array.shape x == Array.shape y+ then and $ zipWith (approx tol) (Array.toList x) (Array.toList y)+ else error "approxArray: shapes mismatch"++approxArray ::+ (Shape.C shape, Eq shape, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Array shape a -> Array shape a -> Bool+approxArray = approxArrayTol 1e-5++approxRealArrayTol ::+ (Shape.C shape, Eq shape, Class.Real a) =>+ a -> Array shape a -> Array shape a -> Bool+approxRealArrayTol tol x y =+ if Array.shape x == Array.shape y+ then and $ zipWith (approxReal tol) (Array.toList x) (Array.toList y)+ else error "approxRealArray: shapes mismatch"++approxMatrix ::+ (Extent.C vert, Extent.C horiz,+ Shape.C height, Eq height, Shape.C width, Eq width,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ ar ->+ Matrix.Full vert horiz height width a ->+ Matrix.Full vert horiz height width a -> Bool+approxMatrix tol x y =+ approxArrayTol tol+ (Matrix.toRowMajor $ Matrix.fromFull x)+ (Matrix.toRowMajor $ Matrix.fromFull y)+++genReal :: (Class.Real a) => Integer -> QC.Gen a+genReal n = fromInteger <$> QC.choose (-n,n)++genComplex :: (Class.Real a) => Integer -> QC.Gen (Complex a)+genComplex n = liftA2 (Complex.:+) (genReal n) (genReal n)++genElement :: (Class.Floating a) => Integer -> QC.Gen a+genElement n =+ Class.switchFloating (genReal n) (genReal n) (genComplex n) (genComplex n)++genArray ::+ (Shape.C shape, Class.Floating a) =>+ Integer -> shape -> QC.Gen (Array shape a)+genArray n shape =+ Array.fromList shape <$> replicateM (Shape.size shape) (genElement n)+++select :: [a] -> QC.Gen (a, [a])+select = QC.elements . ListHT.removeEach++genDistinct ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Integer -> Integer -> ZeroInt -> QC.Gen (Vector ZeroInt a)+genDistinct maxElemS maxElemD size@(Shape.ZeroBased n) = do+ let range k = map fromInteger [(-k)..k]+ xs <-+ MS.evalStateT (replicateM n $ MS.StateT select) $+ Class.switchFloating+ (range maxElemS)+ (range maxElemD)+ (liftA2 (:+) (range maxElemS) (range maxElemS))+ (liftA2 (:+) (range maxElemD) (range maxElemD))+ return $ Vector.fromList size xs+++genOrder :: QC.Gen Order+genOrder = QC.elements [RowMajor, ColumnMajor]++++invertible ::+ (Shape.C sh, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Square sh a -> Bool+invertible a = absolute (Square.determinant a) > 0.1++fullRankTall ::+ (Shape.C height, Shape.C width,+ Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Matrix.Tall height width a -> Bool+fullRankTall a = Ortho.determinantAbsolute a > 0.1+++isIdentity ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ ar -> Square ZeroInt a -> Bool+isIdentity tol eye =+ approxArrayTol tol eye (Square.identityFrom eye)++++newtype Tagged tag a = Tagged a+type TaggedGen tag a = Tagged tag (QC.Gen a)++instance Functor (Tagged tag) where+ fmap f (Tagged a) = Tagged (f a)++instance Applicative (Tagged tag) where+ pure = Tagged+ Tagged f <*> Tagged a = Tagged (f a)++++checkForAllPlain ::+ (Show a, QC.Testable test) =>+ TaggedGen tag a -> (a -> test) -> Tagged tag QC.Property+checkForAllPlain (Tagged gen) test = Tagged $ QC.forAll gen test++checkForAll ::+ (Show a, QC.Testable test) =>+ TaggedGen tag (a, Match) -> (a -> test) -> Tagged tag QC.Property+checkForAll taggedGen test =+ checkForAllPlain taggedGen $ \(a,match) ->+ case match of+ Match -> QC.property $ test a+ Mismatch -> QC.property $ isBottom $ test a++{- |+In @DontForceMatch@ mode the test generators+may ignore generating matching dimensions.+If dimensions actually mismatch, a @Mismatch@ value is returned.+In this case the test driver asserts that+the test routine is aborted with an error.+However, a typical test type might be+\"generic implementation = specialized implementation\".+If the generic implementation correctly checks the sizes,+then the tester cannot detect a missing check in the specialized implementation.+So far the proposed way to avoid this problem+is to add a test that relies solely on the function to be tested.+If you have no better idea, compare an implementation with itself.+-}+data Match = Mismatch | Match+ deriving (Eq, Show)++instance Semigroup Match where+ (<>) = mappend++instance Monoid Match where+ mempty = Match+ mappend Match Match = Match+ mappend _ _ = Mismatch++++prefix :: String -> [(String, test)] -> [(String, test)]+prefix msg =+ map (\(str,test) -> (msg ++ "." ++ str, test))
+ test/Test/Vector.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE TypeFamilies #-}+module Test.Vector (testsVar) where++import qualified Test.Generator as Gen+import qualified Test.Utility as Util+import Test.Utility (Tagged(Tagged), TaggedGen)++import qualified Numeric.LAPACK.Vector as Vector+import qualified Numeric.LAPACK.Scalar as Scalar+import Numeric.LAPACK.Matrix (ZeroInt, zeroInt)+import Numeric.LAPACK.Vector (Vector)+import Numeric.LAPACK.Scalar (RealOf)++import qualified Numeric.Netlib.Class as Class++import Control.Applicative (liftA2, (<$>))++import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Shape as Shape+import Data.Array.Comfort.Storable ((!))++import qualified Data.NonEmpty as NonEmpty+import Data.NonEmpty ((!:))++import qualified Test.QuickCheck as QC+import Test.ChasingBottoms.IsBottom (isBottom)+++appendTakeDrop ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Int -> Vector ZeroInt a -> Bool+appendTakeDrop n x =+ Util.approxArray x $+ Array.mapShape (zeroInt . Shape.size)+ (Vector.append (Vector.take n x) (Vector.drop n x))++takeLeftRightAppend ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ (Vector ZeroInt a, Vector ZeroInt a) -> Bool+takeLeftRightAppend (x,y) =+ let xy = Vector.append x y+ in Util.approxArray x (Vector.takeLeft xy)+ &&+ Util.approxArray y (Vector.takeRight xy)+++normInf ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Vector ZeroInt a -> Bool+normInf x =+ Vector.normInf x+ ==+ (NonEmpty.maximum $ 0 !: map Scalar.absolute (Array.toList x))++normInf1 ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Vector ZeroInt a -> Bool+normInf1 x =+ Vector.normInf1 x+ ==+ (NonEmpty.maximum $ 0 !: map Scalar.norm1 (Array.toList x))+++genVector :: (Class.Floating a) => TaggedGen a (Vector ZeroInt a)+genVector = Tagged $ Util.genArray 10 . zeroInt =<< QC.choose (0,5)++normInfAppend ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar, RealOf ar ~ ar) =>+ (Vector ZeroInt a, Vector ZeroInt a) -> Bool+normInfAppend (x,y) =+ Vector.normInf (Vector.append x y)+ ==+ Vector.normInf (Vector.autoFromList [Vector.normInf x, Vector.normInf y])++normInf1Append ::+ (Class.Floating a, RealOf a ~ ar, Class.Real ar, RealOf ar ~ ar) =>+ (Vector ZeroInt a, Vector ZeroInt a) -> Bool+normInf1Append (x,y) =+ Vector.normInf1 (Vector.append x y)+ ==+ Vector.normInf1 (Vector.autoFromList [Vector.normInf1 x, Vector.normInf1 y])+++argAbsMaximum ::+ (Eq a, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Vector ZeroInt a -> Bool+argAbsMaximum xs =+ let kx@(k,x) = Vector.argAbsMaximum xs+ in if Array.shape xs == zeroInt 0+ then isBottom kx+ else xs!k == x && Scalar.absolute x == Vector.normInf xs++argAbs1Maximum ::+ (Eq a, Class.Floating a, RealOf a ~ ar, Class.Real ar) =>+ Vector ZeroInt a -> Bool+argAbs1Maximum xs =+ let kx@(k,x) = Vector.argAbs1Maximum xs+ in if Array.shape xs == zeroInt 0+ then isBottom kx+ else xs!k == x && Scalar.norm1 x == Vector.normInf1 xs+++checkForAll ::+ (Show a, QC.Testable test, Gen.Required required) =>+ Gen.T tag required actual a -> (a -> test) -> Tagged tag QC.Property+checkForAll gen = Util.checkForAll (Gen.run gen 10 5)+++testsVar ::+ (Show a,+ Class.Floating a, Eq a, RealOf a ~ ar, Class.Real ar, RealOf ar ~ ar) =>+ [(String, Tagged a QC.Property)]+testsVar =+ ("appendTakeDrop",+ Gen.withExtra checkForAll+ (QC.getNonNegative <$> QC.arbitrary) Gen.vector appendTakeDrop) :+ ("takeLeftRightAppend",+ Util.checkForAllPlain+ (liftA2 (liftA2 (,)) genVector genVector) takeLeftRightAppend) :+ ("normInf",+ checkForAll Gen.vector normInf) :+ ("normInf1",+ checkForAll Gen.vector normInf1) :+ ("normInfAppend",+ Util.checkForAllPlain+ (liftA2 (liftA2 (,)) genVector genVector) normInfAppend) :+ ("normInf1Append",+ Util.checkForAllPlain+ (liftA2 (liftA2 (,)) genVector genVector) normInf1Append) :+ ("argAbsMaximum",+ checkForAll Gen.vector argAbsMaximum) :+ ("argAbs1Maximum",+ checkForAll Gen.vector argAbs1Maximum) :+ []