{-# LANGUAGE TypeFamilies #-}
module Data.Array.Comfort.Shape.Static where

import qualified Data.FixedLength as FL

import qualified Data.Array.Comfort.Storable as Array
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable (Array)

import qualified Type.Data.Num.Unary as Unary
import Type.Data.Num (integralFromProxy)
import Type.Base.Proxy (Proxy(Proxy))

import Foreign.Storable (Storable)


{- $setup
>>> import qualified Data.Array.Comfort.Shape.Static as Static
>>> import qualified Data.Array.Comfort.Shape as Shape
>>>
>>> import qualified Type.Data.Num.Unary.Literal as TypeNum
>>> import qualified Type.Data.Num.Unary as Unary
-}


{- |
'ZeroBased' denotes a range starting at zero and has a certain length.

>>> Shape.indices (Static.ZeroBased (Unary.unary TypeNum.u0))
[]
>>> Shape.indices (Static.ZeroBased (Unary.unary TypeNum.u1))
[i0]
>>> Shape.indices (Static.ZeroBased (Unary.unary TypeNum.u7))
[i0,i1,i2,i3,i4,i5,i6]
-}
newtype ZeroBased n = ZeroBased {ZeroBased n -> Proxy (Un n)
zeroBasedSize :: Proxy (Unary.Un n)}
   deriving (ZeroBased n -> ZeroBased n -> Bool
(ZeroBased n -> ZeroBased n -> Bool)
-> (ZeroBased n -> ZeroBased n -> Bool) -> Eq (ZeroBased n)
forall n. ZeroBased n -> ZeroBased n -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ZeroBased n -> ZeroBased n -> Bool
$c/= :: forall n. ZeroBased n -> ZeroBased n -> Bool
== :: ZeroBased n -> ZeroBased n -> Bool
$c== :: forall n. ZeroBased n -> ZeroBased n -> Bool
Eq, Int -> ZeroBased n -> ShowS
[ZeroBased n] -> ShowS
ZeroBased n -> String
(Int -> ZeroBased n -> ShowS)
-> (ZeroBased n -> String)
-> ([ZeroBased n] -> ShowS)
-> Show (ZeroBased n)
forall n. Natural n => Int -> ZeroBased n -> ShowS
forall n. Natural n => [ZeroBased n] -> ShowS
forall n. Natural n => ZeroBased n -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ZeroBased n] -> ShowS
$cshowList :: forall n. Natural n => [ZeroBased n] -> ShowS
show :: ZeroBased n -> String
$cshow :: forall n. Natural n => ZeroBased n -> String
showsPrec :: Int -> ZeroBased n -> ShowS
$cshowsPrec :: forall n. Natural n => Int -> ZeroBased n -> ShowS
Show)

instance (Unary.Natural n) => Shape.C (ZeroBased n) where
   size :: ZeroBased n -> Int
size (ZeroBased Proxy (Un n)
len) = Proxy (Un n) -> Int
forall x y. (Integer x, Num y) => Proxy x -> y
integralFromProxy Proxy (Un n)
len

instance (Unary.Natural n) => Shape.Indexed (ZeroBased n) where
   type Index (ZeroBased n) = FL.Index n
   indices :: ZeroBased n -> [Index (ZeroBased n)]
indices ZeroBased n
_len = T n (Index n) -> [Index n]
forall n a. Natural n => T n a -> [a]
FL.toList T n (Index n)
forall n. Natural n => T n (Index n)
FL.indices
   unifiedOffset :: ZeroBased n -> Index (ZeroBased n) -> Result check Int
unifiedOffset ZeroBased n
_len = Int -> Result check Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Result check Int)
-> (Index n -> Int) -> Index n -> Result check Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> (Index n -> Word) -> Index n -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index n -> Word
forall n. Natural n => Index n -> Word
FL.numFromIndex
   inBounds :: ZeroBased n -> Index (ZeroBased n) -> Bool
inBounds ZeroBased n
_len Index (ZeroBased n)
_ix = Bool
True

instance (Unary.Natural n) => Shape.InvIndexed (ZeroBased n) where
   -- could be implemented using new fixed-length-0.2.1:FL.indexFromNum
   unifiedIndexFromOffset :: ZeroBased n -> Int -> Result check (Index (ZeroBased n))
unifiedIndexFromOffset ZeroBased n
len Int
k =
      case (Int
0Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
k, Int -> [Index n] -> [Index n]
forall a. Int -> [a] -> [a]
drop Int
k ([Index n] -> [Index n]) -> [Index n] -> [Index n]
forall a b. (a -> b) -> a -> b
$ ZeroBased n -> [Index (ZeroBased n)]
forall sh. Indexed sh => sh -> [Index sh]
Shape.indices ZeroBased n
len) of
         (Bool
True, Index n
i:[Index n]
_) -> Index n -> Result check (Index n)
forall (m :: * -> *) a. Monad m => a -> m a
return Index n
i
         (Bool, [Index n])
_ ->
            String -> Result check (Index n)
forall check a. Checking check => String -> Result check a
Shape.throwOrError (String -> Result check (Index n))
-> String -> Result check (Index n)
forall a b. (a -> b) -> a -> b
$
            String -> Int -> String
Shape.messageIndexFromOffset String
"ShapeStatic.ZeroBased" Int
k

instance (Unary.Natural n) => Shape.Static (ZeroBased n) where
   static :: ZeroBased n
static = Proxy (Un n) -> ZeroBased n
forall n. Proxy (Un n) -> ZeroBased n
ZeroBased Proxy (Un n)
forall a. Proxy a
Proxy


vector :: (Unary.Natural n, Storable a) => FL.T n a -> Array (ZeroBased n) a
vector :: T n a -> Array (ZeroBased n) a
vector = ZeroBased n -> [a] -> Array (ZeroBased n) a
forall sh a. (C sh, Storable a) => sh -> [a] -> Array sh a
Array.fromList (Proxy (Un n) -> ZeroBased n
forall n. Proxy (Un n) -> ZeroBased n
ZeroBased Proxy (Un n)
forall a. Proxy a
Proxy) ([a] -> Array (ZeroBased n) a)
-> (T n a -> [a]) -> T n a -> Array (ZeroBased n) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T n a -> [a]
forall n a. Natural n => T n a -> [a]
FL.toList