Thread overview | ||||||
---|---|---|---|---|---|---|
|
August 25, 2010 Three floating point questions | ||||
---|---|---|---|---|
| ||||
This program prints (dmd 2.048): 7ff4000000000000 7ffc000000000000 // program #1 import std.stdio: writeln, writefln; import std.string: format; void main() { string toHex(T)(T x) { string result; ubyte* ptr = cast(ubyte*)&x; foreach (i; 0 .. T.sizeof) result = format("%02x", ptr[i]) ~ result; return result; } writeln(toHex(double.init)); writefln("%x", cast(ulong)double.init); } Do you know what cast(ulong) is doing here? --------------------------- This program prints (dmd 2.048):: -nan // program #2 import std.stdio: writeln; void main() { writeln(0.0 / 0.0); } Is it a bug of writeln? --------------------------- Do you know why this isn't raising runtime errors? // program #3 import std.math: FloatingPointControl; import std.c.stdlib: atof; void main() { double d3 = atof("3.0"); double x; // nan FloatingPointControl fpc; fpc.enableExceptions(FloatingPointControl.severeExceptions); double r = x * d3; } Bye, bearophile |
August 26, 2010 Re: Three floating point questions | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote: > This program prints (dmd 2.048): > 7ff4000000000000 > 7ffc000000000000 > > // program #1 > import std.stdio: writeln, writefln; > import std.string: format; > void main() { > string toHex(T)(T x) { > string result; > ubyte* ptr = cast(ubyte*)&x; > foreach (i; 0 .. T.sizeof) > result = format("%02x", ptr[i]) ~ result; > return result; > } > writeln(toHex(double.init)); > writefln("%x", cast(ulong)double.init); > } > > Do you know what cast(ulong) is doing here? Turning it from a signalling nan to a quiet nan. > --------------------------- > > This program prints (dmd 2.048):: > -nan > > // program #2 > import std.stdio: writeln; > void main() { > writeln(0.0 / 0.0); > } > > Is it a bug of writeln? You mean, because it's a negative nan? > --------------------------- > > Do you know why this isn't raising runtime errors? > > // program #3 > import std.math: FloatingPointControl; > import std.c.stdlib: atof; > void main() { > double d3 = atof("3.0"); > double x; // nan > FloatingPointControl fpc; > fpc.enableExceptions(FloatingPointControl.severeExceptions); > double r = x * d3; > } That's a known bug in the backend, which I still haven't fixed. The signalling nans get triggered in the 'double x; ' line. This happens because there's a difference in the way AMD and Intel deal with signalling nans, which is completely unpublicised. So my initial testing was inadequate. |
August 26, 2010 Re: Three floating point questions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | Don: > > Do you know what cast(ulong) is doing here? > > Turning it from a signalling nan to a quiet nan. I really really didn't know this. Is this written somewhere in the D docs? :-) > You mean, because it's a negative nan? Yes, I mean that. Is a negative nan a meaningful concept? Is it a true negative nan coming from the division of two positive values, or it's just a bug of writeln, or is it something completely different? > The signalling nans get triggered in the 'double x; ' line. (You are often two steps forward compared to my thought patterns, so please be patient with me) In this program the FP register is modified after that definition line, so I don't expect 'double x; ' to trigger an hardware exception. But the 'double r = x * d3;' line computes the product of a signaling nan and a normal double, so this is an operation that has to produce an error, I think. > This happens because there's a difference in the way AMD and Intel deal with signalling nans, which is completely unpublicised. So my initial testing was inadequate. I see. If not even official CPU specs show such data, then not being right in the first (and second) implementation is forgiveable, I presume :o) Bye and thank you, bearophile |
August 26, 2010 Re: Three floating point questions | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote: > Don: >>> Do you know what cast(ulong) is doing here? >> Turning it from a signalling nan to a quiet nan. > > I really really didn't know this. Is this written somewhere in the D docs? :-) It's the way signalling nans work. _Any_ use of them raises a floating point exception, then turns them into a quiet NaN. >> You mean, because it's a negative nan? > > Yes, I mean that. Is a negative nan a meaningful concept? It's part of the payload of the nan. Is it a true negative nan coming from the division of two positive values, or it's just a bug of writeln, or is it something completely different? > > >> The signalling nans get triggered in the 'double x; ' line. > > (You are often two steps forward compared to my thought patterns, so please be patient with me) > In this program the FP register is modified after that definition line, so I don't expect 'double x; ' to trigger an hardware exception. Unfortunately the way the backend deals with it at present is to do: double x; x = double.init; which is wrong because it involves an assignment, which may or may not trigger a floating point exception, depending on your cpu*. If it triggers one, then x contains a quiet nan, instead of a signalling one! So the signalling nan idea doesn't quite work yet. * it actually is documented in Intel/AMD docs for the FLD and FSTP instructions, but you have to read it _very_ carefully to notice. As far as I can tell, nobody has noticed the difference before. I only discovered it through experiment. |
Copyright © 1999-2021 by the D Language Foundation