ndarray/numeric/impl_float_maths.rs
1// Element-wise methods for ndarray
2
3#[cfg(feature = "std")]
4use num_traits::Float;
5
6use crate::imp_prelude::*;
7
8#[cfg(feature = "std")]
9macro_rules! boolean_ops {
10 ($(#[$meta1:meta])* fn $func:ident
11 $(#[$meta2:meta])* fn $all:ident
12 $(#[$meta3:meta])* fn $any:ident) => {
13 $(#[$meta1])*
14 #[must_use = "method returns a new array and does not mutate the original value"]
15 pub fn $func(&self) -> Array<bool, D> {
16 self.mapv(A::$func)
17 }
18 $(#[$meta2])*
19 #[must_use = "method returns a new boolean value and does not mutate the original value"]
20 pub fn $all(&self) -> bool {
21 $crate::Zip::from(self).all(|&elt| !elt.$func())
22 }
23 $(#[$meta3])*
24 #[must_use = "method returns a new boolean value and does not mutate the original value"]
25 pub fn $any(&self) -> bool {
26 !self.$all()
27 }
28 };
29}
30
31#[cfg(feature = "std")]
32macro_rules! unary_ops {
33 ($($(#[$meta:meta])* fn $id:ident)+) => {
34 $($(#[$meta])*
35 #[must_use = "method returns a new array and does not mutate the original value"]
36 pub fn $id(&self) -> Array<A, D> {
37 self.mapv(A::$id)
38 })+
39 };
40}
41
42#[cfg(feature = "std")]
43macro_rules! binary_ops {
44 ($($(#[$meta:meta])* fn $id:ident($ty:ty))+) => {
45 $($(#[$meta])*
46 #[must_use = "method returns a new array and does not mutate the original value"]
47 pub fn $id(&self, rhs: $ty) -> Array<A, D> {
48 self.mapv(|v| A::$id(v, rhs))
49 })+
50 };
51}
52
53/// # Element-wise methods for float arrays
54///
55/// Element-wise math functions for any array type that contains float number.
56#[cfg(feature = "std")]
57#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
58impl<A, D> ArrayRef<A, D>
59where
60 A: 'static + Float,
61 D: Dimension,
62{
63 boolean_ops! {
64 /// If the number is `NaN` (not a number), then `true` is returned for each element.
65 fn is_nan
66 /// Return `true` if all elements are `NaN` (not a number).
67 fn is_all_nan
68 /// Return `true` if any element is `NaN` (not a number).
69 fn is_any_nan
70 }
71 boolean_ops! {
72 /// If the number is infinity, then `true` is returned for each element.
73 fn is_infinite
74 /// Return `true` if all elements are infinity.
75 fn is_all_infinite
76 /// Return `true` if any element is infinity.
77 fn is_any_infinite
78 }
79 unary_ops! {
80 /// The largest integer less than or equal to each element.
81 fn floor
82 /// The smallest integer less than or equal to each element.
83 fn ceil
84 /// The nearest integer of each element.
85 fn round
86 /// The integer part of each element.
87 fn trunc
88 /// The fractional part of each element.
89 fn fract
90 /// Absolute of each element.
91 fn abs
92 /// Sign number of each element.
93 ///
94 /// + `1.0` for all positive numbers.
95 /// + `-1.0` for all negative numbers.
96 /// + `NaN` for all `NaN` (not a number).
97 fn signum
98 /// The reciprocal (inverse) of each element, `1/x`.
99 fn recip
100 /// Square root of each element.
101 fn sqrt
102 /// `e^x` of each element (exponential function).
103 fn exp
104 /// `2^x` of each element.
105 fn exp2
106 /// `e^x - 1` of each element.
107 fn exp_m1
108 /// Natural logarithm of each element.
109 fn ln
110 /// Base 2 logarithm of each element.
111 fn log2
112 /// Base 10 logarithm of each element.
113 fn log10
114 /// `ln(1 + x)` of each element.
115 fn ln_1p
116 /// Cubic root of each element.
117 fn cbrt
118 /// Sine of each element (in radians).
119 fn sin
120 /// Cosine of each element (in radians).
121 fn cos
122 /// Tangent of each element (in radians).
123 fn tan
124 /// Arcsine of each element (return in radians).
125 fn asin
126 /// Arccosine of each element (return in radians).
127 fn acos
128 /// Arctangent of each element (return in radians).
129 fn atan
130 /// Hyperbolic sine of each element.
131 fn sinh
132 /// Hyperbolic cosine of each element.
133 fn cosh
134 /// Hyperbolic tangent of each element.
135 fn tanh
136 /// Inverse hyperbolic sine of each element.
137 fn asinh
138 /// Inverse hyperbolic cosine of each element.
139 fn acosh
140 /// Inverse hyperbolic tangent of each element.
141 fn atanh
142 /// Converts radians to degrees for each element.
143 fn to_degrees
144 /// Converts degrees to radians for each element.
145 fn to_radians
146 }
147 binary_ops! {
148 /// Integer power of each element.
149 ///
150 /// This function is generally faster than using float power.
151 fn powi(i32)
152 /// Float power of each element.
153 fn powf(A)
154 /// Logarithm of each element with respect to an arbitrary base.
155 fn log(A)
156 /// The positive difference between given number and each element.
157 fn abs_sub(A)
158 /// Length of the hypotenuse of a right-angle triangle of each element
159 fn hypot(A)
160 }
161
162 /// Square (two powers) of each element.
163 #[must_use = "method returns a new array and does not mutate the original value"]
164 pub fn pow2(&self) -> Array<A, D>
165 {
166 self.mapv(|v: A| v * v)
167 }
168}
169
170impl<A, D> ArrayRef<A, D>
171where
172 A: 'static + PartialOrd + Clone,
173 D: Dimension,
174{
175 /// Limit the values for each element, similar to NumPy's `clip` function.
176 ///
177 /// ```
178 /// use ndarray::array;
179 ///
180 /// let a = array![0., 1., 2., 3., 4., 5., 6., 7., 8., 9.];
181 /// assert_eq!(a.clamp(1., 8.), array![1., 1., 2., 3., 4., 5., 6., 7., 8., 8.]);
182 /// assert_eq!(a.clamp(3., 6.), array![3., 3., 3., 3., 4., 5., 6., 6., 6., 6.]);
183 /// ```
184 ///
185 /// # Panics
186 ///
187 /// Panics if `!(min <= max)`.
188 pub fn clamp(&self, min: A, max: A) -> Array<A, D>
189 {
190 assert!(min <= max, "min must be less than or equal to max");
191 self.mapv(|a| num_traits::clamp(a, min.clone(), max.clone()))
192 }
193}