Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

math: Pow(x,y) fails for large values of y #7394

Closed
gopherbot opened this issue Feb 23, 2014 · 10 comments
Closed

math: Pow(x,y) fails for large values of y #7394

gopherbot opened this issue Feb 23, 2014 · 10 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@gopherbot
Copy link

by nicolas.riesch:

What steps will reproduce the problem?

see http://play.golang.org/p/rcVquN_0xc


What is the expected output?

for x=2.0 and y>=2147483648.0, math.Pow(x,y) should return +Inf

What do you see instead?

It returns 0.0


Please provide any additional information below.

On my 64bits computer, "Linux VBox-Mint15-64bits 3.8.0-19-generic #29-Ubuntu SMP
Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux"
with "go version go1.2rc5 linux/amd64", I have a similar problem :

for x = 2.0 and y = 9223372036854775808.0, math.Pow(x,y) should return +Inf
but it returns 0.0
@minux
Copy link
Member

minux commented Feb 23, 2014

Comment 1:

Labels changed: added release-go1.3, repo-main.

Status changed to Accepted.

@minux
Copy link
Member

minux commented Feb 23, 2014

Comment 2:

the msun implementation is correct in this regard, should we
move to a rewrite of the msun implementation? or just
fix the problem before calling Ldexp if the exponent is
too large?

@rsc
Copy link
Contributor

rsc commented Mar 4, 2014

Comment 3:

It's probably too late to rewrite Pow completely, but I wouldn't object to a simple bug
fix. I don't see anything there that uses an int32, but I imagine it should be a fairly
simple fix.

@gopherbot
Copy link
Author

Comment 4 by pcaven:

I was looking for a simple Go 1.3 issue to help out with the release effort, so I
thought I'd start with this one. It didn't look like anyone had investigated it yet.
I've reproduced the problem on GOARCH="386" (Linux), but it seems to work correctly on
GOARCH=amd64 (Windows). I think that explains why it fails on the Playground, but not
why the original submitter saw the problem on linux/amd64.
I don't have suggested fix yet, but I've tracked it down to the use of 'int' (32 bits on
'386, 64 bits on amd64), which overflows an int variable in the math.Pow code at some
point after the call to math.Frexp. At the end of math.Pow it is passed as a negative
int value to math.Ldexp, which at line #29, after normalization of the mantissa,
executes:
return Copysign(0, frac) // underflow
I'll look at it some more tonight. I think there might be a simple fix in math.Pow that
avoids the call to math.Ldexp in that case, but I haven't implemented it or run any
tests yet.

@ianlancetaylor
Copy link
Contributor

Comment 5:

Owner changed to @griesemer.

@griesemer
Copy link
Contributor

Comment 6:

Also, Exp(1<<30) returns +Inf, but Exp(1<<31) returns 0. There may be more
cases like this.

Labels changed: added release-go1.3maybe, removed release-go1.3.

@griesemer
Copy link
Contributor

Comment 7:

Labels changed: added release-go1.4, removed release-go1.3maybe.

@griesemer
Copy link
Contributor

Comment 8:

Labels changed: added release-none, removed release-go1.4.

@gopherbot
Copy link
Author

CL https://golang.org/cl/48290 mentions this issue.

@bradfitz bradfitz modified the milestones: Go1.10, Unplanned Jul 13, 2017
@bradfitz bradfitz added NeedsFix The path to resolution is known, but the work has not been done. release-blocker labels Jul 13, 2017
@bradfitz bradfitz changed the title math: math.Pow(x,y) fails for large values of y math: Pow(x,y) fails for large values of y Jul 13, 2017
@bmkessler
Copy link
Contributor

The loop that accumulates the exponent ae by effectively multiplying the 11-bit exponent of x (xe) with yi (int64) overflows both 32 and 64-bit int since the resulting value could be up to 74-bits. The code computes the multiplication by summing shifts of xe so the CL above checks for overflow of the output float64 exponent (11 bits plus denormals) by monitoring the magnitude of xe and exits the loop early.

Additionally, for yi >= 1<<63 the code was using Exp( y * Log(x)) which gave Nan incorrectly for x<0 and 0/Inf otherwise. The CL drops the call to Exp and replaces it with a case statement since for yi that large Pow always under/overflows and handles x<0 correctly.

@golang golang locked and limited conversation to collaborators Aug 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

7 participants