php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42143 The constant NAN is reported as 0 on Windows build
Submitted: 2007-07-30 08:05 UTC Modified: 2011-11-21 11:03 UTC
Votes:3
Avg. Score:5.0 ± 0.0
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:3 (100.0%)
From: zoe at uk dot ibm dot com Assigned: pajoye (profile)
Status: Closed Package: Math related
PHP Version: 5CVS, 6CVS (2008-11-01) OS: win32 only
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
30 - 19 = ?
Subscribe to this entry?

 
 [2007-07-30 08:05 UTC] zoe at uk dot ibm dot com
Description:
------------
The constant NAN is reported as '0' on the Windows binary downloaded from the snaps.php.net site. The function is correct on Linux.

A colleague built locally (on Windows) from source and got the correct value for NAN (ie NAN). We stepped through this code (in basic_functions.c): 

PHPAPI double php_get_nan(void)
{
#if HAVE_HUGE_VAL_NAN
        return HUGE_VAL + -HUGE_VAL;
#elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha)
        double val = 0.0;
        ((php_uint32*)&val)[1] = PHP_DOUBLE_QUIET_NAN_HIGH;
        ((php_uint32*)&val)[0] = 0;
        return val;
#elif HAVE_ATOF_ACCEPTS_NAN
        return atof("NAN");
#else
        return 0.0/0.0;
#endif
}

and found that the local build goes through the first "if" section, that is, HAVE_HUGE_VAL_NAN is true. We can't step through the Windows binary we downloaded but guessing that it's not executing the same section. 

Reproduce code:
---------------
<?php
echo "NAN= ";
var_dump(NAN);
?>


Expected result:
----------------
NAN= float(NAN)

Actual result:
--------------
NAN= float(0)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-07-31 11:42 UTC] jani@php.net
Edin, can you check if there's some problem with the win32 build in this?
 [2007-08-02 09:47 UTC] pajoye@php.net
I tried using vc 2k3 and 2k5 and NAN is correctly defined. VC6 seems to have a different way to define/get/use NAN. Maybe we can rely on fmod(1,0) instead (always return NaN on windows).
 [2007-08-02 22:27 UTC] stas@php.net
Saw a bug under msvc2005 that can be related to this - get_nan() function produced FP exception. Weird thing is that it happens only if engine is started, shut down and then started again inside the same process. Maybe has something to do with some kind of floating point. Using PHP_DOUBLE_QUIET_NAN_HIGH instead seems to fix the problem. 
 [2007-08-03 05:24 UTC] pajoye@php.net
Little notice about VC6, using it with the very last SDK works. I'm not sure which SDK is used on our win32 build box. It may be a platform sdk bug more than a VC bug. Edin, can you try to upgrade the SDK (if we can upgrade it:)?
 [2008-07-18 16:24 UTC] jani@php.net
Pierre, assigning to you since Edin is MIA.
 [2009-05-24 11:57 UTC] php-lists at stanvassilev dot com
There are two separate bugs here. I've actually reported the other 
part individually but it was marked bogus (see #46868).

Bug 1) PHP relies on the compiler's semantics alone for NaN 
comparisons, and that seems to differ from compiler to compiler, and 
even in the same compiler depending on the particular setup. This 
means on some builds NaN == NaN and on some NaN != NaN. On the current 
builds at  On Windows in particular, VC9, however will compute NaN == 
NaN as false, while with VC6 it'll be false or true depending on the 
particular setup.

Note that I'm not comparing the constants, but actual NaN (this test 
is carried out on a VC6 TS build of PHP 5.2.9):

var_dump(NAN); // float(0)
var_dump(sqrt(-1)); // float(NAN)
var_dump(sqrt(-1) == sqrt(-1)); // true (should be false)

This means that we should codify how exactly does NaN compare to other 
values and itself, and add a special case code above compiler logic in 
the equality operators. As a high level language, there's no need for 
PHP to depend on compiler's minutae, when we at the same time do such 
expensive operations such as checking two strings for numeric content 
before comparing. 

In the definition of NaN itself is said that NaN should not match 
anything or even itself, and this is the consistent implementation in 
all popular script languages today:
http://en.wikipedia.org/wiki/NaN

Given the current status quo, most deployments are under *nix, where 
the behavior is silent NaN (no errors, propagates on math operations 
having one or more NaN), and NaN doesn't match itself. 

So to stabilize this behavior for "niche" platforms, we just need to 
compiler-proof the code a bit with a special case logic (pseudo code):

function equals(op1, op2) {
	if (is_nan(op1) || is_nan(op2)) {
		return false;
	} else {
		return op1 == op2; // else use current equality logic
	}
}

I've not done work on the PHP core, so I hope someone can provide the 
patch here.

Bug 2) On Windows platforms it seems in most builds NAN is just 
reported as 0 (this bug). From my tests, on all current Win32 builds 
of 5.2.x and 5.3.x, NAN is reported as 0, including *VC9* builds.

I have no idea why this is happening, but this might be a clue 
(implicit conversion and the value is lost):
http://www.velocityreviews.com/forums/t283018-compiletime-constant-
quiet-nan-double-.html

The strange thing here is that math operations apparently *do* produce 
actual NaN (see test above on Bug 1), even if the constant NAN is 0.
 [2009-05-24 12:45 UTC] php-lists at stanvassilev dot com
Actually I just tested on Win32 PHP 5.2.9 VC6 TS (official php.net 
build) and this is a lot worse than I thought:

var_dump(sqrt(-1) == 123); // float(true)
var_dump(sqrt(-1) == "hi there"); // float(true)
var_dump(sqrt(-1) == null); // float(true)
var_dump(sqrt(-1) == false); // float(true)
var_dump(sqrt(-1) == 0.1); // float(true)

Instead of being equal to nothing, it's equal to almost everything...
 [2009-05-24 12:58 UTC] php-lists at stanvassilev dot com
Naturally I mean bool(true) in the previous comment, not float(true)... 
;)
 [2009-05-29 08:18 UTC] pajoye@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 22:01:28 2024 UTC