module Data.PrimitiveArray.Index.Class where
import Control.Applicative
import Control.DeepSeq (NFData(..))
import Control.Monad (liftM2)
import Data.Aeson
import Data.Binary
import Data.Hashable (Hashable)
import Data.Serialize
import Data.Vector.Fusion.Stream.Monadic (Stream)
import Data.Vector.Unboxed.Deriving
import Data.Vector.Unboxed (Unbox(..))
import GHC.Generics
import qualified Data.Vector.Fusion.Stream.Monadic as SM
import Test.QuickCheck
infixl 3 :.
data a :. b = !a :. !b
deriving (Eq,Ord,Show,Generic)
derivingUnbox "StrictPair"
[t| forall a b . (Unbox a, Unbox b) => (a:.b) -> (a,b) |]
[| \(a:.b) -> (a, b) |]
[| \(a,b) -> (a:.b) |]
instance (Binary a, Binary b) => Binary (a:.b)
instance (Serialize a, Serialize b) => Serialize (a:.b)
instance (ToJSON a, ToJSON b) => ToJSON (a:.b)
instance (FromJSON a, FromJSON b) => FromJSON (a:.b)
instance (Hashable a, Hashable b) => Hashable (a:.b)
deriving instance (Read a, Read b) => Read (a:.b)
instance (NFData a, NFData b) => NFData (a:.b) where
rnf (a:.b) = rnf a `seq` rnf b
instance (Arbitrary a, Arbitrary b) => Arbitrary (a :. b) where
arbitrary = liftM2 (:.) arbitrary arbitrary
shrink (a:.b) = [ (a':.b) | a' <- shrink a ] ++ [ (a:.b') | b' <- shrink b ]
infixr 3 :>
data a :> b = !a :> !b
deriving (Eq,Ord,Show,Generic)
derivingUnbox "StrictIxPair"
[t| forall a b . (Unbox a, Unbox b) => (a:>b) -> (a,b) |]
[| \(a:>b) -> (a, b) |]
[| \(a,b) -> (a:>b) |]
instance (Binary a, Binary b) => Binary (a:>b)
instance (Serialize a, Serialize b) => Serialize (a:>b)
instance (ToJSON a, ToJSON b) => ToJSON (a:>b)
instance (FromJSON a, FromJSON b) => FromJSON (a:>b)
instance (Hashable a, Hashable b) => Hashable (a:>b)
deriving instance (Read a, Read b) => Read (a:>b)
instance (NFData a, NFData b) => NFData (a:>b) where
rnf (a:>b) = rnf a `seq` rnf b
data Z = Z
deriving (Eq,Ord,Read,Show,Generic)
derivingUnbox "Z"
[t| Z -> () |]
[| const () |]
[| const Z |]
instance Binary Z
instance Serialize Z
instance ToJSON Z
instance FromJSON Z
instance Hashable Z
instance Arbitrary Z where
arbitrary = return Z
instance NFData Z where
rnf Z = ()
class Index i where
linearIndex :: i -> i -> i -> Int
smallestLinearIndex :: i -> Int
largestLinearIndex :: i -> Int
size :: i -> i -> Int
inBounds :: i -> i -> i -> Bool
class IndexStream i where
streamUp :: Monad m => i -> i -> Stream m i
default streamUp :: (Monad m, IndexStream (Z:.i)) => i -> i -> Stream m i
streamUp l h = SM.map (\(Z:.i) -> i) $ streamUp (Z:.l) (Z:.h)
streamDown :: Monad m => i -> i -> Stream m i
default streamDown :: (Monad m, IndexStream (Z:.i)) => i -> i -> Stream m i
streamDown l h = SM.map (\(Z:.i) -> i) $ streamDown (Z:.l) (Z:.h)
instance Index Z where
linearIndex _ _ _ = 0
smallestLinearIndex _ = 0
largestLinearIndex _ = 0
size _ _ = 1
inBounds _ _ _ = True
instance IndexStream Z where
streamUp Z Z = SM.singleton Z
streamDown Z Z = SM.singleton Z
instance (Index zs, Index z) => Index (zs:.z) where
linearIndex (ls:.l) (hs:.h) (zs:.z) = linearIndex ls hs zs * (largestLinearIndex h + 1) + linearIndex l h z
smallestLinearIndex (ls:.l) = smallestLinearIndex ls * smallestLinearIndex l
largestLinearIndex (hs:.h) = largestLinearIndex hs * largestLinearIndex h
size (ls:.l) (hs:.h) = size ls hs * (size l h)
inBounds (ls:.l) (hs:.h) (zs:.z) = inBounds ls hs zs && inBounds l h z
instance (Index zs, Index z) => Index (zs:>z) where
linearIndex (ls:>l) (hs:>h) (zs:>z) = linearIndex ls hs zs * (largestLinearIndex h + 1) + linearIndex l h z
smallestLinearIndex (ls:>l) = smallestLinearIndex ls * smallestLinearIndex l
largestLinearIndex (hs:>h) = largestLinearIndex hs * largestLinearIndex h
size (ls:>l) (hs:>h) = size ls hs * (size l h)
inBounds (ls:>l) (hs:>h) (zs:>z) = inBounds ls hs zs && inBounds l h z