conspire 0.7.2

The Rust interface to conspire.
Documentation
use super::{TensorRank2, TensorRank2SparseVec};
use crate::math::Tensor;

fn block(value: f64) -> TensorRank2<2, 1, 1> {
    TensorRank2::from([[value, 2.0 * value], [3.0 * value, 4.0 * value]])
}

fn sparse_vec() -> TensorRank2SparseVec<2, 1, 1> {
    let mut vec = TensorRank2SparseVec::default();
    vec[2] += block(1.0);
    vec[0] += block(2.0);
    vec[0] += block(3.0);
    vec
}

#[test]
fn insertion_sums_and_sorts() {
    let vec = sparse_vec();
    assert_eq!(vec[0][0][0], 5.0);
    assert_eq!(vec[2][0][0], 1.0);
    let columns: Vec<usize> = vec.entries().map(|(column, _)| column).collect();
    assert_eq!(columns, [0, 2]);
}

#[test]
#[should_panic(expected = "Entry (1) not present.")]
fn indexing_missing_entry_panics() {
    let vec = sparse_vec();
    let _ = &vec[1];
}

#[test]
fn tensor_len_and_size() {
    let vec = sparse_vec();
    assert_eq!(vec.len(), 2);
    assert_eq!(vec.size(), 2 * 2 * 2);
}

#[test]
fn from_iterator_indexes_sequentially() {
    let vec: TensorRank2SparseVec<2, 1, 1> =
        [block(1.0), block(2.0), block(3.0)].into_iter().collect();
    assert_eq!(vec[0][0][0], 1.0);
    assert_eq!(vec[1][0][0], 2.0);
    assert_eq!(vec[2][0][0], 3.0);
}

#[test]
fn add_and_sub_merge_disjoint_and_overlapping_entries() {
    let mut other = TensorRank2SparseVec::<2, 1, 1>::default();
    other[0] += block(7.0);
    other[1] += block(5.0);
    let sum = sparse_vec() + other.clone();
    assert_eq!(sum[0][0][0], 12.0);
    assert_eq!(sum[1][0][0], 5.0);
    assert_eq!(sum[2][0][0], 1.0);
    let difference = sparse_vec() - other;
    assert_eq!(difference[0][0][0], -2.0);
    assert_eq!(difference[1][0][0], -5.0);
    assert_eq!(difference[2][0][0], 1.0);
}

#[test]
fn add_assign_and_sub_assign_by_reference() {
    let mut vec = sparse_vec();
    let other = sparse_vec();
    vec += &other;
    assert_eq!(vec[0][0][0], 10.0);
    vec -= &other;
    assert_eq!(vec[0][0][0], 5.0);
}

#[test]
fn mul_and_div_scale_all_entries() {
    let scaled = sparse_vec() * 2.0;
    assert_eq!(scaled[0][0][0], 10.0);
    assert_eq!(scaled[2][0][0], 2.0);
    let divided = scaled / 2.0;
    assert_eq!(divided[0][0][0], 5.0);
    assert_eq!(divided[2][0][0], 1.0);
}

#[test]
fn sum_folds_over_iterator() {
    let total: TensorRank2SparseVec<2, 1, 1> = vec![sparse_vec(), sparse_vec()].into_iter().sum();
    assert_eq!(total[0][0][0], 10.0);
    assert_eq!(total[2][0][0], 2.0);
}