www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to test if float is NaN?

reply clayasaurus <clayasaurus gmail.com> writes:
How do you test if float is Nan? == and is doesn't seem to work.

float num;
if (num ==/is float.nan)
{
// true
}
else
{
// false
}

?
May 16 2006
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"clayasaurus" <clayasaurus gmail.com> wrote in message 
news:e4e1qd$jb6$1 digitaldaemon.com...

 How do you test if float is Nan? == and is doesn't seem to work.

Try std.math.isnan().
May 16 2006
prev sibling next sibling parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

clayasaurus schrieb am 2006-05-17:
 How do you test if float is Nan? == and is doesn't seem to work.

1) # # if(num !<>= 0.0){ # // ... # } 2) # import std.math; # # if(isnan(num)){ # // ... # } Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFEaqeQ3w+/yD4P9tIRAk/1AJsHaMIYMVQ1GgjTg8Yn3afE8ilMfgCfb+15 BLGWcCiaGKR3GjBEeXtmZGg= =w7vc -----END PGP SIGNATURE-----
May 16 2006
parent clayasaurus <clayasaurus gmail.com> writes:
Thomas Kuehne wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 clayasaurus schrieb am 2006-05-17:
 How do you test if float is Nan? == and is doesn't seem to work.

1) # # if(num !<>= 0.0){ # // ... # }

Nice, learn something new every day.
 
 2)
 # import std.math;
 #
 # if(isnan(num)){
 #     // ...
 # }
 
 Thomas
 
 
 -----BEGIN PGP SIGNATURE-----
 
 iD8DBQFEaqeQ3w+/yD4P9tIRAk/1AJsHaMIYMVQ1GgjTg8Yn3afE8ilMfgCfb+15
 BLGWcCiaGKR3GjBEeXtmZGg=
 =w7vc
 -----END PGP SIGNATURE-----

Thank you Thomas and Jarret :) ~ Clay
May 16 2006
prev sibling parent reply xs0 <xs0 xs0.com> writes:
clayasaurus wrote:
 How do you test if float is Nan? == and is doesn't seem to work.
 
 float num;
 if (num ==/is float.nan)
 {
 // true
 }
 else
 {
 // false
 }
 
 ?

I think this should work as well: if (num == num) { // not NaN } else { // NaN } xs0
May 17 2006
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
xs0 wrote:
 I think this should work as well:
 
 if (num == num) {
     // not NaN
 } else {
     // NaN
 }

Indeed! This works just fine in VC on x86, but fails miserably on x64... In a release build the VC8 x64 compiler optimized that "if" to "if(1)" :D Here's the assembly from a debug build: inline bool _is_nan( double d ) { return !(d==d); } 0000000000404000 movsd mmword ptr [rsp+8],xmm0 0000000000404006 push rdi 0000000000404007 sub rsp,10h 000000000040400B mov rdi,rsp 000000000040400E mov rcx,4 0000000000404018 mov eax,0CCCCCCCCh 000000000040401D rep stos dword ptr [rdi] 000000000040401F movsd xmm0,mmword ptr [d] 0000000000404025 ucomisd xmm0,mmword ptr [d] 000000000040402B je citkTypes::_is_nan+36h (404036h) 000000000040402D mov dword ptr [rsp],1 0000000000404034 jmp citkTypes::_is_nan+3Dh (40403Dh) 0000000000404036 mov dword ptr [rsp],0 000000000040403D mov al,byte ptr [rsp] 0000000000404040 add rsp,10h 0000000000404044 pop rdi 0000000000404045 ret According to http://www.ews.uiuc.edu/~cjiang/reference/vc314.htm they should not have been checking for ZF,PF,CF==1,0,0, but the code only checks ZF? Since by definition a NaN is not equal to anything, including itself, I suppose it's a compiler bug? L.
May 19 2006
next sibling parent Lionello Lunesu <lio lunesu.remove.com> writes:
I really should proof read my posts first; scrap the 'not':
 they should have been checking for ZF,PF,CF==1,0,0, but the code only checks
ZF? 

May 19 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Lionello Lunesu wrote:
 xs0 wrote:
 I think this should work as well:

 if (num == num) {
     // not NaN
 } else {
     // NaN
 }

Indeed! This works just fine in VC on x86, but fails miserably on x64... In a release build the VC8 x64 compiler optimized that "if" to "if(1)" :D Here's the assembly from a debug build: inline bool _is_nan( double d ) { return !(d==d); } 0000000000404000 movsd mmword ptr [rsp+8],xmm0 0000000000404006 push rdi 0000000000404007 sub rsp,10h 000000000040400B mov rdi,rsp 000000000040400E mov rcx,4 0000000000404018 mov eax,0CCCCCCCCh 000000000040401D rep stos dword ptr [rdi] 000000000040401F movsd xmm0,mmword ptr [d] 0000000000404025 ucomisd xmm0,mmword ptr [d] 000000000040402B je citkTypes::_is_nan+36h (404036h) 000000000040402D mov dword ptr [rsp],1 0000000000404034 jmp citkTypes::_is_nan+3Dh (40403Dh) 0000000000404036 mov dword ptr [rsp],0 000000000040403D mov al,byte ptr [rsp] 0000000000404040 add rsp,10h 0000000000404044 pop rdi 0000000000404045 ret According to http://www.ews.uiuc.edu/~cjiang/reference/vc314.htm they should not have been checking for ZF,PF,CF==1,0,0, but the code only checks ZF? Since by definition a NaN is not equal to anything, including itself, I suppose it's a compiler bug?

Definitely. I've seen that sort of behaviour before in VC++. <cynic> Does anyone at Microsoft understand floating point arithmetic? </cynic>
May 19 2006
next sibling parent Lionello Lunesu <lio lunesu.remove.com> writes:
Don Clugston wrote:
 Lionello Lunesu wrote:
 Since by definition a NaN is not equal to anything, including itself, 
 I suppose it's a compiler bug?

Definitely. I've seen that sort of behaviour before in VC++. <cynic> Does anyone at Microsoft understand floating point arithmetic? </cynic>

I must mention that I have the unstable floating point optimizations turned on, /fp:fast.. I'll have to try the default before trashing the VC team ;) L.
May 19 2006
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 Since by definition a NaN is not equal to anything, including itself, 
 I suppose it's a compiler bug?

Definitely. I've seen that sort of behaviour before in VC++. <cynic> Does anyone at Microsoft understand floating point arithmetic? </cynic>

At least up until VC6, it did not check the parity bit for floating point comparisons (the P bit is set if one of the operands is NaN). In fact, I know of no C++ compiler other than DMC++ that does this correctly. VC dropping support for 80 bit long doubles is not an encouraging sign. This is typical for C++ compiler vendors. Handling of NaN arguments to the math.h functions is routinely erratic and buggy. This can be traced back to the Standards committee, who failed to specify NaN behavior.
May 24 2006
next sibling parent Don Clugston <dac nospam.com.au> writes:
Walter Bright wrote:
 Don Clugston wrote:
 Since by definition a NaN is not equal to anything, including itself, 
 I suppose it's a compiler bug?

Definitely. I've seen that sort of behaviour before in VC++. <cynic> Does anyone at Microsoft understand floating point arithmetic? </cynic>

At least up until VC6, it did not check the parity bit for floating point comparisons (the P bit is set if one of the operands is NaN). In fact, I know of no C++ compiler other than DMC++ that does this correctly.

I've been bitten by that before. Incorrect NaN support coupled with uninitialized variables is a deadly combination. Because negative numbers fill the stack with 0xFF bytes, it's relatively common for uninitialized floating-point stack variables to intermittently be NaN in release mode. The most-difficult-to-track-down bug I've ever had was a consequence of this.
 
 VC dropping support for 80 bit long doubles is not an encouraging sign.
 
 This is typical for C++ compiler vendors. Handling of NaN arguments to 
 the math.h functions is routinely erratic and buggy. This can be traced 
 back to the Standards committee, who failed to specify NaN behavior.

May 26 2006
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:e53c1b$11rl$1 digitaldaemon.com...

 VC dropping support for 80 bit long doubles is not an encouraging sign.

Well, correct me of I'm wrong, but aren't 80-bit floats being sort of "phased out" along with the x87 FP stack in favor of the new SSE2/3 instruction sets and 128-bit floats? That might explain their decision. For that matter, what's the plan for D when it comes to 128-bit floats? A new type? "quad"?
May 26 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Jarrett Billingsley wrote:
 "Walter Bright" <newshound digitalmars.com> wrote in message 
 news:e53c1b$11rl$1 digitaldaemon.com...
 VC dropping support for 80 bit long doubles is not an encouraging sign.

"phased out" along with the x87 FP stack in favor of the new SSE2/3 instruction sets and 128-bit floats? That might explain their decision.

I suspect it's the other way around. VC dropped 80 bit support long before those instructions were added.
 For that matter, what's the plan for D when it comes to 128-bit floats?  A 
 new type?  "quad"? 

'real's are supposed to be the longest floating point type available on the hardware, so they'd be reals.
May 26 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:e587a9$1k6q$1 digitaldaemon.com...

 'real's are supposed to be the longest floating point type available on 
 the hardware, so they'd be reals.

What about hardware that has both 80-bit _and_ 128-bit floats? ;)
May 26 2006
next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Jarrett Billingsley wrote:
 "Walter Bright" <newshound digitalmars.com> wrote in message 
 news:e587a9$1k6q$1 digitaldaemon.com...
 
 'real's are supposed to be the longest floating point type available on 
 the hardware, so they'd be reals.

What about hardware that has both 80-bit _and_ 128-bit floats? ;)

There is already hardware that supports both 96-bit and 128-bit floats (sort of) -- it's called 64-bit Linux <g>. I really think that 'real' should not be viewed as a built-in type, it should be a typedef, since that's how it behaves. The built-in types could have really obscure names to discourage their use: eg typedef float80pad96 real; // a Linux32 80-bit real typedef float80pad128 real; // a Linux64 80-bit real typedef float80pad80 real; // a Win32 80-bit real Or they could have even more obscure names, and equivalents to the above could be exposed only in std.stdint. Name mangling would need to be sorted out, though. However... 80-bit floats are really a poor man's 128 floats. If you had access to 128 bits, I don't think you'd ever want to use 80 bits, except for accessing legacy code. I think we can safely assume that 128 bit floats will only exist on 64-bit OS-es. An 80-bit float on 64-bit Linux is binary compatible with a 128-bit IEEE float, the only difference is that the lowest bits in the mantissa are always zero. So it should be possible to mix 80-bit and 128-bit Linux code without recompiling. 64-bit Windows is more of a problem. And calling 32-bit Linux code from 64-bit Linux is definitely an issue (but in that case it's 128-bit vs 96-bit floats!). Two questions: (a) Are there any signs of Intel or AMD actually implementing 128 -bit floats? (b) Are any compiler vendors using 80-bit or 128-bit floats in Win64 yet? How fixed is the ABI?
May 28 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Don Clugston" <dac nospam.com.au> wrote in message 
news:e5e621$2232$1 digitaldaemon.com...

 I really think that 'real' should not be viewed as a built-in type, it 
 should be a typedef, since that's how it behaves.
 The built-in types could have really obscure names to discourage their 
 use:
 eg
 typedef float80pad96 real;  // a Linux32 80-bit real
 typedef float80pad128 real; // a Linux64 80-bit real
 typedef float80pad80 real;  // a Win32 80-bit real

I agree.
 (a) Are there any signs of Intel or AMD actually implementing 128 -bit 
 floats?

Well, as far as I know (and as you probably already know and could have been on the designing committee for it), IEEE has already defined the 754 spec for 128-bit floats. Considering that we've got (I suppose) 10-15 years before the 128-bit processor generation begins, and considering the ever-increasing demand for multimedia and floating-point performance, and considering Intel/AMD's desire to phase out x87 instructions in favor of the SSE/2/3/4 instructions (which have 32- and 64-bit float support already), I'd say the chances of 128-bit floats being created, maybe in just a couple years, is pretty high. SSE5?
May 29 2006
parent reply Don Clugston <dac nospam.com.au> writes:
Jarrett Billingsley wrote:
 "Don Clugston" <dac nospam.com.au> wrote in message 
 news:e5e621$2232$1 digitaldaemon.com...
 
 I really think that 'real' should not be viewed as a built-in type, it 
 should be a typedef, since that's how it behaves.
 The built-in types could have really obscure names to discourage their 
 use:
 eg
 typedef float80pad96 real;  // a Linux32 80-bit real
 typedef float80pad128 real; // a Linux64 80-bit real
 typedef float80pad80 real;  // a Win32 80-bit real

I agree.
 (a) Are there any signs of Intel or AMD actually implementing 128 -bit 
 floats?

Well, as far as I know (and as you probably already know and could have been on the designing committee for it),

LOL! I am just a humble cheesemaker. IEEE has already defined the 754 spec
 for 128-bit floats.  Considering that we've got (I suppose) 10-15 years 
 before the 128-bit processor generation begins, and considering the 
 ever-increasing demand for multimedia and floating-point performance, and 
 considering Intel/AMD's desire to phase out x87 instructions in favor of the 
 SSE/2/3/4 instructions (which have 32- and 64-bit float support already), 
 I'd say the chances of 128-bit floats being created, maybe in just a couple 
 years, is pretty high.  SSE5? 

It seems clear that all future developments in floating point hardware will be driven by games, and not by science (that's already true of MMX and SSE). But maybe there is a market for 128-bit FP for graphics. I just found a graphics card that is already using 128-bit floats: http://www.firingsquad.com/hardware/radeon_9700/page2.asp I *hope* they're using IEEE 754r.
May 30 2006
parent Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 LOL! I am just a humble cheesemaker.

Blessed are the cheesemakers!
May 30 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 (b) Are any compiler vendors using 80-bit or 128-bit floats in Win64 
 yet? How fixed is the ABI?

My sources at Microsoft told me that 80 bit support was added to the core Win64 operating system (i.e. the task switcher). I haven't verified it personally.
May 30 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Jarrett Billingsley wrote:
 "Walter Bright" <newshound digitalmars.com> wrote in message 
 news:e587a9$1k6q$1 digitaldaemon.com...
 
 'real's are supposed to be the longest floating point type available on 
 the hardware, so they'd be reals.

What about hardware that has both 80-bit _and_ 128-bit floats? ;)

We'll add another basic type to D. But I don't know of any such hardware, or plans for any.
May 30 2006