Document: WG14 N1629


DR 410 discussion


Submitter: Fred J. Tydeman (USA)
Submission Date: 2012-8-30
Related:WG14 N1593
Subject: f(inf) is inf being a range error

  1. Fixing a contradiction.

    7.12.1 paragraph 5 has:

    A floating result overflows if the magnitude of the mathematical result is finite but so large that the mathematical result cannot be represented without extraordinary roundoff error ...

    For example, exp(+DBL_MAX) is a very very large finite number that cannot be represented as a double, so is overflow, so is a range error.

    7.12.1 paragraph 6 has:

    The result underflows if the magnitude of the mathematical result is so small that the mathematical result cannot be represented, without extraordinary roundoff error ...

    For example, exp(-DBL_MAX) is a very very small (non-zero) finite number that cannot be represented as a double, so is underflow, so is a range error.

    For the type double, since +DBL_MAX < +infinity and -infinity < -DBL_MAX, it follows that |+/-DBL_MAX| < |+/-infinity|; that is, the magnitude of infinity is larger than the magnitude of any finite number. So, if x being DBL_MAX is "too large", then x being infinity is also "too large".

    exp(+infinity) is exactly +infinity (which is representable, but not finite, so it is not an overflow, so is not a range error).

    exp(-infinity) is exactly zero (which is representable, so it is not an underflow, so is not a range error).

    However, 7.12.6.1 exp() has:

    A range error occurs if the magnitude of x is too large.

    This is a contradiction in the C standard. x being +/-infinity is "too large", so exp(too large) is a range error. But, exp(+/-infinity) is exact and representable, so is not a range error. Other standards, such as IEEE-754-2008, LIA (Language Independent Arithmetic) and POSIX-2008 all consider exp(+/-infinity) as NOT an error.

    There appears to be two ways to fix this contradiction. The first is to somehow add infinity to the definition of overflow, underflow, and range error. This seems like a non-starter.

    The other way to fix this contradiction is to remove infinity from the "too large" requirement. That can be done by adding "finite" giving:

    A range error occurs if the magnitude of finite x is too large.

    Or, it can be done by altering the first sentence of 7.12.1 to:

    The behavior of each of the functions in <math.h> is specified for all representable finite values of its input arguments, except where stated otherwise.

    That also matches the floating-point number model in 5.2.4.2.2 (that only has finite numbers).

  2. Taking care of infinity.

    Now, what should happen for the infinity cases?

    There are several choices:

    1. Say nothing, which means we have an implicit undefined behaviour (as per section 4.0 paragraph 2).
    2. Add a global statment (as a new paragraph in 7.12) along the lines of:
      Unless stated otherwise, the behaviour of a math function with an infinity argument is undefined behaviour.

      Or

      Unless stated otherwise, the behaviour of a math function with an infinity argument is bounded undefined behaviour (as per section L.2.2).

      Or

      Unless stated otherwise, the behaviour of a math function with an infinity argument is implementation defined.
    3. Add a local statment (to those few functions where we are adding "finite") along the lines of:
      The behaviour of this math function with an infinity argument is undefined behaviour.

      Or

      The behaviour of this math function with an infinity argument is bounded undefined behaviour.

      Or

      The behaviour of this math function with an infinity argument is implementation defined if a range error occurs or not.

    Independent of the above, we could add to 7.12.1 paragraph 4 along the lines of:

    The description of each function lists any required range errors; an implementation may define additional range errors, provided that such errors are consistent with the mathematical definition of the function.

    Independent of the above, we could do one of the following:

    1. Add a footnote to 7.12.1 paragraph 4 along the lines of:
      In an implementation that supports infinities, a range error may happen for functions that map an infinity argument into an exact result (such as infinity, zero, or subnormal).
    2. We could add a global statement to 7.12.1 paragraph 4 along the lines of:
      Recommended practice

      In an implementation that supports infinities, a range error should not happen for functions that map an infinity argument into an exact result (such as infinity, zero, or subnormal).

    3. We could add a local statement (to those few functions where we are adding "finite") along the lines of:
      Recommended practice

      In an implementation that supports infinities, a range error should not happen for an infinite argument.