hullabaloo 0.1.0

Backend-agnostic geometry construction utilities.
Documentation
use crate::error::{HullabalooError, HullabalooResult};
use crate::matrix::Matrix;
use calculo::num::Num;

pub trait Geometrizable: Clone {
    type N: Num;

    fn into_vertices(self) -> Vec<Vec<Self::N>>;

    fn into_matrix(self) -> HullabalooResult<Matrix<Self::N>>
    where
        Self: Sized,
    {
        let vertices = self.into_vertices();
        let Some(first) = vertices.first() else {
            return Err(HullabalooError::InvalidInput {
                message: "howzat conversion requires at least one vertex".to_string(),
            });
        };

        let dim = first.len();
        if dim == 0 {
            return Err(HullabalooError::InvalidInput {
                message: "howzat conversion requires positive vertex dimension".to_string(),
            });
        }
        if vertices.iter().skip(1).any(|v| v.len() != dim) {
            return Err(HullabalooError::InvalidInput {
                message: "howzat conversion requires consistent vertex dimensions".to_string(),
            });
        }

        let generator_rows: Vec<Vec<Self::N>> = vertices
            .into_iter()
            .map(|coords| {
                let mut row = Vec::with_capacity(coords.len() + 1);
                row.push(Self::N::one());
                row.extend(coords);
                row
            })
            .collect();

        Matrix::from_rows(generator_rows).map_err(Into::into)
    }
}

impl<N: Num> Geometrizable for Vec<Vec<N>> {
    type N = N;

    fn into_vertices(self) -> Vec<Vec<Self::N>> {
        self
    }
}