module Biobase.Types.Index
( module Biobase.Types.Index
, getIndex
, index
, maybeIndex
, Index
) where
import Data.Coerce
import Data.Proxy
import GHC.TypeLits
import Text.Printf
import Biobase.Types.Index.Type
import qualified Biobase.Types.Index.Type as IT
checkIndex :: forall t . KnownNat t => Index t -> Index t
checkIndex i@(Index z)
| z >= 0 = i
| otherwise = error $ printf "%d < Index %d\n" (z+n) n
where n :: Int = fromIntegral $ natVal (Proxy :: Proxy t)
{-# Inline checkIndex #-}
reIndex ∷ Index n → Index m
{-# Inline reIndex #-}
reIndex = coerce
(+.) :: forall t . KnownNat t => Index t -> Int -> Index t
(+.) i n = checkIndex $ unsafePlus i n
{-# Inline (+.) #-}
(-.) :: forall t . KnownNat t => Index t -> Int -> Index t
(-.) i n = checkIndex $ unsafePlus i (negate n)
{-# Inline (-.) #-}
unsafePlus :: forall t . KnownNat t => Index t -> Int -> Index t
unsafePlus i n = Index $ IT.getIndex i + n
{-# Inline unsafePlus #-}
delta :: forall t . KnownNat t => Index t -> Index t -> Int
delta i j = abs . IT.getIndex $ i - j
{-# Inline delta #-}
toInt ∷ forall t . KnownNat t ⇒ Index t → Int
{-# Inline toInt #-}
toInt i = IT.getIndex i + (fromIntegral $ natVal (Proxy ∷ Proxy t))
toInt0 :: forall t . KnownNat t => Index t -> Int
toInt0 = IT.getIndex
{-# Inline toInt0 #-}
fromInt0 :: forall t . KnownNat t => Int -> Index t
fromInt0 i
| i >= 0 = Index i
| otherwise = error "fromInt0 needs an Int >= 0"
where t = fromIntegral $ natVal (Proxy :: Proxy t)
{-# Inline fromInt0 #-}
type I0 = Index 0
type I1 = Index 1