mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
4e05a070c4
commit
25c2d4109f
6 changed files with 13 additions and 90 deletions
|
|
@ -66,11 +66,18 @@ func Trunc(x float64) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func trunc(x float64) float64 {
|
func trunc(x float64) float64 {
|
||||||
if x == 0 || IsNaN(x) || IsInf(x, 0) {
|
if Abs(x) < 1 {
|
||||||
return x
|
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.
|
// Round returns the nearest integer, rounding half away from zero.
|
||||||
|
|
|
||||||
|
|
@ -12,32 +12,7 @@ package math
|
||||||
// Modf(±Inf) = ±Inf, NaN
|
// Modf(±Inf) = ±Inf, NaN
|
||||||
// Modf(NaN) = NaN, NaN
|
// Modf(NaN) = NaN, NaN
|
||||||
func Modf(f float64) (int float64, frac float64) {
|
func Modf(f float64) (int float64, frac float64) {
|
||||||
if haveArchModf {
|
int = Trunc(f)
|
||||||
return archModf(f)
|
frac = Copysign(f-int, 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
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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")
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue