[PATCH] libm/math: Use __math_xflow in obsolete math code
Szabolcs Nagy
szabolcs.nagy@arm.com
Fri Jul 31 15:19:41 GMT 2020
The 07/30/2020 16:42, Keith Packard via Newlib wrote:
> C compilers may fold const values at compile time, so expressions
> which try to elicit underflow/overflow by performing simple
> arithemetic on suitable values will not generate the required
> exceptions.
>
> Work around this by replacing code which does these arithmetic
> operations with calls to the existing __math_xflow functions that are
> designed to do this correctly.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>
this looks good.
note1: i used c99 code when i wrote the
new math code and currently the old math
code can be compiled with older compilers,
this change might prevent that.
note2: xflow may also try to set errno,
depending on the WANT_ERRNO setting (which
is on by default).
in the old style math functions errno is
handled in wrappers but presumably this fix
is for the case when error handling wrappers
are not in use.
in that case note that some compilers may
model math functions as pure (no sideeffect)
and apply optimizations accrodingly, this
may create unexpected errno clobbers if
math functions actually set errno.
(-fno-math-errno behaviour in gcc)
but this affects other libm implementations
too and so far we haven't run into issues.
> --- a/newlib/libm/math/ef_pow.c
> +++ b/newlib/libm/math/ef_pow.c
...
> @@ -219,14 +217,14 @@ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
> i = j&0x7fffffff;
> if (j>0) {
> if (i>FLT_UWORD_EXP_MAX)
> - return s*huge*huge; /* overflow */
> + return s*__math_oflowf(0); /* overflow */
> else if (i==FLT_UWORD_EXP_MAX)
> - if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
> + if(p_l+ovt>z-p_h) return s*__math_oflowf(0); /* overflow */
> } else {
> if (i>FLT_UWORD_EXP_MIN)
> - return s*tiny*tiny; /* underflow */
> + return s*__math_uflowf(0); /* underflow */
> else if (i==FLT_UWORD_EXP_MIN)
> - if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
> + if(p_l<=z-p_h) return s*__math_uflowf(0); /* underflow */
this is suboptimal: the reason there is
a 'sign' argument to these functions is
that you don't need mul with the sign
(which is wrong with upward or downward
rounding:
s*huge*huge != (s*huge)*huge
but newlib may not care about rounding
modes, however it also prevents the
call to be a tail call and turns the
math function into a non-leaf function)
i think e.g. return __math_uflowf(s == -1.0f)
would work better (but it's better to set a
sign flag where s is set).
More information about the Newlib
mailing list