99 lines
1.4 KiB
Go
99 lines
1.4 KiB
Go
package goja
|
|
|
|
// inspired by https://gist.github.com/orlp/3551590
|
|
|
|
var overflows = [64]int64{
|
|
9223372036854775807, 9223372036854775807, 3037000499, 2097151,
|
|
55108, 6208, 1448, 511,
|
|
234, 127, 78, 52,
|
|
38, 28, 22, 18,
|
|
15, 13, 11, 9,
|
|
8, 7, 7, 6,
|
|
6, 5, 5, 5,
|
|
4, 4, 4, 4,
|
|
3, 3, 3, 3,
|
|
3, 3, 3, 3,
|
|
2, 2, 2, 2,
|
|
2, 2, 2, 2,
|
|
2, 2, 2, 2,
|
|
2, 2, 2, 2,
|
|
2, 2, 2, 2,
|
|
2, 2, 2, 2,
|
|
}
|
|
|
|
var highestBitSet = [63]byte{
|
|
0, 1, 2, 2, 3, 3, 3, 3,
|
|
4, 4, 4, 4, 4, 4, 4, 4,
|
|
5, 5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5, 5,
|
|
6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6,
|
|
}
|
|
|
|
func ipow(base, exp int64) (result int64) {
|
|
if exp >= 63 {
|
|
if base == 1 {
|
|
return 1
|
|
}
|
|
|
|
if base == -1 {
|
|
return 1 - 2*(exp&1)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
if base > overflows[exp] || -base > overflows[exp] {
|
|
return 0
|
|
}
|
|
|
|
result = 1
|
|
|
|
switch highestBitSet[byte(exp)] {
|
|
case 6:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
exp >>= 1
|
|
base *= base
|
|
fallthrough
|
|
case 5:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
exp >>= 1
|
|
base *= base
|
|
fallthrough
|
|
case 4:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
exp >>= 1
|
|
base *= base
|
|
fallthrough
|
|
case 3:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
exp >>= 1
|
|
base *= base
|
|
fallthrough
|
|
case 2:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
exp >>= 1
|
|
base *= base
|
|
fallthrough
|
|
case 1:
|
|
if exp&1 != 0 {
|
|
result *= base
|
|
}
|
|
fallthrough
|
|
default:
|
|
return result
|
|
}
|
|
}
|