{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module HaskellWorks.Data.Network.Ip.Word128 where
import Data.Maybe
import Data.Word
import Prelude hiding (words)
import qualified Data.Bits as B
type Word128 = (Word32, Word32, Word32, Word32)
instance Enum Word128 where
fromEnum = fromIntegral . word128ToInteger
toEnum i = integerToWord128 $ fromIntegral i
succ (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff) = (0, 0, 0, 0)
succ (a, 0xffffffff, 0xffffffff, 0xffffffff) = (succ a, 0, 0, 0)
succ (a, b, 0xffffffff, 0xffffffff) = (a, succ b, 0, 0)
succ (a, b, c, 0xffffffff) = (a, b, succ c, 0)
succ (a, b, c, d) = (a, b, c, succ d)
pred (0, 0, 0, 0) = (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
pred (a, 0, 0, 0) = ( pred a, 0xffffffff, 0xffffffff, 0xffffffff)
pred (a, b, 0, 0) = ( a, pred b, 0xffffffff, 0xffffffff)
pred (a, b, c, 0) = ( a, b, pred c, 0xffffffff)
pred (a, b, c, d) = ( a, b, c, pred d)
integerToWord128 :: Integer -> Word128
integerToWord128 i = let a = fromIntegral (i `B.shiftR` 96 B..&. 0xffffffff)
b = fromIntegral (i `B.shiftR` 64 B..&. 0xffffffff)
c = fromIntegral (i `B.shiftR` 32 B..&. 0xffffffff)
d = fromIntegral (i `B.shiftR` 00 B..&. 0xffffffff)
in (a, b, c, d)
word128ToInteger :: Word128 -> Integer
word128ToInteger (a, b, c, d) = let a' = fromIntegral a `B.shift` 96
b' = fromIntegral b `B.shift` 64
c' = fromIntegral c `B.shift` 32
d' = fromIntegral d `B.shift` 0
in a' B..|. b' B..|. c' B..|. d' :: Integer
instance Num Word128 where
(+) l r = integerToWord128 $ (word128ToInteger l) + (word128ToInteger r)
(-) l r = integerToWord128 $ (word128ToInteger l) - (word128ToInteger r)
(*) l r = integerToWord128 $ (word128ToInteger l) * (word128ToInteger r)
abs a = a
signum (0, 0, 0, 0) = minBound
signum _ = 1
fromInteger = integerToWord128
instance B.Bits Word128 where
(.&.) (a, b, c, d) (e, f, g, h) = (a B..&. e, b B..&. f, c B..&. g, d B..&. h)
(.|.) (a, b, c, d) (e, f, g, h) = (a B..|. e, b B..|. f, c B..|. g, d B..|. h)
xor (a, b, c, d) (e, f, g, h) = (a `B.xor` e, b `B.xor` f, c `B.xor` g, d `B.xor` h)
complement (a, b, c, d) = (B.complement a, B.complement b, B.complement c, B.complement d)
shift w n = integerToWord128 $ word128ToInteger w `B.shift` n
shiftL w n
| n < 0 = minBound
| otherwise = integerToWord128 $ word128ToInteger w `B.shiftL` n
shiftR w n = integerToWord128 $ word128ToInteger w `B.shiftR` n
rotate w n = integerToWord128 $ word128ToInteger w `B.rotate` n
rotateL w n = integerToWord128 $ word128ToInteger w `B.rotateL` n
rotateR w n = integerToWord128 $ word128ToInteger w `B.rotateR` n
bitSize _ = 128
bitSizeMaybe _ = Just 128
isSigned _ = False
testBit w = B.testBit (word128ToInteger w)
bit n = integerToWord128 $ B.bit n
popCount w = B.popCount $ word128ToInteger w
instance B.FiniteBits Word128 where
finiteBitSize _ = 128