]> Cypherpunks repositories - gostls13.git/commit
math: eliminate overflow in Pow(x,y) for large y
authorBrian Kessler <brian.m.kessler@gmail.com>
Thu, 13 Jul 2017 05:02:39 +0000 (22:02 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 16 Aug 2017 09:10:10 +0000 (09:10 +0000)
commit12465661421f3598cb76a787fba75da8cabc220d
treed97825ea626f7b2533465e60773b34a22e53ca0a
parenta9257b6b694c1eb743537e948e379ddda232a7a8
math: eliminate overflow in Pow(x,y) for large y

The current implementation uses a shift and add
loop to compute the product of x's exponent xe and
the integer part of y (yi) for yi up to 1<<63.
Since xe is an 11-bit exponent, this product can be
up to 74-bits and overflow both 32 and 64-bit int.

This change checks whether the accumulated exponent
will fit in the 11-bit float exponent of the output
and breaks out of the loop early if overflow is detected.

The current handling of yi >= 1<<63 uses Exp(y * Log(x))
which incorrectly returns Nan for x<0.  In addition,
for y this large, Exp(y * Log(x)) can be enumerated
to only overflow except when x == -1 since the
boundary cases computed exactly:

Pow(NextAfter(1.0, Inf(1)), 1<<63)  == 2.72332... * 10^889
Pow(NextAfter(1.0, Inf(-1)), 1<<63) == 1.91624... * 10^-445

exceed the range of float64. So, the call can be
replaced with a simple case statement analgous to
y == Inf that correctly handles x < 0 as well.

Fixes #7394

Change-Id: I6f50dc951f3693697f9669697599860604323102
Reviewed-on: https://go-review.googlesource.com/48290
Reviewed-by: Robert Griesemer <gri@golang.org>
src/math/all_test.go
src/math/pow.go