1 /** @file collect_vargs.cpp
3 * Utility functions. */
6 * GiNaC Copyright (C) 1999-2010 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "operators.h"
27 #include "collect_vargs.h"
28 #include "smod_helpers.h"
32 #include <cln/integer.h>
40 typedef std::map<exp_vector_t, ex> ex_collect_priv_t;
43 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars);
45 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars);
46 static void wipe_out_zeros(ex_collect_priv_t& ec);
48 template<typename T, typename CoeffCMP>
51 const CoeffCMP& coeff_cmp;
52 explicit compare_terms(const CoeffCMP& coeff_cmp_) : coeff_cmp(coeff_cmp_)
54 inline bool operator()(const T& t1, const T& t2) const
56 bool exponent_is_less =
57 std::lexicographical_compare(t1.first.rbegin(),
64 if ((t1.first == t2.first) &&
65 coeff_cmp(t2.second, t2.second))
71 template<typename T, typename CoeffCMP>
72 static struct compare_terms<T, CoeffCMP>
73 make_compare_terms(const T& dummy, const CoeffCMP& coeff_cmp)
75 return compare_terms<T, CoeffCMP>(coeff_cmp);
78 void collect_vargs(ex_collect_t& ec, const ex& e, const exvector& vars)
80 ex_collect_priv_t ecp;
81 collect_vargs(ecp, e, vars);
82 ec.reserve(ecp.size());
83 std::copy(ecp.begin(), ecp.end(), std::back_inserter(ec));
84 std::sort(ec.begin(), ec.end(),
85 make_compare_terms(*ec.begin(), ex_is_less()));
89 collect_vargs(ex_collect_priv_t& ec, ex e, const exvector& vars)
98 collect_term(ec, e, vars);
102 for (const_iterator i = e.begin(); i != e.end(); ++i)
103 collect_term(ec, *i, vars);
109 collect_term(ex_collect_priv_t& ec, const ex& e, const exvector& vars)
113 static const ex ex1(1);
114 exp_vector_t key(vars.size());
116 for (std::size_t i = 0; i < vars.size(); ++i) {
117 const int var_i_pow = pre_coeff.degree(vars[i]);
119 pre_coeff = pre_coeff.coeff(vars[i], var_i_pow);
121 ex_collect_priv_t::iterator i = ec.find(key);
123 i->second += pre_coeff;
125 ec.insert(ex_collect_priv_t::value_type(key, pre_coeff));
128 static void wipe_out_zeros(ex_collect_priv_t& m)
130 ex_collect_priv_t::iterator i = m.begin();
131 while (i != m.end()) {
132 // be careful to not invalide iterator, use post-increment
133 // for that, see e.g.
134 // http://coding.derkeiler.com/Archive/C_CPP/comp.lang.cpp/2004-02/0502.html
135 if (i->second.is_zero())
143 ex_collect_to_ex(const ex_collect_t& ec, const GiNaC::exvector& vars)
146 ev.reserve(ec.size());
147 for (std::size_t i = 0; i < ec.size(); ++i) {
149 tv.reserve(vars.size() + 1);
150 for (std::size_t j = 0; j < vars.size(); ++j) {
151 if (ec[i].first[j] != 0)
152 tv.push_back(power(vars[j], ec[i].first[j]));
154 tv.push_back(ec[i].second);
155 ex tmp = (new mul(tv))->setflag(status_flags::dynallocated);
158 ex ret = (new add(ev))->setflag(status_flags::dynallocated);
162 ex lcoeff_wrt(ex e, const exvector& x)
164 static const ex ex0(0);
170 collect_vargs(ec, e, x);
171 return ec.rbegin()->second;
174 cln::cl_I integer_lcoeff(const ex& e, const exvector& vars)
177 collect_vargs(ec, e, vars);
180 ex lc = ec.rbegin()->second;
181 bug_on(!is_a<numeric>(lc), "leading coefficient is not an integer");
182 bug_on(!lc.info(info_flags::integer),
183 "leading coefficient is not an integer");