use crate::{
latex_modes::{
CategorizedLatexModeKindExt, CategoryEnumVariantExt, MathLatexMode, MathLatexModeKind,
},
lin_sys::{
err::OutOfBoundsError,
numbering::{Numbering, NumberingTy},
},
};
use core::{fmt::Write, marker::PhantomData};
use either::Either;
use nalgebra::Dim;
pub trait Unknowns {
fn len(&self) -> Result<usize, OutOfBoundsError>;
fn write_latex<IM, OM, W>(&self, dest: &mut W) -> Result<(), core::fmt::Error>
where
IM: CategorizedLatexModeKindExt,
OM: MathLatexMode + CategoryEnumVariantExt<MathLatexModeKind>,
W: Write;
fn validate_idx(&self, zbi: usize) -> Result<(), OutOfBoundsError>;
unsafe fn write_latex_for_ith_unchecked<M, W>(
&self,
dest: &mut W,
zbi: usize,
) -> Result<(), core::fmt::Error>
where
M: MathLatexMode + CategoryEnumVariantExt<MathLatexModeKind>,
W: Write;
fn write_latex_for_ith<M, W>(
&self,
dest: &mut W,
zbi: usize,
) -> Result<(), Either<core::fmt::Error, OutOfBoundsError>>
where
M: MathLatexMode + CategoryEnumVariantExt<MathLatexModeKind>,
W: Write,
{
self.validate_idx(zbi).map_err(Either::Right)?;
unsafe {
self.write_latex_for_ith_unchecked::<M, W>(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 len(&self) -> Result<usize, OutOfBoundsError> {
Ok(self.len.value())
}
fn write_latex<IM, OM, W>(&self, w: &mut W) -> Result<(), core::fmt::Error>
where
IM: CategorizedLatexModeKindExt,
OM: MathLatexMode + CategoryEnumVariantExt<MathLatexModeKind>,
W: Write,
{
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<M, W>(
&self,
w: &mut W,
zbi: usize,
) -> Result<(), core::fmt::Error>
where
M: MathLatexMode + CategoryEnumVariantExt<MathLatexModeKind>,
W: Write,
{
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"),
}
))
}
}