brush-strokes-0.1.0.0: src/lib/Math/Linear/Internal.hs
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Math.Linear.Internal
( ℝ(..)
, Fin(..), MFin(..)
, RepDim
, RepresentableQ(..)
, Representable(..)
, set
, projection, injection
)
where
-- base
import Data.Kind
( Type, Constraint )
import Data.List
( intersperse )
import GHC.Generics
( Generic )
import GHC.Show
( showSpace )
import GHC.TypeNats
( Nat, KnownNat )
-- template-haskell
import Language.Haskell.TH
( CodeQ )
-- deepseq
import Control.DeepSeq
( NFData)
--------------------------------------------------------------------------------
-- | Euclidean space \( \mathbb{R}^n \).
type ℝ :: Nat -> Type
data family ℝ n
data instance ℝ 0 = ℝ0
deriving stock ( Show, Eq, Ord, Generic )
deriving anyclass NFData
newtype instance ℝ 1 = ℝ1 { unℝ1 :: Double }
deriving stock ( Generic )
deriving newtype ( Eq, Ord, NFData )
data instance ℝ 2 = ℝ2 { _ℝ2_x, _ℝ2_y :: Double }
deriving stock Generic
deriving anyclass NFData
deriving stock ( Eq, Ord )
data instance ℝ 3 = ℝ3 { _ℝ3_x, _ℝ3_y, _ℝ3_z :: Double }
deriving stock Generic
deriving anyclass NFData
deriving stock ( Eq, Ord )
data instance ℝ 4 = ℝ4 { _ℝ4_x, _ℝ4_y, _ℝ4_z, _ℝ4_w :: Double }
deriving stock Generic
deriving anyclass NFData
deriving stock ( Eq, Ord )
instance Show ( ℝ 1 ) where
showsPrec p ( ℝ1 x )
= showParen ( p >= 11 )
$ showString "ℝ1"
. foldr (.) id ( showSpace : intersperse showSpace coords )
where
coords = map ( showsPrec 0 ) [ x ]
instance Show ( ℝ 2 ) where
showsPrec p ( ℝ2 x y )
= showParen ( p >= 11 )
$ showString "ℝ2"
. foldr (.) id ( showSpace : intersperse showSpace coords )
where
coords = map ( showsPrec 0 ) [ x, y ]
instance Show ( ℝ 3 ) where
showsPrec p ( ℝ3 x y z )
= showParen ( p >= 11 )
$ showString "ℝ3"
. foldr (.) id ( showSpace : intersperse showSpace coords )
where
coords = map ( showsPrec 0 ) [ x, y, z ]
instance Show ( ℝ 4 ) where
showsPrec p ( ℝ4 x y z w )
= showParen ( p >= 11 )
$ showString "ℝ4"
. foldr (.) id ( showSpace : intersperse showSpace coords )
where
coords = map ( showsPrec 0 ) [ x, y, z, w ]
--------------------------------------------------------------------------------
-- | 1, ..., n
type Fin :: Nat -> Type
newtype Fin n = Fin Word
deriving stock ( Eq, Ord, Show )
-- | 0, ..., n
type MFin :: Nat -> Type
newtype MFin n = MFin Word
type RepDim :: k -> Nat
type family RepDim v
type RepresentableQ :: Type -> Type -> Constraint
class RepresentableQ r v | v -> r where
tabulateQ :: ( Fin ( RepDim v ) -> CodeQ r ) -> CodeQ v
indexQ :: CodeQ v -> Fin ( RepDim v ) -> CodeQ r
type Representable :: Type -> Type -> Constraint
class KnownNat ( RepDim v ) => Representable r v | v -> r where
tabulate :: ( Fin ( RepDim v ) -> r ) -> v
index :: v -> Fin ( RepDim v ) -> r
set :: Representable r v => Fin ( RepDim v ) -> r -> v -> v
set i r u = tabulate \ j ->
if i == j
then r
else index u j
{-# INLINEABLE set #-}
projection :: ( Representable r u, Representable r v )
=> ( Fin ( RepDim v ) -> Fin ( RepDim u ) )
-> u -> v
projection f = \ u ->
tabulate \ i -> index u ( f i )
{-# INLINEABLE projection #-}
injection :: ( Representable r u, Representable r v )
=> ( Fin ( RepDim v ) -> MFin ( RepDim u ) )
-> u -> v -> v
injection f = \ u v ->
tabulate \ i -> case f i of
MFin 0 -> index v i
MFin j -> index u ( Fin j )
{-# INLINEABLE injection #-}
--------------------------------------------------------------------------------
type instance RepDim ( ℝ n ) = n
instance RepresentableQ Double ( ℝ 0 ) where
tabulateQ _ = [|| ℝ0 ||]
indexQ _ _ = [|| 0 ||]
instance RepresentableQ Double ( ℝ 1 ) where
tabulateQ f = [|| ℝ1 $$( f ( Fin 1 ) ) ||]
indexQ p = \ case
_ -> [|| unℝ1 $$p ||]
instance RepresentableQ Double ( ℝ 2 ) where
tabulateQ f = [|| ℝ2 $$( f ( Fin 1 ) ) $$( f ( Fin 2 ) ) ||]
indexQ p = \ case
Fin 1 -> [|| _ℝ2_x $$p ||]
_ -> [|| _ℝ2_y $$p ||]
instance RepresentableQ Double ( ℝ 3 ) where
tabulateQ f = [|| ℝ3 $$( f ( Fin 1 ) ) $$( f ( Fin 2 ) ) $$( f ( Fin 3 ) ) ||]
indexQ p = \ case
Fin 1 -> [|| _ℝ3_x $$p ||]
Fin 2 -> [|| _ℝ3_y $$p ||]
_ -> [|| _ℝ3_z $$p ||]
instance RepresentableQ Double ( ℝ 4 ) where
tabulateQ f = [|| ℝ4 $$( f ( Fin 1 ) ) $$( f ( Fin 2 ) ) $$( f ( Fin 3 ) ) $$( f ( Fin 4 ) ) ||]
indexQ p = \ case
Fin 1 -> [|| _ℝ4_x $$p ||]
Fin 2 -> [|| _ℝ4_y $$p ||]
Fin 3 -> [|| _ℝ4_z $$p ||]
_ -> [|| _ℝ4_w $$p ||]
instance Representable Double ( ℝ 0 ) where
tabulate _ = ℝ0
{-# INLINE tabulate #-}
index _ _ = 0
{-# INLINE index #-}
instance Representable Double ( ℝ 1 ) where
tabulate f = ℝ1 ( f ( Fin 1 ) )
{-# INLINE tabulate #-}
index p = \ case
_ -> unℝ1 p
{-# INLINE index #-}
instance Representable Double ( ℝ 2 ) where
tabulate f = ℝ2 ( f ( Fin 1 ) ) ( f ( Fin 2 ) )
{-# INLINE tabulate #-}
index p = \ case
Fin 1 -> _ℝ2_x p
_ -> _ℝ2_y p
{-# INLINE index #-}
instance Representable Double ( ℝ 3 ) where
tabulate f = ℝ3 ( f ( Fin 1 ) ) ( f ( Fin 2 ) ) ( f ( Fin 3 ) )
{-# INLINE tabulate #-}
index p = \ case
Fin 1 -> _ℝ3_x p
Fin 2 -> _ℝ3_y p
_ -> _ℝ3_z p
{-# INLINE index #-}
instance Representable Double ( ℝ 4 ) where
tabulate f = ℝ4 ( f ( Fin 1 ) ) ( f ( Fin 2 ) ) ( f ( Fin 3 ) ) ( f ( Fin 4 ) )
{-# INLINE tabulate #-}
index p = \ case
Fin 1 -> _ℝ4_x p
Fin 2 -> _ℝ4_y p
Fin 3 -> _ℝ4_z p
_ -> _ℝ4_w p
{-# INLINE index #-}