Created
July 9, 2019 15:15
-
-
Save lithix-src/c3177abc5babb9f347e72e89e58c56ee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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