use ndarray::Order;
use pyo3::IntoPyObject;
use crate::algebra::rings::traits::RingOperations;
use crate::utilities::order::{is_sorted_strictly, OrderOperatorAuto};
use crate::utilities::sequences_and_ordinals::{SortedVec};
use std::cmp::Ordering;
use std::hash::Hash;
use std::fmt::Debug;
#[derive(Debug, PartialEq, Clone, Eq, Hash, IntoPyObject)]
pub struct Simplex< Vertex >
{
pub vertices: Vec< Vertex > }
impl < Vertex >
Simplex
< Vertex >
{
pub fn number_of_vertices( &self ) -> usize { self.vertices.len() }
pub fn dimension( &self ) -> usize { self.vertices.len() - 1 }
}
impl < Vertex >
PartialOrd for Simplex
< Vertex >
where Vertex: Ord {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl < Vertex >
Ord for Simplex
< Vertex >
where Vertex: Ord {
fn cmp(&self, other: &Self) -> Ordering {
let comp = self.number_of_vertices().cmp( & other.vertices.len() );
if comp != Ordering::Equal { return comp }
self.vertices.cmp( & other.vertices )
}
}
impl < Vertex >
IntoIterator for Simplex
< Vertex > {
type Item = Vertex;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter { self.vertices.into_iter() }
}
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub struct SimplexSafe< Vertex: Ord + PartialEq + Eq >
{
vertices: SortedVec< Vertex > }
impl < Vertex: Ord >
SimplexSafe
< Vertex >
{
pub fn new( vertices: SortedVec< Vertex > ) -> Self { SimplexSafe { vertices } }
pub fn from_vec( vertices: Vec< Vertex > ) -> Result< Self, Vec<Vertex > > where Vertex: Ord {
SortedVec::new( vertices ).map(|x| SimplexSafe{ vertices: x } )
}
pub fn number_of_vertices( &self ) -> usize { self.vertices.len() }
pub fn dimension( &self ) -> usize { self.vertices.len() - 1 }
pub fn sorted_vec( &self ) -> & SortedVec< Vertex > { & self.vertices }
pub fn vertices( &self ) -> & Vec< Vertex > { self.vertices.vec() }
pub fn into_sorted_vec( self ) -> SortedVec< Vertex > { self.vertices }
pub fn into_vec( self ) -> Vec< Vertex > { self.vertices.into_vec() }
}
impl < Vertex >
PartialOrd for SimplexSafe
< Vertex >
where Vertex: Ord {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl < Vertex >
Ord for SimplexSafe
< Vertex >
where Vertex: Ord {
fn cmp(&self, other: &Self) -> Ordering {
let comp = self.number_of_vertices().cmp( & other.number_of_vertices() );
if comp != Ordering::Equal { return comp }
return self.vertices().cmp( other.vertices() )
}
}
impl < Vertex: Ord >
IntoIterator for SimplexSafe
< Vertex > {
type Item = Vertex;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter { self.into_vec().into_iter() }
}
pub fn cofacet_vertex_insertion_locus< Vertex >(
facet: & Vec< Vertex >,
new_vertex: Vertex,
)
-> Result< usize, (Option< &Vec<Vertex> >, Option< Vertex > ) >
where
Vertex: Copy + Ord,
{
let facet_error = if is_sorted_strictly(facet, &OrderOperatorAuto) {
None
} else {
Some(facet)
};
let vertex_error = if facet.contains(&new_vertex) {
Some(new_vertex)
} else {
None
};
if facet_error.is_some() || vertex_error.is_some() {
return Err( (facet_error, vertex_error) );
}
let mut insertion_locus = facet.len();
for p in 0 .. facet.len() {
if facet[p] > new_vertex {
insertion_locus = p;
break;
}
}
return Ok(insertion_locus)
}
pub fn coboundary_entry_for_facet_vertex_pair< Vertex, RingOperator >(
facet: & Vec< Vertex >,
new_vertex: Vertex,
ring_operator: RingOperator,
) -> Result<
( Vec<Vertex>, RingOperator::Element ),
(Option< &Vec<Vertex> >, Option< Vertex > )
>
where
Vertex: Copy + Ord,
RingOperator: RingOperations,
{
let insertion_locus = cofacet_vertex_insertion_locus( facet, new_vertex )?;
let mut cofacet = Vec::with_capacity( facet.len() + 1 );
cofacet.extend_from_slice( &facet[0..insertion_locus] );
cofacet.push( new_vertex );
cofacet.extend_from_slice( &facet[insertion_locus..] );
let coefficient = ring_operator.minus_one_to_power( insertion_locus );
return Ok(( cofacet, coefficient ))
}