From b51def0f60282ddc092ed83bb089d380dd06f545 Mon Sep 17 00:00:00 2001 From: Waterdragen Date: Fri, 9 May 2025 19:20:58 +0800 Subject: [PATCH 1/7] Add more element-wise math functions for floats --- src/numeric/impl_float_maths.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 7012a8b93..358d57cf3 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -103,12 +103,16 @@ where fn exp /// `2^x` of each element. fn exp2 + /// `e^x - 1` of each element. + fn exp_m1 /// Natural logarithm of each element. fn ln /// Base 2 logarithm of each element. fn log2 /// Base 10 logarithm of each element. fn log10 + /// `ln(1 + x)` of each element. + fn ln_1p /// Cubic root of each element. fn cbrt /// Sine of each element (in radians). @@ -117,6 +121,24 @@ where fn cos /// Tangent of each element (in radians). fn tan + /// Arcsine of each element (return in radians). + fn asin + /// Arccosine of each element (return in radians). + fn acos + /// Arctangent of each element (return in radians). + fn atan + /// Hyperbolic sine of each element. + fn sinh + /// Hyperbolic cosine of each element. + fn cosh + /// Hyperbolic tangent of each element. + fn tanh + /// Inverse hyperbolic sine of each element. + fn asinh + /// Inverse hyperbolic cosine of each element. + fn acosh + /// Inverse hyperbolic tangent of each element. + fn atanh /// Converts radians to degrees for each element. fn to_degrees /// Converts degrees to radians for each element. @@ -133,6 +155,8 @@ where fn log(A) /// The positive difference between given number and each element. fn abs_sub(A) + /// Length of the hypotenuse of a right-angle triangle of each element + fn hypot(A) } /// Square (two powers) of each element. From 5675ed501bce6ae25d3f8d7e73bb274d19d504f1 Mon Sep 17 00:00:00 2001 From: Waterdragen Date: Wed, 28 May 2025 19:09:32 +0800 Subject: [PATCH 2/7] Add element-wise binary float fn for two arrays --- src/numeric/impl_float_maths.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 358d57cf3..4f7dbbb94 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -2,8 +2,10 @@ #[cfg(feature = "std")] use num_traits::Float; +use std::borrow::Borrow; use crate::imp_prelude::*; +use crate::IntoNdProducer; #[cfg(feature = "std")] macro_rules! boolean_ops { @@ -50,6 +52,18 @@ macro_rules! binary_ops { }; } +#[cfg(feature = "std")] +macro_rules! binary_ops_array { + ($($(#[$meta:meta])* fn $fn_use:ident($ty:ty) as $fn_name:ident)+) => { + $($(#[$meta])* + #[must_use = "method returns a new array and does not mutate the original value"] + pub fn $fn_name

(&self, rhs: P) -> Array + where P: IntoNdProducer> { + $crate::Zip::from(self).and(rhs).map_collect(|a, b| A::$fn_use(*a, *b.borrow())) + })+ + }; +} + /// # Element-wise methods for float arrays /// /// Element-wise math functions for any array type that contains float number. @@ -157,6 +171,22 @@ where fn abs_sub(A) /// Length of the hypotenuse of a right-angle triangle of each element fn hypot(A) + /// Four quadrant arctangent of each element in radians. + fn atan2(A) + } + binary_ops_array! { + /// Integer power of each element. + fn powi(i32) as powi_all + /// Float power of each element. + fn powf(A) as powf_all + /// Logarithm of each element with respect to an arbitrary base. + fn log(A) as log_all + /// The positive difference between given number and each element. + fn abs_sub(A) as abs_sub_all + /// Length of the hypotenuse of a right-angle triangle of each element + fn hypot(A) as hypot_all + /// Four quadrant arctangent of each element in radians. + fn atan2(A) as atan2_all } /// Square (two powers) of each element. From 5398d47a61e572d80ec21b5b11211bdbd4c0314f Mon Sep 17 00:00:00 2001 From: Waterdragen <96000090+Waterdragen@users.noreply.github.com> Date: Wed, 28 May 2025 19:19:17 +0800 Subject: [PATCH 3/7] Implement two arrays binary float fn --- src/numeric/impl_float_maths.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 358d57cf3..4f7dbbb94 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -2,8 +2,10 @@ #[cfg(feature = "std")] use num_traits::Float; +use std::borrow::Borrow; use crate::imp_prelude::*; +use crate::IntoNdProducer; #[cfg(feature = "std")] macro_rules! boolean_ops { @@ -50,6 +52,18 @@ macro_rules! binary_ops { }; } +#[cfg(feature = "std")] +macro_rules! binary_ops_array { + ($($(#[$meta:meta])* fn $fn_use:ident($ty:ty) as $fn_name:ident)+) => { + $($(#[$meta])* + #[must_use = "method returns a new array and does not mutate the original value"] + pub fn $fn_name

(&self, rhs: P) -> Array + where P: IntoNdProducer> { + $crate::Zip::from(self).and(rhs).map_collect(|a, b| A::$fn_use(*a, *b.borrow())) + })+ + }; +} + /// # Element-wise methods for float arrays /// /// Element-wise math functions for any array type that contains float number. @@ -157,6 +171,22 @@ where fn abs_sub(A) /// Length of the hypotenuse of a right-angle triangle of each element fn hypot(A) + /// Four quadrant arctangent of each element in radians. + fn atan2(A) + } + binary_ops_array! { + /// Integer power of each element. + fn powi(i32) as powi_all + /// Float power of each element. + fn powf(A) as powf_all + /// Logarithm of each element with respect to an arbitrary base. + fn log(A) as log_all + /// The positive difference between given number and each element. + fn abs_sub(A) as abs_sub_all + /// Length of the hypotenuse of a right-angle triangle of each element + fn hypot(A) as hypot_all + /// Four quadrant arctangent of each element in radians. + fn atan2(A) as atan2_all } /// Square (two powers) of each element. From 4baffe4bbeb9d48fae79d37df649648c22d0b53b Mon Sep 17 00:00:00 2001 From: Waterdragen <96000090+Waterdragen@users.noreply.github.com> Date: Wed, 28 May 2025 19:38:35 +0800 Subject: [PATCH 4/7] Fix import lints --- src/numeric/impl_float_maths.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 4f7dbbb94..31d0aaa4b 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -2,10 +2,10 @@ #[cfg(feature = "std")] use num_traits::Float; +#[cfg(feature = "std")] use std::borrow::Borrow; use crate::imp_prelude::*; -use crate::IntoNdProducer; #[cfg(feature = "std")] macro_rules! boolean_ops { @@ -58,7 +58,7 @@ macro_rules! binary_ops_array { $($(#[$meta])* #[must_use = "method returns a new array and does not mutate the original value"] pub fn $fn_name

(&self, rhs: P) -> Array - where P: IntoNdProducer> { + where P: $crate::IntoNdProducer> { $crate::Zip::from(self).and(rhs).map_collect(|a, b| A::$fn_use(*a, *b.borrow())) })+ }; From 2db1a2a6841d44c41ac3faa6d9ae68f92b494cfb Mon Sep 17 00:00:00 2001 From: Waterdragen <96000090+Waterdragen@users.noreply.github.com> Date: Wed, 28 May 2025 19:51:21 +0800 Subject: [PATCH 5/7] Fix unstable associated type bounds --- src/numeric/impl_float_maths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 31d0aaa4b..a59c168ac 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -58,7 +58,7 @@ macro_rules! binary_ops_array { $($(#[$meta])* #[must_use = "method returns a new array and does not mutate the original value"] pub fn $fn_name

(&self, rhs: P) -> Array - where P: $crate::IntoNdProducer> { + where P: $crate::IntoNdProducer,

::Item: Borrow<$ty> { $crate::Zip::from(self).and(rhs).map_collect(|a, b| A::$fn_use(*a, *b.borrow())) })+ }; From 33f18a77db314d021ad27bf6cc4407dc9718d4ea Mon Sep 17 00:00:00 2001 From: Waterdragen Date: Wed, 28 May 2025 22:16:09 +0800 Subject: [PATCH 6/7] Add tests Test a function of: boolean op, unary op, binary op, binary op with arrays --- tests/numeric.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/numeric.rs b/tests/numeric.rs index 7e6964812..83d73c903 100644 --- a/tests/numeric.rs +++ b/tests/numeric.rs @@ -476,3 +476,40 @@ fn diff_panic_axis_out_of_bounds() let data = array![1, 2, 4, 7]; data.diff(1, Axis(2)); } + +#[test] +#[cfg(feature = "std")] +fn test_boolean_op_is_nan() +{ + let data = array![1.0, 2.0, 4.0, 7.0, f64::NAN]; + let expected = array![false, false, false, false, true]; + assert_eq!(data.is_nan(), expected); +} + +#[test] +#[cfg(feature = "std")] +fn test_unary_op_round() +{ + let data = array![0.0, 0.1, 0.5, 0.9, 1.0, 1.5]; + let expected = array![0.0, 0.0, 1.0, 1.0, 1.0, 2.0]; + assert_eq!(data.round(), expected); +} + +#[test] +#[cfg(feature = "std")] +fn test_binary_op_powi() +{ + let data = array![1.0, 2.0, 4.0, 7.0]; + let expected = array![1.0, 8.0, 64.0, 343.0]; + assert_eq!(data.powi(3), expected); +} + +#[test] +#[cfg(feature = "std")] +fn test_binary_op_hypot_all() +{ + let a = array![[3.0, 5.0], [8.0, 7.0]]; + let b = array![[4.0, 12.0], [15.0, 24.0]]; + let expected = array![[5.0, 13.0], [17.0, 25.0]]; + assert_eq!(a.hypot_all(&b), expected); +} From e83565f000498f24cc7f51c85a97d5aeca90a230 Mon Sep 17 00:00:00 2001 From: Waterdragen Date: Wed, 28 May 2025 22:30:08 +0800 Subject: [PATCH 7/7] Add a doc comment --- src/numeric/impl_float_maths.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index a59c168ac..4fa214b77 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -175,7 +175,9 @@ where fn atan2(A) } binary_ops_array! { - /// Integer power of each element. + /// Integer power of each element + /// + /// This function is generally faster than using float power. fn powi(i32) as powi_all /// Float power of each element. fn powf(A) as powf_all