{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-} {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Matrix.TriBase -- Copyright : Copyright (c) , Patrick Perry -- License : BSD3 -- Maintainer : Patrick Perry -- Stability : experimental -- module Data.Matrix.TriBase where import Unsafe.Coerce import Data.Matrix.Class import Data.Tensor.Class import BLAS.Types ( UpLoEnum(..), DiagEnum(..), flipUpLo ) -- | A triangular or trapezoidal view of an underlying matrix. The view -- can either be of the upper or lower triangular part of the matrix, and -- can optionally include or exclude the diagonal. If the diagonal enum -- is @Unit@, the diagonal entries of the underlying matrix are not -- referenced, but are assumed to be @1@. The type arguments are as follows: -- -- * @a@: the underlyting matrix type. -- -- * @np@: a phantom type for the shape of the view. -- -- * @e@: the element type of the matrix. -- data Tri a np e = Tri UpLoEnum DiagEnum (a np e) -- | Cast the phantom shape type. coerceTri :: Tri a np e -> Tri a np' e coerceTri = unsafeCoerce -- | Apply a function to the base matrix. mapTri :: (a np e -> b np' e) -> Tri a np e -> Tri b np' e mapTri f (Tri u d a) = Tri u d $ f a -- | Convert from a base matrix type to a triangular view. triFromBase :: UpLoEnum -> DiagEnum -> a (n,p) e -> Tri a (n,p) e triFromBase = Tri -- | Convert from a triangular view to the base matrix. triToBase :: Tri a (n,p) e -> (UpLoEnum, DiagEnum, a (n,p) e) triToBase (Tri u d a) = (u,d,a) -- | Get a lower triangular view of a matrix. lower :: (MatrixShaped a) => a (n,p) e -> Tri a (n,p) e lower = Tri Lower NonUnit -- | Get a lower triangular view of a matrix, with unit diagonal. lowerU :: (MatrixShaped a) => a (n,p) e -> Tri a (n,p) e lowerU = Tri Lower Unit -- | Get an upper triangular view of a matrix. upper :: (MatrixShaped a) => a (n,p) e -> Tri a (n,p) e upper = Tri Upper NonUnit -- | Get an upper triangular view of a matrix, with unit diagonal. upperU :: (MatrixShaped a) => a (n,p) e -> Tri a (n,p) e upperU = Tri Upper Unit instance (MatrixShaped a) => Shaped (Tri a) (Int,Int) where shape (Tri Lower _ a) = (numRows a, min (numRows a) (numCols a)) shape (Tri Upper _ a) = (min (numRows a) (numCols a), numCols a) {-# INLINE shape #-} bounds a = ((0,0),(m-1,n-1)) where (m,n) = shape a {-# INLINE bounds #-} instance (MatrixShaped a) => MatrixShaped (Tri a) where herm (Tri u d a) = Tri (flipUpLo u) d (herm a) {-# INLINE herm #-} instance (Show (a (n,p) e), MatrixShaped a) => Show (Tri a (n,p) e) where show (Tri u d a) = constructor ++ suffix ++ " (" ++ show a ++ ")" where constructor = case (u,d) of (Lower, NonUnit) -> "lower" (Lower, Unit ) -> "lowerU" (Upper, NonUnit) -> "upper" (Upper, Unit ) -> "upperU" suffix = case undefined of _ | isSquare a -> "" _ | isFat a -> "Fat" _ -> "Tall"