<commit_before>{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}

---------------------------------------------------------
-- |
-- Module      : Data.W
-- Copyright   : (c) 2015 <NAME>
-- License     : MIT
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : provisional
-- Portability : partable
--
-- Fixed-size bit vectors using type-level naturals.
---------------------------------------------------------

module Data.BigWord
    (
    -- * The 'W' newtype
      W
    -- * Operations
    , (>+<)
    , split

    -- * Utility functions
    , accumulate
    , accumulate'
    , chunks
    , chunks'

    ) where

import Data.Bits
import Data.Data
import Data.Function
import Data.Ix
import Data.Proxy
import Data.Monoid
import Data.Traversable
import GHC.TypeLits
import Text.Printf

-- | Type representing a sequence of @n@ bits, or a non-negative integer smaller than @2^n@.
newtype W (n :: Nat) = W { getW :: Integer }
    deriving (Eq, Ord, Real, Ix, PrintfArg, Data, Typeable)

-- Original name was BigWord, but since using this module requires more
-- explicit type signatures, I decided to use just W. This may be stupid.
-- Sorry if the name conflicts with your code.

-------------------------------
-- INSTANCES
-------------------------------

instance KnownNat n => Read (W n) where
    readsPrec = ((.).(.)) (map $ \(a, str) -> (fromInteger a, str)) readsPrec

instance Show (W n) where
    show = show . getW

instance KnownNat n => Bounded (W n) where
    minBound = 0
    maxBound = W (bit (natValInt (Proxy :: Proxy n)) - 1)

-- Can't just derive because it need to get the default for bounded types
instance KnownNat n => Enum (W n) where
    toEnum = W . toEnum
    fromEnum = fromEnum . getW

instance KnownNat n => Integral (W n) where
    toInteger = getW
    quotRem x y = case (quotRem `on` getW) x y of (q, r) -> (W q, W r)

instance KnownNat n => Num (W n) where
    fromInteger = W . flip mod (bit (natValInt (Proxy :: Proxy n)))
    (+) = ((.).(.)) fromInteger ((+) `on` getW)
    (*) = ((.).(.)) fromInteger ((*) `on` getW)
    abs = id
    signum 0 = 0
    signum _ = 1
    negate = (+ 1) . complement

instance KnownNat n => Bits (W n) where
        (.&.) = ((.).(.)) W ((.&.) `on` getW)
        (.|.) = ((.).(.)) W ((.|.) `on` getW)
        xor   = ((.).(.)) W (xor   `on` getW)
        complement = fromInteger . complement . getW
        shift (W x) i = W $ shift x i `mod` bit (natValInt (Proxy :: Proxy n))
        rotate x i = let nat = natValInt (Proxy :: Proxy n)
                         dist = mod i nat
                     in shift x dist .|. shift x (nat - dist)
        bitSizeMaybe = Just . finiteBitSize
        bitSize = finiteBitSize
        isSigned = const False
        testBit = testBit . getW
        bit i = if i < natValInt (Proxy :: Proxy n)
                then W (bit i)
                else 0
        popCount = popCount . getW

instance KnownNat n => FiniteBits (W n) where
    finiteBitSize = const $ natValInt (Proxy :: Proxy n)

-------------------------------
-- EXPORTS
-------------------------------

-- | Appends two @'W'@'s, treating the second's bits as more significant.
(>+<) :: forall n m. (KnownNat m, KnownNat n, KnownNat (m + n)) => W m -> W n -> W (m + n)
(W x) >+< (W y) = fromInteger $ x + shift y (natValInt (Proxy :: Proxy m))

-- | The inverse of @(>+<)@
-- >    forall a b. split (a >+< b) == (a, b)
split :: forall n m. (KnownNat m, KnownNat n, KnownNat (m + n)) => W (m + n) -> (W m, W n)
split (W z) = (fromInteger z, fromInteger $ shiftR z (natValInt (Proxy :: Proxy m)))

-- | Transforms an applicative action that results in a @'W' n@ to one that results in a @'W' m@.
-- @'W' n@'s are accumulated with significance increasing from left to right
-- If m is not a multiple of n, leftover bits are truncated.
--
-- Example usage, parsing a little endian 160-bit word:
--
-- >    parseW160 = accumulate $ (fromIntegral :: Word8 -> W 8) <$> anyWord8
accumulate :: (Applicative f, KnownNat m, KnownNat n) => f (W n) -> f (W m)
accumulate = takeAux mapAccumR

-- | Same as @accumulate@, but gathers in the opposite order
accumulate' :: (Applicative f, KnownNat m, KnownNat n) => f (W n) -> f (W m)
accumulate' = takeAux mapAccumL<commit_msg>fixed haddock mistake<commit_after>{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}

---------------------------------------------------------
-- |
-- Module      : Data.W
-- Copyright   : (c) 2015 <NAME>
-- License     : MIT
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : provisional
-- Portability : partable
--
-- Fixed-size bit vectors using type-level naturals.
---------------------------------------------------------

module Data.BigWord
    (
    -- * The 'W' newtype
      W
    -- * Operations
    , (>+<)
    , split

    -- * Utility functions
    , accumulate
    , accumulate'
    , chunks
    , chunks'

    ) where

import Data.Bits
import Data.Data
import Data.Function
import Data.Ix
import Data.Proxy
import Data.Monoid
import Data.Traversable
import GHC.TypeLits
import Text.Printf

-- | Type representing a sequence of @n@ bits, or a non-negative integer smaller than @2^n@.
newtype W (n :: Nat) = W { getW :: Integer }
    deriving (Eq, Ord, Real, Ix, PrintfArg, Data, Typeable)

-- Original name was BigWord, but since using this module requires more
-- explicit type signatures, I decided to use just W. This may be stupid.
-- Sorry if the name conflicts with your code.

-------------------------------
-- INSTANCES
-------------------------------

instance KnownNat n => Read (W n) where
    readsPrec = ((.).(.)) (map $ \(a, str) -> (fromInteger a, str)) readsPrec

instance Show (W n) where
    show = show . getW

instance KnownNat n => Bounded (W n) where
    minBound = 0
    maxBound = W (bit (natValInt (Proxy :: Proxy n)) - 1)

-- Can't just derive because it need to get the default for bounded types
instance KnownNat n => Enum (W n) where
    toEnum = W . toEnum
    fromEnum = fromEnum . getW

instance KnownNat n => Integral (W n) where
    toInteger = getW
    quotRem x y = case (quotRem `on` getW) x y of (q, r) -> (W q, W r)

instance KnownNat n => Num (W n) where
    fromInteger = W . flip mod (bit (natValInt (Proxy :: Proxy n)))
    (+) = ((.).(.)) fromInteger ((+) `on` getW)
    (*) = ((.).(.)) fromInteger ((*) `on` getW)
    abs = id
    signum 0 = 0
    signum _ = 1
    negate = (+ 1) . complement

instance KnownNat n => Bits (W n) where
        (.&.) = ((.).(.)) W ((.&.) `on` getW)
        (.|.) = ((.).(.)) W ((.|.) `on` getW)
        xor   = ((.).(.)) W (xor   `on` getW)
        complement = fromInteger . complement . getW
        shift (W x) i = W $ shift x i `mod` bit (natValInt (Proxy :: Proxy n))
        rotate x i = let nat = natValInt (Proxy :: Proxy n)
                         dist = mod i nat
                     in shift x dist .|. shift x (nat - dist)
        bitSizeMaybe = Just . finiteBitSize
        bitSize = finiteBitSize
        isSigned = const False
        testBit = testBit . getW
        bit i = if i < natValInt (Proxy :: Proxy n)
                then W (bit i)
                else 0
        popCount = popCount . getW

instance KnownNat n => FiniteBits (W n) where
    finiteBitSize = const $ natValInt (Proxy :: Proxy n)

-------------------------------
-- EXPORTS
-------------------------------

-- | Appends two @'W'@'s, treating the second's bits as more significant.
(>+<) :: forall n m. (KnownNat m, KnownNat n, KnownNat (m + n)) => W m -> W n -> W (m + n)
(W x) >+< (W y) = fromInteger $ x + shift y (natValInt (Proxy :: Proxy m))

-- | The inverse of @(>+<)@
--
-- >    forall a b. split (a >+< b) == (a, b)
split :: forall n m. (KnownNat m, KnownNat n, KnownNat (m + n)) => W (m + n) -> (W m, W n)
split (W z) = (fromInteger z, fromInteger $ shiftR z (natValInt (Proxy :: Proxy m)))

-- | Transforms an applicative action that results in a @'W' n@ to one that results in a @'W' m@.
-- @'W' n@'s are accumulated with significance increasing from left to right
-- If m is not a multiple of n, leftover bits are truncated.
--
-- Example usage, parsing a little endian 160-bit word:
--
-- >    parseW160 = accumulate $ (fromIntegral :: Word8 -> W 8) <$> anyWord8
accumulate :: (Applicative f, KnownNat m, KnownNat n) => f (W n) -> f (W m)
accumulate = takeAux mapAccumR

-- | Same as @accumulate@, but gathers in the opposite order
accumulate' :: (Applicative f, KnownNat m, KnownNat n) => f (W n) -> f (W m)
accumulate' = takeAux mapAccumL
{'fraction_non_alphanumeric': 0.19234676600067727, 'fraction_numerical': 0.004740941415509651, 'mean_word_length': 2.048864418444597, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5766150', 'n_tokens_mistral': 3047, 'n_tokens_neox': 2855, 'n_words': 1061}