math: speedup the pure V math.pow implementation for non-fractional powers (#19270)

This commit is contained in:
Leo Developer 2023-09-04 17:37:29 +02:00 committed by GitHub
parent 78659f48c5
commit a3fa575cf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 3 deletions

View File

@ -1,4 +1,4 @@
- [x] Move `vsl/vmath` to `vlib/math` as default backend - [x] Move `vsl/vmath` to `vlib/math` as default backend
- [ ] Implement `log` in pure V - [x] Implement `log` in pure V
- [ ] Implement `pow` in pure V - [x] Implement `pow` in pure V
- [ ] Define functions for initial release of hardware implementations - [ ] Define functions for initial release of hardware implementations

View File

@ -776,7 +776,8 @@ fn test_pow() {
[pi, nan()], [inf(1), -pi], [inf(1), -0.0], [inf(1), 0], [pi, nan()], [inf(1), -pi], [inf(1), -0.0], [inf(1), 0],
[inf(1), 1], [inf(1), pi], [inf(1), nan()], [nan(), -pi], [inf(1), 1], [inf(1), pi], [inf(1), nan()], [nan(), -pi],
[nan(), -0.0], [nan(), 0], [nan(), 1], [nan(), pi], [nan(), [nan(), -0.0], [nan(), 0], [nan(), 1], [nan(), pi], [nan(),
nan()]] nan()],
[5.0, 2.0], [5.0, 3.0], [5.0, 10.0], [5.0, -2.0], [-5.0, -2.0]]
pow_sc_ := [f64(0), // pow(-inf, -pi) pow_sc_ := [f64(0), // pow(-inf, -pi)
-0.0, // pow(-inf, -3) -0.0, // pow(-inf, -3)
1, // pow(-inf, -0) 1, // pow(-inf, -0)
@ -839,6 +840,11 @@ fn test_pow() {
nan(), // pow(nan, 1) nan(), // pow(nan, 1)
nan(), // pow(nan, pi) nan(), // pow(nan, pi)
nan(), // pow(nan, nan) nan(), // pow(nan, nan)
25, // pow(5, 2) => 5 * 5
125, // pow(5, 3) => 5 * 5 * 5
9765625, // pow(5, 10)
0.04, // pow(5, -2)
-0.04, // pow(-5, -2)
] ]
for i := 0; i < vfpow_sc_.len; i++ { for i := 0; i < vfpow_sc_.len; i++ {
f := pow(vfpow_sc_[i][0], vfpow_sc_[i][1]) f := pow(vfpow_sc_[i][0], vfpow_sc_[i][1])

View File

@ -80,6 +80,10 @@ pub fn pow(x f64, y f64) f64 {
return x return x
} else if is_nan(x) || is_nan(y) { } else if is_nan(x) || is_nan(y) {
return nan() return nan()
} else if y == 2 {
return x * x
} else if y == 3 {
return x * x * x
} else if x == 0 { } else if x == 0 {
if y < 0 { if y < 0 {
if is_odd_int(y) { if is_odd_int(y) {
@ -133,6 +137,17 @@ pub fn pow(x f64, y f64) f64 {
} }
} }
if yf == 0.0 {
mut result := x
for _ in 1 .. i64(yi) {
result *= x
}
if y > 0 {
return result
}
return copysign(1, x) / abs(result)
}
// ans = a1 * 2**ae (= 1 for now). // ans = a1 * 2**ae (= 1 for now).
mut a1 := 1.0 mut a1 := 1.0
mut ae := 0 mut ae := 0