mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
Optimize Integer Square Root (#3785)
This commit is contained in:
parent
acf11262de
commit
0a3825e79e
@ -1,18 +1,32 @@
|
|||||||
package mathutil
|
package mathutil
|
||||||
|
|
||||||
import "math"
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
// IntegerSquareRoot defines a function that returns the
|
// 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 {
|
func IntegerSquareRoot(n uint64) uint64 {
|
||||||
x := n
|
x := uint64(0)
|
||||||
y := (x + 1) / 2
|
y := uint64(1 << 32)
|
||||||
|
for {
|
||||||
for y < x {
|
if y <= 1+x {
|
||||||
x = y
|
return x
|
||||||
y = (x + n/x) / 2
|
}
|
||||||
|
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
|
// CeilDiv8 divides the input number by 8
|
||||||
|
@ -31,12 +31,46 @@ func TestIntegerSquareRoot(t *testing.T) {
|
|||||||
number: 97282,
|
number: 97282,
|
||||||
root: 311,
|
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 {
|
for _, testVals := range tt {
|
||||||
root := mathutil.IntegerSquareRoot(testVals.number)
|
root := mathutil.IntegerSquareRoot(testVals.number)
|
||||||
if testVals.root != root {
|
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