HARM-0.1.4: Arm/BinaryNumber.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
----------------------------------------------------------------------
-- FILE: BinaryNumber.hs
-- DATE: 11/10/2000
-- AUTHOR: Jeffrey A. Meunier
-- EMAIL: jeffm@cse.uconn.edu
----------------------------------------------------------------------
-- This module Arm.represents binary numbers which are read and displayed
-- as a sequence of bits. A Binary32 number is semantically
-- equivalent to a Word32 number, so strictly speaking, all the extra
-- class information is not needed.
module Arm.BinaryNumber
( Binary32
, intToBinary32 -- :: Int -> Binary32
, binary32ToInt -- :: Binary32 -> Int
, binary32ToWord32 -- :: Binary32 -> Word32
, word32ToBinary32 -- :: Word32 -> Binary32
)
where
----------------------------------------------------------------------
-- Standard libraries.
----------------------------------------------------------------------
import Data.Bits
import Data.Word
import Data.Array
import Data.Ratio
----------------------------------------------------------------------
-- New type Binary32.
----------------------------------------------------------------------
newtype Binary32
= B32 Word32
deriving Num
instance Show Binary32 where
showsPrec n (B32 wrd) = showString (biNumToString wrd "")
where
biNumToString 0 accum = ('0' : accum)
biNumToString 1 accum = ('1' : accum)
biNumToString n accum
= if n `rem` 2 == 0
then biNumToString (n `div` 2) ('0' : accum)
else biNumToString (n `div` 2) ('1' : accum)
instance Read Binary32 where
readsPrec n = (stringToBiNum 0)
where
stringToBiNum :: Word32 -> ReadS Binary32
stringToBiNum acc "0" = [(B32 (acc * 2), "")]
stringToBiNum acc "1" = [(B32 (acc * 2 + 1), "")]
stringToBiNum acc (bit : bits)
| bit == '0' = stringToBiNum (acc * 2) bits
| bit == '1' = stringToBiNum (acc * 2 + 1) bits
{-
This expression also converts a binary string into an integer, but it uses
4.3 times the number of reductions, and 4.8 times the number of cells:
s2b x = foldl (+) 0 (map (uncurry (*)) (zip (reverse (map ((flip (-)) (ord '0')) (map ord x))) [floor (2 ** x) | x <- [0..]]))
-}
instance Eq Binary32 where
(==) = binop (==)
instance Ord Binary32 where
compare = binop compare
-- instance Num Binary32 where
-- x + y = to (binop (+) x y)
-- x - y = to (binop (-) x y)
-- negate = to . negate . from
-- x * y = to (binop (*) x y)
-- abs = absReal
-- signum = signumReal
-- -- fromInteger = to . primIntegerToWord
-- -- fromInt = intToBinary32
instance Bounded Binary32 where
minBound = B32 0
maxBound = B32 (maxBound :: Word32)
instance Real Binary32 where
toRational x = toInteger x % 1
instance Integral Binary32 where
x `div` y = to (binop div x y)
x `quot` y = to (binop quot x y)
x `rem` y = to (binop rem x y)
x `mod` y = to (binop mod x y)
x `quotRem` y = to2 (binop quotRem x y)
divMod = quotRem
toInteger = toInteger . from
-- toInt = binary32ToInt
instance Ix Binary32 where
range (m,n) = [m..n]
index b@(m,n) i
| inRange b i = fromIntegral (from (i - m))
| otherwise = error "index: Index out of range"
inRange (m,n) i = m <= i && i <= n
instance Enum Binary32 where
toEnum = to . fromIntegral
fromEnum = fromIntegral . from
enumFrom = numericEnumFrom
enumFromTo = numericEnumFromTo
enumFromThen = numericEnumFromThen
enumFromThenTo = numericEnumFromThenTo
instance Bits Binary32 where
x .&. y = to (binop (.&.) x y)
x .|. y = to (binop (.|.) x y)
x `xor` y = to (binop xor x y)
complement = to . complement . from
x `shift` i = to (from x `shift` i)
-- rotate
bit = to . bit
setBit x i = to (setBit (from x) i)
clearBit x i = to (clearBit (from x) i)
complementBit x i = to (complementBit (from x) i)
testBit x i = testBit (from x) i
bitSize _ = 32
isSigned _ = False
----------------------------------------------------------------------
-- Conversion functions.
----------------------------------------------------------------------
intToBinary32 :: Int -> Binary32
intToBinary32 = (B32 . fromIntegral)
binary32ToInt :: Binary32 -> Int
binary32ToInt (B32 b) = fromIntegral b
binary32ToWord32 :: Binary32 -> Word32
binary32ToWord32 (B32 b) = b
word32ToBinary32 :: Word32 -> Binary32
word32ToBinary32 = B32
-----------------------------------------------------------------------------
-- Enumeration code: copied from Prelude.
-----------------------------------------------------------------------------
numericEnumFrom :: Real a => a -> [a]
numericEnumFromThen :: Real a => a -> a -> [a]
numericEnumFromTo :: Real a => a -> a -> [a]
numericEnumFromThenTo :: Real a => a -> a -> a -> [a]
numericEnumFrom n = n : (numericEnumFrom $! (n+1))
numericEnumFromThen n m = iterate ((m-n)+) n
numericEnumFromTo n m = takeWhile (<= m) (numericEnumFrom n)
numericEnumFromThenTo n n' m = takeWhile (if n' >= n then (<= m) else (>= m))
(numericEnumFromThen n n')
-----------------------------------------------------------------------------
-- Coercions - used to make the instance declarations more uniform.
-----------------------------------------------------------------------------
class Coerce a where
to :: Word32 -> a
from :: a -> Word32
instance Coerce Binary32 where
from = binary32ToWord32
to = word32ToBinary32
binop :: Coerce word => (Word32 -> Word32 -> a) -> (word -> word -> a)
binop op x y = from x `op` from y
to2 :: Coerce word => (Word32, Word32) -> (word, word)
to2 (x,y) = (to x, to y)
-----------------------------------------------------------------------------
-- Primitives.
-----------------------------------------------------------------------------
-- primitive, primIntegerToWord :: Integer -> Word32
-----------------------------------------------------------------------------
-- Code copied from the Prelude.
-----------------------------------------------------------------------------
absReal x
| x >= 0 = x
| otherwise = -x
signumReal x
| x == 0 = 0
| x > 0 = 1
| otherwise = -1
----------------------------------------------------------------------
-- eof
----------------------------------------------------------------------