|
1 | 1 | use interpolate::Interpolate;
|
2 | 2 | use ndarray::prelude::*;
|
3 | 3 | use ndarray::{Data, DataMut, RemoveAxis};
|
4 |
| -use {MaybeNan, Sort1dExt}; |
| 4 | +use std::cmp; |
| 5 | +use {MaybeNan, MaybeNanExt, Sort1dExt}; |
5 | 6 |
|
6 | 7 | /// Interpolation strategies.
|
7 | 8 | pub mod interpolate {
|
@@ -173,6 +174,62 @@ where
|
173 | 174 | S: Data<Elem = A>,
|
174 | 175 | D: Dimension,
|
175 | 176 | {
|
| 177 | + /// Finds the elementwise minimum of the array. |
| 178 | + /// |
| 179 | + /// **Panics** if the array is empty. |
| 180 | + fn min(&self) -> &A |
| 181 | + where |
| 182 | + A: Ord; |
| 183 | + |
| 184 | + /// Finds the elementwise minimum of the array. |
| 185 | + /// |
| 186 | + /// Returns `None` if any of the pairwise orderings tested by the function |
| 187 | + /// are undefined. (For example, this occurs if there are any |
| 188 | + /// floating-point NaN values in the array.) |
| 189 | + /// |
| 190 | + /// Additionally, returns `None` if the array is empty. |
| 191 | + fn min_partialord(&self) -> Option<&A> |
| 192 | + where |
| 193 | + A: PartialOrd; |
| 194 | + |
| 195 | + /// Finds the elementwise minimum of the array, skipping NaN values. |
| 196 | + /// |
| 197 | + /// **Warning** This method will return a NaN value if none of the values |
| 198 | + /// in the array are non-NaN values. Note that the NaN value might not be |
| 199 | + /// in the array. |
| 200 | + fn min_skipnan(&self) -> &A |
| 201 | + where |
| 202 | + A: MaybeNan, |
| 203 | + A::NotNan: Ord; |
| 204 | + |
| 205 | + /// Finds the elementwise maximum of the array. |
| 206 | + /// |
| 207 | + /// **Panics** if the array is empty. |
| 208 | + fn max(&self) -> &A |
| 209 | + where |
| 210 | + A: Ord; |
| 211 | + |
| 212 | + /// Finds the elementwise maximum of the array. |
| 213 | + /// |
| 214 | + /// Returns `None` if any of the pairwise orderings tested by the function |
| 215 | + /// are undefined. (For example, this occurs if there are any |
| 216 | + /// floating-point NaN values in the array.) |
| 217 | + /// |
| 218 | + /// Additionally, returns `None` if the array is empty. |
| 219 | + fn max_partialord(&self) -> Option<&A> |
| 220 | + where |
| 221 | + A: PartialOrd; |
| 222 | + |
| 223 | + /// Finds the elementwise maximum of the array, skipping NaN values. |
| 224 | + /// |
| 225 | + /// **Warning** This method will return a NaN value if none of the values |
| 226 | + /// in the array are non-NaN values. Note that the NaN value might not be |
| 227 | + /// in the array. |
| 228 | + fn max_skipnan(&self) -> &A |
| 229 | + where |
| 230 | + A: MaybeNan, |
| 231 | + A::NotNan: Ord; |
| 232 | + |
176 | 233 | /// Return the qth percentile of the data along the specified axis.
|
177 | 234 | ///
|
178 | 235 | /// `q` needs to be a float between 0 and 1, bounds included.
|
@@ -227,6 +284,78 @@ where
|
227 | 284 | S: Data<Elem = A>,
|
228 | 285 | D: Dimension,
|
229 | 286 | {
|
| 287 | + fn min(&self) -> &A |
| 288 | + where |
| 289 | + A: Ord, |
| 290 | + { |
| 291 | + let first = self |
| 292 | + .iter() |
| 293 | + .next() |
| 294 | + .expect("Attempted to find min of empty array."); |
| 295 | + self.fold(first, |acc, elem| if elem < acc { elem } else { acc }) |
| 296 | + } |
| 297 | + |
| 298 | + fn min_partialord(&self) -> Option<&A> |
| 299 | + where |
| 300 | + A: PartialOrd, |
| 301 | + { |
| 302 | + let first = self.iter().next()?; |
| 303 | + self.fold(Some(first), |acc, elem| match elem.partial_cmp(acc?)? { |
| 304 | + cmp::Ordering::Less => Some(elem), |
| 305 | + _ => acc, |
| 306 | + }) |
| 307 | + } |
| 308 | + |
| 309 | + fn min_skipnan(&self) -> &A |
| 310 | + where |
| 311 | + A: MaybeNan, |
| 312 | + A::NotNan: Ord, |
| 313 | + { |
| 314 | + let first = self.iter().next().and_then(|v| v.try_as_not_nan()); |
| 315 | + A::from_not_nan_ref_opt(self.fold_skipnan(first, |acc, elem| { |
| 316 | + Some(match acc { |
| 317 | + Some(acc) => acc.min(elem), |
| 318 | + None => elem, |
| 319 | + }) |
| 320 | + })) |
| 321 | + } |
| 322 | + |
| 323 | + fn max(&self) -> &A |
| 324 | + where |
| 325 | + A: Ord, |
| 326 | + { |
| 327 | + let first = self |
| 328 | + .iter() |
| 329 | + .next() |
| 330 | + .expect("Attempted to find max of empty array."); |
| 331 | + self.fold(first, |acc, elem| if elem > acc { elem } else { acc }) |
| 332 | + } |
| 333 | + |
| 334 | + fn max_partialord(&self) -> Option<&A> |
| 335 | + where |
| 336 | + A: PartialOrd, |
| 337 | + { |
| 338 | + let first = self.iter().next()?; |
| 339 | + self.fold(Some(first), |acc, elem| match elem.partial_cmp(acc?)? { |
| 340 | + cmp::Ordering::Greater => Some(elem), |
| 341 | + _ => acc, |
| 342 | + }) |
| 343 | + } |
| 344 | + |
| 345 | + fn max_skipnan(&self) -> &A |
| 346 | + where |
| 347 | + A: MaybeNan, |
| 348 | + A::NotNan: Ord, |
| 349 | + { |
| 350 | + let first = self.iter().next().and_then(|v| v.try_as_not_nan()); |
| 351 | + A::from_not_nan_ref_opt(self.fold_skipnan(first, |acc, elem| { |
| 352 | + Some(match acc { |
| 353 | + Some(acc) => acc.max(elem), |
| 354 | + None => elem, |
| 355 | + }) |
| 356 | + })) |
| 357 | + } |
| 358 | + |
230 | 359 | fn percentile_axis_mut<I>(&mut self, axis: Axis, q: f64) -> Array<A, D::Smaller>
|
231 | 360 | where
|
232 | 361 | D: RemoveAxis,
|
|
0 commit comments