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}