{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall #-}
module Data.Primitive.Indexed.Types
( Index
, Length
, Vector
, PrimVector
, ascendM
, descendM
, ascend
, descend
, with
, reflect
, offset
, zero
, unindex
, unlength
) where
import Data.Primitive.Indexed.Unsafe
import GHC.Exts (remInt#,Int(I#))
ascendM :: forall m n a. (Monoid a, Monad m) => (Index n -> m a) -> Length n -> m a
{-# INLINE ascendM #-}
ascendM f (Length n) = go 0 mempty
where
go :: Int -> a -> m a
go !ix !a = if ix < n
then f (Index ix) >>= go (ix + 1)
else pure a
descendM :: forall m n a. (Monoid a, Monad m) => (Index n -> m a) -> Length n -> m a
{-# INLINE descendM #-}
descendM f (Length n) = go (n - 1) mempty
where
go :: Int -> a -> m a
go !ix !a = if ix >= 0
then f (Index ix) >>= go (ix - 1)
else pure a
ascend :: forall n a. (a -> Index n -> a) -> a -> Length n -> a
{-# INLINE ascend #-}
ascend f a0 (Length n) = go 0 a0
where
go :: Int -> a -> a
go !ix !a = if ix < n
then go (ix + 1) (f a (Index ix))
else a
descend :: forall n a. (a -> Index n -> a) -> a -> Length n -> a
{-# INLINE descend #-}
descend f a0 (Length n) = go (n - 1) a0
where
go :: Int -> a -> a
go !ix !a = if ix >= 0
then go (ix - 1) (f a (Index ix))
else a
with :: Int -> (forall n. Index n -> a) -> a
with n f = f (Index (max n 0))
reflect :: Length n -> Index n -> Index n
{-# INLINE reflect #-}
reflect (Length n) (Index i) = Index ((n - i) - 1)
unindex :: Index n -> Int
unindex (Index n) = n
unlength :: Length n -> Int
unlength (Length n) = n
zero :: Index n -> Index n
zero _ = Index 0
offset :: Length n -> Int -> Index n -> Index n
offset (Length len) off (Index ix) = Index (unsafeRem (ix + off) len)
unsafeRem :: Int -> Int -> Int
unsafeRem (I# a) (I# b) = I# (remInt# a b)