#[repr(u8)]
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StepOutcome {
Continue,
Converged,
NoProgress,
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SolveStatus {
Converged,
NotConverged,
}
impl SolveStatus {
#[inline]
#[must_use]
pub const fn is_converged(self) -> bool {
matches!(self, SolveStatus::Converged)
}
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TerminationReason {
ConvergenceCriterion,
IterationCap,
NoProgress,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct IterationReport {
iterations_executed: u32,
termination: TerminationReason,
}
impl IterationReport {
#[inline]
#[must_use]
pub const fn new(iterations_executed: u32, termination: TerminationReason) -> Self {
Self {
iterations_executed,
termination,
}
}
#[inline]
#[must_use]
pub const fn iterations_executed(&self) -> u32 {
self.iterations_executed
}
#[inline]
#[must_use]
pub const fn termination(&self) -> TerminationReason {
self.termination
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct SolveReport {
status: SolveStatus,
iteration: IterationReport,
}
impl SolveReport {
#[inline]
#[must_use]
pub const fn converged_early(iterations_executed: u32) -> Self {
Self {
status: SolveStatus::Converged,
iteration: IterationReport::new(
iterations_executed,
TerminationReason::ConvergenceCriterion,
),
}
}
#[inline]
#[must_use]
pub const fn converged_at_cap(iterations_executed: u32) -> Self {
Self {
status: SolveStatus::Converged,
iteration: IterationReport::new(iterations_executed, TerminationReason::IterationCap),
}
}
#[inline]
#[must_use]
pub const fn not_converged_cap(iterations_executed: u32) -> Self {
Self {
status: SolveStatus::NotConverged,
iteration: IterationReport::new(iterations_executed, TerminationReason::IterationCap),
}
}
#[inline]
#[must_use]
pub const fn not_converged_stalled(iterations_executed: u32) -> Self {
Self {
status: SolveStatus::NotConverged,
iteration: IterationReport::new(iterations_executed, TerminationReason::NoProgress),
}
}
#[inline]
#[must_use]
pub const fn status(&self) -> SolveStatus {
self.status
}
#[inline]
#[must_use]
pub const fn iteration(&self) -> IterationReport {
self.iteration
}
#[inline]
#[must_use]
pub const fn iterations_executed(&self) -> u32 {
self.iteration.iterations_executed
}
#[inline]
#[must_use]
pub const fn termination(&self) -> TerminationReason {
self.iteration.termination
}
}
pub trait AsCoreReport {
fn as_core_report(&self) -> SolveReport;
#[inline]
fn core_status(&self) -> SolveStatus {
self.as_core_report().status()
}
}
const _: () = {
assert!(core::mem::size_of::<StepOutcome>() <= 2);
assert!(core::mem::size_of::<SolveStatus>() <= 2);
assert!(core::mem::size_of::<TerminationReason>() <= 2);
assert!(core::mem::size_of::<IterationReport>() <= 12);
assert!(core::mem::size_of::<SolveReport>() <= 16);
};
#[cfg(test)]
mod tests;