Skip to content

Commit

Permalink
Fix toRep on 32-bit architectures
Browse files Browse the repository at this point in the history
The previous implementation was badly broken on 32-bit architectures, as it
would `peek` a value of type `int32_t` at the Haskell type `Int64` (for
instance, this could cause the C value `-2 ^ 31` to be read as `2 ^ 31` on the
Haskell side). We now read this value at the appropriate type (`Int32` on
32-bit architectures and `Int64` on 64-bit architectures) and extend it as
needed.

Fixes #26.
  • Loading branch information
RyanGlScott committed May 13, 2024
1 parent 6cd9af2 commit ed8896b
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/LibBF/Mutable.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ toRep :: BF -> IO BFRep
toRep = bf1 (\ptr ->
do s <- #{peek bf_t, sign} ptr
let sgn = if asBool s then Neg else Pos
e <- #{peek bf_t, expn} ptr
e <- #{peek bf_t, expn} ptr :: IO SLimbT
if | e == #{const BF_EXP_NAN} -> pure BFNaN
| e == #{const BF_EXP_INF} -> pure (BFRep sgn Inf)
| e == #{const BF_EXP_ZERO} -> pure (BFRep sgn Zero)
Expand All @@ -618,9 +618,17 @@ toRep = bf1 (\ptr ->

base <- foldM step 0 (reverse (take len [ 0 .. ]))
let bias = 64 * fromIntegral len

-- `e :: SLimbT`, and we need it to be 64 bits in the code below.
-- On 64-bit architectures, `SLimbT = Int64`, making this a
-- no-op. On 32-bit architectures, `SLimbT = Int32`, so this code
-- will extend `e` to 64 bits.
eInt64 :: Int64
eInt64 = fromIntegral e

norm bs bi
| even bs = norm (bs `shiftR` 1) (bi - 1)
| otherwise = BFRep sgn (Num bs (e - bi))
| otherwise = BFRep sgn (Num bs (eInt64 - bi))

pure (norm base bias) -- (BFRep sgn (Num base (e - bias)))
)

0 comments on commit ed8896b

Please sign in to comment.