{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_GHC -funbox-strict-fields #-}
#include <MachDeps.h>
module Data.WideWord.Word64
( mkWord64
, plusCarrySum
, quotRem2Word64
, showHexWord64
, subCarryDiff
, timesCarryProd
, word64Hi32
, word64Lo32
, zeroWord64
) where
import Data.Bits (shiftL, shiftR)
import Data.WideWord.Compat
#if WORD_SIZE_IN_BITS == 32
import GHC.Prim (Word#, Word64#, uncheckedShiftRL64#, word64ToWord#, wordToWord32#)
#endif
import GHC.Word (Word32 (..), Word64 (..))
import Numeric (showHex)
{-# INLINE mkWord64 #-}
mkWord64 :: Word32 -> Word32 -> Word64
mkWord64 :: Word32 -> Word32 -> Word64
mkWord64 Word32
hi Word32
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
hi forall a. Bits a => a -> Int -> a
`shiftL` Int
32 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
lo
{-# INLINE showHexWord64 #-}
showHexWord64 :: Word64 -> String
showHexWord64 :: Word64 -> String
showHexWord64 Word64
w = forall a. (Integral a, Show a) => a -> ShowS
showHex Word64
w String
""
{-# INLINE word64Hi32 #-}
word64Hi32 :: Word64 -> Word32
word64Hi32 :: Word64 -> Word32
word64Hi32 Word64
w = forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
w forall a. Bits a => a -> Int -> a
`shiftR` Int
32)
{-# INLINE word64Lo32 #-}
word64Lo32 :: Word64 -> Word32
word64Lo32 :: Word64 -> Word32
word64Lo32 = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE zeroWord64 #-}
zeroWord64 :: Word64
zeroWord64 :: Word64
zeroWord64 = Word64
0
#if WORD_SIZE_IN_BITS == 64
{-# INLINE plusCarrySum #-}
plusCarrySum :: Word64 -> Word64 -> (Word64, Word64)
plusCarrySum :: Word64 -> Word64 -> (Word64, Word64)
plusCarrySum (W64# Word#
a) (W64# Word#
b) =
let !(# Word#
c, Word#
s #) = Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
a Word#
b
in (Word# -> Word64
W64# Word#
c, Word# -> Word64
W64# Word#
s)
quotRem2Word64 :: Word64 -> Word64 -> Word64 -> (Word64, Word64)
quotRem2Word64 :: Word64 -> Word64 -> Word64 -> (Word64, Word64)
quotRem2Word64 (W64# Word#
n1) (W64# Word#
n0) (W64# Word#
d) =
case Word# -> Word# -> Word# -> (# Word#, Word# #)
quotRemWord2# Word#
n1 Word#
n0 Word#
d of
(# Word#
q, Word#
r #) -> (Word# -> Word64
W64# Word#
q, Word# -> Word64
W64# Word#
r)
{-# INLINE subCarryDiff #-}
subCarryDiff :: Word64 -> Word64 -> (Word64, Word64)
subCarryDiff :: Word64 -> Word64 -> (Word64, Word64)
subCarryDiff (W64# Word#
a) (W64# Word#
b) =
let !(# Word#
s, Int#
c #) = Word# -> Word# -> (# Word#, Int# #)
subWordC# Word#
a Word#
b
in (Word# -> Word64
W64# (Int# -> Word#
int2Word# Int#
c), Word# -> Word64
W64# Word#
s)
{-# INLINE timesCarryProd #-}
timesCarryProd :: Word64 -> Word64 -> (Word64, Word64)
timesCarryProd :: Word64 -> Word64 -> (Word64, Word64)
timesCarryProd (W64# Word#
a) (W64# Word#
b) =
let !(# Word#
c, Word#
s #) = Word# -> Word# -> (# Word#, Word# #)
timesWord2# Word#
a Word#
b
in (Word# -> Word64
W64# Word#
c, Word# -> Word64
W64# Word#
s)
#elif WORD_SIZE_IN_BITS == 32
{-# INLINE plusCarrySum #-}
plusCarrySum :: Word64 -> Word64 -> (Word64, Word64)
plusCarrySum (W64# a) (W64# b) =
(mkWord64 0 (W32# (wordToWord32# c2)), mkWord64 (W32# (wordToWord32# s1)) (W32# (wordToWord32# s0)))
where
!(# a1, a0 #) = (# word64ToHiWord# a, word64ToWord# a #)
!(# b1, b0 #) = (# word64ToHiWord# b, word64ToWord# b #)
!(# c1, s0 #) = plusWord2# a0 b0
!(# c2a, s1a #) = plusWord2# b1 c1
!(# c2b, s1 #) = plusWord2# a1 s1a
!c2 = plusWord# c2a c2b
quotRem2Word64 :: Word64 -> Word64 -> Word64 -> (Word64, Word64)
quotRem2Word64 n1 n0 d =
case quotRem (toInteger n1 `shiftL` 64 + toInteger n0) (toInteger d) of
(q, r) -> (fromInteger q, fromInteger r)
{-# INLINE subCarryDiff #-}
subCarryDiff :: Word64 -> Word64 -> (Word64, Word64)
subCarryDiff (W64# a) (W64# b) =
(mkWord64 0 (W32# (wordToWord32# c2)), mkWord64 (W32# (wordToWord32# d1)) (W32# (wordToWord32# d0)))
where
!(# a1, a0 #) = (# word64ToHiWord# a, word64ToWord# a #)
!(# b1, b0 #) = (# word64ToHiWord# b, word64ToWord# b #)
!(# d0, c1 #) = subWordC# a0 b0
!(# d1a, c2a #) = subWordC# a1 (int2Word# c1)
!(# d1, c2b #) = subWordC# d1a b1
!c2 = plusWord# (int2Word# c2a) (int2Word# c2b)
{-# INLINE timesCarryProd #-}
timesCarryProd :: Word64 -> Word64 -> (Word64, Word64)
timesCarryProd (W64# a) (W64# b) =
(mkWord64 (W32# (wordToWord32# p3)) (W32# (wordToWord32# p2)), mkWord64 (W32# (wordToWord32# p1)) (W32# (wordToWord32# p0)))
where
!(# a1, a0 #) = (# word64ToHiWord# a, word64ToWord# a #)
!(# b1, b0 #) = (# word64ToHiWord# b, word64ToWord# b #)
!(# c1a, p0 #) = timesWord2# a0 b0
!(# c2a, p1a #) = timesWord2# a1 b0
!(# c2b, p1b #) = timesWord2# a0 b1
!(# c2c, p1c #) = plusWord2# p1a p1b
!(# c2d, p1 #) = plusWord2# p1c c1a
!(# c3a, p2a #) = timesWord2# a1 b1
!(# c3b, p2b #) = plusWord2# p2a c2a
!(# c3c, p2c #) = plusWord2# p2b c2b
!(# c3d, p2d #) = plusWord2# p2c c2c
!(# c3e, p2 #) = plusWord2# p2d c2d
!p3 = c3a `plusWord#` c3b `plusWord#` c3c `plusWord#` c3d `plusWord#` c3e
word64ToHiWord# :: Word64# -> Word#
word64ToHiWord# w = word64ToWord# (w `uncheckedShiftRL64#` 32#)
#else
error "Sorry, this package only supports 32 and 64 bit word sizes."
#endif