sirius/solver/poly/
display.rs1use 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}