i-0.1: hs/I/Int8.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_HADDOCK not-home #-}
module I.Int8 () where
import Control.Monad
import Data.Constraint
import Data.Int
import Data.Maybe
import Data.Proxy
import Data.Type.Ord
import Foreign.C.Types
import KindInteger (type (/=), type (==))
import KindInteger qualified as K
import Prelude hiding (min, max, div)
import Prelude qualified as P
import I.Internal
--------------------------------------------------------------------------------
-- | This is so that GHC doesn't complain about the unused modules,
-- which we import here so that `genmodules.sh` doesn't have to add it
-- to the generated modules.
_ignore :: (CSize, Int)
_ignore = (0, 0)
--------------------------------------------------------------------------------
type instance MinL Int8 = MinT Int8
type instance MaxR Int8 = MaxT Int8
instance forall (l :: K.Integer) (r :: K.Integer).
( IntervalCtx Int8 l r
) => Interval Int8 l r where
type IntervalCtx Int8 l r =
( K.KnownInteger l
, K.KnownInteger r
, MinT Int8 <= l
, l <= r
, r <= MaxT Int8 )
type MinI Int8 l r = l
type MaxI Int8 l r = r
inhabitant = min
from = \x -> unsafest x <$ guard (l <= x && x <= r)
where l = fromInteger (K.integerVal (Proxy @l)) :: Int8
r = fromInteger (K.integerVal (Proxy @r)) :: Int8
negate' (unwrap -> x) = do
guard (x /= minBound)
from (P.negate x)
(unwrap -> a) `plus'` (unwrap -> b)
| b > 0 && a > maxBound - b = Nothing
| b < 0 && a < minBound - b = Nothing
| otherwise = from (a + b)
(unwrap -> a) `mult'` (unwrap -> b) = do
guard $ case a <= 0 of
True | b <= 0 -> a == 0 || b >= (maxBound `quot` a)
| otherwise -> a >= (minBound `quot` b)
False | b <= 0 -> b >= (minBound `quot` a)
| otherwise -> a <= (maxBound `quot` b)
from (a * b)
(unwrap -> a) `minus'` (unwrap -> b)
| b > 0 && a < minBound + b = Nothing
| b < 0 && a > maxBound + b = Nothing
| otherwise = from (a - b)
(unwrap -> a) `div'` (unwrap -> b) = do
guard (b /= 0 && (b /= -1 || a /= minBound))
let (q, m) = divMod a b
guard (m == 0)
from q
instance (Interval Int8 l r) => Clamp Int8 l r
instance (Interval Int8 ld rd, Interval Int8 lu ru, lu <= ld, rd <= ru)
=> Up Int8 ld rd lu ru
instance forall l r t.
( Interval Int8 l r, KnownCtx Int8 l r t
) => Known Int8 l r t where
type KnownCtx Int8 l r t = (K.KnownInteger t, l <= t, t <= r)
known' = unsafe . fromInteger . K.integerVal
instance forall l r. (Interval Int8 l r) => With Int8 l r where
with x g = case K.someIntegerVal (toInteger (unwrap x)) of
K.SomeInteger (pt :: Proxy t) ->
fromMaybe (error "I.with: impossible") $ do
Dict <- leInteger @l @t
Dict <- leInteger @t @r
pure (g pt)
instance (Interval Int8 l r, l /= r) => Discrete Int8 l r where
pred' i = unsafe (unwrap i - 1) <$ guard (min < i)
succ' i = unsafe (unwrap i + 1) <$ guard (i < max)
instance (Zero Int8 l r, l == K.Negate r) => Negate Int8 l r where
negate = unsafe . P.negate . unwrap
instance (Interval Int8 l r, l <= K.P 0, K.P 0 <= r) => Zero Int8 l r where
zero = unsafe 0
instance (Interval Int8 l r, l <= K.P 1, K.P 1 <= r) => One Int8 l r where
one = unsafe 1
instance forall l r. (Interval Int8 l r) => Shove Int8 l r where
shove = \x -> fromMaybe (error "shove(Int8): impossible") $
from $ fromInteger (mod (toInteger x) (r - l + 1) + l)
where l = toInteger (unwrap (min @Int8 @l @r))
r = toInteger (unwrap (max @Int8 @l @r))