1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-}
{-# OPTIONS_GHC -O2 #-}
{-# OPTIONS_HADDOCK not-home #-}
-----------------------------------------------------------------------------
-- |
-- Module : GHC.Float.ConversionUtils
-- Copyright : (c) Daniel Fischer 2010
-- License : see libraries/base/LICENSE
--
-- Maintainer : cvs-ghc@haskell.org
-- Stability : internal
-- Portability : non-portable (GHC Extensions)
--
-- Utilities for conversion between Double/Float and Rational
--
-----------------------------------------------------------------------------
#include "MachDeps.h"
module GHC.Float.ConversionUtils ( elimZerosInteger, elimZerosInt# ) where
import GHC.Base
import GHC.Num.Integer
#if WORD_SIZE_IN_BITS < 64
import GHC.IntWord64
#endif
default ()
#if WORD_SIZE_IN_BITS < 64
#define TO64 integerToInt64#
toByte64# :: Int64# -> Int#
toByte64# i = word2Int# (and# 255## (int2Word# (int64ToInt# i)))
-- Double mantissae have 53 bits, too much for Int#
elim64# :: Int64# -> Int# -> (# Integer, Int# #)
elim64# n e =
case zeroCount (toByte64# n) of
t | isTrue# (e <=# t) -> (# integerFromInt64# (uncheckedIShiftRA64# n e), 0# #)
| isTrue# (t <# 8#) -> (# integerFromInt64# (uncheckedIShiftRA64# n t), e -# t #)
| otherwise -> elim64# (uncheckedIShiftRA64# n 8#) (e -# 8#)
#else
#define TO64 integerToInt#
-- Double mantissae fit it Int#
elim64# :: Int# -> Int# -> (# Integer, Int# #)
elim64# = elimZerosInt#
#endif
{-# INLINE elimZerosInteger #-}
elimZerosInteger :: Integer -> Int# -> (# Integer, Int# #)
elimZerosInteger m e = elim64# (TO64 m) e
elimZerosInt# :: Int# -> Int# -> (# Integer, Int# #)
elimZerosInt# n e =
case zeroCount (toByte# n) of
t | isTrue# (e <=# t) -> (# IS (uncheckedIShiftRA# n e), 0# #)
| isTrue# (t <# 8#) -> (# IS (uncheckedIShiftRA# n t), e -# t #)
| otherwise -> elimZerosInt# (uncheckedIShiftRA# n 8#) (e -# 8#)
{-# INLINE zeroCount #-}
zeroCount :: Int# -> Int#
zeroCount i =
case zeroCountArr of
BA ba -> indexInt8Array# ba i
toByte# :: Int# -> Int#
toByte# i = word2Int# (and# 255## (int2Word# i))
data BA = BA ByteArray#
-- Number of trailing zero bits in a byte
zeroCountArr :: BA
zeroCountArr =
let mkArr s =
case newByteArray# 256# s of
(# s1, mba #) ->
case writeInt8Array# mba 0# 8# s1 of
s2 ->
let fillA step val idx st
| isTrue# (idx <# 256#) =
case writeInt8Array# mba idx val st of
nx -> fillA step val (idx +# step) nx
| isTrue# (step <# 256#) =
fillA (2# *# step) (val +# 1#) step st
| otherwise = st
in case fillA 2# 0# 1# s2 of
s3 -> case unsafeFreezeByteArray# mba s3 of
(# _, ba #) -> ba
in case mkArr realWorld# of
b -> BA b
|