conspire 0.6.0

The Rust interface to conspire.
Documentation
use crate::math::{
    Hessian, SquareMatrix, Tensor, TensorRank0, TensorRank2, TensorRank2Vec,
    tensor::vec::TensorVector,
};
use std::ops::Mul;

#[cfg(test)]
use crate::math::tensor::test::ErrorTensor;

pub type TensorRank2Vec2D<const D: usize, const I: usize, const J: usize> =
    TensorVector<TensorRank2Vec<D, I, J>>;

impl<const D: usize, const I: usize, const J: usize> TensorRank2Vec2D<D, I, J> {
    pub fn zero(len: usize) -> Self {
        (0..len).map(|_| TensorRank2Vec::zero(len)).collect()
    }
}

impl<const D: usize, const I: usize, const J: usize> From<TensorRank2Vec2D<D, I, J>>
    for Vec<TensorRank0>
{
    fn from(tensor_rank_2_vec_2d: TensorRank2Vec2D<D, I, J>) -> Self {
        tensor_rank_2_vec_2d
            .into_iter()
            .flat_map(|tensor_rank_2_vec_1d| {
                tensor_rank_2_vec_1d.into_iter().flat_map(|tensor_rank_2| {
                    tensor_rank_2
                        .into_iter()
                        .flat_map(|tensor_rank_1| tensor_rank_1.into_iter())
                })
            })
            .collect()
    }
}

impl<const D: usize, const I: usize, const J: usize> Hessian for TensorRank2Vec2D<D, I, J> {
    fn fill_into(self, square_matrix: &mut SquareMatrix) {
        self.into_iter().enumerate().for_each(|(a, entry_a)| {
            entry_a.into_iter().enumerate().for_each(|(b, entry_ab)| {
                entry_ab
                    .into_iter()
                    .enumerate()
                    .for_each(|(i, entry_ab_i)| {
                        entry_ab_i
                            .into_iter()
                            .enumerate()
                            .for_each(|(j, entry_ab_ij)| {
                                square_matrix[D * a + i][D * b + j] = entry_ab_ij
                            })
                    })
            })
        });
    }
    fn retain_from(self, retained: &[bool]) -> SquareMatrix {
        SquareMatrix::from(self)
            .into_iter()
            .zip(retained.iter())
            .filter(|(_, retained)| **retained)
            .map(|(self_i, _)| {
                self_i
                    .into_iter()
                    .zip(retained.iter())
                    .filter(|(_, retained)| **retained)
                    .map(|(self_ij, _)| self_ij)
                    .collect()
            })
            .collect()
    }
}

impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<TensorRank2<D, J, K>>
    for TensorRank2Vec2D<D, I, J>
{
    type Output = TensorRank2Vec2D<D, I, K>;
    fn mul(self, tensor_rank_2: TensorRank2<D, J, K>) -> Self::Output {
        self.iter()
            .map(|self_entry| {
                self_entry
                    .iter()
                    .map(|self_tensor_rank_2| self_tensor_rank_2 * &tensor_rank_2)
                    .collect()
            })
            .collect()
    }
}

impl<const D: usize, const I: usize, const J: usize, const K: usize> Mul<&TensorRank2<D, J, K>>
    for TensorRank2Vec2D<D, I, J>
{
    type Output = TensorRank2Vec2D<D, I, K>;
    fn mul(self, tensor_rank_2: &TensorRank2<D, J, K>) -> Self::Output {
        self.iter()
            .map(|self_entry| {
                self_entry
                    .iter()
                    .map(|self_tensor_rank_2| self_tensor_rank_2 * tensor_rank_2)
                    .collect()
            })
            .collect()
    }
}

#[cfg(test)]
impl<const D: usize, const I: usize, const J: usize> ErrorTensor for TensorRank2Vec2D<D, I, J> {
    fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
        let error_count = self
            .iter()
            .zip(comparator.iter())
            .map(|(self_a, comparator_a)| {
                self_a
                    .iter()
                    .zip(comparator_a.iter())
                    .map(|(self_ab, comparator_ab)| {
                        self_ab
                            .iter()
                            .zip(comparator_ab.iter())
                            .map(|(self_ab_i, comparator_ab_i)| {
                                self_ab_i
                                    .iter()
                                    .zip(comparator_ab_i.iter())
                                    .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
                                        (self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
                                            && (self_ab_ij.abs() >= epsilon
                                                || comparator_ab_ij.abs() >= epsilon)
                                    })
                                    .count()
                            })
                            .sum::<usize>()
                    })
                    .sum::<usize>()
            })
            .sum();
        if error_count > 0 {
            let auxiliary = self
                .iter()
                .zip(comparator.iter())
                .map(|(self_a, comparator_a)| {
                    self_a
                        .iter()
                        .zip(comparator_a.iter())
                        .map(|(self_ab, comparator_ab)| {
                            self_ab
                                .iter()
                                .zip(comparator_ab.iter())
                                .map(|(self_ab_i, comparator_ab_i)| {
                                    self_ab_i
                                        .iter()
                                        .zip(comparator_ab_i.iter())
                                        .filter(|&(&self_ab_ij, &comparator_ab_ij)| {
                                            (self_ab_ij / comparator_ab_ij - 1.0).abs() >= epsilon
                                                && (self_ab_ij - comparator_ab_ij).abs() >= epsilon
                                                && (self_ab_ij.abs() >= epsilon
                                                    || comparator_ab_ij.abs() >= epsilon)
                                        })
                                        .count()
                                })
                                .sum::<usize>()
                        })
                        .sum::<usize>()
                })
                .sum::<usize>()
                > 0;
            Some((auxiliary, error_count))
        } else {
            None
        }
    }
}