{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Trustworthy #-}
module ReWire.BitVector
      ( BV.BV (..), BV.width, BV.ones, BV.zeros, BV.nil
      , (BV.@@), BV.bitVec, (BV.>>.), (BV.<<.), (BV.==.), BV.ashr
      , BV.replicate, BV.lsb1, (BV.@.), BV.concat
      , showHex, showHex', nbits, szBitRep
      ) where

import Data.Text (Text, pack)
import Numeric.Natural (Natural)

import qualified Data.BitVector as BV
import qualified Numeric        as Num

-- | Show the bitvec value in hex, with "0x" prefix, but no leading zeros.
showHex :: BV.BV -> Text
showHex :: BV -> Text
showHex = Text -> BV -> Text
toHex Text
"0x"

-- | Like `showHex`, but prefix with `h` instead of `0x`.
showHex' :: BV.BV -> Text
showHex' :: BV -> Text
showHex' = Text -> BV -> Text
toHex Text
"h"

toHex :: Text -> BV.BV -> Text
toHex :: Text -> BV -> Text
toHex Text
pre = (Text
pre Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (BV -> Text) -> BV -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> (BV -> String) -> BV -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> String -> String) -> String -> Integer -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip Integer -> String -> String
forall a. Integral a => a -> String -> String
Num.showHex String
"" (Integer -> String) -> (BV -> Integer) -> BV -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BV -> Integer
BV.nat

-- | Number of bits needed to encode `n` different values: exact integer
--   ceil-log2 via clog2(n) = 1 + clog2(ceil(n/2)) (floating-point logBase
--   mis-rounds near powers of two once n exceeds 2^29 or so).
nbits :: Natural -> Natural
nbits :: Natural -> Natural
nbits Natural
n | Natural
n Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
<= Natural
1    = Natural
0
        | Bool
otherwise = Natural
1 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural -> Natural
nbits ((Natural
n Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
1) Natural -> Natural -> Natural
forall a. Integral a => a -> a -> a
`div` Natural
2)

-- | Number of bits in the binary representation of `n` (with no leading
--   zeros).
szBitRep :: Natural -> Natural
szBitRep :: Natural -> Natural
szBitRep Natural
n = Natural -> Natural
nbits (Natural -> Natural) -> Natural -> Natural
forall a b. (a -> b) -> a -> b
$ Natural
n Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
1