Trait SliceExt
pub trait SliceExt<T> {
// Required methods
fn try_min(&self) -> Result<T, Error>;
fn try_max(&self) -> Result<T, Error>;
fn find_bin_inclusive(&self, value: T) -> Result<usize, Error>;
fn find_bin_exclusive(&self, value: T) -> Result<usize, Error>;
fn find_bin_average(&self, value: T, tol: T) -> Result<Vec<usize>, Error>;
}
Expand description
Extends functionality for slices of float arrays
Required Methods§
fn try_min(&self) -> Result<T, Error>
fn try_min(&self) -> Result<T, Error>
Find the minimum value in float arrays
Only provides the minimum value from a collection of valid numbers. Any NAN values, infinite values, or empty slices will return an error.
// Successful cases
assert_eq!([1.1, 0.5, 2.2].try_min(), Ok(0.5));
assert_eq!([1.1, f32::MIN, 2.2].try_min(), Ok(f32::MIN));
// Error cases
assert_eq!([1.1, f32::NAN, 2.2].try_min(), Err(Error::SliceContainsUndefinedValues));
assert_eq!([1.1, f32::INFINITY, 2.2].try_min(), Err(Error::SliceContainsUndefinedValues));
assert_eq!(Vec::<f32>::new().try_min(), Err(Error::SliceContainsNoValues));
The float primitives (f32
/f64
) do not implement Ord
due to NaN
being incomparable. Calling min()
on a collection of floats is
therefore not implemented in the standard library.
This extension uses total_cmp
to always produce an ordering in
accordance to the totalOrder predicate as defined in the IEEE 754 (2008
revision) floating point standard.
fn try_max(&self) -> Result<T, Error>
fn try_max(&self) -> Result<T, Error>
Find the maximum value in float arrays
Only provides the maximum value from a collection of valid numbers. Any NAN values, infinite values, or empty slices will return an error.
// Successful cases
assert_eq!([1.1, 0.5, 2.2].try_max(), Ok(2.2));
assert_eq!([1.1, f32::MAX, 2.2].try_max(), Ok(f32::MAX));
// Error cases
assert_eq!([1.1, f32::NAN, 2.2].try_max(), Err(Error::SliceContainsUndefinedValues));
assert_eq!([1.1, f32::INFINITY, 2.2].try_max(), Err(Error::SliceContainsUndefinedValues));
assert_eq!(Vec::<f32>::new().try_max(), Err(Error::SliceContainsNoValues));
The float primitives (f32
/f64
) do not implement Ord
due to NaN
being incomparable. Calling max()
on a collection of floats is
therefore not implemented in the standard library.
This extension uses total_cmp
to always produce an ordering in
accordance to the totalOrder predicate as defined in the IEEE 754 (2008
revision) floating point standard.
fn find_bin_inclusive(&self, value: T) -> Result<usize, Error>
fn find_bin_inclusive(&self, value: T) -> Result<usize, Error>
Find index bin containing ‘value’, where bins are low < value <= high
A value on a bin edge returns the bin below. Values equal to the lowest bound are considered part of the first bin.
§Example
MCNP : emesh = 0.1 1.0 20.0
Meshtal: 0.00E+00 1.00E-01 1.00E+00 2.00E+01
view of the requested energy groups
0.0 <= bin 0 <= 0.1
0.1 < bin 1 <= 1.0
1.0 < bin 2 <= 20.0
let bounds = vec![0.0, 0.1, 1.0, 20.0];
// Find values in the array
assert_eq!(bounds.find_bin_inclusive(0.0 ), Ok(0));
assert_eq!(bounds.find_bin_inclusive(0.5 ), Ok(1));
assert_eq!(bounds.find_bin_inclusive(1.0 ), Ok(1));
assert_eq!(bounds.find_bin_inclusive(20.0), Ok(2));
// Values outside the bin bounds are an error case
assert!(bounds.find_bin_inclusive(-1.0).is_err());
assert!(bounds.find_bin_inclusive(21.0).is_err());
fn find_bin_exclusive(&self, value: T) -> Result<usize, Error>
fn find_bin_exclusive(&self, value: T) -> Result<usize, Error>
Find index bin containing ‘value’, where bins are low <= value < high
A value on a bin edge returns the bin above. Values equal to the highest bound are considered part of the last bin.
This mirrors the actual MCNP binning behaviour. EMESH
card entries are
upper edges, so in general values on a boundary will be recorded in the
bin above. A special case is made for energies exactly on the last upper
edge, since this is actually included in the tallied results.
§Example
MCNP card : EMESH = 0.1 1.0 20.0
Mesh.emesh: 0.00E+00 1.00E-01 1.00E+00 2.00E+01
MCNP view of these bins:
0.0 <= bin 0 < 0.1
0.1 <= bin 1 < 1.0
1.0 <= bin 2 <= 20.0
let bounds = vec![0.0, 0.1, 1.0, 20.0];
// Find values in the array
assert_eq!(bounds.find_bin_exclusive(0.0 ), Ok(0));
assert_eq!(bounds.find_bin_exclusive(0.5 ), Ok(1));
assert_eq!(bounds.find_bin_exclusive(1.0 ), Ok(2));
assert_eq!(bounds.find_bin_inclusive(20.0), Ok(2));
// Values outside the bin bounds are an error case
assert!(bounds.find_bin_exclusive(-1.0).is_err());
assert!(bounds.find_bin_exclusive(21.0).is_err());
fn find_bin_average(&self, value: T, tol: T) -> Result<Vec<usize>, Error>
fn find_bin_average(&self, value: T, tol: T) -> Result<Vec<usize>, Error>
Find the index or indicies of bins a value falls on
This handles the case where you may need to average across multiple bins when on/near a bin edge.
Notes: - Bin edges must be in ascending order - Tolerance is a factor, not absolute or percentage
let bounds = vec![0.0, 10.0, 20.0];
// Find one index when not near a bin edge
assert_eq!(bounds.find_bin_average(5.0, 0.1), Ok(vec![0]));
// Find both indices when within 10% of the bin edge
assert_eq!(bounds.find_bin_average( 9.5, 0.1), Ok(vec![0,1]));
assert_eq!(bounds.find_bin_average(10.2, 0.1), Ok(vec![0,1]));
// Values outside the bin bounds are an error case
assert!(bounds.find_bin_average(-1.0, 0.1).is_err());
assert!(bounds.find_bin_average(21.0, 0.1).is_err());