math: sqrti, powi, factoriali (#12072)

pull/12120/head
05st 2021-10-08 14:07:44 -05:00 committed by GitHub
parent cd5b304cbf
commit 43931be451
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 0 deletions

View File

@ -53,3 +53,16 @@ fn log_factorial_asymptotic_expansion(n int) f64 {
}
return log_factorial + sum
}
// factoriali returns 1 for n <= 0 and -1 if the result is too large for a 64 bit integer
pub fn factoriali(n int) i64 {
if n <= 0 {
return i64(1)
}
if n < 21 {
return i64(factorials_table[n])
}
return i64(-1)
}

View File

@ -11,3 +11,12 @@ fn test_log_factorial() {
assert log_factorial(5) == log(120)
assert log_factorial(0) == log(1)
}
fn test_factoriali() {
assert factoriali(20) == 2432902008176640000
assert factoriali(1) == 1
assert factoriali(2) == 2
assert factoriali(0) == 1
assert factoriali(-2) == 1
assert factoriali(1000) == -1
}

View File

@ -946,3 +946,15 @@ fn test_large_tan() {
assert soclose(f1, f2, 4e-8)
}
}
fn test_sqrti() {
assert sqrti(i64(123456789) * i64(123456789)) == 123456789
assert sqrti(144) == 12
assert sqrti(0) == 0
}
fn test_powi() {
assert powi(2, 62) == i64(4611686018427387904)
assert powi(0, -2) == -1 // div by 0
assert powi(2, -1) == 0
}

View File

@ -35,6 +35,41 @@ pub fn pow10(n int) f64 {
return 0.0
}
// powi returns base raised to power (a**b) as an integer (i64)
//
// special case:
// powi(a, b) = -1 for a = 0 and b < 0
pub fn powi(a i64, b i64) i64 {
mut b_ := b
mut p := a
mut v := i64(1)
if b_ < 0 { // exponent < 0
if a == 0 {
return -1 // division by 0
}
return if a * a != 1 {
0
} else {
if (b_ & 1) > 0 {
a
} else {
1
}
}
}
for ; b_ > 0; {
if b_ & 1 > 0 {
v *= p
}
p *= p
b_ >>= 1
}
return v
}
// pow returns base raised to the provided power.
//
// todo(playXE): make this function work on JS backend, probably problem of JS codegen that it does not work.

View File

@ -35,3 +35,22 @@ pub fn sqrt(a f64) f64 {
pub fn sqrtf(a f32) f32 {
return f32(sqrt(a))
}
// sqrti calculates the integer square-root of the provided value. (i64)
pub fn sqrti(a i64) i64 {
mut x := a
mut q, mut r := i64(1), i64(0)
for ; q <= x; {
q <<= 2
}
for ; q > 1; {
q >>= 2
t := x - r - q
r >>= 1
if t >= 0 {
x = t
r += q
}
}
return r
}