From: Michael Munday Date: Mon, 28 Jul 2025 23:30:04 +0000 (+0100) Subject: math: use Trunc to implement Modf X-Git-Tag: go1.26rc1~1020 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=25c2d4109f;p=gostls13.git 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 Reviewed-by: Sean Liao Reviewed-by: Cherry Mui Reviewed-by: Keith Randall --- 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