Skip to main content

sirius/solver/poly/
display.rs

1use fmt::Write;
2use std::fmt;
3
4use crate::solver::poly::{
5    coef::Coef,
6    mono::{Mono, Var},
7};
8
9use super::Poly;
10
11impl fmt::Debug for Poly {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
13        f.write_str(&self.display_with(None))
14    }
15}
16
17impl Poly {
18    pub fn display_with(&self, var_names: Option<&[&str]>) -> String {
19        let mut buf = String::new();
20
21        if self.is_zero() {
22            write!(buf, "0").unwrap();
23        }
24
25        for (i, (c, m)) in self.terms().iter().enumerate() {
26            write_term(&mut buf, m, *c, i == 0, var_names).unwrap();
27        }
28
29        buf
30    }
31}
32
33fn write_term<T: Write>(
34    f: &mut T,
35    m: &Mono,
36    c: Coef,
37    first: bool,
38    names: Option<&[&str]>,
39) -> fmt::Result {
40    let neg = !c.is_positive();
41    if first {
42        if neg {
43            f.write_str("-")?;
44        }
45    } else {
46        f.write_str(if neg { " - " } else { " + " })?;
47    }
48
49    let mag = c.abs();
50    if m.is_unit() {
51        write!(f, "{mag:?}")
52    } else {
53        if mag != 1.into() {
54            write!(f, "{mag:?}*")?;
55        }
56        write_monomial(f, m, names)
57    }
58}
59
60fn write_monomial<T: Write>(f: &mut T, m: &Mono, names: Option<&[&str]>) -> fmt::Result {
61    for (i, &(v, e)) in m.exps().iter().enumerate() {
62        if i > 0 {
63            f.write_str("*")?;
64        }
65        write_var(f, v, names)?;
66        if e > 1 {
67            write!(f, "^{e}")?;
68        }
69    }
70    Ok(())
71}
72
73fn write_var<T: Write>(f: &mut T, v: Var, names: Option<&[&str]>) -> fmt::Result {
74    match names.and_then(|s| s.get(v as usize)) {
75        Some(name) => f.write_str(name),
76        None => match char::from_u32(v) {
77            Some(c @ 'a'..='z') => write!(f, "{}", c),
78            _ => write!(f, "x{}", v),
79        },
80    }
81}