home / grad_rs / src / vec2.rs

vec2.rs



use std::f64;
use std::ops::{Index, IndexMut};

#[derive(Debug)]
pub struct Vec2<T: Copy> {
    pub flat: Vec<T>,
    pub columns: usize,
}

impl<T: Copy> Vec2<T> {

    pub fn create(capacity: usize) -> Vec2<T> {
        return Vec2 {
            columns: 0,
            flat: Vec::with_capacity(capacity)
        }
    }

    pub fn push(&mut self, row: &[T]) {
        if self.columns == 0 {
            self.columns = row.len()
        }
        assert_eq!(row.len(), self.columns);
        for val in row.iter() {
            self.flat.push(*val);
        }
    }

    pub fn iter(&self) -> Vec2Iterator<T> {
        Vec2Iterator {
            reference: self,
            cursor: 0
        }
    }

    pub fn len(&self) -> usize {
        return self.flat.len() / self.columns
    }

    pub fn column(&self, col: usize) -> Vec<T> {
        self.vertical_iter(col).collect()
    }

    pub fn divide(&self, first_percentage: usize) -> (Vec2<T>, Vec2<T>) {
        let first_size = (self.len() as f64 / 100.0) as usize * first_percentage;
        let mid = first_size * self.columns;
        let end = self.flat.len();
        let first = Vec2 { columns: self.columns, flat: self.flat[0..mid].to_vec() };
        let second = Vec2 { columns: self.columns, flat: self.flat[mid..end].to_vec() };
        return (first, second)
    }

    fn vertical_iter<'a>(&'a self, col: usize) -> impl Iterator<Item = T> + 'a {
        self.iter()
            .map(move |l| l[col])
    }
}

impl Vec2<f64> {

    pub fn scale_to(&self, range: (f64, f64)) -> Vec2<f64> {
        let mut result = Vec2::create(self.flat.capacity());

        let scaled: Vec<Vec<f64>> = (0..self.columns)
            .map(|col| {
                let mut c = self.column(col);
                Vec2::scale_vector(&mut c, range);
                return c
            }).collect();

        for y in 0..self.len() {
            let line: Vec<f64> = (0..self.columns).map(|col| scaled[col][y]).collect();
            result.push(&line)
        }

        result
    }

    fn scale_vector(vector: &mut Vec<f64>, range: (f64, f64)) {
        let (min_range, max_range) = range;
        let min = *vector.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
        let max = *vector.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
        let current_range = max - min;
        let desired_range = max_range - min_range;

        for value in vector.iter_mut() {
            // Shift the value to be relative to the minimum value
            let shifted_value = *value - min;
            // Scale the shifted value to the range [0, 1]
            let scaled_value = shifted_value / current_range;
            // Scale the value to the desired range and shift it to the min_range
            *value = scaled_value * desired_range + min_range;
        }
    }


}

pub struct Vec2Iterator<'a, T: Copy> {
    reference: &'a Vec2<T>,
    cursor: usize
}

impl<'a, T: Copy> Iterator for Vec2Iterator<'a, T> {
    type Item = &'a [T];

    fn next(&mut self) -> Option<Self::Item> {
        if self.cursor >= self.reference.flat.len() {
            return None;
        }

        let start = self.cursor;
        let end = start + self.reference.columns;
        self.cursor += self.reference.columns;
        Some(&self.reference.flat[start..end])
    }
}

impl<T: Copy> Index<usize> for Vec2<T> {
    type Output = [T];

    fn index(&self, row: usize) -> &Self::Output {
        let start = self.columns * row;
        let end = start + self.columns;
        &self.flat[start..end]
    }
}

impl<T: Copy> IndexMut<usize> for Vec2<T> {
    fn index_mut(&mut self, row: usize) -> &mut Self::Output {
        let start = self.columns * row;
        let end = start + self.columns;
        &mut self.flat[start..end]
    }
}