Skip to content

Commit a18294b

Browse files
Meroviusseankhliao
authored andcommitted
cmd/internal/obj/arm64, image/gif, runtime, sort: use math/bits to calculate log2
In several places the integer log2 is calculated using loops or similar mechanisms. math/bits.Len* provide a simpler and more efficient mechanisms for this. Annoyingly, every usage has slightly different ideas of what "log2" means and how non-positive inputs should be handled. I verified the replacements in each case by comparing the result for inputs from 0 to 1<<16. Change-Id: Ie962a74674802da363e0038d34c06979ccb41cf3 Reviewed-on: https://go-review.googlesource.com/c/go/+/721880 Reviewed-by: Mark Freeman <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 437323e commit a18294b

File tree

4 files changed

+15
-46
lines changed

4 files changed

+15
-46
lines changed

src/cmd/internal/obj/arm64/asm7.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,32 +1674,7 @@ func log2(x uint64) uint32 {
16741674
if x == 0 {
16751675
panic("log2 of 0")
16761676
}
1677-
n := uint32(0)
1678-
if x >= 1<<32 {
1679-
x >>= 32
1680-
n += 32
1681-
}
1682-
if x >= 1<<16 {
1683-
x >>= 16
1684-
n += 16
1685-
}
1686-
if x >= 1<<8 {
1687-
x >>= 8
1688-
n += 8
1689-
}
1690-
if x >= 1<<4 {
1691-
x >>= 4
1692-
n += 4
1693-
}
1694-
if x >= 1<<2 {
1695-
x >>= 2
1696-
n += 2
1697-
}
1698-
if x >= 1<<1 {
1699-
x >>= 1
1700-
n += 1
1701-
}
1702-
return n
1677+
return uint32(bits.Len64(x) - 1)
17031678
}
17041679

17051680
func autoclass(l int64) int {

src/image/gif/writer.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"image/draw"
1616
"internal/byteorder"
1717
"io"
18+
"math/bits"
1819
)
1920

2021
// Graphic control extension fields.
@@ -23,15 +24,11 @@ const (
2324
gcBlockSize = 0x04
2425
)
2526

26-
var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
27-
2827
func log2(x int) int {
29-
for i, v := range log2Lookup {
30-
if x <= v {
31-
return i
32-
}
28+
if x < 2 {
29+
return 0
3330
}
34-
return -1
31+
return bits.Len(uint(x-1)) - 1
3532
}
3633

3734
// writer is a buffered writer.
@@ -192,7 +189,7 @@ func (e *encoder) writeHeader() {
192189
}
193190

194191
func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
195-
if uint(size) >= uint(len(log2Lookup)) {
192+
if uint(size) >= 8 {
196193
return 0, errors.New("gif: cannot encode color table with more than 256 entries")
197194
}
198195
for i, c := range p {
@@ -212,7 +209,7 @@ func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
212209
dst[3*i+1] = g
213210
dst[3*i+2] = b
214211
}
215-
n := log2Lookup[size]
212+
n := 1 << (size + 1)
216213
if n > len(p) {
217214
// Pad with black.
218215
clear(dst[3*len(p) : 3*n])

src/runtime/stack.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"internal/runtime/atomic"
1313
"internal/runtime/gc"
1414
"internal/runtime/sys"
15+
"math/bits"
1516
"unsafe"
1617
)
1718

@@ -181,12 +182,10 @@ func stackinit() {
181182

182183
// stacklog2 returns ⌊log_2(n)⌋.
183184
func stacklog2(n uintptr) int {
184-
log2 := 0
185-
for n > 1 {
186-
n >>= 1
187-
log2++
185+
if n == 0 {
186+
return 0
188187
}
189-
return log2
188+
return bits.Len64(uint64(n))
190189
}
191190

192191
// Allocates a stack from the free pool. Must be called with

src/sort/search_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package sort_test
66

77
import (
8+
"math/bits"
89
"runtime"
910
. "sort"
1011
stringspkg "strings"
@@ -135,13 +136,10 @@ func TestFind(t *testing.T) {
135136
// log2 computes the binary logarithm of x, rounded up to the next integer.
136137
// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
137138
func log2(x int) int {
138-
n := 0
139-
for p := 1; p < x; p += p {
140-
// p == 2**n
141-
n++
139+
if x < 1 {
140+
return 0
142141
}
143-
// p/2 < x <= p == 2**n
144-
return n
142+
return bits.Len(uint(x - 1))
145143
}
146144

147145
func TestSearchEfficiency(t *testing.T) {

0 commit comments

Comments
 (0)