use pounce_common::types::Number;
pub(crate) fn dense_to_vec(v: &dyn pounce_linalg::Vector) -> Vec<Number> {
let any = v.as_any();
if let Some(d) = any.downcast_ref::<pounce_linalg::dense_vector::DenseVector>() {
return d.expanded_values();
}
if let Some(c) = any.downcast_ref::<pounce_linalg::compound_vector::CompoundVector>() {
let mut out = Vec::with_capacity(v.dim() as usize);
for i in 0..c.n_comps() {
out.extend(dense_to_vec(c.comp(i)));
}
return out;
}
debug_assert!(
false,
"dense_to_vec: unhandled Vector impl, returning zeros (dim {})",
v.dim()
);
vec![0.0; v.dim() as usize]
}
#[cfg(test)]
mod tests {
use super::dense_to_vec;
use pounce_common::types::{Index, Number};
use pounce_linalg::compound_vector::{CompoundVector, CompoundVectorSpace};
use pounce_linalg::dense_vector::{DenseVector, DenseVectorSpace};
use pounce_linalg::vector::Vector;
use std::rc::Rc;
fn make_2block_space(d1: Index, d2: Index) -> Rc<CompoundVectorSpace> {
let space = CompoundVectorSpace::new(2, d1 + d2);
let s1 = DenseVectorSpace::new(d1);
let s2 = DenseVectorSpace::new(d2);
space.set_comp(0, d1, {
let s = Rc::clone(&s1);
move || Box::new(DenseVector::new(Rc::clone(&s)))
});
space.set_comp(1, d2, {
let s = Rc::clone(&s2);
move || Box::new(DenseVector::new(Rc::clone(&s)))
});
space
}
fn fill_dense(v: &mut dyn Vector, vals: &[Number]) {
v.as_any_mut()
.downcast_mut::<DenseVector>()
.expect("DenseVector")
.set_values(vals);
}
#[test]
fn dense_to_vec_flattens_compound_vector_components() {
let space = make_2block_space(2, 3);
let mut v = CompoundVector::new(space);
fill_dense(v.comp_mut(0), &[1.5, -2.0]);
fill_dense(v.comp_mut(1), &[7.0, 0.25, -9.0]);
let flat = dense_to_vec(&v as &dyn Vector);
assert_eq!(flat, vec![1.5, -2.0, 7.0, 0.25, -9.0]);
assert_ne!(flat, vec![0.0; 5]);
}
#[test]
fn dense_to_vec_handles_plain_dense_vector() {
let space = DenseVectorSpace::new(3);
let mut d = DenseVector::new(space);
d.set_values(&[3.0, 4.0, 5.0]);
assert_eq!(dense_to_vec(&d as &dyn Vector), vec![3.0, 4.0, 5.0]);
}
}