6 #include <ginac/ginac.h>
7 #include "collect_vargs.h"
8 #include <cln/integer.h>
9 #include "smod_helpers.h"
15 typedef std::map<exp_vector_t, ex> ex_collect_priv_t;
18 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars);
20 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars);
21 static void wipe_out_zeros(ex_collect_priv_t& ec);
23 template<typename T, typename CoeffCMP>
26 const CoeffCMP& coeff_cmp;
27 explicit compare_terms(const CoeffCMP& coeff_cmp_) : coeff_cmp(coeff_cmp_)
29 inline bool operator()(const T& t1, const T& t2) const
31 bool exponent_is_less =
32 std::lexicographical_compare(t1.first.rbegin(),
39 if ((t1.first == t2.first) &&
40 coeff_cmp(t2.second, t2.second))
46 template<typename T, typename CoeffCMP>
47 static struct compare_terms<T, CoeffCMP>
48 make_compare_terms(const T& dummy, const CoeffCMP& coeff_cmp)
50 return compare_terms<T, CoeffCMP>(coeff_cmp);
53 void collect_vargs(ex_collect_t& ec, const ex& e, const exvector& vars)
55 ex_collect_priv_t ecp;
56 collect_vargs(ecp, e, vars);
57 ec.reserve(ecp.size());
58 std::copy(ecp.begin(), ecp.end(), std::back_inserter(ec));
59 std::sort(ec.begin(), ec.end(),
60 make_compare_terms(*ec.begin(), ex_is_less()));
64 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars)
73 collect_term(ec, e, vars);
77 for (const_iterator i = e.begin(); i != e.end(); ++i)
78 collect_term(ec, *i, vars);
84 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars)
88 static const ex ex1(1);
89 exp_vector_t key(vars.size());
91 for (std::size_t i = 0; i < vars.size(); ++i) {
92 const int var_i_pow = pre_coeff.degree(vars[i]);
94 pre_coeff = pre_coeff.coeff(vars[i], var_i_pow);
96 ex_collect_priv_t::iterator i = ec.find(key);
98 i->second += pre_coeff;
100 ec.insert(ex_collect_priv_t::value_type(key, pre_coeff));
103 static void wipe_out_zeros(ex_collect_priv_t& m)
105 ex_collect_priv_t::iterator i = m.begin();
106 while (i != m.end()) {
107 // be careful to not invalide iterator, use post-increment
108 // for that, see e.g.
109 // http://coding.derkeiler.com/Archive/C_CPP/comp.lang.cpp/2004-02/0502.html
110 if (i->second.is_zero())
118 ex_collect_to_ex(const ex_collect_t& ec, const GiNaC::exvector& vars)
121 ev.reserve(ec.size());
122 for (std::size_t i = 0; i < ec.size(); ++i) {
124 tv.reserve(vars.size() + 1);
125 for (std::size_t j = 0; j < vars.size(); ++j) {
126 if (ec[i].first[j] != 0)
127 tv.push_back(power(vars[j], ec[i].first[j]));
129 tv.push_back(ec[i].second);
130 ex tmp = (new mul(tv))->setflag(status_flags::dynallocated);
133 ex ret = (new add(ev))->setflag(status_flags::dynallocated);
137 ex lcoeff_wrt(ex e, const exvector& x)
139 static const ex ex0(0);
145 collect_vargs(ec, e, x);
146 return ec.rbegin()->second;
149 cln::cl_I integer_lcoeff(const ex& e, const exvector& vars)
152 collect_vargs(ec, e, vars);
155 ex lc = ec.rbegin()->second;
156 bug_on(!is_a<numeric>(lc), "leading coefficient is not an integer");
157 bug_on(!lc.info(info_flags::integer),
158 "leading coefficient is not an integer");