field.rs

1.9 kB · rust · 58 lines

1/// A square grid of f32 samples.2#[derive(Clone, Debug, PartialEq)]3pub struct Field {4    /// The samples in row-major order.5    pub data: Vec<f32>,6    /// The side length in samples.7    pub size: usize,8}910impl Field {11    /// Builds a zeroed field of the given side.12    pub fn new(size: usize) -> Field {13        Field {14            data: vec![0.0; size * size],15            size,16        }17    }18    /// Wraps row-major samples of the given side.19    pub fn from_data(data: Vec<f32>, size: usize) -> Field {20        assert_eq!(data.len(), size * size, "data must be size*size");21        Field { data, size }22    }23    /// Returns the smallest sample.24    pub fn min(&self) -> f32 {25        self.data.iter().cloned().fold(f32::INFINITY, f32::min)26    }27    /// Returns the largest sample.28    pub fn max(&self) -> f32 {29        self.data.iter().cloned().fold(f32::NEG_INFINITY, f32::max)30    }31    /// Returns the mean sample, or zero for an empty field.32    pub fn mean(&self) -> f64 {33        if self.data.is_empty() {34            return 0.0;35        }36        self.data.iter().map(|&v| v as f64).sum::<f64>() / self.data.len() as f6437    }38    /// Returns the samples widened to f64.39    pub fn as_f64(&self) -> Vec<f64> {40        self.data.iter().map(|&v| v as f64).collect()41    }42    /// Returns the samples scaled into 0..1, symmetric about zero on request.43    pub fn normalized(&self, symmetric: bool) -> Vec<f32> {44        if symmetric {45            let m = self46                .data47                .iter()48                .fold(0.0f32, |acc, &v| acc.max(v.abs()))49                .max(f32::EPSILON);50            self.data.iter().map(|&v| (v / m + 1.0) / 2.0).collect()51        } else {52            let lo = self.min();53            let hi = self.max();54            let span = (hi - lo).max(f32::EPSILON);55            self.data.iter().map(|&v| (v - lo) / span).collect()56        }57    }58}