Commit Graph

7 Commits

Author SHA1 Message Date
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
Yaakov Selkowitz 3312f960a7 libm/common: remove TRAD_SYNOPSIS
Signed-off-by: Yaakov Selkowitz <yselkowi@redhat.com>
2017-12-01 03:41:53 -06:00
Jeff Johnston 53617ce4e6 Consistently use an em-dash in math functions.
- also move previous ChangeLog entry to newlib instead of top-level

        * libc/time/wcsftime.c: Consistently use an em-dash in FUNCTION
summary.
        * libm/common/isgreater.c: Ditto.
        * libm/common/s_fdim.c: Ditto.
        * libm/common/s_fma.c: Ditto.
        * libm/common/s_fmax.c: Ditto.
        * libm/common/s_fmin.c: Ditto.
        * libm/common/s_infinity.c: Ditto.
        * libm/common/s_isnan.c: Ditto.
        * libm/common/s_log2.c: Ditto.
        * libm/common/s_logb.c: Ditto.
        * libm/common/s_lrint.c: Ditto.
        * libm/common/s_lround.c: Ditto.
        * libm/common/s_nearbyint.c: Ditto.
        * libm/common/s_remquo.c: Ditto.
        * libm/common/s_rint.c: Ditto.
        * libm/common/s_round.c: Ditto.
        * libm/common/s_scalbn.c: Ditto.
        * libm/common/s_signbit.c: Ditto.
        * libm/common/s_trunc.c: Ditto.
        * libm/math/w_exp2.c: Ditto.
        * libm/math/w_gamma.c: Ditto.
2015-11-02 16:43:22 -05:00
Jeff Johnston 139f923bb4 2009-03-25 Craig Howland <howland@LGSInnovations.com>
* libc/include/math.h:  (llround, llroundf): Declare.
	* libm/common/s_llround.c: New file, implementing llround().
	* libm/common/sf_llround.c: New file, implementing llroundf().
	* libm/common/sf_lround.c: Remove spurious cast in _DOUBLE_IS_32BITS
	version of function.
	* libm/common/sf_lrint.c: Ditto.
	* libm/common/sf_logb.c:  Corrected return for subnormal argument
	by replacing existing function with a version created from sf_ilogb.c.
	* libm/common/s_logb.c: Ditto, except starting point s_ilogb.c.  Also
	added documentation for logb() and logbf().
	* libm/common/s_signbit.c:  Add signbit() documentation.
	* libm/common/s_log2.c: Update return values to match what w_log2.c has,
	since log2 uses log(); add note about being derived instead of direct.
	* libm/common/sf_fma.c: Add casts to attempt to get correct results,
	as well as comments pointing out problems with the implementation.
	* libm/common/s_fma.c: Add fma() and fmaf() documentation.
	* libm/common/sf_remquo.c: Incorrect quotient returns for large values
	corrected by discarding existing function and replacing with Sun
	verion, with some enhancements.
	* libm/common/s_remquo.c: Ditto.  Add remquo() and remquof()
	documentation.
	* libm/common/s_fmax.c: Add fmax() and fmaxf() documentation.
	* libm/common/s_fmin.c: Add fmin() and fminf() documentation.
	* libm/common/s_fdim.c: Return NAN for NAN arg, add fdim() and fdimf()
	documentation.
	* libm/common/sf_fdim.c: Return NAN for NAN arg, HUGE_VALF for inf arg.
	* libm/common/s_trunc.c: Add trunc() and truncf() documentation.
	* libm/common/s_rint.c: Add rint() and rintf() documentation.
	* libm/common/s_round.c: Add round() and roundf() documentation.
	* libm/common/s_scalbn.c: Add scalbln() and scalblnf() documentation.
	* libm/common/s_infinity.c: Add infinity() and infinityf()
	documentation.
	* libm/common/s_lround.c: Add lround(), lroundf(), llround(), and
	llroundf() documentation.
	* libm/common/s_lrint.c: Add lrint(), lrintf(), llrint(), and llrintf()
	documentation.
	* libm/common/isgreater.c: New file for documenting math.h function-like
	macros isgreater(), isgreaterequal(), isless(), islessequal(),
	islessgreater(), and isunordered().
	* libm/common/s_isnan.c: Add documentation for function-like macros
	fpclassify(), isfinite(), isinf(), isnan(), and isnormal().
	* libm/common/s_nearbyint.c: Add nearbyint() and nearbyintf()
	documentation.
	* libm/common/Makefile.am: Add s_llround.c (src); sf_llround.c (fsrc);
	s_fdim.def, s_fma.def, s_fmax.def, s_fmin.def,
	s_logb.def, s_lrint.def, s_lround.def, s_nearbyint.def, s_remquo.def,
        s_rint.def, s_round.def, s_signbit.def, s_trunc.def, and
        isgreater.def (chobj);
	re-name all existing chew files (chobj) to match source file base
	names (put in underscores), delete all special targets for chew files
	(leaving all to be generated by rule).
	* libm/common/Makefile.in: regenerate.
	* libm/math/w_exp2.c: Add "base 2" to documentation description (and
	delete TRAD_SYNOPSIS).
	* libm/math/w_gamma.c: Add tgamma() and tgammaf() documentation, along
	with some history behind the function names.
	* libm/math/math.tex: Add includes for newly-added documentation (see
	.def additions to common/Makefile.am and math/Makefile.am in this
	ChangeLog list), adjusted existing .def file names to match source file
	base names (added underscores); add mention of HUGE_VALF; rename
	"Version of library" section to "Error Handling" and add some text
	about floating-point exception; added section "Standards Compliance And
	Portability".
	* libm/math/Makefile.am: Add w_exp2.def (chobj);
	re-name all existing chew files (chobj) to match source file base
	names, delete all special targets for chew files (leaving all to be
	generated by rule).
	* libm/math/Makefile.in: regenerated
	* doc/makedoc.c: Change silent ignoring of commands < 5 characters
	to a failure when reading macro file for commands < 4 characters;
	add -v (verbose) option for printing some debugging information;
	get rid of spurious translation of "@*" to "*" (no source files used @*,
	so no existing doc pages were affected); clean up some compiler
	warnings.
	* doc/doc.str: add BUGS and SEEALSO sections (to match texi2pod.pl
	which has them); Remove ITEM command (redundant with makedoc built-in
	"o", not used in any present source file so nothing is lost, anyway).
	* HOWTO: New file to hold information for maintainers regarding how
	to do things.  Initial sections on documentation and ELIX levels.
2009-03-25 19:13:24 +00:00
Jeff Johnston 76a7df5256 2003-10-20 Bob Wilson <bob.wilson@acm.org>
* libc/locale/locale.c: Use double quotes in code.
	* libc/locale/locale.tex: Likewise.
	* libc/libc.texinfo: Hyphenate "floating-point".
	* libc/machine/necv70/necv70.tex: Likewise.
	* libc/stdio/sprintf.c: Likewise.
	* libc/stdio/sscanf.c: Likewise.
	* libc/stdlib/atof.c: Likewise.
	* libc/stdlib/ldtoa.c: Fix comment typo.
	* libc/stdlib/div.c: Use @ifnottex instead of @ifinfo.
	* libc/stdlib/ldiv.c: Likewise.
	* libm/common/s_expm1.c: Likewise.
	* libm/common/s_ilogb.c: Hyphenate "floating-point".  Use "nonzero".
	* libm/common/s_infinity: Hyphenate "double- and single-precision".
	* libm/common/s_nan.c: Likewise.  Also correct the FUNCTION summary.
	* libm/common/s_nextafter.c: Fix typo.  Hyphenate "double-precision"
	and "floating-point".
	* libm/common/s_scalbn.c: Correct the FUNCTION summary.
	* libm/math/e_pow.c: Fix comment typo.
	* libm/math/math.tex: Hyphenate "single-precision" and "floating-point".
	* libm/math/s_asinh.c: Use @ifnottex instead of @ifinfo.
	* libm/math/s_atan.c: Likewise.
	* libm/math/s_frexp.c: Likewise.  Also use "nonzero".
	* libm/math/s_isnan.c: Hyphenate "single-precision" and
	"floating-point".  Use "nonzero".
	* libm/math/s_ldexp.c: Use @ifnottex instead of @ifinfo.
	* libm/math/w_acos.c: Likewise.
	* libm/math/w_acosh.c: Likewise.
	* libm/math/w_asin.c: Likewise.
	* libm/math/w_atan2.c: Likewise.
	* libm/math/w_atanh.c: Likewise.
	* libm/math/w_cosh.c: Likewise.
	* libm/math/w_exp.c: Likewise.
	* libm/math/w_exp2.c: Likewise.  Add missing @end and missing @tex
	version of 2^x in the description.
	* libm/math/w_fmod.c: Use @ifnottex instead of @ifinfo.
	* libm/math/w_gamma.c: Likewise.
	* libm/math/w_hypot.c: Likewise.
	* libm/math/w_j0.c: Likewise.
	* libm/math/w_sinh.c: Likewise.
	* libm/math/w_pow.c: Replace "exp1.0nt" with "exponent".
	* libm/mathfp/mathfp.tex: Hyphenate "single-precision" and
	"floating-point".
	* libm/mathfp/e_acosh.c: Use @ifnottex instead of @ifinfo.
	* libm/mathfp/e_atanh.c: Likewise.
	* libm/mathfp/e_hypot.c: Likewise.
	* libm/mathfp/er_lgamma.c: Likewise.
	* libm/mathfp/s_acos.c: Likewise.
	* libm/mathfp/s_asine.c: Likewise.
	* libm/mathfp/s_asinh.c: Likewise.
	* libm/mathfp/s_atan.c: Likewise.
	* libm/mathfp/s_atan2.c: Likewise.
	* libm/mathfp/s_atangent.c: Likewise.
	* libm/mathfp/s_cosh.c: Likewise.
	* libm/mathfp/s_exp.c: Likewise.
	* libm/mathfp/s_fmod.c: Likewise.
	* libm/mathfp/s_frexp.c: Likewise.  Also use "nonzero".
	* libm/mathfp/s_isnan.c: Hyphenate "single-precision" and
	"floating-point".  Use "nonzero".
	* libm/math/s_pow.c: Replace "exp1.0nt" with "exponent".
	* libm/mathfp/s_ldexp.c: Use @ifnottex instead of @ifinfo.
	* libm/mathfp/s_sineh.c: Likewise.
	* libm/mathfp/w_jn.c: Likewise.
2003-10-20 18:46:38 +00:00
Jeff Johnston 8887021868 2000-05-26 Marek Michalkiewicz <marekm@linux.org.pl>
* libm/common/s_expm1.c (expm1): Add curly braces, avoid warnings.
        * libm/common/s_log1p.c (log1p): Likewise.
        * libm/common/s_scalbn.c (scalbn): Likewise.
        * libm/math/e_log.c: Likewise.
        * libm/math/e_asin.c: Likewise.
        * libm/math/ef_asin.c: Likewise.
        * libm/math/e_j0.c (pzero, qzero): Remove redundant test.
        * libm/math/e_j1.c (pone, qone): Likewise.
        * libm/math/ef_j0.c (pzerof, qzerof): Likewise.
        * libm/math/ef_j1.c (ponef, qonef): Likewise.
        * libm/mathfp/e_j0.c (pzero, qzero): Likewise.
        * libm/mathfp/e_j1.c (pone, qone): Likewise.
        * libm/mathfp/ef_j0.c (pzerof, qzerof): Likewise.
        * libm/mathfp/ef_j1.c (ponef, qonef): Likewise.
2000-05-26 22:42:39 +00:00
Christopher Faylor 8a0efa53e4 import newlib-2000-02-17 snapshot 2000-02-17 19:39:52 +00:00