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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
|
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-}
{-# OPTIONS_HADDOCK hide #-}
-----------------------------------------------------------------------------
-- |
-- Module : GHC.Float.RealFracMethods
-- Copyright : (c) Daniel Fischer 2010
-- License : see libraries/base/LICENSE
--
-- Maintainer : cvs-ghc@haskell.org
-- Stability : internal
-- Portability : non-portable (GHC Extensions)
--
-- Methods for the RealFrac instances for 'Float' and 'Double',
-- with specialised versions for 'Int'.
--
-- Moved to their own module to not bloat GHC.Float further.
--
-----------------------------------------------------------------------------
#include "MachDeps.h"
module GHC.Float.RealFracMethods
( -- * Double methods
-- ** Integer results
properFractionDoubleInteger
, truncateDoubleInteger
, floorDoubleInteger
, ceilingDoubleInteger
, roundDoubleInteger
-- ** Int results
, properFractionDoubleInt
, floorDoubleInt
, ceilingDoubleInt
, roundDoubleInt
-- * Double/Int conversions, wrapped primops
, double2Int
, int2Double
-- * Float methods
-- ** Integer results
, properFractionFloatInteger
, truncateFloatInteger
, floorFloatInteger
, ceilingFloatInteger
, roundFloatInteger
-- ** Int results
, properFractionFloatInt
, floorFloatInt
, ceilingFloatInt
, roundFloatInt
-- * Float/Int conversions, wrapped primops
, float2Int
, int2Float
) where
import GHC.Integer
import GHC.Base
import GHC.Num ()
#if WORD_SIZE_IN_BITS < 64
import GHC.IntWord64
#define TO64 integerToInt64
#define FROM64 int64ToInteger
#define MINUS64 minusInt64#
#define NEGATE64 negateInt64#
#else
#define TO64 integerToInt
#define FROM64 smallInteger
#define MINUS64 ( -# )
#define NEGATE64 negateInt#
uncheckedIShiftRA64# :: Int# -> Int# -> Int#
uncheckedIShiftRA64# = uncheckedIShiftRA#
uncheckedIShiftL64# :: Int# -> Int# -> Int#
uncheckedIShiftL64# = uncheckedIShiftL#
#endif
default ()
------------------------------------------------------------------------------
-- Float Methods --
------------------------------------------------------------------------------
-- Special Functions for Int, nice, easy and fast.
-- They should be small enough to be inlined automatically.
-- We have to test for ±0.0 to avoid returning -0.0 in the second
-- component of the pair. Unfortunately the branching costs a lot
-- of performance.
properFractionFloatInt :: Float -> (Int, Float)
properFractionFloatInt (F# x) =
if isTrue# (x `eqFloat#` 0.0#)
then (I# 0#, F# 0.0#)
else case float2Int# x of
n -> (I# n, F# (x `minusFloat#` int2Float# n))
-- truncateFloatInt = float2Int
floorFloatInt :: Float -> Int
floorFloatInt (F# x) =
case float2Int# x of
n | isTrue# (x `ltFloat#` int2Float# n) -> I# (n -# 1#)
| otherwise -> I# n
ceilingFloatInt :: Float -> Int
ceilingFloatInt (F# x) =
case float2Int# x of
n | isTrue# (int2Float# n `ltFloat#` x) -> I# (n +# 1#)
| otherwise -> I# n
roundFloatInt :: Float -> Int
roundFloatInt x = float2Int (c_rintFloat x)
-- Functions with Integer results
-- With the new code generator in GHC 7, the explicit bit-fiddling is
-- slower than the old code for values of small modulus, but when the
-- 'Int' range is left, the bit-fiddling quickly wins big, so we use that.
-- If the methods are called on smallish values, hopefully people go
-- through Int and not larger types.
-- Note: For negative exponents, we must check the validity of the shift
-- distance for the right shifts of the mantissa.
{-# INLINE properFractionFloatInteger #-}
properFractionFloatInteger :: Float -> (Integer, Float)
properFractionFloatInteger v@(F# x) =
case decodeFloat_Int# x of
(# m, e #)
| isTrue# (e <# 0#) ->
case negateInt# e of
s | isTrue# (s ># 23#) -> (0, v)
| isTrue# (m <# 0#) ->
case negateInt# (negateInt# m `uncheckedIShiftRA#` s) of
k -> (smallInteger k,
case m -# (k `uncheckedIShiftL#` s) of
r -> F# (encodeFloatInteger (smallInteger r) e))
| otherwise ->
case m `uncheckedIShiftRL#` s of
k -> (smallInteger k,
case m -# (k `uncheckedIShiftL#` s) of
r -> F# (encodeFloatInteger (smallInteger r) e))
| otherwise -> (shiftLInteger (smallInteger m) e, F# 0.0#)
{-# INLINE truncateFloatInteger #-}
truncateFloatInteger :: Float -> Integer
truncateFloatInteger x =
case properFractionFloatInteger x of
(n, _) -> n
-- floor is easier for negative numbers than truncate, so this gets its
-- own implementation, it's a little faster.
{-# INLINE floorFloatInteger #-}
floorFloatInteger :: Float -> Integer
floorFloatInteger (F# x) =
case decodeFloat_Int# x of
(# m, e #)
| isTrue# (e <# 0#) ->
case negateInt# e of
s | isTrue# (s ># 23#) -> if isTrue# (m <# 0#) then (-1) else 0
| otherwise -> smallInteger (m `uncheckedIShiftRA#` s)
| otherwise -> shiftLInteger (smallInteger m) e
-- ceiling x = -floor (-x)
-- If giving this its own implementation is faster at all,
-- it's only marginally so, hence we keep it short.
{-# INLINE ceilingFloatInteger #-}
ceilingFloatInteger :: Float -> Integer
ceilingFloatInteger (F# x) =
negateInteger (floorFloatInteger (F# (negateFloat# x)))
{-# INLINE roundFloatInteger #-}
roundFloatInteger :: Float -> Integer
roundFloatInteger x = float2Integer (c_rintFloat x)
------------------------------------------------------------------------------
-- Double Methods --
------------------------------------------------------------------------------
-- Special Functions for Int, nice, easy and fast.
-- They should be small enough to be inlined automatically.
-- We have to test for ±0.0 to avoid returning -0.0 in the second
-- component of the pair. Unfortunately the branching costs a lot
-- of performance.
properFractionDoubleInt :: Double -> (Int, Double)
properFractionDoubleInt (D# x) =
if isTrue# (x ==## 0.0##)
then (I# 0#, D# 0.0##)
else case double2Int# x of
n -> (I# n, D# (x -## int2Double# n))
-- truncateDoubleInt = double2Int
floorDoubleInt :: Double -> Int
floorDoubleInt (D# x) =
case double2Int# x of
n | isTrue# (x <## int2Double# n) -> I# (n -# 1#)
| otherwise -> I# n
ceilingDoubleInt :: Double -> Int
ceilingDoubleInt (D# x) =
case double2Int# x of
n | isTrue# (int2Double# n <## x) -> I# (n +# 1#)
| otherwise -> I# n
roundDoubleInt :: Double -> Int
roundDoubleInt x = double2Int (c_rintDouble x)
-- Functions with Integer results
-- The new Code generator isn't quite as good for the old 'Double' code
-- as for the 'Float' code, so for 'Double' the bit-fiddling also wins
-- when the values have small modulus.
-- When the exponent is negative, all mantissae have less than 64 bits
-- and the right shifting of sized types is much faster than that of
-- 'Integer's, especially when we can
-- Note: For negative exponents, we must check the validity of the shift
-- distance for the right shifts of the mantissa.
{-# INLINE properFractionDoubleInteger #-}
properFractionDoubleInteger :: Double -> (Integer, Double)
properFractionDoubleInteger v@(D# x) =
case decodeDoubleInteger x of
(# m, e #)
| isTrue# (e <# 0#) ->
case negateInt# e of
s | isTrue# (s ># 52#) -> (0, v)
| m < 0 ->
case TO64 (negateInteger m) of
n ->
case n `uncheckedIShiftRA64#` s of
k ->
(FROM64 (NEGATE64 k),
case MINUS64 n (k `uncheckedIShiftL64#` s) of
r ->
D# (encodeDoubleInteger (FROM64 (NEGATE64 r)) e))
| otherwise ->
case TO64 m of
n ->
case n `uncheckedIShiftRA64#` s of
k -> (FROM64 k,
case MINUS64 n (k `uncheckedIShiftL64#` s) of
r -> D# (encodeDoubleInteger (FROM64 r) e))
| otherwise -> (shiftLInteger m e, D# 0.0##)
{-# INLINE truncateDoubleInteger #-}
truncateDoubleInteger :: Double -> Integer
truncateDoubleInteger x =
case properFractionDoubleInteger x of
(n, _) -> n
-- floor is easier for negative numbers than truncate, so this gets its
-- own implementation, it's a little faster.
{-# INLINE floorDoubleInteger #-}
floorDoubleInteger :: Double -> Integer
floorDoubleInteger (D# x) =
case decodeDoubleInteger x of
(# m, e #)
| isTrue# (e <# 0#) ->
case negateInt# e of
s | isTrue# (s ># 52#) -> if m < 0 then (-1) else 0
| otherwise ->
case TO64 m of
n -> FROM64 (n `uncheckedIShiftRA64#` s)
| otherwise -> shiftLInteger m e
{-# INLINE ceilingDoubleInteger #-}
ceilingDoubleInteger :: Double -> Integer
ceilingDoubleInteger (D# x) =
negateInteger (floorDoubleInteger (D# (negateDouble# x)))
{-# INLINE roundDoubleInteger #-}
roundDoubleInteger :: Double -> Integer
roundDoubleInteger x = double2Integer (c_rintDouble x)
-- Wrappers around double2Int#, int2Double#, float2Int# and int2Float#,
-- we need them here, so we move them from GHC.Float and re-export them
-- explicitly from there.
double2Int :: Double -> Int
double2Int (D# x) = I# (double2Int# x)
int2Double :: Int -> Double
int2Double (I# i) = D# (int2Double# i)
float2Int :: Float -> Int
float2Int (F# x) = I# (float2Int# x)
int2Float :: Int -> Float
int2Float (I# i) = F# (int2Float# i)
-- Quicker conversions from 'Double' and 'Float' to 'Integer',
-- assuming the floating point value is integral.
--
-- Note: Since the value is integral, the exponent can't be less than
-- (-TYP_MANT_DIG), so we need not check the validity of the shift
-- distance for the right shfts here.
{-# INLINE double2Integer #-}
double2Integer :: Double -> Integer
double2Integer (D# x) =
case decodeDoubleInteger x of
(# m, e #)
| isTrue# (e <# 0#) ->
case TO64 m of
n -> FROM64 (n `uncheckedIShiftRA64#` negateInt# e)
| otherwise -> shiftLInteger m e
{-# INLINE float2Integer #-}
float2Integer :: Float -> Integer
float2Integer (F# x) =
case decodeFloat_Int# x of
(# m, e #)
| isTrue# (e <# 0#) -> smallInteger (m `uncheckedIShiftRA#` negateInt# e)
| otherwise -> shiftLInteger (smallInteger m) e
-- Foreign imports, the rounding is done faster in C when the value
-- isn't integral, so we call out for rounding. For values of large
-- modulus, calling out to C is slower than staying in Haskell, but
-- presumably 'round' is mostly called for values with smaller modulus,
-- when calling out to C is a major win.
-- For all other functions, calling out to C gives at most a marginal
-- speedup for values of small modulus and is much slower than staying
-- in Haskell for values of large modulus, so those are done in Haskell.
foreign import ccall unsafe "rintDouble"
c_rintDouble :: Double -> Double
foreign import ccall unsafe "rintFloat"
c_rintFloat :: Float -> Float
|