diff options
| author | Michael Munday <mndygolang+git@gmail.com> | 2025-07-29 00:30:04 +0100 |
|---|---|---|
| committer | Michael Munday <mndygolang+git@gmail.com> | 2025-08-25 12:46:11 -0700 |
| commit | 25c2d4109f5061425ca2633fb12450d43839bb79 (patch) | |
| tree | 8807499e07fd842e59819ee34bf8c3db888b240c /src | |
| parent | 4e05a070c4f88ebf43f0873e144c62d02d56060b (diff) | |
| download | go-25c2d4109f5061425ca2633fb12450d43839bb79.tar.xz | |
math: use Trunc to implement Modf
By implementing Modf using Trunc, rather than the other way round,
we can get a significant performance improvement on platforms where
Trunc is implemented as an intrinsic.
Trunc is implemented as an intrinsic on ppc64x and arm64 so the assembly
implementations of Modf are no longer needed (the compiler can generate
very similar code that can now potentially be inlined).
GOAMD64=v1
goos: linux
goarch: amd64
pkg: math
cpu: 12th Gen Intel(R) Core(TM) i7-12700T
│ sec/op │ sec/op vs base │
Gamma 4.257n ± 0% 3.890n ± 0% -8.61% (p=0.000 n=10)
Modf 1.6110n ± 0% 0.4243n ± 0% -73.67% (p=0.000 n=10)
geomean 2.619n 1.285n -50.94%
GOAMD64=v2
goos: linux
goarch: amd64
pkg: math
cpu: 12th Gen Intel(R) Core(TM) i7-12700T
│ sec/op │ sec/op vs base │
Gamma 4.100n ± 1% 3.717n ± 0% -9.35% (p=0.000 n=10)
Modf 1.6070n ± 0% 0.2158n ± 1% -86.57% (p=0.000 n=10)
geomean 2.567n 0.8957n -65.11%
Change-Id: I689a560c344cf1d39ef002b540749bacc3179786
Reviewed-on: https://go-review.googlesource.com/c/go/+/694896
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/math/floor.go | 15 | ||||
| -rw-r--r-- | src/math/modf.go | 29 | ||||
| -rw-r--r-- | src/math/modf_arm64.s | 18 | ||||
| -rw-r--r-- | src/math/modf_asm.go | 11 | ||||
| -rw-r--r-- | src/math/modf_noasm.go | 13 | ||||
| -rw-r--r-- | src/math/modf_ppc64x.s | 17 |
6 files changed, 13 insertions, 90 deletions
diff --git a/src/math/floor.go b/src/math/floor.go index cb5856424b..20a7641124 100644 --- a/src/math/floor.go +++ b/src/math/floor.go @@ -66,11 +66,18 @@ func Trunc(x float64) float64 { } func trunc(x float64) float64 { - if x == 0 || IsNaN(x) || IsInf(x, 0) { - return x + if Abs(x) < 1 { + return Copysign(0, x) } - d, _ := Modf(x) - return d + + b := Float64bits(x) + e := uint(b>>shift)&mask - bias + + // Keep the top 12+e bits, the integer part; clear the rest. + if e < 64-12 { + b &^= 1<<(64-12-e) - 1 + } + return Float64frombits(b) } // Round returns the nearest integer, rounding half away from zero. diff --git a/src/math/modf.go b/src/math/modf.go index 613a75fc9a..ab73e2dc36 100644 --- a/src/math/modf.go +++ b/src/math/modf.go @@ -12,32 +12,7 @@ package math // Modf(±Inf) = ±Inf, NaN // Modf(NaN) = NaN, NaN func Modf(f float64) (int float64, frac float64) { - if haveArchModf { - return archModf(f) - } - return modf(f) -} - -func modf(f float64) (int float64, frac float64) { - if f < 1 { - switch { - case f < 0: - int, frac = Modf(-f) - return -int, -frac - case f == 0: - return f, f // Return -0, -0 when f == -0 - } - return 0, f - } - - x := Float64bits(f) - e := uint(x>>shift)&mask - bias - - // Keep the top 12+e bits, the integer part; clear the rest. - if e < 64-12 { - x &^= 1<<(64-12-e) - 1 - } - int = Float64frombits(x) - frac = f - int + int = Trunc(f) + frac = Copysign(f-int, f) return } diff --git a/src/math/modf_arm64.s b/src/math/modf_arm64.s deleted file mode 100644 index 1e4a329a4b..0000000000 --- a/src/math/modf_arm64.s +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 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. - -#include "textflag.h" - -// func archModf(f float64) (int float64, frac float64) -TEXT ·archModf(SB),NOSPLIT,$0 - MOVD f+0(FP), R0 - FMOVD R0, F0 - FRINTZD F0, F1 - FMOVD F1, int+8(FP) - FSUBD F1, F0 - FMOVD F0, R1 - AND $(1<<63), R0 - ORR R0, R1 // must have same sign - MOVD R1, frac+16(FP) - RET diff --git a/src/math/modf_asm.go b/src/math/modf_asm.go deleted file mode 100644 index c63be6cf36..0000000000 --- a/src/math/modf_asm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2021 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. - -//go:build arm64 || ppc64 || ppc64le - -package math - -const haveArchModf = true - -func archModf(f float64) (int float64, frac float64) diff --git a/src/math/modf_noasm.go b/src/math/modf_noasm.go deleted file mode 100644 index 55c6a7f6e2..0000000000 --- a/src/math/modf_noasm.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2021 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. - -//go:build !arm64 && !ppc64 && !ppc64le - -package math - -const haveArchModf = false - -func archModf(f float64) (int float64, frac float64) { - panic("not implemented") -} diff --git a/src/math/modf_ppc64x.s b/src/math/modf_ppc64x.s deleted file mode 100644 index 410b523c0e..0000000000 --- a/src/math/modf_ppc64x.s +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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. - -//go:build ppc64 || ppc64le - -#include "textflag.h" - -// func archModf(f float64) (int float64, frac float64) -TEXT ·archModf(SB),NOSPLIT,$0 - FMOVD f+0(FP), F0 - FRIZ F0, F1 - FMOVD F1, int+8(FP) - FSUB F1, F0, F2 - FCPSGN F2, F0, F2 - FMOVD F2, frac+16(FP) - RET |
