From fb0f12f937ee9d943f9adafa3d350aff65105215 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 4 Sep 2023 21:09:01 +0300 Subject: [PATCH] math: add more C. fn overrides, for the default C backend (speed up examples/path_tracing.v) (#19271) --- bench/vectors/vectors.cs | 10 ++++------ bench/vectors/vectors.v | 13 +++++++------ vlib/math/exp.c.v | 25 +++++++++++++++++++++++++ vlib/math/log.c.v | 17 +++++++++++++++++ vlib/math/log.v | 2 +- vlib/math/pow.c.v | 10 +++++++++- vlib/math/pow.v | 2 +- vlib/math/sin.c.v | 16 ++++++++++++++++ vlib/math/sqrt.c.v | 7 +++++++ vlib/math/square.v | 13 +++++++++++++ vlib/math/square_test.v | 21 +++++++++++++++++++++ vlib/math/unsafe.v | 7 +++++++ vlib/math/vec/vec2_test.v | 5 +++-- 13 files changed, 131 insertions(+), 17 deletions(-) create mode 100644 vlib/math/exp.c.v create mode 100644 vlib/math/log.c.v create mode 100644 vlib/math/square.v create mode 100644 vlib/math/square_test.v diff --git a/bench/vectors/vectors.cs b/bench/vectors/vectors.cs index 691997497d..40a49cc1b5 100644 --- a/bench/vectors/vectors.cs +++ b/bench/vectors/vectors.cs @@ -62,13 +62,11 @@ internal static class Program var differenceY = position.Y - otherPosition.Y; var differenceZ = position.Z - otherPosition.Z; - var distance = Math.Sqrt( - differenceX * differenceX + + var distance = differenceX * differenceX + differenceY * differenceY + - differenceZ * differenceZ - ); + differenceZ * differenceZ; - if (distance <= cohesionDistance) + if (distance <= cohesionDistance * cohesionDistance) { closeBoids.Add(otherBoidIndex); } @@ -188,4 +186,4 @@ internal static class Program Console.WriteLine(positionSum.ToString()); Console.WriteLine(velocitySum.ToString()); } -} \ No newline at end of file +} diff --git a/bench/vectors/vectors.v b/bench/vectors/vectors.v index 0504ff0506..92c8b1d7c7 100644 --- a/bench/vectors/vectors.v +++ b/bench/vectors/vectors.v @@ -44,11 +44,10 @@ fn main() { difference_y := position.y - other_position.y difference_z := position.z - other_position.z - distance := math.sqrt(difference_x * difference_x + - difference_y * difference_y + - difference_z * difference_z) + distance := difference_x * difference_x + difference_y * difference_y + + difference_z * difference_z - if distance <= cohesion_distance { + if distance <= cohesion_distance * cohesion_distance { close_boids_ids << other_boid_index } } @@ -77,8 +76,10 @@ fn main() { z: position.z - close_boid_position.z } - difference_magnitude := math.sqrt(difference_from_closest.x * difference_from_closest.x + - difference_from_closest.y * difference_from_closest.y + difference_from_closest.z * difference_from_closest.z) + difference_magnitude := math.sqrt( + difference_from_closest.x * difference_from_closest.x + + difference_from_closest.y * difference_from_closest.y + + difference_from_closest.z * difference_from_closest.z) if difference_magnitude <= separation_distance { separation = Vector{ diff --git a/vlib/math/exp.c.v b/vlib/math/exp.c.v new file mode 100644 index 0000000000..02596302e5 --- /dev/null +++ b/vlib/math/exp.c.v @@ -0,0 +1,25 @@ +module math + +fn C.exp(x f64) f64 + +fn C.exp2(x f64) f64 + +fn C.ldexp(x f64, exp int) f64 + +// exp returns e**x, the base-e exponential of x. +[inline] +pub fn exp(x f64) f64 { + return C.exp(x) +} + +// exp2 returns 2**x, the base-2 exponential of x. +[inline] +pub fn exp2(x f64) f64 { + return C.exp2(x) +} + +// ldexp calculates frac*(2**exp). +[inline] +pub fn ldexp(frac f64, exp int) f64 { + return C.ldexp(frac, exp) +} diff --git a/vlib/math/log.c.v b/vlib/math/log.c.v new file mode 100644 index 0000000000..17e04a2aec --- /dev/null +++ b/vlib/math/log.c.v @@ -0,0 +1,17 @@ +module math + +fn C.log(x f64) f64 + +fn C.logf(x f32) f32 + +// log returns the natural logarithm of x (float64) +[inline] +pub fn log(a f64) f64 { + return C.log(a) +} + +// log returns the natural logarithm of x (float32) +[inline] +pub fn logf(a f32) f32 { + return C.logf(a) +} diff --git a/vlib/math/log.v b/vlib/math/log.v index da7eaedaa5..1d3d5f0a9c 100644 --- a/vlib/math/log.v +++ b/vlib/math/log.v @@ -77,7 +77,7 @@ fn ilog_b_(x_ f64) int { return int((f64_bits(x) >> shift) & mask) - bias + exp } -// log returns the logarithm of x +// log returns the natural logarithm of x // // Method : // 1. Argument Reduction: find k and f such that diff --git a/vlib/math/pow.c.v b/vlib/math/pow.c.v index 475620cc92..beaa0c026b 100644 --- a/vlib/math/pow.c.v +++ b/vlib/math/pow.c.v @@ -1,8 +1,16 @@ module math +fn C.pow(x f64, y f64) f64 + fn C.powf(x f32, y f32) f32 -// powf returns base raised to the provided power. (float32) +// pow returns the base x, raised to the provided power y. (float64) +[inline] +pub fn pow(x f64, y f64) f64 { + return C.pow(x, y) +} + +// powf returns the base a, raised to the provided power b. (float32) [inline] pub fn powf(a f32, b f32) f32 { return C.powf(a, b) diff --git a/vlib/math/pow.v b/vlib/math/pow.v index f045362f75..ddb06076e6 100644 --- a/vlib/math/pow.v +++ b/vlib/math/pow.v @@ -70,7 +70,7 @@ pub fn powi(a i64, b i64) i64 { return v } -// pow returns base raised to the provided power. +// pow returns the base x, raised to the provided power y. (float64) // // todo(playXE): make this function work on JS backend, probably problem of JS codegen that it does not work. pub fn pow(x f64, y f64) f64 { diff --git a/vlib/math/sin.c.v b/vlib/math/sin.c.v index ef313af18e..6fffa2bc77 100644 --- a/vlib/math/sin.c.v +++ b/vlib/math/sin.c.v @@ -1,9 +1,25 @@ module math +fn C.cos(x f64) f64 + +fn C.sin(x f64) f64 + fn C.cosf(x f32) f32 fn C.sinf(x f32) f32 +// cos calculates cosine in radians (float64) +[inline] +pub fn cos(a f64) f64 { + return C.cos(a) +} + +// sin calculates sine in radians (float64) +[inline] +pub fn sin(a f64) f64 { + return C.sin(a) +} + // cosf calculates cosine in radians (float32) [inline] pub fn cosf(a f32) f32 { diff --git a/vlib/math/sqrt.c.v b/vlib/math/sqrt.c.v index 02766657ff..62382e650b 100644 --- a/vlib/math/sqrt.c.v +++ b/vlib/math/sqrt.c.v @@ -1,7 +1,14 @@ module math +fn C.sqrt(x f64) f64 fn C.sqrtf(x f32) f32 +// sqrt calculates square-root of the provided value. (float64) +[inline] +pub fn sqrt(a f64) f64 { + return C.sqrt(a) +} + // sqrtf calculates square-root of the provided value. (float32) [inline] pub fn sqrtf(a f32) f32 { diff --git a/vlib/math/square.v b/vlib/math/square.v new file mode 100644 index 0000000000..a5ace7ad07 --- /dev/null +++ b/vlib/math/square.v @@ -0,0 +1,13 @@ +module math + +// square returns the square of the argument x, i.e. x * x +[inline] +pub fn square[T](x T) T { + return x * x +} + +// cube returns the cube of the argument x, i.e. x * x * x +[inline] +pub fn cube[T](x T) T { + return x * x * x +} diff --git a/vlib/math/square_test.v b/vlib/math/square_test.v new file mode 100644 index 0000000000..c0ef187967 --- /dev/null +++ b/vlib/math/square_test.v @@ -0,0 +1,21 @@ +import math + +fn test_square() { + assert math.square(0) == 0 + assert math.square(1) == 1 + assert math.square(-1) == 1 + assert math.square(5) == 25 + assert math.square(u8(3)) == 9 + assert math.square(u32(10)) == 100 + assert math.square(-7) == 49 +} + +fn test_cube() { + assert math.cube(0) == 0 + assert math.cube(1) == 1 + assert math.cube(-1) == -1 + assert math.cube(5) == 125 + assert math.cube(u8(3)) == 27 + assert math.cube(u32(10)) == 1000 + assert math.cube(-7) == -343 +} diff --git a/vlib/math/unsafe.v b/vlib/math/unsafe.v index efbb5f0b63..d304299a1c 100644 --- a/vlib/math/unsafe.v +++ b/vlib/math/unsafe.v @@ -6,6 +6,7 @@ module math // f32_bits returns the IEEE 754 binary representation of f, // with the sign bit of f and the result in the same bit position. // f32_bits(f32_from_bits(x)) == x. +[inline] pub fn f32_bits(f f32) u32 { p := *unsafe { &u32(&f) } return p @@ -15,6 +16,7 @@ pub fn f32_bits(f f32) u32 { // to the IEEE 754 binary representation b, with the sign bit of b // and the result in the same bit position. // f32_from_bits(f32_bits(x)) == x. +[inline] pub fn f32_from_bits(b u32) f32 { p := *unsafe { &f32(&b) } return p @@ -23,6 +25,7 @@ pub fn f32_from_bits(b u32) f32 { // f64_bits returns the IEEE 754 binary representation of f, // with the sign bit of f and the result in the same bit position, // and f64_bits(f64_from_bits(x)) == x. +[inline] pub fn f64_bits(f f64) u64 { p := *unsafe { &u64(&f) } return p @@ -32,12 +35,14 @@ pub fn f64_bits(f f64) u64 { // to the IEEE 754 binary representation b, with the sign bit of b // and the result in the same bit position. // f64_from_bits(f64_bits(x)) == x. +[inline] pub fn f64_from_bits(b u64) f64 { p := *unsafe { &f64(&b) } return p } // with_set_low_word sets low word of `f` to `lo` +[inline] pub fn with_set_low_word(f f64, lo u32) f64 { mut tmp := f64_bits(f) tmp &= 0xffffffff_00000000 @@ -46,6 +51,7 @@ pub fn with_set_low_word(f f64, lo u32) f64 { } // with_set_high_word sets high word of `f` to `lo` +[inline] pub fn with_set_high_word(f f64, hi u32) f64 { mut tmp := f64_bits(f) tmp &= 0x00000000_ffffffff @@ -54,6 +60,7 @@ pub fn with_set_high_word(f f64, hi u32) f64 { } // get_high_word returns high part of the word of `f`. +[inline] pub fn get_high_word(f f64) u32 { return u32(f64_bits(f) >> 32) } diff --git a/vlib/math/vec/vec2_test.v b/vlib/math/vec/vec2_test.v index f11d790b19..b20adbabfb 100644 --- a/vlib/math/vec/vec2_test.v +++ b/vlib/math/vec/vec2_test.v @@ -1,3 +1,4 @@ +import math import math.vec fn test_vec2_int() { @@ -72,11 +73,11 @@ fn test_vec2_f64_utils_1() { fn test_vec2_f64_utils_2() { mut v1 := vec.vec2(4.0, 4.0) - assert v1.unit().magnitude() == 1 + assert math.veryclose(v1.unit().magnitude(), 1) v2 := v1.mul_scalar(0.5) assert v2.x == 2 assert v2.y == 2 - assert v2.unit().magnitude() == 1 + assert math.veryclose(v2.unit().magnitude(), 1) invv2 := v2.inv() assert invv2.x == 0.5