From: SourceForge.net <no...@so...> - 2008-10-31 07:50:03
|
Bugs item #2207721, was opened at 2008-10-29 17:40 Message generated for change (Comment added) made by tammer You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=684730&aid=2207721&group_id=119701 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: APIs Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Mark Miesfeld (miesfeld) Assigned to: Nobody/Anonymous (nobody) Summary: ObjectToDouble(nan) native API failure on AIX Initial Comment: Hi Rick, Think I need help with this one too. Rather than post to the list, I thought I'd open up a bug so you can look at it when you have time. On AIX, in the CONVERSION.testGroup these types of test cases are failing: val = "nan" self~assertSame(val, .CONVERSIONTester~TestObjectToDouble(val)) Rather than nan, they are producing +infinity [failure] [20081029 16:31:13.155443] svn: r3371 Change date: 2008-09-21 06:33:29 +0200 Test: TESTDOUBLE03 Class: CONVERSION.testGroup File: /daten/svn/ooRexx/test/trunk/ooRexx/API/oo/CONVERSION.testGroup Line: 827 Failed: assertSame Expected: [[nan], identityHash="100785925"] Actual: [[-infinity], identityHash="112493565"] I think it is a difference in the C++ libraries on AIX, maybe coming from here in StringClass.cpp: // non numeric, so this could be one of the special cases if (strCompare("nan")) { result = std::numeric_limits<double>::signaling_NaN(); return true; } But, I'm not sure. Plus, I don't really know what to do about it even if it is the root cause. <grin> I'll attach the log output. ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-31 08:50 Message: Hello, it looks like not only AIX is acting differently... I have tested this on AIX, Linux and Windows (Windows has two different results depending on the C++ compiler used!!!)... On AIX and Linux NAN from math.h looks good. testnan.cpp =========== #include <iostream> #include <limits> using namespace std; int main( ) { cout << "(double) Has quiet nan: " << numeric_limits<double>::has_quiet_NaN << endl; cout << "(double) Has signaling nan: " << numeric_limits<double>::has_signaling_NaN << endl; cout << "(long double) Has quiet nan: " << numeric_limits<long double>::has_quiet_NaN << endl; cout << "(long double) Has signaling nan: " << numeric_limits<long double>::has_signaling_NaN << endl; cout << "(float) Has quiet nan: " << numeric_limits<float>::has_quiet_NaN << endl; cout << "(float) Has signaling nan: " << numeric_limits<float>::has_signaling_NaN << endl; cout << "The quiet NaN for type float is: " << numeric_limits<float>::quiet_NaN( ) << endl; cout << "The quiet NaN for type double is: " << numeric_limits<double>::quiet_NaN( ) << endl; cout << "The quiet NaN for type long double is: " << numeric_limits<long double>::quiet_NaN( ) << endl; cout << "The signaling NaN for type floatis: " << numeric_limits<float>::signaling_NaN( ) << endl; cout << "The signaling NaN for type double is: " << numeric_limits<double>::signaling_NaN( ) << endl; cout << "The signaling NaN for type long double is: " << numeric_limits<long double>::signaling_NaN( ) << endl; #ifdef NAN cout << "NAN from math.h is: " << NAN << endl; #endif } Linux ===== ./testnan (double) Has quiet nan: 1 (double) Has signaling nan: 1 (long double) Has quiet nan: 1 (long double) Has signaling nan: 1 (float) Has quiet nan: 1 (float) Has signaling nan: 1 The quiet NaN for type float is: nan The quiet NaN for type double is: nan The quiet NaN for type long double is: nan The signaling NaN for type floatis: nan The signaling NaN for type double is: nan The signaling NaN for type long double is: nan NAN from math.h is: nan AIX === ./testnan (double) Has quiet nan: 1 (double) Has signaling nan: 1 (long double) Has quiet nan: 1 (long double) Has signaling nan: 1 (float) Has quiet nan: 1 (float) Has signaling nan: 1 The quiet NaN for type float is: -NaNQ The quiet NaN for type double is: -NaNQ The quiet NaN for type long double is: -NaNQ The signaling NaN for type floatis: -INF The signaling NaN for type double is: -INF The signaling NaN for type long double is: -INF NAN from math.h is: NaNQ Windows MS VC V12 (Visual Studio 6) =================================== testnan.exe (double) Has quiet nan: 1 (double) Has signaling nan: 1 (long double) Has quiet nan: 1 (long double) Has signaling nan: 1 (float) Has quiet nan: 1 (float) Has signaling nan: 1 The quiet NaN for type float is: -1.#IND The quiet NaN for type double is: -1.#IND The quiet NaN for type long double is: -1.#IND The signaling NaN for type floatis: -1.#INF The signaling NaN for type double is: -1.#INF The signaling NaN for type long double is: -1.#INF Windows MS VC V13 (Visual C++ Toolkit 2003) =========================================== testnan.exe (double) Has quiet nan: 1 (double) Has signaling nan: 1 (long double) Has quiet nan: 1 (long double) Has signaling nan: 1 (float) Has quiet nan: 1 (float) Has signaling nan: 1 The quiet NaN for type float is: 1.#QNAN The quiet NaN for type double is: 1.#QNAN The quiet NaN for type long double is: 1.#QNAN The signaling NaN for type floatis: 1.#QNAN The signaling NaN for type double is: 1.#QNAN The signaling NaN for type long double is: 1.#QNAN So this is quite messed up. What do you think Rick ? Bye Rainer ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 17:26 Message: Hello, this was just as a quick test to see if the helps - not a suggestion for an patch. With this hack all unit test passes on AIX. I just have added your suggested code change. It should set the result reliable. Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-30 17:20 Message: Sorry, there should be no platform-specific #ifdefs added to any of the shared code. It would be permissible to use something like #ifdef USE_QUIET_NAN and define that as part of the configuration, but no direct platform references should appear in common code. However, I'd prefer a method that didn't require any conditionals at all. For example, I think this would work: result = std::numeric_limits<double>::signaling_NaN(); // this will be false if this is really a NaN value. If true, // then fall back and use the quiet version. if (!isnan(result)) { result = std::numeric_limits<double>::quiet_NaN(); } ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 17:12 Message: Hello, OK, this is the resilt for Marks sample: (double) Has quiet nan: 1 (double) Has signaling nan: 1 (float) Has quiet nan: 1 (float) Has signaling nan: 1 The quiet NaN for type float is: -NaNQ The quiet NaN for type double is: -NaNQ The signaling NaN for type floatis: -INF The signaling NaN for type double is: -INF currently I have added the following code to StringClass.cpp: // non numeric, so this could be one of the special cases if (strCompare("nan")) { #ifdef AIX result = std::numeric_limits<double>::quiet_NaN(); #else result = std::numeric_limits<double>::signaling_NaN(); #endif return true; } Please could you give me a heads up what the problem is ?? To be honest I do have a little problem with signaling and quiet... Bye Rainer ---------------------------------------------------------------------- Comment By: Mark Miesfeld (miesfeld) Date: 2008-10-30 17:09 Message: Rainer, Why don't you make your last program as the below, to be sure Rick can see what has_signaling_NaN is returning. #include <iostream> #include <limits> using namespace std; int main( ) { cout << "(double) Has quiet nan: " << numeric_limits<double>::has_quiet_NaN << endl; cout << "(double) Has signaling nan: " << numeric_limits<double>::has_signaling_NaN << endl; cout << "(float) Has quiet nan: " << numeric_limits<float>::has_quiet_NaN << endl; cout << "(float) Has signaling nan: " << numeric_limits<float>::has_signaling_NaN << endl; cout << "The quiet NaN for type float is: " << numeric_limits<float>::quiet_NaN( ) << endl; cout << "The quiet NaN for type double is: " << numeric_limits<double>::quiet_NaN( ) << endl; cout << "The signaling NaN for type floatis: " << numeric_limits<float>::signaling_NaN( ) << endl; cout << "The signaling NaN for type double is: " << numeric_limits<double>::signaling_NaN( ) << endl; } ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 16:44 Message: Hello, strange... it really looks like signaling_NaN() returns -INF on AIX. Here is another short test: #include <iostream> #include <limits> using namespace std; int main( ) { cout << "The quiet NaN for type float is: " << numeric_limits<float>::quiet_NaN( ) << endl; cout << "The quiet NaN for type double is: " << numeric_limits<double>::quiet_NaN( ) << endl; cout << "The signaling NaN for type floatis: " << numeric_limits<float>::signaling_NaN( ) << endl; cout << "The signaling NaN for type double is: " << numeric_limits<double>::signaling_NaN( ) << endl; } The quiet NaN for type float is: -NaNQ The quiet NaN for type double is: -NaNQ The signaling NaN for type floatis: -INF The signaling NaN for type double is: -INF Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-30 16:25 Message: But you say that <double>has_signaling_NaN() is returning true? I really don't want to have this returning a quiet NaN on all platforms. This library seems like it's seriously messed up. A potential work around is to add the test "if (value == value)" (or even an isnan() test) to make sure we got a NaN value and fall back to the quiet NaN if necessary. I'd prefer that the sequence just use has_signaling_NaN(), but if that's not returning a valid result, we can't rely on that. ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 16:16 Message: Hello, yes std::numeric_limits<double>::quiet_NaN() is there and it looks like isnan() returns >0.. This is the class for double (from limits) // CLASS numeric_limits<double> template<> class _CXX_IMPORT numeric_limits<double> : public _Num_float_base { public: typedef double _Ty; static _Ty (min)() _THROW0() {return (DBL_MIN); } static _Ty (max)() _THROW0() {return (DBL_MAX); } static _Ty epsilon() _THROW0() {return (DBL_EPSILON); } static _Ty round_error() _THROW0() {return (0.5); } static _Ty denorm_min() _THROW0() {return (_Denorm._D); } static _Ty infinity() _THROW0() {return (_Inf._D); } static _Ty quiet_NaN() _THROW0() {return (_Nan._D); } static _Ty signaling_NaN() _THROW0() {return (_Snan._D); } _STCONS(int, digits, DBL_MANT_DIG); _STCONS(int, digits10, DBL_DIG); _STCONS(int, max_exponent, DBL_MAX_EXP); _STCONS(int, max_exponent10, DBL_MAX_10_EXP); _STCONS(int, min_exponent, DBL_MIN_EXP); _STCONS(int, min_exponent10, DBL_MIN_10_EXP); }; I have changed one line in ooRexx (just as a test): interpreter/classes/StringClass.cpp - result = std::numeric_limits<double>::signaling_NaN(); + result = std::numeric_limits<double>::quiet_NaN(); With this change all tests from ooRexx/API/oo are sucessfully: ./runTest.sh -b -B -R ooRexx/API/oo Setting env for AIX Searching for test containers.. Executing automated test suite.. ooTest Framework - Automated Test of the ooRexx Interpreter Interpreter: REXX-ooRexx_4.0.0(MT) 6.03 30 Oct 2008 ooRexxUnit: 2.0.0_3.2.0 ooTest: 1.0.0_4.0.0 Tests ran: 474 Assertions: 1494 Failures: 0 Errors: 0 Skipped files: 0 File search: 00:00:00.687537 Suite construction: 00:00:00.157881 Test execution: 00:00:00.490093 Total time: 00:00:04.411396 Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-30 16:01 Message: Sorry, I meant std::numeric_limits<double>::quiet_NaN(). But also need to know the result returned by std::numeric_limits<double>::has_signaling_NaN() and std::numeric_limits<double>::has_quiet_NaN(). Trying to do too many things at once leads to copy and paste errors :-) ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 15:59 Message: Hello, if (std::numeric_limits<double>::has_signaling_NaN) printf("std::numeric_limits<double>::has_signaling_NaN() true\n"); => true ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 15:42 Message: Hello, I just checked... it looks like the return is -INF. template<> class _CXX_IMPORT numeric_limits<double> : public _Num_float_base { public: ... static _Ty signaling_NaN() _THROW0() {return (_Snan._D); } from yvals.h #define _Snan _Snan_ieee AIX defines NAN in math.h as: static const unsigned int _SQNAN = 0x7fc00000; #define NAN (*((float *)(&_SQNAN))) >Secondly, try your test using >std::numeric_limits<double>::signaling_NaN(). It this works, there is a >workaround for this problem. ?? std::numeric_limits<double>::signaling_NaN() is what I have used in my example... Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-30 15:25 Message: Well, that certainly seems to point to a problem with the value returned by std::numeric_limits<double>::signaling_NaN(). It appears to be returning the -infinity value rather than the signaling_NaN() value. Ok, a couple of things to try. First, what is the value of std::numeric_limits<double>::has_signaling_NaN()? Secondly, try your test using std::numeric_limits<double>::signaling_NaN(). It this works, there is a workaround for this problem. ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 15:22 Message: Hello, ok here is the thing: With the following test: #include <stdio.h> #include <math.h> #include <limits> int main(void) { /* double number = NAN; */ double number = std::numeric_limits<double>::signaling_NaN(); if (isnan(number)) { printf(">0\n"); } else if (number == +HUGE_VAL) { printf("+HUGE_VAL\n"); } else if (number == -HUGE_VAL) { printf("-HUGE_VAL\n"); } else { printf("none\n"); } return(0); } I get the following results: Linux SLES9 / 32 Bit ./test >0 AIX 5.3 32 bit compile on 64 bit OS: ./test -HUGE_VAL Bye Rainer ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 15:15 Message: Hello, I am not good the the C++ stuff ... but here is another example: #include <stdio.h> #include <math.h> #include <limits> int main(void) { /* double number = NAN; */ double number = std::numeric_limits<double>::signaling_NaN(); printf("number=%lld\n", number); // make a nan value a string value if (isnan(number)) { printf(">0\n"); } else if (number == -HUGE_VAL) { printf("HUGE_VAL"); } else { printf("no\n"); } return(0); } ./test_isnan number=-4503599627370496 HUGE_VAL Bye Rainer ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 15:01 Message: Hello, on Linux (SLES9 / 32 bit): ./test number=1074642088 >0 Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-30 15:00 Message: I'm not sure I understand what you mean by "where is nan defined ??". In that context, "nan" is just the character string "nan". The ObjectToDouble() code recognizes that value as special and returns the value "std::numeric_limits<double>::signaling_NaN()" as a result. This is part of the standard C++ standard library. That's the value you need to be using in your test program. ---------------------------------------------------------------------- Comment By: Rainer Tammer (tammer) Date: 2008-10-30 14:54 Message: Hello, in the test you use val = "nan". where is nan defined ?? this is a little test: #include <stdio.h> #include <math.h> int main(void) { double number = NAN; /* NAN comes from math.h */ printf("number=%ld\n"); .... // make a nan value a string value if (isnan(number)) { printf(">0\n"); } else if (number == +HUGE_VAL) { printf("+infinity\n"); } else if (number == -HUGE_VAL) { printf("-infinity\n"); } return(0); } ./test_isnan number=804399748 >0 Bye Rainer ---------------------------------------------------------------------- Comment By: Rick McGuire (bigrixx) Date: 2008-10-29 17:56 Message: I see two potential places where things can go wrong, but this most likely is due to a problem in the C++ libraries. The first place is where you noted. It's possible that std::numeric_limits<double>::signaling_NaN() is not actually returning a NaN value. The other place is in NumberString::newInstanceFromDouble() where the double object is converted back into a Rexx object. It is possible that the test for isnan() is failing, but given that an "==" comparison is always supposed to fail for a NaN value, the comparison to -HUGE_VAL should not work. The other possibility is it made it through all of the if special cases and sprintf() formatted the value as "-infinity" for us. Understanding where the "-infinity" string comes from would help narrow down the real point of failure. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=684730&aid=2207721&group_id=119701 |