Skip to content

Commit

Permalink
Add formatting functions
Browse files Browse the repository at this point in the history
- Add __repr__ for printing with parsable formatting
- Add to_string() on atom  for printing with parsable formatting
- Add with_stats(f) for printing statistics
  • Loading branch information
benruijl committed Sep 14, 2024
1 parent 9a424cc commit b15c010
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 43 deletions.
110 changes: 110 additions & 0 deletions src/api/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2209,6 +2209,11 @@ impl PythonExpression {
self.expr.clone().into()
}

/// Convert the expression into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(self.to_string())
}

/// Convert the expression into a human-readable string.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!("{}", AtomPrinter::new(self.expr.as_view())))
Expand Down Expand Up @@ -4572,6 +4577,11 @@ impl PythonSeries {
}
}

/// Convert the series into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self.series))
}

pub fn __str__(&self) -> PyResult<String> {
Ok(format!("{}", self.series))
}
Expand Down Expand Up @@ -5040,6 +5050,17 @@ impl PythonPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -5724,6 +5745,17 @@ impl PythonFiniteFieldPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -6294,6 +6326,17 @@ impl PythonPrimeTwoPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -6829,6 +6872,17 @@ impl PythonGaloisFieldPrimeTwoPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -7368,6 +7422,17 @@ impl PythonGaloisFieldPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -7908,6 +7973,17 @@ impl PythonNumberFieldPolynomial {
))
}

/// Convert the polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
PolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file()
}
))
}

/// Print the polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -8446,6 +8522,18 @@ impl PythonRationalPolynomial {
Ok(var_list)
}

/// Convert the rational polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
RationalPolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file(),
add_parentheses: false,
}
))
}

/// Print the rational polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -8760,6 +8848,18 @@ impl PythonFiniteFieldRationalPolynomial {
Ok(var_list)
}

/// Convert the rational polynomial into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"{}",
RationalPolynomialPrinter {
poly: &self.poly,
opts: PrintOptions::file(),
add_parentheses: false,
}
))
}

/// Print the rational polynomial in a human-readable format.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!(
Expand Down Expand Up @@ -9595,6 +9695,11 @@ impl PythonMatrix {
}
}

/// Convert the matrix into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self.matrix))
}

/// Convert the matrix into a human-readable string.
pub fn __str__(&self) -> PyResult<String> {
Ok(format!("{}", self.matrix))
Expand Down Expand Up @@ -10081,6 +10186,11 @@ impl PythonGraph {
}
}

/// Convert the graph into a portable string.
pub fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self.graph))
}

/// Print the graph in a human-readable format.
fn __str__(&self) -> String {
format!("{}", self.graph)
Expand Down
27 changes: 26 additions & 1 deletion src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use representation::{InlineNum, InlineVar};
use crate::{
coefficient::Coefficient,
parser::Token,
printer::AtomPrinter,
printer::{AtomPrinter, PrintOptions},
state::{RecycledAtom, Workspace},
transformer::StatsOptions,
};
use std::{cmp::Ordering, hash::Hash, ops::DerefMut, str::FromStr};

Expand Down Expand Up @@ -346,6 +347,20 @@ impl<'a> AtomView<'a> {
target.set_from_view(self);
}

/// Print the view using the portable [`PrintOptions::file()`] options.
pub fn to_string(&self) -> String {
format!("{}", self.printer(PrintOptions::file()))
}

/// Print statistics about the operation `op`, such as its duration and term growth.
pub fn with_stats<F: Fn(AtomView) -> Atom>(&self, op: F, o: &StatsOptions) -> Atom {
let t = std::time::Instant::now();
let out = op(*self);
let dt = t.elapsed();
o.print(*self, out.as_view(), dt);
out
}

#[inline]
pub fn is_zero(&self) -> bool {
if let AtomView::Num(n) = self {
Expand Down Expand Up @@ -616,6 +631,16 @@ impl Atom {
self.as_view().is_one()
}

/// Print the atom using the portable [`PrintOptions::file()`] options.
pub fn to_string(&self) -> String {
format!("{}", self.printer(PrintOptions::file()))
}

/// Print statistics about the operation `op`, such as its duration and term growth.
pub fn with_stats<F: Fn(AtomView) -> Atom>(&self, op: F, o: &StatsOptions) -> Atom {
self.as_view().with_stats(op, o)
}

/// Repeatedly apply an operation on the atom until the atom no longer changes.
pub fn repeat_map<F: Fn(AtomView) -> Atom>(&mut self, op: F) {
let mut res;
Expand Down
2 changes: 2 additions & 0 deletions src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,8 @@ impl Condition<PatternRestriction> {
match r {
WildcardRestriction::Cmp(v, _) if *v == var => {}
_ => {
// TODO: we can actually return True if the v is in the match stack
// same for cmp if both are in the stack
return ConditionResult::Inconclusive;
}
}
Expand Down
88 changes: 46 additions & 42 deletions src/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,50 @@ impl StatsOptions {
pub fn format_count(&self, count: usize) -> String {
format!("{}", count)
}

pub fn print(&self, input: AtomView, output: AtomView, dt: std::time::Duration) {
let in_nterms = if let AtomView::Add(a) = input {
a.get_nargs()
} else {
1
};
let in_size = input.get_byte_size();

let out_nterms = if let AtomView::Add(a) = output {
a.get_nargs()
} else {
1
};
let out_size = output.get_byte_size();

let in_nterms_s = self.format_count(in_nterms);
let out_nterms_s = self.format_count(out_nterms);

println!(
"Stats for {}:
\tIn │ {:>width$} │ {:>8} │
\tOut │ {:>width$} │ {:>8} │ ⧗ {:#.2?}",
self.tag.bold(),
in_nterms_s,
self.format_size(in_size),
if out_nterms as f64 / in_nterms as f64
> self.color_medium_change_threshold.unwrap_or(f64::INFINITY)
{
if out_nterms as f64 / in_nterms as f64
> self.color_large_change_threshold.unwrap_or(f64::INFINITY)
{
out_nterms_s.red()
} else {
out_nterms_s.bright_magenta()
}
} else {
out_nterms_s.as_str().into()
},
self.format_size(out_size),
dt,
width = in_nterms_s.len().max(out_nterms_s.len()).min(6),
);
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -719,50 +763,10 @@ impl Transformer {
std::mem::swap(out, &mut tmp);
}
Transformer::Stats(o, r) => {
let in_nterms = if let AtomView::Add(a) = cur_input {
a.get_nargs()
} else {
1
};
let in_size = cur_input.get_byte_size();

let t = Instant::now();
Self::execute_chain(cur_input, r, workspace, out)?;

let out_nterms = if let AtomView::Add(a) = out.as_view() {
a.get_nargs()
} else {
1
};
let out_size = out.as_view().get_byte_size();

let in_nterms_s = o.format_count(in_nterms);
let out_nterms_s = o.format_count(out_nterms);

println!(
"Stats for {}:
\tIn │ {:>width$} │ {:>8} │
\tOut │ {:>width$} │ {:>8} │ ⧗ {:#.2?}",
o.tag.bold(),
in_nterms_s,
o.format_size(in_size),
if out_nterms as f64 / in_nterms as f64
> o.color_medium_change_threshold.unwrap_or(f64::INFINITY)
{
if out_nterms as f64 / in_nterms as f64
> o.color_large_change_threshold.unwrap_or(f64::INFINITY)
{
out_nterms_s.red()
} else {
out_nterms_s.bright_magenta()
}
} else {
out_nterms_s.as_str().into()
},
o.format_size(out_size),
Instant::now().duration_since(t),
width = in_nterms_s.len().max(out_nterms_s.len()).min(6),
);
let dt = t.elapsed();
o.print(cur_input, out.as_view(), dt);
}
Transformer::FromNumber => {
if let AtomView::Num(n) = cur_input {
Expand Down

0 comments on commit b15c010

Please sign in to comment.