diff options
author | Charles L. Dorian <cldorian@gmail.com> | 2010-03-05 16:45:39 -0800 |
---|---|---|
committer | Charles L. Dorian <cldorian@gmail.com> | 2010-03-05 16:45:39 -0800 |
commit | 27bf0568af5a4ed7fa5cd540225d5ba9d855079e (patch) | |
tree | bb3d28b0836a096905f74f7af7ab82bd6bf7f1de /src | |
parent | 6fbf0007b69f26ae9eeb6e14e40dc943013e20d5 (diff) | |
download | golang-27bf0568af5a4ed7fa5cd540225d5ba9d855079e.tar.gz |
math: faster hypot
Use hardware sqrt for faster hypot; preserve software-only
hypot as hypotGo (like sqrtGo); enable benchmarking of
hypotGo.
R=rsc
CC=golang-dev
http://codereview.appspot.com/229049
Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/pkg/math/Makefile | 1 | ||||
-rw-r--r-- | src/pkg/math/all_test.go | 6 | ||||
-rw-r--r-- | src/pkg/math/hypot.go | 26 | ||||
-rw-r--r-- | src/pkg/math/hypot_port.go | 63 | ||||
-rw-r--r-- | src/pkg/math/hypot_test.go | 9 |
5 files changed, 81 insertions, 24 deletions
diff --git a/src/pkg/math/Makefile b/src/pkg/math/Makefile index 6650482a7..3b82a786b 100644 --- a/src/pkg/math/Makefile +++ b/src/pkg/math/Makefile @@ -54,6 +54,7 @@ ALLGOFILES=\ fmod.go\ frexp.go\ hypot.go\ + hypot_port.go\ logb.go\ lgamma.go\ ldexp.go\ diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go index 627949971..8cb575659 100644 --- a/src/pkg/math/all_test.go +++ b/src/pkg/math/all_test.go @@ -1754,6 +1754,12 @@ func BenchmarkHypot(b *testing.B) { } } +func BenchmarkHypotGo(b *testing.B) { + for i := 0; i < b.N; i++ { + HypotGo(3, 4) + } +} + func BenchmarkIlogb(b *testing.B) { for i := 0; i < b.N; i++ { Ilogb(.5) diff --git a/src/pkg/math/hypot.go b/src/pkg/math/hypot.go index 31924165e..ecd115d9e 100644 --- a/src/pkg/math/hypot.go +++ b/src/pkg/math/hypot.go @@ -1,4 +1,4 @@ -// Copyright 2009-2010 The Go Authors. All rights reserved. +// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -6,11 +6,6 @@ package math /* Hypot -- sqrt(p*p + q*q), but overflows only if the result does. - See: - Cleve Moler and Donald Morrison, - Replacing Square Roots by Pythagorean Sums - IBM Journal of Research and Development, - Vol. 27, Number 6, pp. 577-581, Nov. 1983 */ // Hypot computes Sqrt(p*p + q*q), taking care to avoid @@ -35,29 +30,12 @@ func Hypot(p, q float64) float64 { if q < 0 { q = -q } - if p < q { p, q = q, p } - if p == 0 { return 0 } - - pfac := p q = q / p - r := q - p = 1 - for { - r = r * r - s := r + 4 - if s == 4 { - return p * pfac - } - r = r / s - p = p + 2*r*p - q = q * r - r = q / p - } - panic("unreachable") + return p * Sqrt(1+q*q) } diff --git a/src/pkg/math/hypot_port.go b/src/pkg/math/hypot_port.go new file mode 100644 index 000000000..27f335ba2 --- /dev/null +++ b/src/pkg/math/hypot_port.go @@ -0,0 +1,63 @@ +// Copyright 2009-2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math + +/* + Hypot -- sqrt(p*p + q*q), but overflows only if the result does. + See: + Cleve Moler and Donald Morrison, + Replacing Square Roots by Pythagorean Sums + IBM Journal of Research and Development, + Vol. 27, Number 6, pp. 577-581, Nov. 1983 +*/ + +// Hypot computes Sqrt(p*p + q*q), taking care to avoid +// unnecessary overflow and underflow. +// +// Special cases are: +// Hypot(p, q) = +Inf if p or q is infinite +// Hypot(p, q) = NaN if p or q is NaN +func hypotGo(p, q float64) float64 { + // TODO(rsc): Remove manual inlining of IsNaN, IsInf + // when compiler does it for us + // special cases + switch { + case p < -MaxFloat64 || p > MaxFloat64 || q < -MaxFloat64 || q > MaxFloat64: // IsInf(p, 0) || IsInf(q, 0): + return Inf(1) + case p != p || q != q: // IsNaN(p) || IsNaN(q): + return NaN() + } + if p < 0 { + p = -p + } + if q < 0 { + q = -q + } + + if p < q { + p, q = q, p + } + + if p == 0 { + return 0 + } + + pfac := p + q = q / p + r := q + p = 1 + for { + r = r * r + s := r + 4 + if s == 4 { + return p * pfac + } + r = r / s + p = p + 2*r*p + q = q * r + r = q / p + } + panic("unreachable") +} diff --git a/src/pkg/math/hypot_test.go b/src/pkg/math/hypot_test.go new file mode 100644 index 000000000..85ce1d404 --- /dev/null +++ b/src/pkg/math/hypot_test.go @@ -0,0 +1,9 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math + +// Make hypotGo available for testing. + +func HypotGo(x, y float64) float64 { return hypotGo(x, y) } |