use std::fmt;
use num_traits::Float;
use crate::opcode::OpCode;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct KinkEntry<F: Float> {
pub tape_index: u32,
pub opcode: OpCode,
pub switching_value: F,
pub branch: i8,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct NonsmoothInfo<F: Float> {
pub kinks: Vec<KinkEntry<F>>,
}
impl<F: Float> NonsmoothInfo<F> {
pub fn active_kinks(&self, tol: F) -> Vec<&KinkEntry<F>> {
self.kinks
.iter()
.filter(|k| k.switching_value.abs() < tol || !k.switching_value.is_finite())
.collect()
}
pub fn is_smooth(&self, tol: F) -> bool {
self.kinks
.iter()
.all(|k| k.switching_value.is_finite() && k.switching_value.abs() >= tol)
}
#[must_use]
pub fn signature(&self) -> Vec<(u32, i8)> {
self.kinks
.iter()
.map(|k| (k.tape_index, k.branch))
.collect()
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub enum ClarkeError {
TooManyKinks {
count: usize,
limit: usize,
},
}
impl fmt::Display for ClarkeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClarkeError::TooManyKinks { count, limit } => {
write!(
f,
"too many active kinks for Clarke enumeration: {} (limit {})",
count, limit
)
}
}
}
}
impl std::error::Error for ClarkeError {}
crate::assert_send_sync!(ClarkeError);