mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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 <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
437323ef7b
commit
a18294bb6a
4 changed files with 15 additions and 46 deletions
|
|
@ -1674,32 +1674,7 @@ func log2(x uint64) uint32 {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
panic("log2 of 0")
|
panic("log2 of 0")
|
||||||
}
|
}
|
||||||
n := uint32(0)
|
return uint32(bits.Len64(x) - 1)
|
||||||
if x >= 1<<32 {
|
|
||||||
x >>= 32
|
|
||||||
n += 32
|
|
||||||
}
|
|
||||||
if x >= 1<<16 {
|
|
||||||
x >>= 16
|
|
||||||
n += 16
|
|
||||||
}
|
|
||||||
if x >= 1<<8 {
|
|
||||||
x >>= 8
|
|
||||||
n += 8
|
|
||||||
}
|
|
||||||
if x >= 1<<4 {
|
|
||||||
x >>= 4
|
|
||||||
n += 4
|
|
||||||
}
|
|
||||||
if x >= 1<<2 {
|
|
||||||
x >>= 2
|
|
||||||
n += 2
|
|
||||||
}
|
|
||||||
if x >= 1<<1 {
|
|
||||||
x >>= 1
|
|
||||||
n += 1
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoclass(l int64) int {
|
func autoclass(l int64) int {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"image/draw"
|
"image/draw"
|
||||||
"internal/byteorder"
|
"internal/byteorder"
|
||||||
"io"
|
"io"
|
||||||
|
"math/bits"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Graphic control extension fields.
|
// Graphic control extension fields.
|
||||||
|
|
@ -23,15 +24,11 @@ const (
|
||||||
gcBlockSize = 0x04
|
gcBlockSize = 0x04
|
||||||
)
|
)
|
||||||
|
|
||||||
var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
|
|
||||||
|
|
||||||
func log2(x int) int {
|
func log2(x int) int {
|
||||||
for i, v := range log2Lookup {
|
if x < 2 {
|
||||||
if x <= v {
|
return 0
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
}
|
return bits.Len(uint(x-1)) - 1
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// writer is a buffered writer.
|
// writer is a buffered writer.
|
||||||
|
|
@ -192,7 +189,7 @@ func (e *encoder) writeHeader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
|
func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
|
||||||
if uint(size) >= uint(len(log2Lookup)) {
|
if uint(size) >= 8 {
|
||||||
return 0, errors.New("gif: cannot encode color table with more than 256 entries")
|
return 0, errors.New("gif: cannot encode color table with more than 256 entries")
|
||||||
}
|
}
|
||||||
for i, c := range p {
|
for i, c := range p {
|
||||||
|
|
@ -212,7 +209,7 @@ func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
|
||||||
dst[3*i+1] = g
|
dst[3*i+1] = g
|
||||||
dst[3*i+2] = b
|
dst[3*i+2] = b
|
||||||
}
|
}
|
||||||
n := log2Lookup[size]
|
n := 1 << (size + 1)
|
||||||
if n > len(p) {
|
if n > len(p) {
|
||||||
// Pad with black.
|
// Pad with black.
|
||||||
clear(dst[3*len(p) : 3*n])
|
clear(dst[3*len(p) : 3*n])
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"internal/runtime/atomic"
|
"internal/runtime/atomic"
|
||||||
"internal/runtime/gc"
|
"internal/runtime/gc"
|
||||||
"internal/runtime/sys"
|
"internal/runtime/sys"
|
||||||
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -181,12 +182,10 @@ func stackinit() {
|
||||||
|
|
||||||
// stacklog2 returns ⌊log_2(n)⌋.
|
// stacklog2 returns ⌊log_2(n)⌋.
|
||||||
func stacklog2(n uintptr) int {
|
func stacklog2(n uintptr) int {
|
||||||
log2 := 0
|
if n == 0 {
|
||||||
for n > 1 {
|
return 0
|
||||||
n >>= 1
|
|
||||||
log2++
|
|
||||||
}
|
}
|
||||||
return log2
|
return bits.Len64(uint64(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocates a stack from the free pool. Must be called with
|
// Allocates a stack from the free pool. Must be called with
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package sort_test
|
package sort_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/bits"
|
||||||
"runtime"
|
"runtime"
|
||||||
. "sort"
|
. "sort"
|
||||||
stringspkg "strings"
|
stringspkg "strings"
|
||||||
|
|
@ -135,13 +136,10 @@ func TestFind(t *testing.T) {
|
||||||
// log2 computes the binary logarithm of x, rounded up to the next integer.
|
// log2 computes the binary logarithm of x, rounded up to the next integer.
|
||||||
// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
|
// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
|
||||||
func log2(x int) int {
|
func log2(x int) int {
|
||||||
n := 0
|
if x < 1 {
|
||||||
for p := 1; p < x; p += p {
|
return 0
|
||||||
// p == 2**n
|
|
||||||
n++
|
|
||||||
}
|
}
|
||||||
// p/2 < x <= p == 2**n
|
return bits.Len(uint(x - 1))
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchEfficiency(t *testing.T) {
|
func TestSearchEfficiency(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue