{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstrainedClassMethods #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE ScopedTypeVariables #-} -- | Types with finite bit count module Haskus.Binary.Bits.Finite ( FiniteBits (..) ) where import Haskus.Utils.Types import Haskus.Number.Word import Haskus.Number.Int import GHC.Exts #include "MachDeps.h" -- | Type representable by a fixed amount of bits class FiniteBits a where -- | Number of bits type BitSize a :: Nat -- | Number of bits (the value is ignored) bitSize :: (Integral i, KnownNat (BitSize a)) => a -> i bitSize _ = natValue @(BitSize a) -- | All bits set to 0 zeroBits :: a -- | All bits set to 1 oneBits :: a oneBits = complement zeroBits -- | Count number of zero bits preceding the most significant set bit countLeadingZeros :: a -> Word -- | Count number of zero bits following the least significant set bit countTrailingZeros :: a -> Word -- | Complement complement :: a -> a instance FiniteBits Word where type BitSize Word = WORD_SIZE_IN_BITS zeroBits = 0 oneBits = maxBound countLeadingZeros (W# x#) = W# (clz# x#) countTrailingZeros (W# x#) = W# (ctz# x#) complement (W# x#) = W# (x# `xor#` mb#) where !(W# mb#) = maxBound instance FiniteBits Word8 where type BitSize Word8 = 8 zeroBits = 0 oneBits = maxBound countLeadingZeros (W8# x#) = W# (clz8# x#) countTrailingZeros (W8# x#) = W# (ctz8# x#) complement (W8# x#) = W8# (x# `xor#` mb#) where !(W8# mb#) = maxBound instance FiniteBits Word16 where type BitSize Word16 = 16 zeroBits = 0 oneBits = maxBound countLeadingZeros (W16# x#) = W# (clz16# x#) countTrailingZeros (W16# x#) = W# (ctz16# x#) complement (W16# x#) = W16# (x# `xor#` mb#) where !(W16# mb#) = maxBound instance FiniteBits Word32 where type BitSize Word32 = 32 zeroBits = 0 oneBits = maxBound countLeadingZeros (W32# x#) = W# (clz32# x#) countTrailingZeros (W32# x#) = W# (ctz32# x#) complement (W32# x#) = W32# (x# `xor#` mb#) where !(W32# mb#) = maxBound instance FiniteBits Word64 where type BitSize Word64 = 64 zeroBits = 0 oneBits = maxBound countLeadingZeros (W64# x#) = W# (clz64# x#) countTrailingZeros (W64# x#) = W# (ctz64# x#) complement (W64# x#) = W64# (x# `xor#` mb#) where !(W64# mb#) = maxBound instance FiniteBits Int where type BitSize Int = WORD_SIZE_IN_BITS zeroBits = 0 oneBits = (-1) countLeadingZeros (I# x#) = W# (clz# (int2Word# x#)) countTrailingZeros (I# x#) = W# (ctz# (int2Word# x#)) complement (I# x#) = I# (notI# x#) instance FiniteBits Int8 where type BitSize Int8 = 8 zeroBits = 0 oneBits = (-1) countLeadingZeros (I8# x#) = W# (clz8# (int2Word# x#)) countTrailingZeros (I8# x#) = W# (ctz8# (int2Word# x#)) complement (I8# x#) = I8# (word2Int# (not# (int2Word# x#))) instance FiniteBits Int16 where type BitSize Int16 = 16 zeroBits = 0 oneBits = (-1) countLeadingZeros (I16# x#) = W# (clz16# (int2Word# x#)) countTrailingZeros (I16# x#) = W# (ctz16# (int2Word# x#)) complement (I16# x#) = I16# (word2Int# (not# (int2Word# x#))) instance FiniteBits Int32 where type BitSize Int32 = 32 zeroBits = 0 oneBits = (-1) countLeadingZeros (I32# x#) = W# (clz32# (int2Word# x#)) countTrailingZeros (I32# x#) = W# (ctz32# (int2Word# x#)) complement (I32# x#) = I32# (word2Int# (not# (int2Word# x#))) instance FiniteBits Int64 where type BitSize Int64 = 64 zeroBits = 0 oneBits = (-1) countLeadingZeros (I64# x#) = W# (clz64# (int2Word# x#)) countTrailingZeros (I64# x#) = W# (ctz64# (int2Word# x#)) complement (I64# x#) = I64# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))