module Word12(Word12) where import Data.Word(Word32(..)) import Data.Bits import Data.Ix import Data.Ratio newtype Word12 = Word12 {unWord12 :: Word32} deriving (Eq,Ord) -- for other bit lengths, just change these definitions type T = Word12 bits :: Int bits = 12 wrap :: Word32 -> Word12 wrap = Word12 unwrap :: Word12 -> Word32 unwrap = unWord12 maxVal :: Word32 maxVal = (1 `shiftL` bits) - 1 narrow :: Word32 -> Word32 narrow w = w .&. maxVal instance Show Word12 where showsPrec p x = showsPrec p (unwrap x) instance Num Word12 where x + y = wrap (narrow (unwrap x + unwrap y)) x - y = wrap (narrow (unwrap x - unwrap y)) x * y = wrap (narrow (unwrap x * unwrap y)) negate x = wrap (narrow (negate (unwrap x))) abs x = x signum x | unwrap x == 0 = 0 signum _ = 1 fromInteger i = wrap (narrow(fromInteger i)) instance Bounded Word12 where minBound = 0 maxBound = wrap maxVal instance Real Word12 where toRational x = toInteger (unwrap x) % 1 {- following Enum support stuff stolen from GHC libraries -} {-# NOINLINE toEnumError #-} toEnumError :: (Show a) => String -> Int -> (a,a) -> b toEnumError inst_ty i bnds = error $ "Enum.toEnum{" ++ inst_ty ++ "}: tag (" ++ show i ++ ") is outside of bounds " ++ show bnds {-# NOINLINE succError #-} succError :: String -> a succError inst_ty = error $ "Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound" {-# NOINLINE predError #-} predError :: String -> a predError inst_ty = error $ "Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound" integralEnumFrom :: (Integral a, Bounded a) => a -> [a] integralEnumFrom n = map fromInteger [toInteger n .. toInteger (maxBound `asTypeOf` n)] integralEnumFromThen :: (Integral a, Bounded a) => a -> a -> [a] integralEnumFromThen n1 n2 | i_n2 >= i_n1 = map fromInteger [i_n1, i_n2 .. toInteger (maxBound `asTypeOf` n1)] | otherwise = map fromInteger [i_n1, i_n2 .. toInteger (minBound `asTypeOf` n1)] where i_n1 = toInteger n1 i_n2 = toInteger n2 integralEnumFromTo :: Integral a => a -> a -> [a] integralEnumFromTo n m = map fromInteger [toInteger n .. toInteger m] integralEnumFromThenTo :: Integral a => a -> a -> a -> [a] integralEnumFromThenTo n1 n2 m = map fromInteger [toInteger n1, toInteger n2 .. toInteger m] instance Enum Word12 where succ x | x /= maxBound = x + 1 | otherwise = succError ("Word" ++ show bits) pred x | x /= minBound = x - 1 | otherwise = predError ("Word" ++ show bits) toEnum i | i >= 0 && i <= fromIntegral (maxBound::T) = wrap (toEnum i) | otherwise = toEnumError ("Word" ++ show bits) i (0,maxBound::T) fromEnum x = fromEnum (unwrap x) enumFrom = integralEnumFrom enumFromThen = integralEnumFromThen enumFromTo = integralEnumFromTo enumFromThenTo = integralEnumFromThenTo {-# RULES "fromIntegral/Word12->Word32" fromIntegral = fromIntegral . unwrap "fromIntegral/Word12->Int" fromIntegral = fromIntegral . unwrap "fromIntegral/Word12->Word12" fromIntegral = id :: Word12 -> Word12 #-} instance Ix Word12 where range (m,n) = [m..n] index b@(m,_) i | inRange b i = fromIntegral (i - m) | otherwise = error "Error in array index" inRange (m,n) i = m <= i && i <= n instance Read Word12 where readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s] instance Integral Word12 where x `quot` y = wrap(unwrap x `quot` unwrap y) x `rem` y = wrap(unwrap x `rem` unwrap y) x `div` y = wrap(unwrap x `div` unwrap y) x `mod` y = wrap(unwrap x `mod` unwrap y) quotRem x y = (wrap q,wrap r) where (q,r) = quotRem (unwrap x) (unwrap y) divMod x y = (wrap d,wrap m) where (d,m) = divMod (unwrap x) (unwrap y) toInteger x = toInteger (unwrap x) instance Bits Word12 where x .&. y = wrap (unwrap x .&. unwrap y) x .|. y = wrap (unwrap x .|. unwrap y) x `xor` y = wrap (unwrap x `xor` unwrap y) complement x = wrap (unwrap x `xor` maxVal) x `shift` i = wrap (narrow (unwrap x `shift` i)) x `rotate` i | i == 0 = x | otherwise = wrap (narrow ((x' `shiftL` i') .|. (x' `shiftR` (bits - i')))) where x' = unwrap x i' = i `mod` bits -- always positive bitSize _ = bits isSigned _ = False