From 8f5f08b7060cac59335c21efd13c0482c26e8c54 Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Tue, 13 Jul 2021 11:35:54 +0800 Subject: [PATCH 1/8] Add common used functions. --- src/impl_float_maths.rs | 181 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 2 files changed, 183 insertions(+) create mode 100644 src/impl_float_maths.rs diff --git a/src/impl_float_maths.rs b/src/impl_float_maths.rs new file mode 100644 index 000000000..c7402cebe --- /dev/null +++ b/src/impl_float_maths.rs @@ -0,0 +1,181 @@ +//! Element-wise methods for ndarray + +use num_traits::Float; + +use crate::imp_prelude::*; + +macro_rules! boolean_op { + ($(#[$meta1:meta])* fn $id1:ident $(#[$meta2:meta])* fn $id2:ident -> $func:ident) => { + $(#[$meta1])* + pub fn $id1(&self) -> Array { + self.mapv(A::$func) + } + $(#[$meta2])* + pub fn $id2(&self) -> bool { + self.mapv(A::$func).iter().any(|&b|b) + } + }; +} + +macro_rules! map_op { + ($(#[$meta:meta])* fn $id:ident) => { + $(#[$meta])* + pub fn $id(&self) -> Array { + self.mapv(A::$id) + } + }; +} + +macro_rules! bin_op { + ($(#[$meta:meta])* fn $id:ident($ty:ty)) => { + $(#[$meta])* + pub fn $id(&self, rhs: $ty) -> Array { + self.mapv(|v| A::$id(v, rhs)) + } + }; +} + +/// # Element-wise methods for Float Array +/// +/// Element-wise math functions for any array type that contains float number. +impl ArrayBase +where + A: Float, + S: RawData + Data, + D: Dimension, +{ + boolean_op! { + /// If the number is `NaN` (not a number), then `true` is returned for each element. + fn is_nan + /// Return `true` if any element is `NaN` (not a number). + fn is_nan_any -> is_nan + } + boolean_op! { + /// If the number is infinity, then `true` is returned for each element. + fn is_infinite + /// Return `true` if any element is infinity. + fn is_infinite_any -> is_infinite + } + map_op! { + /// The largest integer less than or equal to each element. + fn floor + } + map_op! { + /// The smallest integer less than or equal to each element. + fn ceil + } + map_op! { + /// The nearest integer of each element. + fn round + } + map_op! { + /// The integer part of each element. + fn trunc + } + map_op! { + /// The fractional part of each element. + fn fract + } + map_op! { + /// Absolute of each element. + fn abs + } + map_op! { + /// Sign number of each element. + /// + /// + `1.0` for all positive numbers. + /// + `-1.0` for all negative numbers. + /// + `NaN` for all `NaN` (not a number). + fn signum + } + map_op! { + /// The reciprocal (inverse) of each element, `1/x`. + fn recip + } + bin_op! { + /// Integer power of each element. + /// + /// This function is generally faster than using float power. + fn powi(i32) + } + bin_op! { + /// Float power of each element. + fn powf(A) + } + + /// Square of each element. + pub fn square(&self) -> Array { + self.mapv(|v| v * v) + } + + map_op! { + /// Square root of each element. + fn sqrt + } + map_op! { + /// `e^x` of each element. (Exponential function) + fn exp + } + map_op! { + /// `2^x` of each element. + fn exp2 + } + map_op! { + /// Natural logarithm of each element. + fn ln + } + bin_op! { + /// Logarithm of each element with respect to an arbitrary base. + fn log(A) + } + map_op! { + /// Base 2 logarithm of each element. + fn log2 + } + map_op! { + /// Base 10 logarithm of each element. + fn log10 + } + bin_op! { + /// The positive difference between given number and each element. + fn abs_sub(A) + } + map_op! { + /// Cubic root of each element. + fn cbrt + } + map_op! { + /// Sine of each element. (in radians) + fn sin + } + map_op! { + /// Cosine of each element. (in radians) + fn cos + } + map_op! { + /// Tangent of each element. (in radians) + fn tan + } + map_op! { + /// Converts radians to degrees for each element. + fn to_degrees + } + map_op! { + /// Converts degrees to radians for each element. + fn to_radians + } + + /// Limit the values for each element. + /// + /// ``` + /// use ndarray::{Array1, array}; + /// + /// let a = Array1::range(0., 10., 1.); + /// assert_eq!(a.clip(1., 8.), array![1., 1., 2., 3., 4., 5., 6., 7., 8., 8.]); + /// assert_eq!(a.clip(8., 1.), array![1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]); + /// assert_eq!(a.clip(3., 6.), array![3., 3., 3., 3., 4., 5., 6., 6., 6., 6.]); + /// ``` + pub fn clip(&self, min: A, max: A) -> Array { + self.mapv(|v| A::max(v, min)).mapv(|v| A::min(v, max)) + } +} diff --git a/src/lib.rs b/src/lib.rs index f773226f5..8beb575f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1515,6 +1515,8 @@ mod impl_internal_constructors; mod impl_constructors; mod impl_methods; +#[cfg(feature = "std")] +mod impl_float_maths; mod impl_owned_array; mod impl_special_element_types; From 80f684b6165fed80051af3f9fdc17b36d2f89ee9 Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Tue, 13 Jul 2021 14:38:22 +0800 Subject: [PATCH 2/8] Chain the mapping. --- src/impl_float_maths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impl_float_maths.rs b/src/impl_float_maths.rs index c7402cebe..9433aecec 100644 --- a/src/impl_float_maths.rs +++ b/src/impl_float_maths.rs @@ -176,6 +176,6 @@ where /// assert_eq!(a.clip(3., 6.), array![3., 3., 3., 3., 4., 5., 6., 6., 6., 6.]); /// ``` pub fn clip(&self, min: A, max: A) -> Array { - self.mapv(|v| A::max(v, min)).mapv(|v| A::min(v, max)) + self.mapv(|v| A::min(A::max(v, min), max)) } } From 35f99b452408fd40581630051a92ab612f85fad1 Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Fri, 23 Jul 2021 18:07:00 +0800 Subject: [PATCH 3/8] Change macro names. --- src/impl_float_maths.rs | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/impl_float_maths.rs b/src/impl_float_maths.rs index 9433aecec..aebab2084 100644 --- a/src/impl_float_maths.rs +++ b/src/impl_float_maths.rs @@ -17,7 +17,7 @@ macro_rules! boolean_op { }; } -macro_rules! map_op { +macro_rules! unary_op { ($(#[$meta:meta])* fn $id:ident) => { $(#[$meta])* pub fn $id(&self) -> Array { @@ -26,7 +26,7 @@ macro_rules! map_op { }; } -macro_rules! bin_op { +macro_rules! binary_op { ($(#[$meta:meta])* fn $id:ident($ty:ty)) => { $(#[$meta])* pub fn $id(&self, rhs: $ty) -> Array { @@ -56,31 +56,31 @@ where /// Return `true` if any element is infinity. fn is_infinite_any -> is_infinite } - map_op! { + unary_op! { /// The largest integer less than or equal to each element. fn floor } - map_op! { + unary_op! { /// The smallest integer less than or equal to each element. fn ceil } - map_op! { + unary_op! { /// The nearest integer of each element. fn round } - map_op! { + unary_op! { /// The integer part of each element. fn trunc } - map_op! { + unary_op! { /// The fractional part of each element. fn fract } - map_op! { + unary_op! { /// Absolute of each element. fn abs } - map_op! { + unary_op! { /// Sign number of each element. /// /// + `1.0` for all positive numbers. @@ -88,17 +88,17 @@ where /// + `NaN` for all `NaN` (not a number). fn signum } - map_op! { + unary_op! { /// The reciprocal (inverse) of each element, `1/x`. fn recip } - bin_op! { + binary_op! { /// Integer power of each element. /// /// This function is generally faster than using float power. fn powi(i32) } - bin_op! { + binary_op! { /// Float power of each element. fn powf(A) } @@ -108,59 +108,59 @@ where self.mapv(|v| v * v) } - map_op! { + unary_op! { /// Square root of each element. fn sqrt } - map_op! { + unary_op! { /// `e^x` of each element. (Exponential function) fn exp } - map_op! { + unary_op! { /// `2^x` of each element. fn exp2 } - map_op! { + unary_op! { /// Natural logarithm of each element. fn ln } - bin_op! { + binary_op! { /// Logarithm of each element with respect to an arbitrary base. fn log(A) } - map_op! { + unary_op! { /// Base 2 logarithm of each element. fn log2 } - map_op! { + unary_op! { /// Base 10 logarithm of each element. fn log10 } - bin_op! { + binary_op! { /// The positive difference between given number and each element. fn abs_sub(A) } - map_op! { + unary_op! { /// Cubic root of each element. fn cbrt } - map_op! { + unary_op! { /// Sine of each element. (in radians) fn sin } - map_op! { + unary_op! { /// Cosine of each element. (in radians) fn cos } - map_op! { + unary_op! { /// Tangent of each element. (in radians) fn tan } - map_op! { + unary_op! { /// Converts radians to degrees for each element. fn to_degrees } - map_op! { + unary_op! { /// Converts degrees to radians for each element. fn to_radians } From 3296660e7b4e5ff8925e341237d7cd3683903f4d Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Fri, 6 Aug 2021 07:37:06 +0800 Subject: [PATCH 4/8] Simplify macros. --- src/impl_float_maths.rs | 120 ++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 72 deletions(-) diff --git a/src/impl_float_maths.rs b/src/impl_float_maths.rs index aebab2084..3037a05b4 100644 --- a/src/impl_float_maths.rs +++ b/src/impl_float_maths.rs @@ -5,33 +5,33 @@ use num_traits::Float; use crate::imp_prelude::*; macro_rules! boolean_op { - ($(#[$meta1:meta])* fn $id1:ident $(#[$meta2:meta])* fn $id2:ident -> $func:ident) => { - $(#[$meta1])* + ($($(#[$meta1:meta])* fn $id1:ident $(#[$meta2:meta])* fn $id2:ident -> $func:ident)+) => { + $($(#[$meta1])* pub fn $id1(&self) -> Array { self.mapv(A::$func) } $(#[$meta2])* pub fn $id2(&self) -> bool { self.mapv(A::$func).iter().any(|&b|b) - } + })+ }; } macro_rules! unary_op { - ($(#[$meta:meta])* fn $id:ident) => { - $(#[$meta])* + ($($(#[$meta:meta])* fn $id:ident)+) => { + $($(#[$meta])* pub fn $id(&self) -> Array { self.mapv(A::$id) - } + })+ }; } macro_rules! binary_op { - ($(#[$meta:meta])* fn $id:ident($ty:ty)) => { - $(#[$meta])* + ($($(#[$meta:meta])* fn $id:ident($ty:ty))+) => { + $($(#[$meta])* pub fn $id(&self, rhs: $ty) -> Array { self.mapv(|v| A::$id(v, rhs)) - } + })+ }; } @@ -49,8 +49,7 @@ where fn is_nan /// Return `true` if any element is `NaN` (not a number). fn is_nan_any -> is_nan - } - boolean_op! { + /// If the number is infinity, then `true` is returned for each element. fn is_infinite /// Return `true` if any element is infinity. @@ -59,111 +58,88 @@ where unary_op! { /// The largest integer less than or equal to each element. fn floor - } - unary_op! { + /// The smallest integer less than or equal to each element. fn ceil - } - unary_op! { + /// The nearest integer of each element. fn round - } - unary_op! { + /// The integer part of each element. fn trunc - } - unary_op! { + /// The fractional part of each element. fn fract - } - unary_op! { + /// Absolute of each element. fn abs - } - unary_op! { + /// Sign number of each element. /// /// + `1.0` for all positive numbers. /// + `-1.0` for all negative numbers. /// + `NaN` for all `NaN` (not a number). fn signum - } - unary_op! { + /// The reciprocal (inverse) of each element, `1/x`. fn recip - } - binary_op! { - /// Integer power of each element. - /// - /// This function is generally faster than using float power. - fn powi(i32) - } - binary_op! { - /// Float power of each element. - fn powf(A) - } - - /// Square of each element. - pub fn square(&self) -> Array { - self.mapv(|v| v * v) - } - unary_op! { /// Square root of each element. fn sqrt - } - unary_op! { + /// `e^x` of each element. (Exponential function) fn exp - } - unary_op! { + /// `2^x` of each element. fn exp2 - } - unary_op! { + /// Natural logarithm of each element. fn ln - } - binary_op! { - /// Logarithm of each element with respect to an arbitrary base. - fn log(A) - } - unary_op! { + /// Base 2 logarithm of each element. fn log2 - } - unary_op! { + /// Base 10 logarithm of each element. fn log10 - } - binary_op! { - /// The positive difference between given number and each element. - fn abs_sub(A) - } - unary_op! { + /// Cubic root of each element. fn cbrt - } - unary_op! { + /// Sine of each element. (in radians) fn sin - } - unary_op! { + /// Cosine of each element. (in radians) fn cos - } - unary_op! { + /// Tangent of each element. (in radians) fn tan - } - unary_op! { + /// Converts radians to degrees for each element. fn to_degrees - } - unary_op! { + /// Converts degrees to radians for each element. fn to_radians } + binary_op! { + /// Integer power of each element. + /// + /// This function is generally faster than using float power. + fn powi(i32) + + /// Float power of each element. + fn powf(A) + + /// Logarithm of each element with respect to an arbitrary base. + fn log(A) + + /// The positive difference between given number and each element. + fn abs_sub(A) + } + + /// Square of each element. + pub fn square(&self) -> Array { + self.mapv(|v| v * v) + } /// Limit the values for each element. /// From 6b25dca84043e6afe3a6712b2bd271e316fad81e Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Sun, 3 Oct 2021 10:21:30 +0800 Subject: [PATCH 5/8] Apply partial suggestions. --- src/impl_float_maths.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/impl_float_maths.rs b/src/impl_float_maths.rs index 3037a05b4..12100fb99 100644 --- a/src/impl_float_maths.rs +++ b/src/impl_float_maths.rs @@ -7,12 +7,14 @@ use crate::imp_prelude::*; macro_rules! boolean_op { ($($(#[$meta1:meta])* fn $id1:ident $(#[$meta2:meta])* fn $id2:ident -> $func:ident)+) => { $($(#[$meta1])* + #[must_use = "method returns a new array and does not mutate the original value"] pub fn $id1(&self) -> Array { self.mapv(A::$func) } $(#[$meta2])* + #[must_use = "method returns a new boolean value and does not mutate the original value"] pub fn $id2(&self) -> bool { - self.mapv(A::$func).iter().any(|&b|b) + self.mapv(A::$func).iter().any(|&b| b) })+ }; } @@ -20,6 +22,7 @@ macro_rules! boolean_op { macro_rules! unary_op { ($($(#[$meta:meta])* fn $id:ident)+) => { $($(#[$meta])* + #[must_use = "method returns a new array and does not mutate the original value"] pub fn $id(&self) -> Array { self.mapv(A::$id) })+ @@ -29,6 +32,7 @@ macro_rules! unary_op { macro_rules! binary_op { ($($(#[$meta:meta])* fn $id:ident($ty:ty))+) => { $($(#[$meta])* + #[must_use = "method returns a new array and does not mutate the original value"] pub fn $id(&self, rhs: $ty) -> Array { self.mapv(|v| A::$id(v, rhs)) })+ @@ -41,19 +45,19 @@ macro_rules! binary_op { impl ArrayBase where A: Float, - S: RawData + Data, + S: Data, D: Dimension, { boolean_op! { /// If the number is `NaN` (not a number), then `true` is returned for each element. fn is_nan /// Return `true` if any element is `NaN` (not a number). - fn is_nan_any -> is_nan + fn is_any_nan -> is_nan /// If the number is infinity, then `true` is returned for each element. fn is_infinite /// Return `true` if any element is infinity. - fn is_infinite_any -> is_infinite + fn is_any_infinite -> is_infinite } unary_op! { /// The largest integer less than or equal to each element. @@ -87,7 +91,7 @@ where /// Square root of each element. fn sqrt - /// `e^x` of each element. (Exponential function) + /// `e^x` of each element (exponential function). fn exp /// `2^x` of each element. @@ -105,13 +109,13 @@ where /// Cubic root of each element. fn cbrt - /// Sine of each element. (in radians) + /// Sine of each element (in radians). fn sin - /// Cosine of each element. (in radians) + /// Cosine of each element (in radians). fn cos - /// Tangent of each element. (in radians) + /// Tangent of each element (in radians). fn tan /// Converts radians to degrees for each element. @@ -136,9 +140,10 @@ where fn abs_sub(A) } - /// Square of each element. - pub fn square(&self) -> Array { - self.mapv(|v| v * v) + /// Square (two powers) of each element. + #[must_use = "method returns a new array and does not mutate the original value"] + pub fn pow2(&self) -> Array { + self.mapv(|v: A| v * v) } /// Limit the values for each element. From 11ad08e8ad4262ffbc2fd7824006e93bb0d72d8c Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Wed, 8 Dec 2021 15:10:11 +0800 Subject: [PATCH 6/8] Apply most of the suggestions. --- src/lib.rs | 26 +++--- src/{ => numeric}/impl_float_maths.rs | 110 +++++++++++++++----------- src/numeric/mod.rs | 2 + 3 files changed, 74 insertions(+), 64 deletions(-) rename src/{ => numeric}/impl_float_maths.rs (63%) diff --git a/src/lib.rs b/src/lib.rs index 8beb575f0..da5473b00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,13 +125,12 @@ //! For conversion between `ndarray`, [`nalgebra`](https://crates.io/crates/nalgebra) and //! [`image`](https://crates.io/crates/image) check out [`nshare`](https://crates.io/crates/nshare). - extern crate alloc; -#[cfg(feature = "std")] -extern crate std; #[cfg(not(feature = "std"))] extern crate core as std; +#[cfg(feature = "std")] +extern crate std; #[cfg(feature = "blas")] extern crate cblas_sys; @@ -139,8 +138,8 @@ extern crate cblas_sys; #[cfg(feature = "docs")] pub mod doc; -use std::marker::PhantomData; use alloc::sync::Arc; +use std::marker::PhantomData; pub use crate::dimension::dim::*; pub use crate::dimension::{Axis, AxisDescription, Dimension, IntoDimension, RemoveAxis}; @@ -159,16 +158,16 @@ use crate::iterators::Baseiter; use crate::iterators::{ElementsBase, ElementsBaseMut, Iter, IterMut}; pub use crate::arraytraits::AsArray; +pub use crate::linalg_traits::LinalgScalar; #[cfg(feature = "std")] pub use crate::linalg_traits::NdFloat; -pub use crate::linalg_traits::LinalgScalar; #[allow(deprecated)] // stack_new_axis pub use crate::stacking::{concatenate, stack, stack_new_axis}; -pub use crate::math_cell::MathCell; pub use crate::impl_views::IndexLonger; -pub use crate::shape_builder::{Shape, ShapeBuilder, ShapeArg, StrideShape}; +pub use crate::math_cell::MathCell; +pub use crate::shape_builder::{Shape, ShapeArg, ShapeBuilder, StrideShape}; #[macro_use] mod macro_utils; @@ -189,8 +188,7 @@ mod data_traits; pub use crate::aliases::*; pub use crate::data_traits::{ - Data, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut, - RawDataSubst, + Data, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut, RawDataSubst, }; mod free_functions; @@ -213,9 +211,9 @@ mod partial; mod shape_builder; #[macro_use] mod slice; +mod low_level_util; mod split_at; mod stacking; -mod low_level_util; #[macro_use] mod zip; @@ -1511,12 +1509,10 @@ impl<'a, A> CowRepr<'a, A> { // Consider the doc effect of ordering modules here. mod impl_clone; -mod impl_internal_constructors; mod impl_constructors; +mod impl_internal_constructors; mod impl_methods; -#[cfg(feature = "std")] -mod impl_float_maths; mod impl_owned_array; mod impl_special_element_types; @@ -1575,9 +1571,7 @@ where let d = self.dim.try_remove_axis(axis); let s = self.strides.try_remove_axis(axis); // safe because new dimension, strides allow access to a subset of old data - unsafe { - self.with_strides_dim(s, d) - } + unsafe { self.with_strides_dim(s, d) } } } diff --git a/src/impl_float_maths.rs b/src/numeric/impl_float_maths.rs similarity index 63% rename from src/impl_float_maths.rs rename to src/numeric/impl_float_maths.rs index 12100fb99..55cc57d3f 100644 --- a/src/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -1,25 +1,35 @@ -//! Element-wise methods for ndarray +// Element-wise methods for ndarray +#[cfg(feature = "std")] use num_traits::Float; use crate::imp_prelude::*; -macro_rules! boolean_op { - ($($(#[$meta1:meta])* fn $id1:ident $(#[$meta2:meta])* fn $id2:ident -> $func:ident)+) => { - $($(#[$meta1])* +#[cfg(feature = "std")] +macro_rules! boolean_ops { + ($(#[$meta1:meta])* fn $func:ident + $(#[$meta2:meta])* fn $all:ident + $(#[$meta3:meta])* fn $any:ident) => { + $(#[$meta1])* #[must_use = "method returns a new array and does not mutate the original value"] - pub fn $id1(&self) -> Array { + pub fn $func(&self) -> Array { self.mapv(A::$func) } $(#[$meta2])* #[must_use = "method returns a new boolean value and does not mutate the original value"] - pub fn $id2(&self) -> bool { - self.mapv(A::$func).iter().any(|&b| b) - })+ + pub fn $all(&self) -> bool { + $crate::Zip::from(self).all(|&elt| !elt.$func()) + } + $(#[$meta3])* + #[must_use = "method returns a new boolean value and does not mutate the original value"] + pub fn $any(&self) -> bool { + !self.$all() + } }; } -macro_rules! unary_op { +#[cfg(feature = "std")] +macro_rules! unary_ops { ($($(#[$meta:meta])* fn $id:ident)+) => { $($(#[$meta])* #[must_use = "method returns a new array and does not mutate the original value"] @@ -29,7 +39,8 @@ macro_rules! unary_op { }; } -macro_rules! binary_op { +#[cfg(feature = "std")] +macro_rules! binary_ops { ($($(#[$meta:meta])* fn $id:ident($ty:ty))+) => { $($(#[$meta])* #[must_use = "method returns a new array and does not mutate the original value"] @@ -39,103 +50,87 @@ macro_rules! binary_op { }; } -/// # Element-wise methods for Float Array +/// # Element-wise methods for float arrays /// /// Element-wise math functions for any array type that contains float number. +#[cfg(feature = "std")] impl ArrayBase where - A: Float, + A: 'static + Float, S: Data, D: Dimension, { - boolean_op! { + boolean_ops! { /// If the number is `NaN` (not a number), then `true` is returned for each element. fn is_nan + /// Return `true` if all elements are `NaN` (not a number). + fn is_all_nan /// Return `true` if any element is `NaN` (not a number). - fn is_any_nan -> is_nan - + fn is_any_nan + } + boolean_ops! { /// If the number is infinity, then `true` is returned for each element. fn is_infinite + /// Return `true` if all elements are infinity. + fn is_all_infinite /// Return `true` if any element is infinity. - fn is_any_infinite -> is_infinite + fn is_any_infinite } - unary_op! { + unary_ops! { /// The largest integer less than or equal to each element. fn floor - /// The smallest integer less than or equal to each element. fn ceil - /// The nearest integer of each element. fn round - /// The integer part of each element. fn trunc - /// The fractional part of each element. fn fract - /// Absolute of each element. fn abs - /// Sign number of each element. /// /// + `1.0` for all positive numbers. /// + `-1.0` for all negative numbers. /// + `NaN` for all `NaN` (not a number). fn signum - /// The reciprocal (inverse) of each element, `1/x`. fn recip - /// Square root of each element. fn sqrt - /// `e^x` of each element (exponential function). fn exp - /// `2^x` of each element. fn exp2 - /// Natural logarithm of each element. fn ln - /// Base 2 logarithm of each element. fn log2 - /// Base 10 logarithm of each element. fn log10 - /// Cubic root of each element. fn cbrt - /// Sine of each element (in radians). fn sin - /// Cosine of each element (in radians). fn cos - /// Tangent of each element (in radians). fn tan - /// Converts radians to degrees for each element. fn to_degrees - /// Converts degrees to radians for each element. fn to_radians } - binary_op! { + binary_ops! { /// Integer power of each element. /// /// This function is generally faster than using float power. fn powi(i32) - /// Float power of each element. fn powf(A) - /// Logarithm of each element with respect to an arbitrary base. fn log(A) - /// The positive difference between given number and each element. fn abs_sub(A) } @@ -145,18 +140,37 @@ where pub fn pow2(&self) -> Array { self.mapv(|v: A| v * v) } +} - /// Limit the values for each element. +impl ArrayBase +where + A: 'static + PartialOrd + Clone, + S: Data, + D: Dimension, +{ + /// Limit the values for each element, similar to NumPy's `clip` function. /// /// ``` - /// use ndarray::{Array1, array}; + /// use ndarray::array; /// - /// let a = Array1::range(0., 10., 1.); - /// assert_eq!(a.clip(1., 8.), array![1., 1., 2., 3., 4., 5., 6., 7., 8., 8.]); - /// assert_eq!(a.clip(8., 1.), array![1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]); - /// assert_eq!(a.clip(3., 6.), array![3., 3., 3., 3., 4., 5., 6., 6., 6., 6.]); + /// let a = array![0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]; + /// assert_eq!(a.clamp(1., 8.), array![1., 1., 2., 3., 4., 5., 6., 7., 8., 8.]); + /// assert_eq!(a.clamp(3., 6.), array![3., 3., 3., 3., 4., 5., 6., 6., 6., 6.]); /// ``` - pub fn clip(&self, min: A, max: A) -> Array { - self.mapv(|v| A::min(A::max(v, min), max)) + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is `NaN`, or `max` is `NaN`. + pub fn clamp(&self, min: A, max: A) -> Array { + assert!(min <= max, "min must be less than or equal to max"); + self.mapv(|v| { + if v < min { + min.clone() + } else if v > max { + max.clone() + } else { + v + } + }) } } diff --git a/src/numeric/mod.rs b/src/numeric/mod.rs index b3da06746..c0a7228c5 100644 --- a/src/numeric/mod.rs +++ b/src/numeric/mod.rs @@ -1 +1,3 @@ mod impl_numeric; + +mod impl_float_maths; From 57be7242ecdf691a1c971ca297e154377b77ed91 Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Wed, 8 Dec 2021 15:30:34 +0800 Subject: [PATCH 7/8] Revert cargo fmt. --- src/lib.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index da5473b00..f773226f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,12 +125,13 @@ //! For conversion between `ndarray`, [`nalgebra`](https://crates.io/crates/nalgebra) and //! [`image`](https://crates.io/crates/image) check out [`nshare`](https://crates.io/crates/nshare). + extern crate alloc; -#[cfg(not(feature = "std"))] -extern crate core as std; #[cfg(feature = "std")] extern crate std; +#[cfg(not(feature = "std"))] +extern crate core as std; #[cfg(feature = "blas")] extern crate cblas_sys; @@ -138,8 +139,8 @@ extern crate cblas_sys; #[cfg(feature = "docs")] pub mod doc; -use alloc::sync::Arc; use std::marker::PhantomData; +use alloc::sync::Arc; pub use crate::dimension::dim::*; pub use crate::dimension::{Axis, AxisDescription, Dimension, IntoDimension, RemoveAxis}; @@ -158,16 +159,16 @@ use crate::iterators::Baseiter; use crate::iterators::{ElementsBase, ElementsBaseMut, Iter, IterMut}; pub use crate::arraytraits::AsArray; -pub use crate::linalg_traits::LinalgScalar; #[cfg(feature = "std")] pub use crate::linalg_traits::NdFloat; +pub use crate::linalg_traits::LinalgScalar; #[allow(deprecated)] // stack_new_axis pub use crate::stacking::{concatenate, stack, stack_new_axis}; -pub use crate::impl_views::IndexLonger; pub use crate::math_cell::MathCell; -pub use crate::shape_builder::{Shape, ShapeArg, ShapeBuilder, StrideShape}; +pub use crate::impl_views::IndexLonger; +pub use crate::shape_builder::{Shape, ShapeBuilder, ShapeArg, StrideShape}; #[macro_use] mod macro_utils; @@ -188,7 +189,8 @@ mod data_traits; pub use crate::aliases::*; pub use crate::data_traits::{ - Data, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut, RawDataSubst, + Data, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut, + RawDataSubst, }; mod free_functions; @@ -211,9 +213,9 @@ mod partial; mod shape_builder; #[macro_use] mod slice; -mod low_level_util; mod split_at; mod stacking; +mod low_level_util; #[macro_use] mod zip; @@ -1509,8 +1511,8 @@ impl<'a, A> CowRepr<'a, A> { // Consider the doc effect of ordering modules here. mod impl_clone; -mod impl_constructors; mod impl_internal_constructors; +mod impl_constructors; mod impl_methods; mod impl_owned_array; @@ -1571,7 +1573,9 @@ where let d = self.dim.try_remove_axis(axis); let s = self.strides.try_remove_axis(axis); // safe because new dimension, strides allow access to a subset of old data - unsafe { self.with_strides_dim(s, d) } + unsafe { + self.with_strides_dim(s, d) + } } } From 81b3debb494520acec990a2790aaf8da9e41f51a Mon Sep 17 00:00:00 2001 From: KmolYuan Date: Sun, 26 Nov 2023 20:46:08 +0800 Subject: [PATCH 8/8] Improve clamp implementation --- src/numeric/impl_float_maths.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/numeric/impl_float_maths.rs b/src/numeric/impl_float_maths.rs index 55cc57d3f..4b3208800 100644 --- a/src/numeric/impl_float_maths.rs +++ b/src/numeric/impl_float_maths.rs @@ -160,17 +160,9 @@ where /// /// # Panics /// - /// Panics if `min > max`, `min` is `NaN`, or `max` is `NaN`. + /// Panics if `!(min <= max)`. pub fn clamp(&self, min: A, max: A) -> Array { assert!(min <= max, "min must be less than or equal to max"); - self.mapv(|v| { - if v < min { - min.clone() - } else if v > max { - max.clone() - } else { - v - } - }) + self.mapv(|a| num_traits::clamp(a, min.clone(), max.clone())) } }