From b5afa049e942db44ea4bfe3433317c91783520cb Mon Sep 17 00:00:00 2001 From: Cabral <17774851+cabralski@users.noreply.github.com> Date: Sat, 8 May 2021 08:32:18 -0300 Subject: [PATCH] math: sign function (#10014) --- vlib/math/const.v | 2 +- vlib/math/math.v | 23 ++++++++++++++++++++++ vlib/math/math_test.v | 45 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/vlib/math/const.v b/vlib/math/const.v index 7049680e4e..5a831a97c8 100644 --- a/vlib/math/const.v +++ b/vlib/math/const.v @@ -37,7 +37,7 @@ pub const ( min_i16 = -32768 max_i32 = 2147483647 min_i32 = -2147483648 - // -9223372036854775808 is wrong because C compilers parse litteral values + // -9223372036854775808 is wrong because C compilers parse literal values // without sign first, and 9223372036854775808 overflows i64, hence the // consecutive subtraction by 1 min_i64 = i64(-9223372036854775807 - 1) diff --git a/vlib/math/math.v b/vlib/math/math.v index f7cb6f6d7e..f102f39257 100644 --- a/vlib/math/math.v +++ b/vlib/math/math.v @@ -31,11 +31,13 @@ pub fn aprox_cos(a f64) f64 { } // copysign returns a value with the magnitude of x and the sign of y +[inline] pub fn copysign(x f64, y f64) f64 { return f64_from_bits((f64_bits(x) & ~sign_mask) | (f64_bits(y) & sign_mask)) } // degrees convert from degrees to radians. +[inline] pub fn degrees(radians f64) f64 { return radians * (180.0 / pi) } @@ -59,6 +61,7 @@ pub fn digits(_n int, base int) []int { return res } +[inline] pub fn fabs(x f64) f64 { if x < 0.0 { return -x @@ -99,6 +102,7 @@ pub fn lcm(a i64, b i64) i64 { } // max returns the maximum value of the two provided. +[inline] pub fn max(a f64, b f64) f64 { if a > b { return a @@ -107,6 +111,7 @@ pub fn max(a f64, b f64) f64 { } // min returns the minimum value of the two provided. +[inline] pub fn min(a f64, b f64) f64 { if a < b { return a @@ -114,12 +119,30 @@ pub fn min(a f64, b f64) f64 { return b } +// sign returns the corresponding sign -1.0, 1.0 of the provided number. +// if n is not a number, its sign is nan too. +[inline] +pub fn sign(n f64) f64 { + if is_nan(n) { + return nan() + } + return copysign(1.0, n) +} + +// signi returns the corresponding sign -1.0, 1.0 of the provided number. +[inline] +pub fn signi(n f64) int { + return int(copysign(1.0, n)) +} + // radians convert from radians to degrees. +[inline] pub fn radians(degrees f64) f64 { return degrees * (pi / 180.0) } // signbit returns a value with the boolean representation of the sign for x +[inline] pub fn signbit(x f64) bool { return f64_bits(x) & sign_mask != 0 } diff --git a/vlib/math/math_test.v b/vlib/math/math_test.v index 2aa0e5e640..b3dece0893 100644 --- a/vlib/math/math_test.v +++ b/vlib/math/math_test.v @@ -368,6 +368,49 @@ fn test_min() { } } +fn test_signi() { + assert signi(inf(-1)) == -1 + assert signi(-72234878292.4586129) == -1 + assert signi(-10) == -1 + assert signi(-pi) == -1 + assert signi(-1) == -1 + assert signi(-0.000000000001) == -1 + assert signi(-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001) == -1 + assert signi(-0.0) == -1 + // + assert signi(inf(1)) == 1 + assert signi(72234878292.4586129) == 1 + assert signi(10) == 1 + assert signi(pi) == 1 + assert signi(1) == 1 + assert signi(0.000000000001) == 1 + assert signi(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001) == 1 + assert signi(0.0) == 1 + assert signi(nan()) == 1 +} + +fn test_sign() { + assert sign(inf(-1)) == -1.0 + assert sign(-72234878292.4586129) == -1.0 + assert sign(-10) == -1.0 + assert sign(-pi) == -1.0 + assert sign(-1) == -1.0 + assert sign(-0.000000000001) == -1.0 + assert sign(-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001) == -1.0 + assert sign(-0.0) == -1.0 + // + assert sign(inf(1)) == 1.0 + assert sign(72234878292.4586129) == 1 + assert sign(10) == 1.0 + assert sign(pi) == 1.0 + assert sign(1) == 1.0 + assert sign(0.000000000001) == 1.0 + assert sign(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001) == 1.0 + assert sign(0.0) == 1.0 + assert is_nan(sign(nan())) + assert is_nan(sign(-nan())) +} + fn test_exp() { for i := 0; i < math.vf_.len; i++ { f := exp(math.vf_[i]) @@ -576,7 +619,7 @@ fn test_round() { [f64(4503599627370495.5), 4503599627370496], /* 1 bit fraction, rounding to 0 bit fractian */ [f64(4503599627370497), 4503599627370497], /* large integer */ ] - _ := vfround_even_sc_[0][0] + _ := vfround_even_sc_[0][0] for i := 0; i < vfround_sc_.len; i++ { f := round(vfround_sc_[i][0]) assert alike(vfround_sc_[i][1], f)