#1221 ldexp() functions mishandle exponent overflow


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 cross-environment.

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 ?


  • Roumen Petrov

    Roumen Petrov - 2008-12-06

    the ldexp test case

  • Keith Marshall

    Keith Marshall - 2008-12-09
    • milestone: --> 519164
    • summary: mingwex - native and cross-build --> ldexp() functions mishandle exponent overflow
    • status: open --> pending-wont-fix
  • Keith Marshall

    Keith Marshall - 2008-12-09


    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.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf says only:
    |The ldexp functions multiply a floating-point 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),
    |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.

  • Keith Marshall

    Keith Marshall - 2008-12-09
    • milestone: 519164 -->
    • status: pending-wont-fix --> open
  • Keith Marshall

    Keith Marshall - 2008-12-09

    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

  • Keith Marshall

    Keith Marshall - 2008-12-09

    Proposed new generic function implementation.

  • Roumen Petrov

    Roumen Petrov - 2008-12-09

    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 .

  • Earnie Boyd

    Earnie Boyd - 2013-02-05

    Keith, what is the status of this issue?

    • Keith Marshall

      Keith Marshall - 2013-02-06

      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).

  • Earnie Boyd

    Earnie Boyd - 2013-02-05
    • labels: gcc --> ldexp, ldexpl, ldexpf
    • status: open --> pending
    • assigned_to: Keith Marshall
    • resolution: --> none
    • category: --> Unknown
    • milestone: --> WSL
  • Earnie Boyd

    Earnie Boyd - 2013-02-06
    • assigned_to: Keith Marshall --> Earnie Boyd
    • resolution: none --> later
  • Earnie Boyd

    Earnie Boyd - 2013-02-06

    I review a bit later.

  • Earnie Boyd

    Earnie Boyd - 2013-02-19
    • type: --> Bug
    • category: Unknown --> Feature_in_WSL_4.1
    • patch_attached: --> False

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.

No, thanks