#[derive (Clone)]
pub struct Vec2d<T> {
data: Vec<T>,
width: usize,
}
impl<T: Default> Vec2d<T> {
pub fn new_with_default(rows: usize, cols: usize) -> Vec2d<T> {
Vec2d::new_empty(rows, cols).initialize_to_default()
}
pub fn add_row_of_default(&mut self) {
if self.width == 0 { self.width += 1; }
let size = self.count() + self.width;
while self.data.len() < size {
self.data.push(T::default());
}
}
pub fn add_col_of_default(&mut self) {
let new_width = self.width + 1;
let mut idx = self.width;
for _row in 0..self.count_rows() {
self.data.insert(idx, T::default());
idx += new_width;
}
self.width = new_width;
}
fn initialize_to_default(mut self) -> Vec2d<T> {
let size = self.data.capacity();
while self.data.len() < size {
self.data.push(T::default());
}
self
}
}
impl<T: Copy> Vec2d<T> {
pub fn new_with_value(rows: usize, cols: usize, val:T) -> Vec2d<T> {
Vec2d::new_empty(rows, cols).initialize_to_value(val)
}
pub fn from(width: usize, arr: &[T]) -> Vec2d<T> {
let size = arr.len();
assert_eq!(size % width, 0);
let mut data: Vec<T> = Vec::with_capacity(size);
for idx in 0..size {
data.push(arr[idx]);
}
Vec2d {
data,
width,
}
}
pub fn insert_col(&mut self, index: usize, data: &[T]) {
let size: usize = data.len();
if self.width == 0 {
self.width = 1;
for item in data {
self.data.push(*item);
}
}
else {
assert_eq!(size, self.count_rows());
let mut idx = index;
self.width += 1;
for row in 0..size {
self.data.insert(idx, data[row]);
idx += self.width;
}
}
}
pub fn insert_row(&mut self, index: usize, data: &[T]) {
if self.width > 0 {
assert_eq!(self.width, data.len());
let mut idx = self.width * index;
for item in data {
self.data.insert(idx, *item);
idx += 1;
}
}
else { self.push_row(data); }
}
pub fn push_col(&mut self, data: &[T]) {
self.insert_col(self.count_cols(), data);
}
pub fn push_row(&mut self, data: &[T]) {
if self.width > 0 { assert_eq!(self.width, data.len()); }
else { self.width = data.len(); }
for item in data {
self.data.push(*item);
}
}
fn initialize_to_value(mut self, val: T) -> Vec2d<T> {
let size = self.data.capacity();
while self.data.len() < size {
self.data.push(val);
}
self
}
}
impl<T: PartialEq> Vec2d<T> {
pub fn contains(&self, val: &T) -> bool {
for idx in 0..self.count() {
if *val == self.data[idx] { return true; }
}
false
}
}
impl<T> Vec2d<T> {
pub fn new() -> Vec2d<T> {
Vec2d {
data: Vec::new(),
width: 0,
}
}
pub fn from_fn(rows: usize, cols: usize, initializer: &dyn Fn(usize, usize) -> T) -> Vec2d<T> {
Vec2d::new_empty(rows, cols).initialize_from_fn(initializer)
}
pub fn as_ptr(&self) -> *const T {
self.data.as_ptr()
}
pub fn as_vec(&self) -> &Vec<T> {
&self.data
}
pub fn count(&self) -> usize {
self.width * self.count_rows()
}
pub fn count_cols(&self) -> usize {
self.width
}
pub fn count_rows(&self) -> usize {
if self.width == 0 { 0 } else { self.data.len() / self.width }
}
pub fn size(&self) -> (usize, usize) {
(self.count_rows(), self.count_cols())
}
fn new_empty(rows: usize, cols: usize) -> Vec2d<T> {
Vec2d {
data: Vec::with_capacity(rows*cols),
width: cols,
}
}
fn initialize_from_fn(mut self, initializer: &dyn Fn(usize, usize) -> T) -> Vec2d<T> {
let size = self.data.capacity();
for idx in 0..size {
let row = idx / self.width;
let col = idx - (row * self.width);
self.data.push(initializer(row, col));
}
self
}
}
impl<T> std::ops::Index<usize> for Vec2d<T> {
type Output = [T];
fn index(&self, row: usize) -> &[T] {
let start = row * self.width;
let end = start + self.width;
&self.data[start..end]
}
}
impl<T> std::ops::IndexMut<usize> for Vec2d<T> {
fn index_mut(&mut self, row: usize) -> &mut Self::Output {
let start = row * self.width;
let end = start + self.width;
&mut self.data[start..end]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_initializer() {
let v = Vec2d::from_fn(3, 3, &|row, col| row + col);
for idx in 0..v.count() {
let row = idx / v.count_cols();
let col = idx - (row * v.count_cols());
assert_eq!(v[row][col], row+col);
}
}
#[test]
#[should_panic]
fn panics_on_mismatched_arr_size() {
let arr: [i32;4] = [1,2,3,4];
let slc: &[i32] = &arr[0..3];
let _v: Vec2d<i32> = Vec2d::from(2, slc);
let arr: [i32;5] = [1,2,3,4,5];
let _v = Vec2d::from(2, &arr);
}
#[test]
fn build_from_data() {
let data: [i32;12] = [1,2,3,4,5,6,7,8,9,10,11,12];
for divs in 1..13 {
if 12 % divs == 0 {
let _v = Vec2d::from(divs, &data);
for row in 0.._v.count_rows() {
for col in 0.._v.count_cols() {
let idx = row * _v.count_cols() + col;
assert_eq!(data[idx], _v[row][col]);
}
}
}
}
}
#[test]
fn build_from_defaults() {
type DataType = i32;
let mut v:Vec2d<DataType> = Vec2d::new();
assert_eq!(v.count(), 0);
v.add_row_of_default();
assert_eq!(v.count_rows(), 1);
v.add_row_of_default();
v.add_col_of_default();
assert_eq!(v.count(), 4);
assert_eq!(v.count_rows(), 2);
assert_eq!(v.count_cols(), 2);
}
#[test]
fn test_data_pushing() {
type DataType = i32;
let mut v: Vec2d<DataType> = Vec2d::new();
let data = [1,2,3,4,5,6,7,8,9,10,11,12];
v.push_row(&data[0..1]);
v.push_col(&data[1..2]);
v.push_row(&data[2..4]);
v.push_row(&data[4..6]);
v.push_col(&data[6..9]);
v.push_col(&data[9..12]);
assert_eq!(v.count(), 12);
assert_eq!(v.count_rows(), 3);
assert_eq!(v.count_cols(), 4);
let answers = [1,2,7,10,3,4,8,11,5,6,9,12];
let mut idx: usize = 0;
for row in 0..v.count_rows() {
for col in 0..v.count_cols() {
assert_eq!(v[row][col], answers[idx]);
idx += 1;
}
}
}
#[test]
fn test_data_insertion() {
type DataType = i32;
let mut v: Vec2d<DataType> = Vec2d::new();
let data = [1,2,3,4,5,6,7,8,9,10,11,12];
v.insert_row(0,&data[0..1]);
v.insert_col(0,&data[1..2]);
v.insert_row(1,&data[2..4]);
v.insert_row(1, &data[4..6]);
v.insert_col(1,&data[6..9]);
v.insert_col(3,&data[9..12]);
assert_eq!(v.count(), 12);
assert_eq!(v.count_rows(), 3);
assert_eq!(v.count_cols(), 4);
let answers = [2,7,1,10,5,8,6,11,3,9,4,12];
let mut idx: usize = 0;
for row in 0..v.count_rows() {
for col in 0..v.count_cols() {
assert_eq!(v[row][col], answers[idx]);
idx += 1;
}
}
}
}