use crate::lin_sys::{
err::OutOfBoundsError,
numbering::{Numbering, NumberingTy},
};
use core::{fmt::Write, marker::PhantomData};
use either::Either;
use nalgebra::Dim;
pub trait Unknowns {
fn write_latex<W: Write>(&self, dest: &mut W) -> Result<(), core::fmt::Error>;
fn validate_idx(&self, zbi: usize) -> Result<(), OutOfBoundsError>;
unsafe fn write_latex_for_ith_unchecked<W: Write>(
&self,
dest: &mut W,
zbi: usize,
) -> Result<(), core::fmt::Error>;
fn write_latex_for_ith<W: Write>(
&self,
dest: &mut W,
zbi: usize,
) -> Result<(), Either<core::fmt::Error, OutOfBoundsError>> {
self.validate_idx(zbi).map_err(Either::Right)?;
unsafe {
self.write_latex_for_ith_unchecked(dest, zbi)
.map_err(Either::Left)
}
}
}
pub struct SingleLetterBoldfaceVecOfUnknowns<L, const N: NumberingTy> {
pub c: char,
pub len: L,
phantom: PhantomData<()>,
}
impl<L, const N: NumberingTy> SingleLetterBoldfaceVecOfUnknowns<L, N> {
#[cfg_attr(not(feature = "adt_const_params"), allow(non_upper_case_globals))]
pub fn new(c: char, len: L) -> Self {
use Numbering::*;
debug_assert!(matches!(N, ZeroBased | OneBased));
Self {
c,
len,
phantom: PhantomData::<()>,
}
}
}
impl<L, const N: NumberingTy> Unknowns for SingleLetterBoldfaceVecOfUnknowns<L, N>
where
L: Copy + Dim,
{
fn write_latex<W: Write>(&self, w: &mut W) -> Result<(), core::fmt::Error> {
w.write_fmt(format_args!("\\textbf{{{}}}", self.c))
}
fn validate_idx(&self, zbi: usize) -> Result<(), OutOfBoundsError> {
if zbi >= self.len.value() {
Err(OutOfBoundsError)
} else {
Ok(())
}
}
#[cfg_attr(not(feature = "adt_const_params"), allow(non_upper_case_globals))]
unsafe fn write_latex_for_ith_unchecked<W: Write>(
&self,
w: &mut W,
zbi: usize,
) -> Result<(), core::fmt::Error> {
use Numbering::*;
w.write_fmt(format_args!(
"{}_{{{}}}",
self.c,
match N {
ZeroBased => zbi,
OneBased => zbi + 1,
#[cfg_attr(feature = "adt_const_params", allow(unreachable_patterns))]
_ => panic!("unsupported numbering"),
}
))
}
}