-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from haskell-compat/almost-all-your-base
More functions from base-4.7.0.0 and base-4.8.0.0
- Loading branch information
Showing
14 changed files
with
490 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
{-# LANGUAGE CPP, NoImplicitPrelude #-} | ||
{-# LANGUAGE BangPatterns, PatternGuards #-} | ||
module Data.Bits.Compat ( | ||
module Base | ||
, bitDefault | ||
, testBitDefault | ||
, popCountDefault | ||
#if MIN_VERSION_base(4,7,0) | ||
, toIntegralSized | ||
#endif | ||
) where | ||
|
||
import Data.Bits as Base | ||
|
||
#if !(MIN_VERSION_base(4,8,0)) | ||
import Prelude | ||
#endif | ||
|
||
#if !(MIN_VERSION_base(4,6,0)) | ||
-- | Default implementation for 'bit'. | ||
-- | ||
-- Note that: @bitDefault i = 1 `shiftL` i@ | ||
-- | ||
-- /Since: 4.6.0.0/ | ||
bitDefault :: (Bits a, Num a) => Int -> a | ||
bitDefault = \i -> 1 `shiftL` i | ||
{-# INLINE bitDefault #-} | ||
|
||
-- | Default implementation for 'testBit'. | ||
-- | ||
-- Note that: @testBitDefault x i = (x .&. bit i) /= 0@ | ||
-- | ||
-- /Since: 4.6.0.0/ | ||
testBitDefault :: (Bits a, Num a) => a -> Int -> Bool | ||
testBitDefault = \x i -> (x .&. bit i) /= 0 | ||
{-# INLINE testBitDefault #-} | ||
|
||
-- | Default implementation for 'popCount'. | ||
-- | ||
-- This implementation is intentionally naive. Instances are expected to provide | ||
-- an optimized implementation for their size. | ||
-- | ||
-- /Since: 4.6.0.0/ | ||
popCountDefault :: (Bits a, Num a) => a -> Int | ||
popCountDefault = go 0 | ||
where | ||
go !c 0 = c | ||
go c w = go (c+1) (w .&. (w - 1)) -- clear the least significant | ||
{-# INLINABLE popCountDefault #-} | ||
#endif | ||
|
||
#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0)) | ||
-- | Attempt to convert an 'Integral' type @a@ to an 'Integral' type @b@ using | ||
-- the size of the types as measured by 'Bits' methods. | ||
-- | ||
-- A simpler version of this function is: | ||
-- | ||
-- > toIntegral :: (Integral a, Integral b) => a -> Maybe b | ||
-- > toIntegral x | ||
-- > | toInteger x == y = Just (fromInteger y) | ||
-- > | otherwise = Nothing | ||
-- > where | ||
-- > y = toInteger x | ||
-- | ||
-- This version requires going through 'Integer', which can be inefficient. | ||
-- However, @toIntegralSized@ is optimized to allow GHC to statically determine | ||
-- the relative type sizes (as measured by 'bitSizeMaybe' and 'isSigned') and | ||
-- avoid going through 'Integer' for many types. (The implementation uses | ||
-- 'fromIntegral', which is itself optimized with rules for @base@ types but may | ||
-- go through 'Integer' for some type pairs.) | ||
-- | ||
-- /Since: 4.8.0.0/ | ||
|
||
toIntegralSized :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b | ||
toIntegralSized x -- See Note [toIntegralSized optimization] | ||
| maybe True (<= x) yMinBound | ||
, maybe True (x <=) yMaxBound = Just y | ||
| otherwise = Nothing | ||
where | ||
y = fromIntegral x | ||
|
||
xWidth = bitSizeMaybe x | ||
yWidth = bitSizeMaybe y | ||
|
||
yMinBound | ||
| isBitSubType x y = Nothing | ||
| isSigned x, not (isSigned y) = Just 0 | ||
| isSigned x, isSigned y | ||
, Just yW <- yWidth = Just (negate $ bit (yW-1)) -- Assumes sub-type | ||
| otherwise = Nothing | ||
|
||
yMaxBound | ||
| isBitSubType x y = Nothing | ||
| isSigned x, not (isSigned y) | ||
, Just xW <- xWidth, Just yW <- yWidth | ||
, xW <= yW+1 = Nothing -- Max bound beyond a's domain | ||
| Just yW <- yWidth = if isSigned y | ||
then Just (bit (yW-1)-1) | ||
else Just (bit yW-1) | ||
| otherwise = Nothing | ||
{-# INLINEABLE toIntegralSized #-} | ||
|
||
-- | 'True' if the size of @a@ is @<=@ the size of @b@, where size is measured | ||
-- by 'bitSizeMaybe' and 'isSigned'. | ||
isBitSubType :: (Bits a, Bits b) => a -> b -> Bool | ||
isBitSubType x y | ||
-- Reflexive | ||
| xWidth == yWidth, xSigned == ySigned = True | ||
|
||
-- Every integer is a subset of 'Integer' | ||
| ySigned, Nothing == yWidth = True | ||
| not xSigned, not ySigned, Nothing == yWidth = True | ||
|
||
-- Sub-type relations between fixed-with types | ||
| xSigned == ySigned, Just xW <- xWidth, Just yW <- yWidth = xW <= yW | ||
| not xSigned, ySigned, Just xW <- xWidth, Just yW <- yWidth = xW < yW | ||
|
||
| otherwise = False | ||
where | ||
xWidth = bitSizeMaybe x | ||
xSigned = isSigned x | ||
|
||
yWidth = bitSizeMaybe y | ||
ySigned = isSigned y | ||
{-# INLINE isBitSubType #-} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{-# LANGUAGE CPP, NoImplicitPrelude #-} | ||
module Data.Word.Compat ( | ||
module Base | ||
, byteSwap16 | ||
, byteSwap32 | ||
, byteSwap64 | ||
) where | ||
|
||
import Data.Word as Base | ||
|
||
#if !(MIN_VERSION_base(4,7,0)) | ||
import Data.Bits | ||
|
||
-- | Swap bytes in 'Word16'. | ||
-- | ||
-- /Since: 4.7.0.0/ | ||
byteSwap16 :: Word16 -> Word16 | ||
byteSwap16 w = ((w `shiftR` 8) .&. 0x00ff) | ||
.|. ((w .&. 0x00ff) `shiftL` 8) | ||
|
||
-- | Reverse order of bytes in 'Word32'. | ||
-- | ||
-- /Since: 4.7.0.0/ | ||
byteSwap32 :: Word32 -> Word32 | ||
byteSwap32 w = ((w .&. 0xff000000) `shiftR` 24) | ||
.|. ((w .&. 0x00ff0000) `shiftR` 8) | ||
.|. ((w .&. 0x0000ff00) `shiftL` 8) | ||
.|. ((w .&. 0x000000ff) `shiftL` 24) | ||
|
||
-- | Reverse order of bytes in 'Word64'. | ||
-- | ||
-- /Since: 4.7.0.0/ | ||
byteSwap64 :: Word64 -> Word64 | ||
byteSwap64 w = ((w .&. 0xff00000000000000) `shiftR` 56) | ||
.|. ((w .&. 0x00ff000000000000) `shiftR` 40) | ||
.|. ((w .&. 0x0000ff0000000000) `shiftR` 24) | ||
.|. ((w .&. 0x000000ff00000000) `shiftR` 8) | ||
.|. ((w .&. 0x00000000ff000000) `shiftL` 8) | ||
.|. ((w .&. 0x0000000000ff0000) `shiftL` 24) | ||
.|. ((w .&. 0x000000000000ff00) `shiftL` 40) | ||
.|. ((w .&. 0x00000000000000ff) `shiftL` 56) | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{-# LANGUAGE CPP, NoImplicitPrelude #-} | ||
{-# LANGUAGE ForeignFunctionInterface #-} | ||
module Foreign.Marshal.Utils.Compat ( | ||
module Base | ||
, fillBytes | ||
) where | ||
|
||
import Foreign.Marshal.Utils as Base | ||
|
||
#if !(MIN_VERSION_base(4,8,0)) | ||
import Data.Word (Word8) | ||
import Foreign.C.Types | ||
import Foreign.Ptr | ||
import Prelude | ||
|
||
-- |Fill a given number of bytes in memory area with a byte value. | ||
-- | ||
-- /Since: 4.8.0.0/ | ||
fillBytes :: Ptr a -> Word8 -> Int -> IO () | ||
fillBytes dest char size = do | ||
_ <- memset dest (fromIntegral char) (fromIntegral size) | ||
return () | ||
|
||
foreign import ccall unsafe "string.h" memset :: Ptr a -> CInt -> CSize -> IO (Ptr a) | ||
#endif |
Oops, something went wrong.