Hi... Recently a problem was discovered with the function pow().
It is possible to let it's computation run into an infinite loop, when using mingw-w64-crt! I took a *DEEP* look into it: This - fortunately - only happens with a special case: x^-2147483648 This is (in hexadecimal) 0x80000000. pow() detects that the exponent is an integer and diverts execution to powi() which is specialized to integer exponents. As x^-y is mathematically handled as 1/(x^y) powi() tries to invert y (the exponent) by executing y = -y; and continues to do computation as having a positive exponent. But, 0x80000000 cannot be inverted. The result is again 0x80000000. Afterwards powi() shifts y by one bit to the right as long as y is > 0. This can never be 0. After 31 shifts y is 0xffffffff => Endless loop. I created 2 patches to solve this problem. The patches have undergone an intensive test during the last weekend. One to powi.def.h and one to pow.def.h. powi.def.h patch: ================= It simply catches the case when powi() is called with this very special exponent and returns 0 as result. pow.def.h patch: ================ pow() calls powi() in case y is an integer and INT_MIN <= y <= INT_MAX. My patch changes to call powi() only if INT_MIN < y <= INT_MAX.When y = -2147483648 (INT_MIN) now it uses floating point implementation now which produces the correct result but has a
slight speed impact for THIS exponent. Well the pow() patch itself is sufficient to solve the problem. I created the additional powi() patch just for the case powi() is once called directly without pow() in front to prevent an endless loop. Furthermore I have removed duplicate including of errno.h in both files. I hope this can easily be applied. Greetings from OneVision, Roland
--- mingw-w64-crt/math/pow.def.h.orig 2013-01-02 15:40:35.000000000 +0100 +++ mingw-w64-crt/math/pow.def.h 2014-03-24 11:30:45.726875500 +0100 @@ -71,7 +71,7 @@ #include <limits.h> #include <fenv.h> #include <math.h> -#include <errno.h> + #define FE_ROUNDING_MASK \ (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO) @@ -204,7 +204,7 @@ return rslt; } } - else if ((d <= (__FLT_TYPE) INT_MAX && d >= (__FLT_TYPE) INT_MIN)) + else if ((d <= (__FLT_TYPE) INT_MAX && d > (__FLT_TYPE) INT_MIN)) return __FLT_ABI (__powi) (x, (int) y); /* As exp already checks for minlog and maxlog no further checks are necessary. */ rslt = (__FLT_TYPE) exp2l ((long double) y * log2l ((long double) __FLT_ABI(fabs) (x)));
--- mingw-w64-crt/math/powi.def.h.orig 2012-01-18 22:30:59.000000000 +0100 +++ mingw-w64-crt/math/powi.def.h 2014-03-21 10:38:37.746213800 +0100 @@ -66,7 +66,6 @@ #include <limits.h> #include <fenv.h> #include <math.h> -#include <errno.h> __FLT_TYPE __cdecl __FLT_ABI(__powi) (__FLT_TYPE x, int y); @@ -125,6 +124,11 @@ if (y < 0) { + /* corner case y == -2147483648 (0x80000000) + this is not negateable => return 0 */ + if (y == -2147483648) + return __FLT_CST (0.0); + d = __FLT_CST(1.0) / d; y = -y; }
------------------------------------------------------------------------------ Learn Graph Databases - Download FREE O'Reilly Book "Graph Databases" is the definitive new guide to graph databases and their applications. Written by three acclaimed leaders in the field, this first edition is now available. Download your free book today! http://p.sf.net/sfu/13534_NeoTech
_______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public