+/** Get denominator of an expression. If the expression is not of the normal
+ * form "numerator/denominator", it is first converted to this form and
+ * then the denominator is returned.
+ *
+ * @see ex::normal
+ * @return denominator */
+ex ex::denom(void) const
+{
+ lst sym_lst, repl_lst;
+
+ ex e = bp->normal(sym_lst, repl_lst, 0);
+ GINAC_ASSERT(is_ex_of_type(e, lst));
+
+ // Re-insert replaced symbols
+ if (sym_lst.nops() > 0)
+ return e.op(1).subs(sym_lst, repl_lst);
+ else
+ return e.op(1);
+}
+
+/** Get numerator and denominator of an expression. If the expresison is not
+ * of the normal form "numerator/denominator", it is first converted to this
+ * form and then a list [numerator, denominator] is returned.
+ *
+ * @see ex::normal
+ * @return a list [numerator, denominator] */
+ex ex::numer_denom(void) const
+{
+ lst sym_lst, repl_lst;
+
+ ex e = bp->normal(sym_lst, repl_lst, 0);
+ GINAC_ASSERT(is_ex_of_type(e, lst));
+
+ // Re-insert replaced symbols
+ if (sym_lst.nops() > 0)
+ return e.subs(sym_lst, repl_lst);
+ else
+ return e;
+}
+
+
+/** Default implementation of ex::to_rational(). It replaces the object with a
+ * temporary symbol.
+ * @see ex::to_rational */
+ex basic::to_rational(lst &repl_lst) const
+{
+ return replace_with_symbol(*this, repl_lst);
+}
+
+
+/** Implementation of ex::to_rational() for symbols. This returns the
+ * unmodified symbol.
+ * @see ex::to_rational */
+ex symbol::to_rational(lst &repl_lst) const
+{
+ return *this;
+}
+
+
+/** 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_rational())
+ return replace_with_symbol(*this, repl_lst);
+ } else { // complex
+ numeric re = real();
+ numeric im = imag();
+ ex re_ex = re.is_rational() ? re : replace_with_symbol(re, repl_lst);
+ ex im_ex = im.is_rational() ? im : replace_with_symbol(im, repl_lst);
+ return re_ex + im_ex * replace_with_symbol(I, repl_lst);
+ }
+ return *this;
+}
+
+
+/** Implementation of ex::to_rational() for powers. It replaces non-integer
+ * powers by temporary symbols.
+ * @see ex::to_rational */
+ex power::to_rational(lst &repl_lst) const
+{
+ if (exponent.info(info_flags::integer))
+ return power(basis.to_rational(repl_lst), exponent);
+ else
+ return replace_with_symbol(*this, repl_lst);
+}
+
+
+/** Implementation of ex::to_rational() for expairseqs.
+ * @see ex::to_rational */
+ex expairseq::to_rational(lst &repl_lst) const
+{
+ epvector s;
+ s.reserve(seq.size());
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ s.push_back(split_ex_to_pair(recombine_pair_to_ex(*i).to_rational(repl_lst)));
+ ++i;
+ }
+ 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());
+}
+
+
+/** Rationalization of non-rational functions.
+ * This function converts a general expression to a rational polynomial
+ * by replacing all non-rational subexpressions (like non-rational numbers,
+ * non-integer powers or functions like sin(), cos() etc.) to temporary
+ * symbols. This makes it possible to use functions like gcd() and divide()
+ * on non-rational functions by applying to_rational() on the arguments,
+ * calling the desired function and re-substituting the temporary symbols
+ * in the result. To make the last step possible, all temporary symbols and
+ * their associated expressions are collected in the list specified by the
+ * repl_lst parameter in the form {symbol == expression}, ready to be passed
+ * as an argument to ex::subs().
+ *
+ * @param repl_lst collects a list of all temporary symbols and their replacements
+ * @return rationalized expression */
+ex ex::to_rational(lst &repl_lst) const
+{
+ return bp->to_rational(repl_lst);
+}
+
+