The situation with Enum on Ratio is pretty bad but at least it's not hopeless, since rational numbers are at least exact. But for Float/Double it seems to be a total disaster area. Since it seems to be impossible to abolish Enum Float/Double altogether, would it at least be possible to make it rather more useful, by making succ x return the next representable float after x (or x if x is non-finite) and pred x the previous representable float. This would (a) be useful; (b) make mathematical sense; (c) is tricky to implement with the existing primitives. Before someone else points it out, this is of course unimplementable should someone in the future implement infinite-precision reals in Haskell, but as (barring a solution to the halting problem) Eq would be as well, that does not bother me. My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros. Feri wrote
Everybody working with floats should know their quirks While in an ideal world, everyone who represented a mouse position or anything else as a float should have a PhD in numerical analysis, in practice they do not. Indeed I think the Haskell Library Report contains quite a few examples of floating point code which a numerical analyst would have written rather better. So I don't think it's good enough to treat every Float/Double operation as if it had an implicit "UNSAFE" flag indicating that the compiler was entitled to wierd behaviour only comprehensible to experts, as seems to be the case with floating enumerations now.
George Russell wrote:
Indeed I think the Haskell Library Report contains quite a few examples of floating point code which a numerical analyst would have written rather better.
Like the Float and Double implementations enumFrom{Then}To. Heck, even I can tell that these are Just Plain Wrong -- they're subject to horribly bad roundoff errors -- and I'm not even close to being a numerical analyst. --Joe English jenglish@flightlab.com
George Russell <ger@tzi.de> writes:
The situation with Enum on Ratio is pretty bad but at least it's not hopeless, since rational numbers are at least exact. But for Float/Double it seems to be a total disaster area.
My vote would be to scrap it. Enum sounds like it defines an ordering of elements, and that's IMHO not what the actual implementation looks like. But I suppose it will have to wait.
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-) -kzm -- If I haven't seen further, it is by standing in the footprints of giants
Ketil Z Malde <ketil@ii.uib.no> writes:
My vote would be to scrap it. Enum sounds like it defines an ordering of elements, and that's IMHO not what the actual implementation looks
Just before everybody else points it out; that's a bit imprecise. But the IMHO obvious way to regard succ would be to provide a succession of all the elements in a set, rather than just add one to a numeric interpretation of the value. Defining [x..y] in terms of succ sound counter-intuitive to me (and isn't a different mechanism needed for [x,y..z] anyway?) -kzm -- If I haven't seen further, it is by standing in the footprints of giants
Ketil Z Malde wrote:
George Russell <ger@tzi.de> writes:
The situation with Enum on Ratio is pretty bad but at least it's not hopeless, since rational numbers are at least exact. But for Float/Double it seems to be a total disaster area.
My vote would be to scrap it. Enum sounds like it defines an ordering of elements, and that's IMHO not what the actual implementation looks like. But I suppose it will have to wait.
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
succ +- 0 is not very important, but having succ/pred return the next representable real is occasionally useful.
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
Is there any way to do this (yet)? I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y even if i have to FFI to C, I'd really like a solution. any help would be appreciated. - Hal
The C function you are looking for is called 'nextafter', and is present on all systems/libraries that pretend to be fully IEEE-754 compliant (as this is a required function from the standard). It even takes a direction parameter (so you can do both nextafter and firstbefore). Since its API is simple, an FFI should be rather straightforward. Jacques -----Original Message----- From: haskell-bounces@haskell.org [mailto:haskell-bounces@haskell.org] On Behalf Of Hal Daume III Sent: October 21, 2003 2:37 PM To: Ketil Z Malde Cc: haskell@haskell.org; Simon Peyton-Jones; George Russell Subject: Re: Enum on Float/Double
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
Is there any way to do this (yet)? I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y even if i have to FFI to C, I'd really like a solution. any help would be appreciated. - Hal _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
So this has been a while, but i think that decodeFloat, incrementing the mantissa, encodeFloat might work. But then again, it might not. :) -- Lennart Hal Daume III wrote:
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
Is there any way to do this (yet)? I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y
even if i have to FFI to C, I'd really like a solution.
any help would be appreciated.
- Hal
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
This works great for when x/=0...is there a good (Haskell) solution for the smallest positive float? On Tue, 21 Oct 2003, Lennart Augustsson wrote:
So this has been a while, but i think that decodeFloat, incrementing the mantissa, encodeFloat might work. But then again, it might not. :)
-- Lennart
Hal Daume III wrote:
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
Is there any way to do this (yet)? I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y
even if i have to FFI to C, I'd really like a solution.
any help would be appreciated.
- Hal
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
-- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
I think you need to be careful when you reach the smallest number that can be normalized. Let's face it, Haskell just doesn't provide the right functions for this. :) -- Lennart Hal Daume III wrote:
This works great for when x/=0...is there a good (Haskell) solution for the smallest positive float?
On Tue, 21 Oct 2003, Lennart Augustsson wrote:
So this has been a while, but i think that decodeFloat, incrementing the mantissa, encodeFloat might work. But then again, it might not. :)
-- Lennart
Hal Daume III wrote:
My preference would be for succ (+-0) to return the smallest positive real, since then you could define succ x to be the unique y with x < y and forall z . z < y => not (x < z), where such a y exists, and I'm not sure if the Haskell standard knows about signed zeros.
Is this really useful? Why would you need this number? Peano artithmetic on reals? :-)
Is there any way to do this (yet)? I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y
even if i have to FFI to C, I'd really like a solution.
any help would be appreciated.
- Hal
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
I found a case where I really need: f :: Float -> Float where f x is the least y such that x < y
This seems to be the problem of finding the unnormalized epsilon: the smallest positive number one can meaningfully add to the given number x. If that x is 1.0, we're talking about the epsilon. There are several approaches: - Consult the file /usr/include/float.h and find FLT_EPSILON and DBL_EPSILON there. One can write a Haskell program that parses that file, if one so wishes. - apply the formula epsilon = base^(1-p) - write a program everybody has written in good old Fortran days
nextafter1:: Float -> Float nextafter1 0 = 0 nextafter1 x | GHC.Float.isNaN x = x nextafter1 x | GHC.Float.isInfinite x = x nextafter1 x = try (abs x) where try d = let d1 = d/2 in if x + d1 == x then improve d1 d else try d1 -- improve a b -- we know that the number we seek is between a and b -- try to see if there is a number in between that -- still can be meaningfully added to x improve a b = let middle = (a+b)/2 in if middle == b || middle == a then x + b else if x + middle > x then improve a middle else improve middle b
Standard caveat applies: some overly smart compilers arrange for the whole iteration to be done with CPU registers, which often have extra precision. Therefore, one might need to disable optimizations or play other tricks to force storing/reloading the number to/from memory.
test_delta:: Float -> Float -> Bool test_delta x y = y > x && (let x'=x+(0.9*(y-x)) in x'==y || x'==x)
*Main> test_delta (1.0::Float) (nextafter1 (1.0::Float)) True *Main> test_delta (0.1::Float) (nextafter1 (0.1::Float)) True *Main> test_delta (-42.3e20::Float) (nextafter1 (-42.3e20::Float)) True *Main> (nextafter1 (-42.3e50::Float)) -Infinity We can also deal with denormalized numbers: *Main> GHC.Float.isDenormalized (12.0e-40::Float) True *Main> test_delta (12.0e-40::Float) (nextafter1 (12.0e-40::Float)) True
On Tue, 21 Oct 2003, Lennart Augustsson wrote:
So this has been a while, but i think that decodeFloat, incrementing the mantissa, encodeFloat might work.
But what if the mantissa is 0xffffff? We are at mercy of encodeFloat doing the right thing. Furthermore, this technique doesn't seem to work with denormalized numbers *Main> GHC.Float.decodeFloat (1.0::Float) (8388608,-23) *Main> GHC.Float.decodeFloat (nextafter1 (1.0::Float)) (8388609,-23) *Main> GHC.Float.decodeFloat (0.1::Float) (13421773,-27) *Main> GHC.Float.decodeFloat (nextafter1 (0.1::Float)) (13421774,-27) So far, so good. However, *Main> GHC.Float.decodeFloat (12.0e-40::Float) (13701584,-153) *Main> GHC.Float.decodeFloat (nextafter1 (12.0e-40::Float)) (13701600,-153) Indeed, *Main> GHC.Float.encodeFloat 13701584 (-153) == (12.0e-40::Float) True *Main> GHC.Float.encodeFloat 13701585 (-153) == (12.0e-40::Float) True so incrementing the mantissa by one doesn't actually work in all circumstances.
Hal Daume III wrote:
This works great for when x/=0...is there a good (Haskell) solution for the smallest positive float?
I think that the following are correct for the smallest normalised Float and Double values: Prelude> encodeFloat 1 (fst (floatRange (0 :: Float)) - 1) :: Float 1.1754944e-38 Prelude> encodeFloat 1 (fst (floatRange (0 :: Double)) - 1) :: Double 2.2250738585072014e-308 They (roughly) agree with FLT_MIN and DBL_MIN from <float.h>: #define FLT_MIN 1.17549435e-38F ... #define DBL_MIN 2.2250738585072014e-308 Furthermore, these values aren't denormalised, but reducing the exponent by one gives a denormalised value: Prelude> isDenormalized (encodeFloat 1 (fst (floatRange (0 :: Float)) - 1) :: Float) False Prelude> isDenormalized (encodeFloat 1 (fst (floatRange (0 :: Float)) - 2) :: Float) True Prelude> isDenormalized (encodeFloat 1 (fst (floatRange (0 :: Double)) - 1) :: Double) False Prelude> isDenormalized (encodeFloat 1 (fst (floatRange (0 :: Double)) - 2) :: Double) True These appear to give the smallest possible Float/Double values: Prelude> encodeFloat 1 (fst (floatRange (0 :: Double)) - floatDigits (0 :: Double)) :: Double 5.0e-324 Prelude> encodeFloat 1 (fst (floatRange (0 :: Float)) - floatDigits (0 :: Float)) :: Float 1.0e-45 Reducing the exponent by 1 gives 0.0: Prelude> encodeFloat 1 (fst (floatRange (0 :: Float)) - floatDigits (0 :: Float) - 1) :: Float 0.0 Prelude> encodeFloat 1 (fst (floatRange (0 :: Double)) - floatDigits (0 :: Double) - 1) :: Double 0.0 -- Glynn Clements <glynn.clements@virgin.net>
participants (8)
-
George Russell -
Glynn Clements -
Hal Daume III -
Jacques Carette -
Joe English -
Ketil Z Malde -
Lennart Augustsson -
oleg@pobox.com