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


-- |
-- Module      : Data.Word.Word12
-- License     : see  src/Data/LICENSE
-- Stability   : experimental
-- Portability : non-portable (GHC Extensions)

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

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           GHC.Word

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

-- 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
/= :: Word12 -> Word12 -> Bool
$c/= :: Word12 -> Word12 -> Bool
== :: Word12 -> Word12 -> Bool
$c== :: 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
min :: Word12 -> Word12 -> Word12
$cmin :: Word12 -> Word12 -> Word12
max :: Word12 -> Word12 -> Word12
$cmax :: Word12 -> Word12 -> Word12
>= :: Word12 -> Word12 -> Bool
$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
compare :: Word12 -> Word12 -> Ordering
$ccompare :: Word12 -> Word12 -> Ordering
$cp1Ord :: Eq 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 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 = \(W8# x#) -> W12# x#
"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)
  #-}