From: "h.shirosaki (Hiroshi Shirosaki)" Date: 2012-10-11T22:13:26+09:00 Subject: [ruby-core:47911] [ruby-trunk - Bug #7142][Open] mingw TestFloat#test_round_with_precision failure Issue #7142 has been reported by h.shirosaki (Hiroshi Shirosaki). ---------------------------------------- Bug #7142: mingw TestFloat#test_round_with_precision failure https://bugs.ruby-lang.org/issues/7142 Author: h.shirosaki (Hiroshi Shirosaki) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-10-09 trunk 37127) [i386-mingw32] =begin Trunk ruby on Windows XP x86 with mingw-w64 gcc 4.7.2 has the following test failure. 1) Failure: test_round_with_precision(TestFloat) [C:/Users/Worker/Jenkins/workspace/ruby-trunk-x86-build/test/ruby/test_float.rb:389]: <1.0e-300> expected but was <9.999999999999994e-301>. I get the failure with `make test-all TESTS="-qv -n test_round_with_precision"`. But it's strange that I don't get the failure with `make test-all TESTS="-qv ruby/test_float.rb"`. And This failure doesn't occur on Win7. Floating-point precision seems to be changed for some reason. Mingw-w64 has own pow() implementation and the precision of pow(10, ndigits) is not proper. I found calling (({_controlfp(_PC_64, _MCW_PC)})) before pow() improves precision and fixes this failure. I'll commit this patch if there is no other better fix. Index: include/ruby/win32.h =================================================================== --- include/ruby/win32.h (revision 37136) +++ include/ruby/win32.h (working copy) @@ -764,7 +764,7 @@ } /* extern "C" { */ #endif -#ifdef __MINGW64__ +#if defined(__MINGW64__) /* * Use powl() instead of broken pow() of x86_64-w64-mingw32. * This workaround will fix test failures in test_bignum.rb, @@ -775,6 +775,24 @@ { return powl(x, y); } +#elif defined(__MINGW64_VERSION_MAJOR) +/* + * Set floating point precision for pow() of mingw-w64 x86. + * With default precision the result is not proper on WinXP. + */ +static inline double +rb_w32_pow(double x, double y) +{ + double r; + unsigned int default_control = _controlfp(0, 0); + _controlfp(_PC_64, _MCW_PC); + r = pow(x, y); + /* Restore setting */ + _controlfp(default_control, _MCW_PC); + return r; +} +#endif +#if defined(__MINGW64_VERSION_MAJOR) || defined(__MINGW64__) #define pow rb_w32_pow #endif =end -- http://bugs.ruby-lang.org/