mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 04:47:18 +00:00
Optimize Integer Square Root (#3785)
This commit is contained in:
parent
acf11262de
commit
0a3825e79e
@ -1,18 +1,32 @@
|
||||
package mathutil
|
||||
|
||||
import "math"
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// IntegerSquareRoot defines a function that returns the
|
||||
// largest possible integer root of a number.
|
||||
// largest possible integer root of a number using a divide and conquer
|
||||
// binary search approach:
|
||||
//
|
||||
// inspiration: https://www.geeksforgeeks.org/square-root-of-an-integer
|
||||
func IntegerSquareRoot(n uint64) uint64 {
|
||||
x := n
|
||||
y := (x + 1) / 2
|
||||
|
||||
for y < x {
|
||||
x = y
|
||||
y = (x + n/x) / 2
|
||||
x := uint64(0)
|
||||
y := uint64(1 << 32)
|
||||
for {
|
||||
if y <= 1+x {
|
||||
return x
|
||||
}
|
||||
sqt := x + ((y - x) >> 1)
|
||||
sq := sqt * sqt
|
||||
if sq == n {
|
||||
return sqt
|
||||
}
|
||||
if sq > n {
|
||||
y = sqt
|
||||
} else {
|
||||
x = sqt
|
||||
}
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// CeilDiv8 divides the input number by 8
|
||||
|
@ -31,12 +31,46 @@ func TestIntegerSquareRoot(t *testing.T) {
|
||||
number: 97282,
|
||||
root: 311,
|
||||
},
|
||||
{
|
||||
number: 1 << 32,
|
||||
root: 1 << 16,
|
||||
},
|
||||
{
|
||||
number: (1 << 32) + 1,
|
||||
root: 1 << 16,
|
||||
},
|
||||
{
|
||||
number: 1 << 33,
|
||||
root: 92681,
|
||||
},
|
||||
{
|
||||
number: 1 << 60,
|
||||
root: 1 << 30,
|
||||
},
|
||||
{
|
||||
number: 1 << 53,
|
||||
root: 94906265,
|
||||
},
|
||||
{
|
||||
number: 1 << 62,
|
||||
root: 1 << 31,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testVals := range tt {
|
||||
root := mathutil.IntegerSquareRoot(testVals.number)
|
||||
if testVals.root != root {
|
||||
t.Fatalf("expected root and computed root are not equal %d, %d", testVals.root, root)
|
||||
t.Errorf("For %d, expected root and computed root are not equal want %d, got %d", testVals.number, testVals.root, root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIntegerSquareRoot(b *testing.B) {
|
||||
val := uint64(1 << 62)
|
||||
for i := 0; i < b.N; i++ {
|
||||
root := mathutil.IntegerSquareRoot(val)
|
||||
if root != 1<<31 {
|
||||
b.Fatalf("Expected root and computed root are not equal 1<<31, %d", root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user