Conflict API definitions of Math.pow(x, 0.5) and Math.sqrt(x) for x={-0.0, Double.NEGATIVE_INFINITY}(Internet mail)
Raffaello Giulietti
raffaello.giulietti at gmail.com
Sat May 15 22:55:40 UTC 2021
Hi Jie,
I don't think that changing the spec of Math.pow() to be misaligned with
IEEE 754 would be a wise option. IEEE is much more pervasive than Java.
There are many aspects in IEEE that might be seen as questionable, but
at least it is a widely adopted standard.
AFAIU, the only reason you would like to "optimize" the special case of
y = 0.5 in pow(x, y) to return sqrt(x) is for performance, more accuracy
and some kind of consistency.
But then, why not a special case for y = 0.25 as sqrt(sqrt(x))?
And what about y = 0.75? Should this be translated to sqrt(sqrt(pow(x, 3)))?
What about y = 1.0 / 3.0? Should this become cbrt(x)?
And why not consider y = 2.0 / 3.0 in a special rule: cbrt(x * x)?
You see, the special cases can quickly become unmanageable. Also,
special rules would produce results which are "discontinuous" with
nearby exponents, like y = 0.5000000000000001.
That's probably why IEEE doesn't propose translation rules for finite
numerical exponents that are not integers, except when x is a special value.
Greetings
Raffaello
On 2021-04-12 13:44, jiefu(傅杰) wrote:
> Hi Andrew H, Andrew D, and Raffaello,
>
> Thank you all for your kind reply and helpful comments.
>
> Now I got where the rules come from.
> But I don't think the IEEE standars are reasonable to specify conflits rules.
> Maybe, these computations should be open to be implementation dependent.
>
> (If it's possible) I really hope the special cases of Math.pow(x, 0.5) can be aligned with Math.sqrt(x) in Java.
> We already allow some plausible behaviors to be different with the IEEE recommendations for some special cases, right?
> And in that case, we can replace pow(x, 0.5) with sqrt(x) safely.
>
> Thanks.
> Best regards,
> Jie
>
>
> On 2021/4/12, 6:40 PM, "Raffaello Giulietti" <raffaello.giulietti at gmail.com> wrote:
>
> Hi Jie,
>
> the behavior you report is the one specified by the standard IEEE 754.
> Java follows this standard as closely as it can.
>
> The standard says that
> * squareRoot(-0) = -0
> * squareRoot(-∞) = NaN
>
> Also, the standard has a long lists of special cases for pow(x, y),
> among them:
> * pow(±0, y) is +0 for finite y > 0 and not an odd integer
> * pow(-∞, y) is +∞ for finite y > 0 and not an odd integer
>
> Thus, the conflicts you observe originate in following the standard, not
> by special Java rules.
>
> Unfortunately, the IEEE standard does not explain the reasons for the
> special rules. Some are obvious, some are not.
>
>
> HTH
> Raffaello
>
>
> > Hi all,
> >
> > I found Math.pow(x, 0.5) and Math.sqrt(x) would compute different values as the following:
> > ```
> > Math.pow(-0.0, 0.5) = 0.0
> > Math.sqrt(-0.0) = -0.0
> >
> > Math.pow(Double.NEGATIVE_INFINITY, 0.5) = Infinity
> > Math.sqrt(Double.NEGATIVE_INFINITY) = NaN
> > ```
> >
> > The reason is that both of pow and sqrt have special rules for these computations.
> > For example, this rule [1] specifies Math.pow(-0.0, 0.5) must be 0.0.
> > And this one [2] specifies Math.sqrt(-0.0) must be -0.0.
> > And we do have rules for Math.pow(Double.NEGATIVE_INFINITY, 0.5) = Infinity and Math.sqrt(Double.NEGATIVE_INFINITY) = NaN too.
> >
> > I think most people will be confused by these rules because from the view of mathematics, Math.pow(x, 0.5) should be equal to Math.sqrt(x).
> >
> > So why Java creates conflict special rules for them?
> > Is it possible to let Math.pow(-0.0, 0.5) = -0.0 and Math.pow(Double.NEGATIVE_INFINITY, 0.5) = NaN also be allowed?
> >
> > I came across this problem when I was trying to optimize pow(x, 0.5) with sqrt(x).
> > If pow(x, 0.5)'s two special rules can be aligned with sqrt(x), then pow(x, 0.5)'s performance can be improved by 7x~14x [3].
> >
> > Thanks.
> > Best regards,
> > Jie
>
>
>
More information about the compiler-dev
mailing list