the ldexp test case
The mingwex library contain functions ldexpl() and ldexpf() .
The function ldexp() from msvcrt library is buggy and
as example result of ldexp(1., INT_MAX) is 0(zero) instead inf. The tested msvcrt is 7.0+. May be is fixed in recent but not system default libraries.
As work around I test with a new mingwex double function. The body of ldexp() is same as for ldexpf() only float is replaced by double. After this the library is rebuild in crossenvironment.
The test case is attached and results are:
1) before
ldexpf(1., 2147483647)=0, errno=0
ldexp (1., 2147483647)=0, errno=0
ldexpl(1., 2147483647)=inf, errno=34
2) after
ldexpf(1., 2147483647)=inf, errno=34
ldexp (1., 2147483647)=inf, errno=34
ldexpl(1., 2147483647)=inf, errno=34
The result for ldexp (double argument and result) is expected.
The issue is for ldexpf (float argument and result). Before (mingwex library is from distribution) result is zero and without error.
Is possible this to be compiler/linker issue, mainly in native build ?
the ldexp test case
Roumen,
Thanks for the report; herewith, some initial comments:
1) Please choose a title, (SF call it the `summary'), which describes the actual problem.
2) C99 is extremely vague about how the ldexp() functions should handle exponent overflow;
http://www.openstd.org/jtc1/sc22/wg14/www/docs/n1124.pdf 7.12.6.6 says only:
The ldexp functions multiply a floatingpoint number by an
integral power of 2. A range error may occur.
3) POSIX is more prescriptive;
http://www.opengroup.org/onlinepubs/009695399/functions/ldexp.html says:
Upon successful completion, these functions shall return x
multiplied by 2, raised to the power exp.

If these functions would cause overflow, a range error shall
occur and ldexp(), ldexpf(), and ldexpl() shall return ±HUGE_VAL,
±HUGE_VALF, and ±HUGE_VALL (according to the sign of x),
respectively.

If the correct value would cause underflow, and is not
representable, a range error may occur, and an implementation
defined value shall be returned.
In this latter case, the return value of 0.0 is preferred, especially if IEC 60559 floating point is supported. Additional requirements for IEC 60559 support also demand:
If x is NaN, a NaN shall be returned.
If x is ±0 or ±Inf, x shall be returned.
If exp is 0, x shall be returned.
If the correct value would cause underflow, and is
representable, a range error may occur and the correct
value shall be returned.
4) libmingwex.a does not actually provide any implementation for either ldexp() or ldexpf(); the ldexpf() you see there is nothing more than a wrapper around the MSVCRT implementation of ldexp(). The bug you report lies in this Microsoft implementation.
5) MinGW's minimalist philosophy does not aim to fix Microsoft bugs; indeed there are even some users who get very upset, when we do so. While fixing this particular bug may be trivial, the fix doesn't belong in libmingwex.a, without a clear directive from a majority of the user community, to override the broken Microsoft behaviour.
6) Since the effect of any of the ldexp() functions is to add the value of the second argument to the exponent value already defined within the floating point representation of the first, it makes no sense whatsoever to add INT_MAX to a field value which is already bounded by the limits FLT_MIN_EXP...FLT_MAX_EXP, DBL_MIN_EXP...DBL_MAX_EXP or LDBL_MIN_EXP...LDBL_MAX_EXP. While it would be nice if all ldexp() implementations did trap this error, you should recognise that some don't, (Microsoft's being a case in point), and you should code defensively, to avoid the issue.
After some further thought, I believe we could adapt the existing MinGW implementation of ldexpl(), to provide a generic implementation for ldexpf() and ldexp(), such as the attached; (I already have a Makefile infrastructure patch to support such generic implementations). This would provide __mingw_ldexp(), __mingw_ldexpf() and __mingw_ldexpl() in libmingwex.a, with two of these aliased to ldexpf() and ldexpl() as appropriate, but leaving MSVCRT.DLL to provide ldexp(). This way, those who expect the MSVCRT behaviour would not be disappointed, while those who prefer the behaviour you advocate may
#define ldexp __mingw_ldexp
to get a (hopefully better) implementation. (Caveat: I haven't tested this rigorously).
File Added: ldexp_generic.c
Proposed new generic function implementation.
Uhh, Keith you find the bug.
I didn't realize that ldexpf use ldexp. All the time, may be because I expect this, I think that ldexpf call ldexpl (!). So may initial report is without base. This explain my initial subject/title/summary.
About 6) The value of INT_MAX is from python function from math module. Now I see that implementation is not correct for overflow. For underflow it is not correct too.
My test show that ldexpl(1., N) return nonzero and no error , if N is __LDBL_MIN_EXP__  64. For N=__LDBL_MIN_EXP__65 , the result is zero and errno is ERANGE.
About ldexp_generic.c  looks good.
No idea for replacement #define ldexp __mingw_ldexp.
My experience show that results of math functions from msvcrt 7.0 are far from expected results from some test vectors. May be define has to be default if posix flag is set, i.e. same as for posix io.
The python (www.python.org) provide a (may be too strict for some libraries) math regression test case. Test for ldexp is from <REPOROOT>/Lib/test/test_math.py .
Keith, what is the status of this issue?
I guess it stalled. There was no peer review, so I took it no further. Since the MSVCRT implementation appears to be comprehensively broken, it would seem prudent to resurrect; would you like me to run with it?
Any thoughts about Roumen's idea to promote the replacement in all three cases, when posix is in effect? (It seems a reasonable option, IMO).
I review a bit later.
Log in to post a comment.