Re: [PATCH] libm/math: Use __math_xflow in obsolete math code

Szabolcs Nagy <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
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 <[email protected]>

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).
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.