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>

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>

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>

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>

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>

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());

Implementations on Foreign Types§

§

impl SliceExt<f32> for [f32]

§

fn try_min(&self) -> Result<f32, Error>

§

fn try_max(&self) -> Result<f32, Error>

§

fn find_bin_inclusive(&self, value: f32) -> Result<usize, Error>

§

fn find_bin_exclusive(&self, value: f32) -> Result<usize, Error>

§

fn find_bin_average(&self, value: f32, tol: f32) -> Result<Vec<usize>, Error>

§

impl SliceExt<f64> for [f64]

§

fn try_min(&self) -> Result<f64, Error>

§

fn try_max(&self) -> Result<f64, Error>

§

fn find_bin_inclusive(&self, value: f64) -> Result<usize, Error>

§

fn find_bin_exclusive(&self, value: f64) -> Result<usize, Error>

§

fn find_bin_average(&self, value: f64, tol: f64) -> Result<Vec<usize>, Error>

Implementors§