use super::{MatrixSlice, VectorSlice};
use crate::algebra::{SMatrix, SVector};
use nalgebra::*;
use nalgebra::{storage::Storage, Dyn, U1};
#[cfg_attr(feature = "friedrich_serde", derive(serde::Deserialize, serde::Serialize))]
pub struct EMatrix
{
data: DMatrix<f64>,
nrows: usize
}
impl EMatrix
{
pub fn new(data: DMatrix<f64>) -> Self
{
let nrows = data.nrows();
EMatrix { data, nrows }
}
pub fn add_rows<S: Storage<f64, Dyn, Dyn>>(&mut self, rows: &SMatrix<S>)
{
let capacity = self.data.nrows();
let required_size = self.nrows + rows.nrows();
if required_size > capacity
{
let growed_capacity = (3 * capacity) / 2; let new_capacity = std::cmp::max(required_size, growed_capacity);
let mut new_data = DMatrix::from_element(new_capacity, self.data.ncols(), f64::NAN);
new_data.index_mut((..self.nrows, ..)).copy_from(&self.as_matrix());
self.data = new_data;
}
self.data.index_mut((self.nrows..required_size, ..)).copy_from(rows);
self.nrows += rows.nrows();
}
pub fn as_matrix(&self) -> MatrixSlice<'_>
{
self.data.index((..self.nrows, ..))
}
}
#[cfg_attr(feature = "friedrich_serde", derive(serde::Deserialize, serde::Serialize))]
pub struct EVector
{
data: DVector<f64>,
nrows: usize
}
impl EVector
{
pub fn new(data: DVector<f64>) -> Self
{
let nrows = data.nrows();
EVector { data, nrows }
}
pub fn add_rows<S: Storage<f64, Dyn, U1>>(&mut self, rows: &SVector<S>)
{
let capacity = self.data.nrows();
let required_size = self.nrows + rows.nrows();
if required_size > capacity
{
let growed_capacity = (3 * capacity) / 2; let new_capacity = std::cmp::max(required_size, growed_capacity);
let mut new_data = DVector::from_element(new_capacity, f64::NAN);
new_data.index_mut((..self.nrows, ..)).copy_from(&self.as_vector());
self.data = new_data;
}
self.data.index_mut((self.nrows..required_size, ..)).copy_from(rows);
self.nrows += rows.nrows();
}
pub fn as_vector(&self) -> VectorSlice<'_>
{
self.data.index((..self.nrows, ..))
}
pub fn assign<S: Storage<f64, Dyn, U1>>(&mut self, rows: &SVector<S>)
{
assert_eq!(rows.nrows(), self.nrows);
self.data.index_mut((..rows.nrows(), ..)).copy_from(rows);
}
}
#[cfg(test)]
mod tests
{
use super::*;
use crate::conversion::Input;
#[test]
fn ematrix_add_rows_extend_size_when_some_of_current_data_is_masked()
{
let x = Input::into_dmatrix(vec![vec![1.0f64], vec![2.0f64]]);
let mut e = EMatrix::new(x.clone());
for _ in 0..5
{
e.add_rows(&x);
}
}
}