Skip to content

Commit 544bfa2

Browse files
committed
math: Add ARM64 implementation of frexp
The implementation of Frexp on ARM64 has been implemented in this PR. The following benchmark was run on Apple Silicon M1 chips. BenchmarkArchFrexp-8 1.581 ns/op 0 B/op 0 allocs/op BenchmarkFrexpGO-8 2.079 ns/op 0 B/op 0 allocs/op The time spent on each iteration drop 23.95%.
1 parent 891547e commit 544bfa2

File tree

7 files changed

+95
-13
lines changed

7 files changed

+95
-13
lines changed

src/math/all_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -2541,7 +2541,7 @@ func TestFrexp(t *testing.T) {
25412541
}
25422542
}
25432543
for i := 0; i < len(vffrexpBC); i++ {
2544-
if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j {
2544+
if f, j := Frexp(vffrexpBC[i]); !veryclose(frexpBC[i].f, f) || frexpBC[i].i != j {
25452545
t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i)
25462546
}
25472547
}
@@ -3467,6 +3467,16 @@ func BenchmarkFrexp(b *testing.B) {
34673467
GlobalI = y
34683468
}
34693469

3470+
func BenchmarkFrexpGO(b *testing.B) {
3471+
x := 0.0
3472+
y := 0
3473+
for i := 0; i < b.N; i++ {
3474+
x, y = FrexpGO(8)
3475+
}
3476+
GlobalF = x
3477+
GlobalI = y
3478+
}
3479+
34703480
func BenchmarkGamma(b *testing.B) {
34713481
x := 0.0
34723482
for i := 0; i < b.N; i++ {

src/math/arith_s390x.go

-6
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,6 @@ func archPow(x, y float64) float64
135135
func powTrampolineSetup(x, y float64) float64
136136
func powAsm(x, y float64) float64
137137

138-
const haveArchFrexp = false
139-
140-
func archFrexp(x float64) (float64, int) {
141-
panic("not implemented")
142-
}
143-
144138
const haveArchLdexp = false
145139

146140
func archLdexp(frac float64, exp int) float64 {

src/math/export_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package math
88
var ExpGo = exp
99
var Exp2Go = exp2
1010
var HypotGo = hypot
11+
var FrexpGo = frexp
1112
var SqrtGo = sqrt
1213
var TrigReduce = trigReduce
1314

src/math/frexp_arm64.s

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
#include "textflag.h"
6+
7+
#define PosInf 0x7FF0000000000000
8+
#define Float64SmallestNormal 2.2250738585072014e-308
9+
10+
// func archFrexp(x float64) (frac float64, exp int)
11+
TEXT ·archFrexp(SB),NOSPLIT,$0-24
12+
FMOVD x+0(FP), F0
13+
MOVD ZR, R1 // R1 is the ret exp
14+
FABSD F0, F3 // F3 is the absolute of 'x'
15+
FCMPD $(0.0), F0
16+
BEQ isInfOrNaNOrZero
17+
18+
MOVD $PosInf, R3
19+
FMOVD R3, F30 // F30 is PosInf
20+
FCMPD F30, F3
21+
BGE isInfOrNaNOrZero // isInf
22+
FCMPED F0, F0
23+
BNE isInfOrNaNOrZero // isNaN
24+
25+
FMOVD F3, R0
26+
UBFX $52, R0, $11, R0
27+
28+
FMOVD $Float64SmallestNormal, F29
29+
FCMPD F29, F3
30+
BGE pass
31+
32+
// if abs(x) < SmallestNormal ,then run the following special case
33+
FMOVD $(4503599627370496.0), F2 // 4503599627370496.0 is (1<<52)
34+
FMULD F2, F0, F0
35+
SUB $(52), R1, R1 // set R1 to -52
36+
FMOVD F0, R0
37+
// tmp = int((x>>shift)&mask)
38+
UBFX $52, R0, $11, R0
39+
40+
pass:
41+
// tmp = tmp - bias + 1
42+
SUB $0x3FE, R0, R3
43+
// exp = exp + tmp
44+
ADD R3, R1, R1
45+
46+
FMOVD F0, R0
47+
AND $0x800FFFFFFFFFFFFF, R0, R0
48+
ORR $0x3FE0000000000000, R0, R0
49+
FMOVD R0, F0
50+
FMOVD F0, frac+8(FP)
51+
MOVD R1, exp+16(FP)
52+
RET
53+
54+
isInfOrNaNOrZero:
55+
FMOVD F0, frac+8(FP)
56+
MOVD R1, exp+16(FP)
57+
RET

src/math/frexp_asm.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build arm64
6+
// +build arm64
7+
8+
package math
9+
10+
const haveArchFrexp = true
11+
12+
func archFrexp(x float64) (frac float64, exp int)

src/math/frexp_noasm.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !arm64
6+
// +build !arm64
7+
8+
package math
9+
10+
const haveArchFrexp = false
11+
12+
func archFrexp(x float64) (frac float64, exp int)
13+
panic("not implemented")
14+
}

src/math/stubs.go

-6
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ func archExpm1(x float64) float64 {
8888
panic("not implemented")
8989
}
9090

91-
const haveArchFrexp = false
92-
93-
func archFrexp(x float64) (float64, int) {
94-
panic("not implemented")
95-
}
96-
9791
const haveArchLdexp = false
9892

9993
func archLdexp(frac float64, exp int) float64 {

0 commit comments

Comments
 (0)