Skip to content

Instantly share code, notes, and snippets.

@lithix-src
Created July 9, 2019 15:15
Show Gist options
  • Save lithix-src/c3177abc5babb9f347e72e89e58c56ee to your computer and use it in GitHub Desktop.
Save lithix-src/c3177abc5babb9f347e72e89e58c56ee to your computer and use it in GitHub Desktop.
extern crate rand;
use rand::Rng;
#[derive(Debug)]
pub struct GhettoTrix {
pub data: Vec<Vec<f32>>,
pub rows: u32,
pub columns: u32,
}
impl GhettoTrix {
pub fn new(rows: u32, cols: u32) -> GhettoTrix {
let c_sz = cols as usize;
let mut mtx = vec![];
for _ in 0..rows {
mtx.push(vec![0.0; c_sz]);
}
GhettoTrix {
rows: rows,
columns: cols,
data: mtx,
}
}
pub fn show(&self) {
println!("data matrx: {:?}", self)
}
pub fn randomix(r: u32, c: u32, r_rng: (f32, f32)) -> GhettoTrix {
let mut rng = rand::thread_rng();
let mut mtx = GhettoTrix::new(r, c);
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
mtx.data[r][c] = rng.gen_range(r_rng.0, r_rng.1);
}
}
mtx
}
pub fn add_scalar(m1: &GhettoTrix, s: f32) -> GhettoTrix {
let mut mtx = GhettoTrix::new(m1.rows, m1.columns);
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
mtx.data[r][c] = m1.data[r][c] + s;
}
}
mtx
}
pub fn add_mtx(m1: &GhettoTrix, m2: &GhettoTrix) -> GhettoTrix {
assert_eq!(m1.rows, m2.rows);
assert_eq!(m1.columns, m2.columns);
let mut mtx = GhettoTrix::new(m1.rows, m1.columns);
for r in 0..m1.rows as usize {
for c in 0..m1.columns as usize {
let sum = m1.data[r][c] + m2.data[r][c];
mtx.data[r][c] = sum;
}
}
mtx
}
pub fn mult_scalar(m: &GhettoTrix, s: f32) -> GhettoTrix {
let mut mtx = GhettoTrix::new(m.rows, m.columns);
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
mtx.data[r][c] = m.data[r][c] * s;
}
}
mtx
}
pub fn mult_mtx(m: &GhettoTrix, v: &GhettoTrix) -> GhettoTrix {
assert_eq!(m.columns, v.rows);
let mut mtx = GhettoTrix::new(m.rows, v.columns);
let a = &m.data;
let b = &v.data;
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
let mut sum = 0.0;
for k in 0..v.rows as usize {
sum += a[r][k] * b[k][c];
}
mtx.data[r][c] = sum;
}
}
mtx
}
pub fn transpose(m: &GhettoTrix) -> GhettoTrix {
let mut mtx = GhettoTrix::new(m.columns, m.rows);
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
mtx.data[r][c] = m.data[c][r];
}
}
mtx
}
// figure out how to tell that you're on the edge
// or otherwise be aware of the current index position
// and acc to matrix
pub fn ghetto_map(m: &GhettoTrix, f: &Fn(f32) -> f32) -> GhettoTrix {
let mut mtx = GhettoTrix::new(m.rows, m.columns);
for r in 0..mtx.rows as usize {
for c in 0..mtx.columns as usize {
mtx.data[r][c] = f(m.data[r][c]);
}
}
mtx
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_ghettotrx() {
let m_rows = 1;
let m_cols = 2;
let test_m = vec![vec![0.0; m_cols as usize]];
let m = GhettoTrix::new(m_rows, m_cols);
// test that the struct attrs match
assert_eq!(m_rows, m.rows);
assert_eq!(m_cols, m.columns);
// test that the struct data matches
// what a manually created matrix of
// the same size would look like
assert_eq!(test_m, m.data);
}
#[test]
fn test_new_randomix() {
let range = (0.0, 0.5);
let m_rows = 1;
let m_cols = 2;
let m = GhettoTrix::randomix(m_rows, m_cols, range);
// test that the randomix has values
// within the expected range
assert!(m.data[0][0] > -1.0);
assert!(m.data[0][1] < 2.0);
}
#[test]
fn test_mult_scalar() {
let empty_m = GhettoTrix::new(1, 2);
let empty_vector_m = GhettoTrix::new(2, 1);
let test_m = GhettoTrix::mult_scalar(&empty_m, 3.0);
// test that an empty, 0'ed out vec
// multipled by any scalar is still 0
assert_eq!(test_m.data[0][0], 0.0);
// test that multi_mtx pukes if the matrices
// don't meet the dot product spec and
// if the math is right
assert_eq!(empty_m.data[0][0], empty_vector_m.data[0][0]);
}
#[test]
fn test_mult_mtx() {
let full_m = GhettoTrix::randomix(1, 2, (0.1, 1.0));
let mut vector_m = GhettoTrix::new(2, 1);
vector_m.data = vec![vec![1.0; 1], vec![1.0; 1]];
let full_test_m = GhettoTrix::mult_mtx(&full_m, &vector_m);
// math should be [[a, b]] * [[c], [d]] = [[a * c + b * c, a * d + b * d]]
let a = full_m.data[0][0];
let b = full_m.data[0][1];
let c = vector_m.data[0][0];
let expected_sum = a * c + b * c;
assert_eq!(expected_sum, full_test_m.data[0][0]);
}
#[test]
fn test_transpose() {
let m = GhettoTrix::new(2, 1);
let tans_m = GhettoTrix::transpose(&m);
assert_eq!(vec![vec![0.0, 0.0]], tans_m.data);
}
#[test]
fn test_add_scalar() {
let m = GhettoTrix::new(2, 1);
let new_m = GhettoTrix::add_scalar(&m, 1.0);
assert_eq!(new_m.data[0][0], 1.0);
}
#[test]
fn test_add_mtx() {
let a = GhettoTrix::new(2, 1);
let b = GhettoTrix::randomix(2, 1, (0.0, 1.0));
let ab = GhettoTrix::add_mtx(&a, &b);
assert_eq!(b.data[0][0], ab.data[0][0]);
}
#[test]
fn test_map() {
let m = GhettoTrix::new(2, 1);
let new_m = GhettoTrix::ghetto_map(&m, &|x| x + 1.0);
assert_eq!(1.0, new_m.data[0][0]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment