#include "archive.h"
#include "utils.h"
#include "relational.h"
+#include "compiler.h"
namespace GiNaC {
print_func<print_latex>(&power::do_print_latex).
print_func<print_csrc>(&power::do_print_csrc).
print_func<print_python>(&power::do_print_python).
- print_func<print_python_repr>(&power::do_print_python_repr))
+ print_func<print_python_repr>(&power::do_print_python_repr).
+ print_func<print_csrc_cl_N>(&power::do_print_csrc_cl_N))
typedef std::vector<int> intvector;
}
}
+void power::do_print_csrc_cl_N(const print_csrc_cl_N& c, unsigned level) const
+{
+ if (exponent.is_equal(_ex_1)) {
+ c.s << "recip(";
+ basis.print(c);
+ c.s << ')';
+ return;
+ }
+ c.s << "expt(";
+ basis.print(c);
+ c.s << ", ";
+ exponent.print(c);
+ c.s << ')';
+}
+
void power::do_print_csrc(const print_csrc & c, unsigned level) const
{
// Integer powers of symbols are printed in a special, optimized way
c.s << '(';
else {
exp = -exp;
- if (is_a<print_csrc_cl_N>(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
}
print_sym_pow(c, ex_to<symbol>(basis), exp);
c.s << ')';
// <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
} else if (exponent.is_equal(_ex_1)) {
- if (is_a<print_csrc_cl_N>(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
basis.print(c);
c.s << ')';
- // Otherwise, use the pow() or expt() (CLN) functions
+ // Otherwise, use the pow() function
} else {
- if (is_a<print_csrc_cl_N>(c))
- c.s << "expt(";
- else
- c.s << "pow(";
+ c.s << "pow(";
basis.print(c);
c.s << ',';
exponent.print(c);
case info_flags::algebraic:
return !exponent.info(info_flags::integer) ||
basis.info(inf);
+ case info_flags::expanded:
+ return (flags & status_flags::expanded);
}
return inherited::info(inf);
}
if (is_exactly_a<numeric>(sub_exponent)) {
const numeric & num_sub_exponent = ex_to<numeric>(sub_exponent);
GINAC_ASSERT(num_sub_exponent!=numeric(1));
- if (num_exponent->is_integer() || (abs(num_sub_exponent) - (*_num1_p)).is_negative())
+ if (num_exponent->is_integer() || (abs(num_sub_exponent) - (*_num1_p)).is_negative()) {
return power(sub_basis,num_sub_exponent.mul(*num_exponent));
+ }
}
}
if (num_exponent->is_integer() && is_exactly_a<mul>(ebasis)) {
return expand_mul(ex_to<mul>(ebasis), *num_exponent, 0);
}
-
+
+ // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4)
+ if (num_exponent->is_integer() && is_exactly_a<add>(ebasis)) {
+ numeric icont = ebasis.integer_content();
+ const numeric& lead_coeff =
+ ex_to<numeric>(ex_to<add>(ebasis).seq.begin()->coeff).div_dyn(icont);
+
+ const bool canonicalizable = lead_coeff.is_integer();
+ const bool unit_normal = lead_coeff.is_pos_integer();
+ if (canonicalizable && (! unit_normal))
+ icont = icont.mul(*_num_1_p);
+
+ if (canonicalizable && (icont != *_num1_p)) {
+ const add& addref = ex_to<add>(ebasis);
+ add* addp = new add(addref);
+ addp->setflag(status_flags::dynallocated);
+ addp->clearflag(status_flags::hash_calculated);
+ addp->overall_coeff = ex_to<numeric>(addp->overall_coeff).div_dyn(icont);
+ for (epvector::iterator i = addp->seq.begin(); i != addp->seq.end(); ++i)
+ i->coeff = ex_to<numeric>(i->coeff).div_dyn(icont);
+
+ const numeric c = icont.power(*num_exponent);
+ if (likely(c != *_num1_p))
+ return (new mul(power(*addp, *num_exponent), c))->setflag(status_flags::dynallocated);
+ else
+ return power(*addp, *num_exponent);
+ }
+ }
+
// ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2) (c1, c2 numeric(), c1>0)
// ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2) (c1, c2 numeric(), c1<0)
if (is_exactly_a<mul>(ebasis)) {
return (new add(sum))->setflag(status_flags::dynallocated | status_flags::expanded);
}
-/** Expand factors of m in m^n where m is a mul and n is and integer.
+/** Expand factors of m in m^n where m is a mul and n is an integer.
* @see power::expand */
ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool from_expand) const
{