{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- Provide a 12-bit unsigned integral type: 'Word12', analagous to Word8,
-- Word16, etc.
--

{- |
Module      : Data.Word.Word12
License     : see  src/Data/LICENSE
Stability   : experimental
Portability : non-portable (GHC Extensions)
-}
module Data.Word.Synthetic.Word12
  ( -- * Word12 type
    Word12 (..)

    -- * Internal helpers
  , narrow12Word#
  , clz12#
  , ctz12#
  , popCnt12#
  )
where

import Data.Bits
import Data.Data
import Data.Maybe

import GHC.Arr
import GHC.Base
import GHC.Enum
#if MIN_VERSION_base(4,15,0)
import           GHC.Integer (integerToWord, smallInteger)
import           GHC.Num hiding (integerToWord)
#else
import           GHC.Num
#endif
import GHC.Read
import GHC.Real
import GHC.Show

import qualified GHC.Word.Compat as Compat

------------------------------------------------------------------------

-- Word12 is represented in the same way as Word.  Operations may assume and
-- must ensure that it holds only values in its logical range.

-- | 12-bit unsigned integer type
data Word12 = W12# Word# deriving (Word12 -> Word12 -> Bool
(Word12 -> Word12 -> Bool)
-> (Word12 -> Word12 -> Bool) -> Eq Word12
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Word12 -> Word12 -> Bool
== :: Word12 -> Word12 -> Bool
$c/= :: Word12 -> Word12 -> Bool
/= :: Word12 -> Word12 -> Bool
Eq, Eq Word12
Eq Word12 =>
(Word12 -> Word12 -> Ordering)
-> (Word12 -> Word12 -> Bool)
-> (Word12 -> Word12 -> Bool)
-> (Word12 -> Word12 -> Bool)
-> (Word12 -> Word12 -> Bool)
-> (Word12 -> Word12 -> Word12)
-> (Word12 -> Word12 -> Word12)
-> Ord Word12
Word12 -> Word12 -> Bool
Word12 -> Word12 -> Ordering
Word12 -> Word12 -> Word12
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Word12 -> Word12 -> Ordering
compare :: Word12 -> Word12 -> Ordering
$c< :: Word12 -> Word12 -> Bool
< :: Word12 -> Word12 -> Bool
$c<= :: Word12 -> Word12 -> Bool
<= :: Word12 -> Word12 -> Bool
$c> :: Word12 -> Word12 -> Bool
> :: Word12 -> Word12 -> Bool
$c>= :: Word12 -> Word12 -> Bool
>= :: Word12 -> Word12 -> Bool
$cmax :: Word12 -> Word12 -> Word12
max :: Word12 -> Word12 -> Word12
$cmin :: Word12 -> Word12 -> Word12
min :: Word12 -> Word12 -> Word12
Ord)

word12Type :: DataType
word12Type :: DataType
word12Type = String -> DataType
mkIntType String
"Data.Word.Synthetic.Word12.Word12"

instance Data Word12 where
  toConstr :: Word12 -> Constr
toConstr Word12
x = DataType -> Word12 -> Constr
forall a. (Integral a, Show a) => DataType -> a -> Constr
mkIntegralConstr DataType
word12Type Word12
x
  gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Word12
gunfold forall b r. Data b => c (b -> r) -> c r
_ forall r. r -> c r
z Constr
c = case Constr -> ConstrRep
constrRep Constr
c of
    (IntConstr Integer
x) -> Word12 -> c Word12
forall r. r -> c r
z (Integer -> Word12
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
x)
    ConstrRep
_ ->
      String -> c Word12
forall a. HasCallStack => String -> a
error (String -> c Word12) -> String -> c Word12
forall a b. (a -> b) -> a -> b
$
        String
"Data.Data.gunfold: Constructor "
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ Constr -> String
forall a. Show a => a -> String
show Constr
c
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not of type Word12."
  dataTypeOf :: Word12 -> DataType
dataTypeOf Word12
_ = DataType
word12Type

-- | narrowings represented as primop 'and#' in GHC.
narrow12Word# :: Word# -> Word#
narrow12Word# :: Word# -> Word#
narrow12Word# = Word# -> Word# -> Word#
and# Word#
0xFFF##

-- | count leading zeros
clz12# :: Word# -> Word#
clz12# :: Word# -> Word#
clz12# Word#
w# = Word# -> Word#
clz32# (Word# -> Word#
narrow12Word# Word#
w#) Word# -> Word# -> Word#
`minusWord#` Word#
20##

-- | count trailing zeros
ctz12# :: Word# -> Word#
ctz12# :: Word# -> Word#
ctz12# Word#
w# = Word# -> Word#
ctz# Word#
w#

-- | the number of set bits
popCnt12# :: Word# -> Word#
popCnt12# :: Word# -> Word#
popCnt12# Word#
w# = Word# -> Word#
popCnt# (Word# -> Word#
narrow12Word# Word#
w#)

instance Show Word12 where
  showsPrec :: Int -> Word12 -> String -> String
showsPrec Int
p Word12
x = Int -> Int -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
p (Word12 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word12
x :: Int)

instance Num Word12 where
  (W12# Word#
x#) + :: Word12 -> Word12 -> Word12
+ (W12# Word#
y#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Word# -> Word#
`plusWord#` Word#
y#))
  (W12# Word#
x#) - :: Word12 -> Word12 -> Word12
- (W12# Word#
y#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Word# -> Word#
`minusWord#` Word#
y#))
  (W12# Word#
x#) * :: Word12 -> Word12 -> Word12
* (W12# Word#
y#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Word# -> Word#
`timesWord#` Word#
y#))
  negate :: Word12 -> Word12
negate (W12# Word#
x#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Int# -> Word#
int2Word# (Int# -> Int#
negateInt# (Word# -> Int#
word2Int# Word#
x#))))
  abs :: Word12 -> Word12
abs Word12
x = Word12
x
  signum :: Word12 -> Word12
signum Word12
0 = Word12
0
  signum Word12
_ = Word12
1
  fromInteger :: Integer -> Word12
fromInteger Integer
i = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Integer -> Word#
integerToWord Integer
i))

instance Real Word12 where
  toRational :: Word12 -> Rational
toRational Word12
x = Word12 -> Integer
forall a. Integral a => a -> Integer
toInteger Word12
x Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1

instance Enum Word12 where
  succ :: Word12 -> Word12
succ Word12
x
    | Word12
x Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
forall a. Bounded a => a
maxBound = Word12
x Word12 -> Word12 -> Word12
forall a. Num a => a -> a -> a
+ Word12
1
    | Bool
otherwise = String -> Word12
forall a. String -> a
succError String
"Word12"
  pred :: Word12 -> Word12
pred Word12
x
    | Word12
x Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
forall a. Bounded a => a
minBound = Word12
x Word12 -> Word12 -> Word12
forall a. Num a => a -> a -> a
- Word12
1
    | Bool
otherwise = String -> Word12
forall a. String -> a
predError String
"Word12"
  toEnum :: Int -> Word12
toEnum i :: Int
i@(I# Int#
i#)
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Word12 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word12
forall a. Bounded a => a
maxBound :: Word12) =
        Word# -> Word12
W12# (Int# -> Word#
int2Word# Int#
i#)
    | Bool
otherwise = String -> Int -> (Word12, Word12) -> Word12
forall a b. Show a => String -> Int -> (a, a) -> b
toEnumError String
"Word12" Int
i (Word12
forall a. Bounded a => a
minBound :: Word12, Word12
forall a. Bounded a => a
maxBound :: Word12)
  fromEnum :: Word12 -> Int
fromEnum (W12# Word#
x#) = Int# -> Int
I# (Word# -> Int#
word2Int# Word#
x#)
  enumFrom :: Word12 -> [Word12]
enumFrom = Word12 -> [Word12]
forall a. (Enum a, Bounded a) => a -> [a]
boundedEnumFrom
  enumFromThen :: Word12 -> Word12 -> [Word12]
enumFromThen = Word12 -> Word12 -> [Word12]
forall a. (Enum a, Bounded a) => a -> a -> [a]
boundedEnumFromThen

instance Integral Word12 where
  quot :: Word12 -> Word12 -> Word12
quot (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`quotWord#` Word#
y#)
    | Bool
otherwise = Word12
forall a. a
divZeroError
  rem :: Word12 -> Word12 -> Word12
rem (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`remWord#` Word#
y#)
    | Bool
otherwise = Word12
forall a. a
divZeroError
  div :: Word12 -> Word12 -> Word12
div (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`quotWord#` Word#
y#)
    | Bool
otherwise = Word12
forall a. a
divZeroError
  mod :: Word12 -> Word12 -> Word12
mod (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`remWord#` Word#
y#)
    | Bool
otherwise = Word12
forall a. a
divZeroError
  quotRem :: Word12 -> Word12 -> (Word12, Word12)
quotRem (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = (Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`quotWord#` Word#
y#), Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`remWord#` Word#
y#))
    | Bool
otherwise = (Word12, Word12)
forall a. a
divZeroError
  divMod :: Word12 -> Word12 -> (Word12, Word12)
divMod (W12# Word#
x#) y :: Word12
y@(W12# Word#
y#)
    | Word12
y Word12 -> Word12 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word12
0 = (Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`quotWord#` Word#
y#), Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`remWord#` Word#
y#))
    | Bool
otherwise = (Word12, Word12)
forall a. a
divZeroError
  toInteger :: Word12 -> Integer
toInteger (W12# Word#
x#) = Int# -> Integer
smallInteger (Word# -> Int#
word2Int# Word#
x#)

instance Bounded Word12 where
  minBound :: Word12
minBound = Word12
0
  maxBound :: Word12
maxBound = Word12
0xFFFFFF

instance Ix Word12 where
  range :: (Word12, Word12) -> [Word12]
range (Word12
m, Word12
n) = [Word12
m .. Word12
n]
  unsafeIndex :: (Word12, Word12) -> Word12 -> Int
unsafeIndex (Word12
m, Word12
_) Word12
i = Word12 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word12
i Word12 -> Word12 -> Word12
forall a. Num a => a -> a -> a
- Word12
m)
  inRange :: (Word12, Word12) -> Word12 -> Bool
inRange (Word12
m, Word12
n) Word12
i = Word12
m Word12 -> Word12 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word12
i Bool -> Bool -> Bool
&& Word12
i Word12 -> Word12 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word12
n

instance Read Word12 where
  readsPrec :: Int -> ReadS Word12
readsPrec Int
p String
s = [(Int -> Word12
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
x :: Int), String
r) | (Int
x, String
r) <- Int -> ReadS Int
forall a. Read a => Int -> ReadS a
readsPrec Int
p String
s]

instance Bits Word12 where
  {-# INLINE shift #-}
  {-# INLINE bit #-}
  {-# INLINE testBit #-}

  (W12# Word#
x#) .&. :: Word12 -> Word12 -> Word12
.&. (W12# Word#
y#) = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`and#` Word#
y#)
  (W12# Word#
x#) .|. :: Word12 -> Word12 -> Word12
.|. (W12# Word#
y#) = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`or#` Word#
y#)
  (W12# Word#
x#) xor :: Word12 -> Word12 -> Word12
`xor` (W12# Word#
y#) = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`xor#` Word#
y#)
  complement :: Word12 -> Word12
complement (W12# Word#
x#) = Word# -> Word12
W12# (Word#
x# Word# -> Word# -> Word#
`xor#` Word#
mb#) where !(W12# Word#
mb#) = Word12
forall a. Bounded a => a
maxBound
  (W12# Word#
x#) shift :: Word12 -> Int -> Word12
`shift` (I# Int#
i#)
    | Int# -> Bool
isTrue# (Int#
i# Int# -> Int# -> Int#
>=# Int#
0#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Int# -> Word#
`shiftL#` Int#
i#))
    | Bool
otherwise = Word# -> Word12
W12# (Word#
x# Word# -> Int# -> Word#
`shiftRL#` Int# -> Int#
negateInt# Int#
i#)
  (W12# Word#
x#) shiftL :: Word12 -> Int -> Word12
`shiftL` (I# Int#
i#) = Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Int# -> Word#
`shiftL#` Int#
i#))
  (W12# Word#
x#) unsafeShiftL :: Word12 -> Int -> Word12
`unsafeShiftL` (I# Int#
i#) =
    Word# -> Word12
W12# (Word# -> Word#
narrow12Word# (Word#
x# Word# -> Int# -> Word#
`uncheckedShiftL#` Int#
i#))
  (W12# Word#
x#) shiftR :: Word12 -> Int -> Word12
`shiftR` (I# Int#
i#) = Word# -> Word12
W12# (Word#
x# Word# -> Int# -> Word#
`shiftRL#` Int#
i#)
  (W12# Word#
x#) unsafeShiftR :: Word12 -> Int -> Word12
`unsafeShiftR` (I# Int#
i#) = Word# -> Word12
W12# (Word#
x# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
i#)
  (W12# Word#
x#) rotate :: Word12 -> Int -> Word12
`rotate` Int
i
    | Int# -> Bool
isTrue# (Int#
i'# Int# -> Int# -> Int#
==# Int#
0#) = Word# -> Word12
W12# Word#
x#
    | Bool
otherwise =
        Word# -> Word12
W12#
          ( Word# -> Word#
narrow12Word#
              ( (Word#
x# Word# -> Int# -> Word#
`uncheckedShiftL#` Int#
i'#)
                  Word# -> Word# -> Word#
`or#` (Word#
x# Word# -> Int# -> Word#
`uncheckedShiftRL#` (Int#
12# Int# -> Int# -> Int#
-# Int#
i'#))
              )
          )
   where
    !(I# Int#
i'#) = Int
i Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12
  bitSizeMaybe :: Word12 -> Maybe Int
bitSizeMaybe Word12
i = Int -> Maybe Int
forall a. a -> Maybe a
Just (Word12 -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize Word12
i)
  bitSize :: Word12 -> Int
bitSize = Word12 -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize
  isSigned :: Word12 -> Bool
isSigned Word12
_ = Bool
False
  popCount :: Word12 -> Int
popCount (W12# Word#
x#) = Int# -> Int
I# (Word# -> Int#
word2Int# (Word# -> Word#
popCnt12# Word#
x#))
  bit :: Int -> Word12
bit = Int -> Word12
forall a. (Bits a, Num a) => Int -> a
bitDefault
  testBit :: Word12 -> Int -> Bool
testBit = Word12 -> Int -> Bool
forall a. (Bits a, Num a) => a -> Int -> Bool
testBitDefault

instance FiniteBits Word12 where
  finiteBitSize :: Word12 -> Int
finiteBitSize Word12
_ = Int
12
  countLeadingZeros :: Word12 -> Int
countLeadingZeros (W12# Word#
x#) = Int# -> Int
I# (Word# -> Int#
word2Int# (Word# -> Word#
clz12# Word#
x#))
  countTrailingZeros :: Word12 -> Int
countTrailingZeros (W12# Word#
x#) = Int# -> Int
I# (Word# -> Int#
word2Int# (Word# -> Word#
ctz12# Word#
x#))

{-# RULES
"fromIntegral/Word8->Word12" fromIntegral = \x -> case x of Compat.W8# y -> W12# y
"fromIntegral/Word12->Word12" fromIntegral = id :: Word12 -> Word12
"fromIntegral/Word12->Integer" fromIntegral = toInteger :: Word12 -> Integer
"fromIntegral/a->Word12" fromIntegral = \x -> case fromIntegral x of W# x# -> W12# (narrow12Word# x#)
"fromIntegral/Word12->a" fromIntegral = \(W12# x#) -> fromIntegral (W# x#)
  #-}

{-# RULES
"properFraction/Float->(Word12,Float)"
  properFraction =
    \x ->
      case properFraction x of
        (n, y) -> ((fromIntegral :: Int -> Word12) n, y :: Float)
"truncate/Float->Word12"
  truncate =
    (fromIntegral :: Int -> Word12) . (truncate :: Float -> Int)
"floor/Float->Word12"
  floor =
    (fromIntegral :: Int -> Word12) . (floor :: Float -> Int)
"ceiling/Float->Word12"
  ceiling =
    (fromIntegral :: Int -> Word12) . (ceiling :: Float -> Int)
"round/Float->Word12"
  round =
    (fromIntegral :: Int -> Word12) . (round :: Float -> Int)
  #-}

{-# RULES
"properFraction/Double->(Word12,Double)"
  properFraction =
    \x ->
      case properFraction x of
        (n, y) -> ((fromIntegral :: Int -> Word12) n, y :: Double)
"truncate/Double->Word12"
  truncate =
    (fromIntegral :: Int -> Word12) . (truncate :: Double -> Int)
"floor/Double->Word12"
  floor =
    (fromIntegral :: Int -> Word12) . (floor :: Double -> Int)
"ceiling/Double->Word12"
  ceiling =
    (fromIntegral :: Int -> Word12) . (ceiling :: Double -> Int)
"round/Double->Word12"
  round =
    (fromIntegral :: Int -> Word12) . (round :: Double -> Int)
  #-}