]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64, image/gif, runtime, sort: use math/bits to calculate log2
authorAxel Wagner <axel.wagner.hh@googlemail.com>
Wed, 19 Nov 2025 08:28:16 +0000 (09:28 +0100)
committerSean Liao <sean@liao.dev>
Sun, 23 Nov 2025 11:49:34 +0000 (03:49 -0800)
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>
src/cmd/internal/obj/arm64/asm7.go
src/image/gif/writer.go
src/runtime/stack.go
src/sort/search_test.go

index ccf8eda495a83c30456bbd2cd80eff7eb1730777..7addf0ddadf28a6ae35d2635366ad4b36d5cc224 100644 (file)
@@ -1674,32 +1674,7 @@ func log2(x uint64) uint32 {
        if x == 0 {
                panic("log2 of 0")
        }
-       n := uint32(0)
-       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
+       return uint32(bits.Len64(x) - 1)
 }
 
 func autoclass(l int64) int {
index 129d0ab28207590ab7ad4bee1545df920b3dcd04..2a3e33c145f7843dd9b3ce37137dc56e98c0cef0 100644 (file)
@@ -15,6 +15,7 @@ import (
        "image/draw"
        "internal/byteorder"
        "io"
+       "math/bits"
 )
 
 // Graphic control extension fields.
@@ -23,15 +24,11 @@ const (
        gcBlockSize = 0x04
 )
 
-var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
-
 func log2(x int) int {
-       for i, v := range log2Lookup {
-               if x <= v {
-                       return i
-               }
+       if x < 2 {
+               return 0
        }
-       return -1
+       return bits.Len(uint(x-1)) - 1
 }
 
 // writer is a buffered writer.
@@ -192,7 +189,7 @@ func (e *encoder) writeHeader() {
 }
 
 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")
        }
        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+2] = b
        }
-       n := log2Lookup[size]
+       n := 1 << (size + 1)
        if n > len(p) {
                // Pad with black.
                clear(dst[3*len(p) : 3*n])
index 55e97e77afa9576b515901d7e237145488e03b1d..c92accf18826e058218b03f0f2f82f985fd49671 100644 (file)
@@ -12,6 +12,7 @@ import (
        "internal/runtime/atomic"
        "internal/runtime/gc"
        "internal/runtime/sys"
+       "math/bits"
        "unsafe"
 )
 
@@ -181,12 +182,10 @@ func stackinit() {
 
 // stacklog2 returns ⌊log_2(n)⌋.
 func stacklog2(n uintptr) int {
-       log2 := 0
-       for n > 1 {
-               n >>= 1
-               log2++
+       if n == 0 {
+               return 0
        }
-       return log2
+       return bits.Len64(uint64(n))
 }
 
 // Allocates a stack from the free pool. Must be called with
index 49813eaecb0fe474d4ec07b6245c270991d1e454..b6ab900abebcbab9076ce8d278410b0b298af868 100644 (file)
@@ -5,6 +5,7 @@
 package sort_test
 
 import (
+       "math/bits"
        "runtime"
        . "sort"
        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(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
 func log2(x int) int {
-       n := 0
-       for p := 1; p < x; p += p {
-               // p == 2**n
-               n++
+       if x < 1 {
+               return 0
        }
-       // p/2 < x <= p == 2**n
-       return n
+       return bits.Len(uint(x - 1))
 }
 
 func TestSearchEfficiency(t *testing.T) {