}
+/** Sparse pseudo-remainder of polynomials a(x) and b(x) in Z[x].
+ *
+ * @param a first polynomial in x (dividend)
+ * @param b second polynomial in x (divisor)
+ * @param x a and b are polynomials in x
+ * @param check_args check whether a and b are polynomials with rational
+ * coefficients (defaults to "true")
+ * @return sparse pseudo-remainder of a(x) and b(x) in Z[x] */
+
+ex sprem(const ex &a, const ex &b, const symbol &x, bool check_args)
+{
+ if (b.is_zero())
+ throw(std::overflow_error("prem: division by zero"));
+ if (is_ex_exactly_of_type(a, numeric)) {
+ if (is_ex_exactly_of_type(b, numeric))
+ return _ex0();
+ else
+ return b;
+ }
+ if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)))
+ throw(std::invalid_argument("prem: arguments must be polynomials over the rationals"));
+
+ // Polynomial long division
+ ex r = a.expand();
+ ex eb = b.expand();
+ int rdeg = r.degree(x);
+ int bdeg = eb.degree(x);
+ ex blcoeff;
+ if (bdeg <= rdeg) {
+ blcoeff = eb.coeff(x, bdeg);
+ if (bdeg == 0)
+ eb = _ex0();
+ else
+ eb -= blcoeff * power(x, bdeg);
+ } else
+ blcoeff = _ex1();
+
+ while (rdeg >= bdeg && !r.is_zero()) {
+ ex rlcoeff = r.coeff(x, rdeg);
+ ex term = (power(x, rdeg - bdeg) * eb * rlcoeff).expand();
+ if (rdeg == 0)
+ r = _ex0();
+ else
+ r -= rlcoeff * power(x, rdeg);
+ r = (blcoeff * r).expand() - term;
+ rdeg = r.degree(x);
+ }
+ return r;
+}
+
+
/** Exact polynomial division of a(X) by b(X) in Q[X].
*
* @param a first multivariate polynomial (dividend)
return true;
}
#endif
- if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)))
+ if (check_args && (!a.info(info_flags::rational_polynomial) ||
+ !b.info(info_flags::rational_polynomial)))
throw(std::invalid_argument("divide: arguments must be polynomials over the rationals"));
// Find first symbol
* @see ex::normal */
ex add::normal(lst &sym_lst, lst &repl_lst, int level) const
{
+ if (level == 1)
+ return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated);
+ else if (level == -max_recursion_level)
+ throw(std::runtime_error("max recursion level reached"));
+
// Normalize and expand children, chop into summands
exvector o;
o.reserve(seq.size()+1);
* @see ex::normal() */
ex mul::normal(lst &sym_lst, lst &repl_lst, int level) const
{
+ if (level == 1)
+ return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated);
+ else if (level == -max_recursion_level)
+ throw(std::runtime_error("max recursion level reached"));
+
// Normalize children, separate into numerator and denominator
ex num = _ex1();
ex den = _ex1();
* @see ex::normal */
ex power::normal(lst &sym_lst, lst &repl_lst, int level) const
{
+ if (level == 1)
+ return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated);
+ else if (level == -max_recursion_level)
+ throw(std::runtime_error("max recursion level reached"));
+
// Normalize basis
ex n = basis.bp->normal(sym_lst, repl_lst, level-1);
}
-/** Implementation of ex::to_rational() for symbols. This returns the unmodified symbol.
+/** Implementation of ex::to_rational() for symbols. This returns the
+ * unmodified symbol.
* @see ex::to_rational */
ex symbol::to_rational(lst &repl_lst) const
{
}
-/** Implementation of ex::to_rational() for a numeric. It splits complex numbers
- * into re+I*im and replaces I and non-rational real numbers with a temporary
- * symbol.
+/** Implementation of ex::to_rational() for a numeric. It splits complex
+ * numbers into re+I*im and replaces I and non-rational real numbers with a
+ * temporary symbol.
* @see ex::to_rational */
ex numeric::to_rational(lst &repl_lst) const
{
if (is_real()) {
- if (!is_integer())
+ if (!is_rational())
return replace_with_symbol(*this, repl_lst);
} else { // complex
numeric re = real();
epvector s;
s.reserve(seq.size());
for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
- s.push_back(combine_ex_with_coeff_to_pair((*it).rest.to_rational(repl_lst),
- (*it).coeff));
+ s.push_back(split_ex_to_pair(recombine_pair_to_ex(*it).to_rational(repl_lst)));
+ // s.push_back(combine_ex_with_coeff_to_pair((*it).rest.to_rational(repl_lst),
}
- return thisexpairseq(s, overall_coeff);
+ ex oc = overall_coeff.to_rational(repl_lst);
+ if (oc.info(info_flags::numeric))
+ return thisexpairseq(s, overall_coeff);
+ else s.push_back(combine_ex_with_coeff_to_pair(oc,_ex1()));
+ return thisexpairseq(s, default_overall_coeff());
}