10 #include "collect_vargs.h"
11 #include <cln/integer.h>
12 #include "smod_helpers.h"
18 typedef std::map<exp_vector_t, ex> ex_collect_priv_t;
21 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars);
23 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars);
24 static void wipe_out_zeros(ex_collect_priv_t& ec);
26 template<typename T, typename CoeffCMP>
29 const CoeffCMP& coeff_cmp;
30 explicit compare_terms(const CoeffCMP& coeff_cmp_) : coeff_cmp(coeff_cmp_)
32 inline bool operator()(const T& t1, const T& t2) const
34 bool exponent_is_less =
35 std::lexicographical_compare(t1.first.rbegin(),
42 if ((t1.first == t2.first) &&
43 coeff_cmp(t2.second, t2.second))
49 template<typename T, typename CoeffCMP>
50 static struct compare_terms<T, CoeffCMP>
51 make_compare_terms(const T& dummy, const CoeffCMP& coeff_cmp)
53 return compare_terms<T, CoeffCMP>(coeff_cmp);
56 void collect_vargs(ex_collect_t& ec, const ex& e, const exvector& vars)
58 ex_collect_priv_t ecp;
59 collect_vargs(ecp, e, vars);
60 ec.reserve(ecp.size());
61 std::copy(ecp.begin(), ecp.end(), std::back_inserter(ec));
62 std::sort(ec.begin(), ec.end(),
63 make_compare_terms(*ec.begin(), ex_is_less()));
67 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars)
76 collect_term(ec, e, vars);
80 for (const_iterator i = e.begin(); i != e.end(); ++i)
81 collect_term(ec, *i, vars);
87 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars)
91 static const ex ex1(1);
92 exp_vector_t key(vars.size());
94 for (std::size_t i = 0; i < vars.size(); ++i) {
95 const int var_i_pow = pre_coeff.degree(vars[i]);
97 pre_coeff = pre_coeff.coeff(vars[i], var_i_pow);
99 ex_collect_priv_t::iterator i = ec.find(key);
101 i->second += pre_coeff;
103 ec.insert(ex_collect_priv_t::value_type(key, pre_coeff));
106 static void wipe_out_zeros(ex_collect_priv_t& m)
108 ex_collect_priv_t::iterator i = m.begin();
109 while (i != m.end()) {
110 // be careful to not invalide iterator, use post-increment
111 // for that, see e.g.
112 // http://coding.derkeiler.com/Archive/C_CPP/comp.lang.cpp/2004-02/0502.html
113 if (i->second.is_zero())
121 ex_collect_to_ex(const ex_collect_t& ec, const GiNaC::exvector& vars)
124 ev.reserve(ec.size());
125 for (std::size_t i = 0; i < ec.size(); ++i) {
127 tv.reserve(vars.size() + 1);
128 for (std::size_t j = 0; j < vars.size(); ++j) {
129 if (ec[i].first[j] != 0)
130 tv.push_back(power(vars[j], ec[i].first[j]));
132 tv.push_back(ec[i].second);
133 ex tmp = (new mul(tv))->setflag(status_flags::dynallocated);
136 ex ret = (new add(ev))->setflag(status_flags::dynallocated);
140 ex lcoeff_wrt(ex e, const exvector& x)
142 static const ex ex0(0);
148 collect_vargs(ec, e, x);
149 return ec.rbegin()->second;
152 cln::cl_I integer_lcoeff(const ex& e, const exvector& vars)
155 collect_vargs(ec, e, vars);
158 ex lc = ec.rbegin()->second;
159 bug_on(!is_a<numeric>(lc), "leading coefficient is not an integer");
160 bug_on(!lc.info(info_flags::integer),
161 "leading coefficient is not an integer");