fix SteppedVector

This commit is contained in:
Simon Gardling 2022-03-22 13:51:45 -04:00
parent 5599b92bd2
commit 0cd8f28aad

View File

@ -6,7 +6,7 @@ use std::ops::Range;
/// index was calculated with `.iter().position(....` which was horribly /// index was calculated with `.iter().position(....` which was horribly
/// inefficient /// inefficient
pub struct SteppedVector { pub struct SteppedVector {
// Actual data being referenced. HAS to be sorted from maximum value to minumum // Actual data being referenced. HAS to be sorted from minimum to maximum
data: Vec<f64>, data: Vec<f64>,
// Minimum value // Minimum value
@ -30,17 +30,25 @@ impl SteppedVector {
return None; return None;
} }
if x == self.min {
return Some(0);
}
if x == self.max {
return Some(self.data.len() - 1);
}
// Do some math in order to calculate the expected index value // Do some math in order to calculate the expected index value
let possible_i = (((x + self.min) / self.step) as usize) - 1; let possible_i = ((x - self.min) / self.step) as usize;
// Make sure that the index is valid by checking the data returned vs the actual // Make sure that the index is valid by checking the data returned vs the actual
// data (just in case) // data (just in case)
if self.data[possible_i] == x { if self.data[possible_i] == x {
// It is valid! // It is valid!
Some(possible_i) return Some(possible_i);
} else { } else {
// (For some reason) it wasn't! // (For some reason) it wasn't!
None return None;
} }
// Old (inefficent) code // Old (inefficent) code
@ -55,6 +63,15 @@ impl SteppedVector {
None None
*/ */
} }
#[allow(dead_code)]
pub fn get_min(&self) -> f64 { self.min }
#[allow(dead_code)]
pub fn get_max(&self) -> f64 { self.max }
#[allow(dead_code)]
pub fn get_data(&self) -> Vec<f64> { self.data.clone() }
} }
// Convert `Vec<f64>` into `SteppedVector` // Convert `Vec<f64>` into `SteppedVector`
@ -63,27 +80,30 @@ impl From<Vec<f64>> for SteppedVector {
let mut data = input_data; let mut data = input_data;
// length of data // length of data
let data_length = data.len(); let data_length = data.len();
// length of data subtracted by 1 (represents the maximum index value)
let data_i_length = data_length - 1;
// Ensure data is of correct length // Ensure data is of correct length
if data_length < 2 { if data_length < 2 {
panic!("SteppedVector: data should have a length longer than 2"); panic!("SteppedVector: data should have a length longer than 2");
} }
let mut max: f64 = data[0]; // The max value should be the first element // length of data subtracted by 1 (represents the maximum index value)
let mut min: f64 = data[data_i_length]; // The minimum value should be the last element let data_i_length = data_length - 1;
let mut max: f64 = data[data_i_length]; // The max value should be the first element
let mut min: f64 = data[0]; // The minimum value should be the last element
// if min is bigger than max, sort the input data
if min > max { if min > max {
tracing::debug!("SteppedVector: min is larger than max, sorting."); tracing::debug!("SteppedVector: min is larger than max, sorting.");
data.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap()); data.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
max = data[0]; max = data[data_i_length];
min = data[data_i_length]; min = data[0];
} }
assert!(min >= 0.0);
assert!(max >= 0.0);
// Calculate the step between elements // Calculate the step between elements
let step = (max - min).abs() / (data_i_length as f64); let step = (max - min).abs() / (data_length as f64);
// Create and return the struct // Create and return the struct
SteppedVector { SteppedVector {
@ -95,6 +115,33 @@ impl From<Vec<f64>> for SteppedVector {
} }
} }
#[test]
fn stepped_vector_test() {
let min = 0;
let max = 10;
let data: Vec<f64> = (min..=max).map(|x| x as f64).collect();
let len_data = data.len();
let stepped_vector: SteppedVector = data.into();
assert_eq!(
stepped_vector.get_data(),
vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
);
assert_eq!(stepped_vector.get_min(), min as f64);
assert_eq!(stepped_vector.get_max(), max as f64);
assert_eq!(stepped_vector.get_index(min as f64), Some(0));
assert_eq!(stepped_vector.get_index(max as f64), Some(len_data - 1));
for i in min..=max {
assert_eq!(stepped_vector.get_index(i as f64), Some(i));
}
assert_eq!(stepped_vector.get_index(-1.0), None);
assert_eq!(stepped_vector.get_index(11.0), None);
}
// Rounds f64 to specific number of decimal places // Rounds f64 to specific number of decimal places
pub fn decimal_round(x: f64, n: usize) -> f64 { pub fn decimal_round(x: f64, n: usize) -> f64 {
let large_number: f64 = 10.0_f64.powf(n as f64); // 10^n let large_number: f64 = 10.0_f64.powf(n as f64); // 10^n