Skip to content
Snippets Groups Projects
Commit 613558d8 authored by Simon Marlow's avatar Simon Marlow
Browse files

[project @ 1997-09-26 13:38:58 by simonm]

this file got lost somehow
parent 7908b385
No related merge requests found
import Ratio -- 1.3
main = putStr (
shows tinyFloat ( '\n'
: shows t_f ( '\n'
: shows hugeFloat ( '\n'
: shows h_f ( '\n'
: shows tinyDouble ( '\n'
: shows t_d ( '\n'
: shows hugeDouble ( '\n'
: shows h_d ( '\n'
: shows x_f ( '\n'
: shows x_d ( '\n'
: shows y_f ( '\n'
: shows y_d ( "\n"
)))))))))))))
where
t_f :: Float
t_d :: Double
h_f :: Float
h_d :: Double
x_f :: Float
x_d :: Double
y_f :: Float
y_d :: Double
t_f = fromRationalX (toRational tinyFloat)
t_d = fromRationalX (toRational tinyDouble)
h_f = fromRationalX (toRational hugeFloat)
h_d = fromRationalX (toRational hugeDouble)
x_f = fromRationalX (1.82173691287639817263897126389712638972163e-300 :: Rational)
x_d = fromRationalX (1.82173691287639817263897126389712638972163e-300 :: Rational)
y_f = 1.82173691287639817263897126389712638972163e-300
y_d = 1.82173691287639817263897126389712638972163e-300
--!! fromRational woes
fromRationalX :: (RealFloat a) => Rational -> a
fromRationalX r =
let
h = ceiling (huge `asTypeOf` x)
b = toInteger (floatRadix x)
x = fromRat 0 r
fromRat e0 r' =
let d = denominator r'
n = numerator r'
in if d > h then
let e = integerLogBase b (d `div` h) + 1
in fromRat (e0-e) (n % (d `div` (b^e)))
else if abs n > h then
let e = integerLogBase b (abs n `div` h) + 1
in fromRat (e0+e) ((n `div` (b^e)) % d)
else
scaleFloat e0 (rationalToRealFloat {-fromRational-} r')
in x
{-
fromRationalX r =
rationalToRealFloat r
{- Hmmm...
let
h = ceiling (huge `asTypeOf` x)
b = toInteger (floatRadix x)
x = fromRat 0 r
fromRat e0 r' =
{--} trace (shows e0 ('/' : shows r' ('/' : shows h "\n"))) (
let d = denominator r'
n = numerator r'
in if d > h then
let e = integerLogBase b (d `div` h) + 1
in fromRat (e0-e) (n % (d `div` (b^e)))
else if abs n > h then
let e = integerLogBase b (abs n `div` h) + 1
in fromRat (e0+e) ((n `div` (b^e)) % d)
else
scaleFloat e0 (rationalToRealFloat r')
-- now that we know things are in-bounds,
-- we use the "old" Prelude code.
{--} )
in x
-}
-}
-- Compute the discrete log of i in base b.
-- Simplest way would be just divide i by b until it's smaller then b, but that would
-- be very slow! We are just slightly more clever.
integerLogBase :: Integer -> Integer -> Int
integerLogBase b i =
if i < b then
0
else
-- Try squaring the base first to cut down the number of divisions.
let l = 2 * integerLogBase (b*b) i
doDiv :: Integer -> Int -> Int
doDiv i l = if i < b then l else doDiv (i `div` b) (l+1)
in doDiv (i `div` (b^l)) l
------------
-- Compute smallest and largest floating point values.
tiny :: (RealFloat a) => a
tiny =
let (l, _) = floatRange x
x = encodeFloat 1 (l-1)
in x
huge :: (RealFloat a) => a
huge =
let (_, u) = floatRange x
d = floatDigits x
x = encodeFloat (floatRadix x ^ d - 1) (u - d)
in x
tinyDouble = tiny :: Double
tinyFloat = tiny :: Float
hugeDouble = huge :: Double
hugeFloat = huge :: Float
{-
[In response to a request by simonpj, Joe Fasel writes:]
A quite reasonable request! This code was added to the Prelude just
before the 1.2 release, when Lennart, working with an early version
of hbi, noticed that (read . show) was not the identity for
floating-point numbers. (There was a one-bit error about half the time.)
The original version of the conversion function was in fact simply
a floating-point divide, as you suggest above. The new version is,
I grant you, somewhat denser.
How's this?
--Joe
-}
rationalToRealFloat :: (RealFloat a) => Rational -> a
rationalToRealFloat x = x'
where x' = f e
-- If the exponent of the nearest floating-point number to x
-- is e, then the significand is the integer nearest xb^(-e),
-- where b is the floating-point radix. We start with a good
-- guess for e, and if it is correct, the exponent of the
-- floating-point number we construct will again be e. If
-- not, one more iteration is needed.
f e = if e' == e then y else f e'
where y = encodeFloat (round (x * (1%b)^^e)) e
(_,e') = decodeFloat y
b = floatRadix x'
-- We obtain a trial exponent by doing a floating-point
-- division of x's numerator by its denominator. The
-- result of this division may not itself be the ultimate
-- result, because of an accumulation of three rounding
-- errors.
(s,e) = decodeFloat (fromInteger (numerator x) `asTypeOf` x'
/ fromInteger (denominator x))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment