newlib-cygwin/newlib/libm
Kito Cheng ca7b4bd236 libm: Fixing overflow handling issue for scalbnf and scalbn
cc Aldy Hernandez <aldyh@redhat.com> and Andrew MacLeod <amacleod@redhat.com>,
they are author of new VRP analysis for GCC, just to make sure I didn't
mis-understanding or mis-interpreting anything on GCC site.

GCC 11 have better value range analysis, that give GCC more confidence
to perform more aggressive optimization, but it cause scalbn/scalbnf get
wrong result.

Using scalbn to demostrate what happened on GCC 11, see comments with VRP
prefix:

```c
double scalbn (double x, int n)
{
	/* VRP RESULT: n = [-INF, +INF] */
        __int32_t  k,hx,lx;
        ...
        k = (hx&0x7ff00000)>>20;
	/* VRP RESULT: k = [0, 2047] */
        if (k==0) {
	    /* VRP RESULT: k = 0 */
	    ...
	    k = ((hx&0x7ff00000)>>20) - 54;
            if (n< -50000) return tiny*x;       /*underflow*/
	    /* VRP RESULT: k = -54 */
	}
	/* VRP RESULT: k = [-54, 2047] */
        if (k==0x7ff) return x+x;               /* NaN or Inf */
	/* VRP RESULT: k = [-54, 2046] */
        k = k+n;
        if (k > 0x7fe) return huge*copysign(huge,x); /* overflow  */
	/* VRP RESULT: k = [-INF, 2046] */
	/* VRP RESULT: n = [-INF, 2100],
	   because k + n <= 0x7fe is false, so:
	   1. -INF < [-54, 2046] + n <= 0x7fe(2046) < INF
	   2. -INF < [-54, 2046] + n <= 2046 < INF
	   3. -INF < n <= 2046 - [-54, 2046] < INF
	   4. -INF < n <= [0, 2100] < INF
	   5. n = [-INF, 2100] */
        if (k > 0)                              /* normal result */
            {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
        if (k <= -54) {
	    /* VRP OPT: Evaluate n > 50000 as true...*/
            if (n > 50000)      /* in case integer overflow in n+k */
                return huge*copysign(huge,x);   /*overflow*/
            else return tiny*copysign(tiny,x);  /*underflow*/
	}
        k += 54;                                /* subnormal result */
        SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
        return x*twom54;
}
```

However give the input n = INT32_MAX, k = k+n will overflow, and then we
expect got `huge*copysign(huge,x)`, but new VRP optimization think
`n > 50000` is never be true, so optimize that into `tiny*copysign(tiny,x)`.

so the solution here is to moving the overflow handle logic before `k = k + n`.
2021-07-21 09:56:04 +02:00
..
common libm: Fixing overflow handling issue for scalbnf and scalbn 2021-07-21 09:56:04 +02:00
complex Add build mechanism to share common header files between machines 2021-04-13 12:55:33 +02:00
fenv fenv: fix up stub file comment, drop symlinks from description 2021-04-13 12:55:34 +02:00
machine fix some Arm FP routines not checking if floating point is enabled 2021-04-21 16:18:09 +01:00
math Fix rounding issues with sqrt/sqrtf 2021-06-04 14:42:58 -04:00
mathfp Add build mechanism to share common header files between machines 2021-04-13 12:55:33 +02:00
test Remove matherr, and SVID and X/Open math library configurations 2019-01-23 10:46:24 +01:00
Makefile.am Add default implementation of fenv.h and all methods 2019-08-09 17:49:16 +02:00
Makefile.in Add build mechanism to share common header files between machines 2021-04-13 12:55:33 +02:00
aclocal.m4 Fix libm regenerated files again. 2016-02-17 17:06:46 -05:00
config.h.in import newlib-2000-02-17 snapshot 2000-02-17 19:39:52 +00:00
configure Add build mechanism to share common header files between machines 2021-04-13 12:55:33 +02:00
configure.in Add default implementation of fenv.h and all methods 2019-08-09 17:49:16 +02:00
libm.in.xml fenv: Include documentation in generated .info file 2019-08-15 12:04:50 +02:00
libm.texinfo fenv: Include documentation in generated .info file 2019-08-15 12:04:50 +02:00