Skip to main content

sirius/solver/poly/
macros.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! __poly_term {
4    () => {{ std::collections::VecDeque::new() }};
5    ($var:ident ^ $pow:literal $(* $($rest:tt)*)?) => {{
6        use $crate::solver::poly::mono::{Var, __read_var_name};
7        const VAR_NAME: Var = __read_var_name(stringify!($var));
8
9        let mut rest = $crate::__poly_term!($($($rest)*)?);
10        if rest.is_empty() {
11            rest.push_front((1, vec![(VAR_NAME, $pow)]));
12        } else {
13            rest[0].1.push((VAR_NAME, $pow));
14        }
15        rest
16    }};
17
18    ($var:ident ^ $pow:literal $(+ $($rest:tt)*)?) => {{
19        use $crate::solver::poly::mono::{Var, __read_var_name};
20        const VAR_NAME: Var = __read_var_name(stringify!($var));
21
22        let mut rest = $crate::__poly_sum!($($($rest)*)?);
23        rest.push_front((1, vec![(VAR_NAME, $pow)]));
24        rest
25    }};
26
27    ($var:ident ^ $pow:literal $(- $($rest:tt)*)?) => {{
28        use $crate::solver::poly::mono::{Var, __read_var_name};
29        const VAR_NAME: Var = __read_var_name(stringify!($var));
30
31        let mut rest = $crate::__poly_sum!($($($rest)*)?);
32        match rest.get_mut(0) {
33            Some(term) => term.0 *= -1,
34            None => {}
35        }
36        rest.push_front((1, vec![(VAR_NAME, $pow)]));
37        rest
38    }};
39
40    ($var:ident $(* $($rest:tt)*)?) => {{
41        $crate::__poly_term!($var ^ 1 * $($($rest)*)?)
42    }};
43
44    ($var:ident $(+ $($rest:tt)*)?) => {{
45        $crate::__poly_term!($var ^ 1 + $($($rest)*)?)
46    }};
47
48    ($var:ident $(- $($rest:tt)*)?) => {{
49        $crate::__poly_term!($var ^ 1 - $($($rest)*)?)
50    }};
51}
52
53#[doc(hidden)]
54#[macro_export]
55macro_rules! __poly_sum {
56    ()             => {{ std::collections::VecDeque::new() }};
57    ($c:literal)   => {{ std::collections::VecDeque::from([($c, vec![])]) }};
58    ($c:literal+$($rest:tt)+) => {{
59        let mut rest = $crate::__poly_sum!($($rest)*);
60        rest.push_front(($c, vec![]));
61        rest
62    }};
63    ($c:literal-$($rest:tt)+) => {{
64        let mut rest = $crate::__poly_sum!($($rest)*);
65        rest[0].0 *= -1;
66        rest.push_front(($c, vec![]));
67        rest
68    }};
69    ($c:literal*$($rest:tt)+) => {{
70        let mut v = $crate::__poly_term!($($rest)*);
71        v[0].0 *= $c;
72        v
73    }};
74    ($($rest:tt)+) => {{ $crate::__poly_term!($($rest)*) }};
75}
76
77/// Create a [`Poly`](super::Poly). Accepts 1-character ASCII variable names; <nobr>`poly!(2*x*y^5 + 8*z)`</nobr>.
78#[doc(hidden)]
79#[macro_export]
80macro_rules! __poly {
81    ($($body:tt)*) => {{
82        use $crate::solver::poly::{Poly, mono::{Var, Pow, Mono}};
83        let v: Vec<(i128, Vec<(Var, Pow)>)> = $crate::__poly_sum!($($body)*).into();
84        Poly::from_terms(v.into_iter().map(|(c, exps)| (c.into(), Mono::new(exps))))
85    }};
86}
87
88#[doc(inline)]
89pub use crate::__poly as poly;