Optimize Integer Square Root (#3785)

This commit is contained in:
Raul Jordan 2019-10-24 21:32:04 +08:00 committed by terence tsao
parent acf11262de
commit 0a3825e79e
2 changed files with 58 additions and 10 deletions

View File

@ -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

View File

@ -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)
}
}
}