[GiNaC-devel] why does power(add) switch the sign of the add?

Jan jrheinlaender at gmx.de
Sun Aug 3 18:56:47 CEST 2014


Hi,

I noticed the following behaviour of power::eval(), for example in ginsh:

> (x_1 - x_2 + x_3 - x_4)^2;
(x_4-x_1-x_3+x_2)^2

The sign of the sum is switched. Of course, mathematically this is
totally correct, but is there any good reason why GiNaC should do it? It
seems to go back to the following piece of code in power.cpp, power::eval()

---------
// (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(icont);

                        const bool canonicalizable =
lead_coeff.is_integer();
>>> HERE ============================
                        const bool unit_normal =
lead_coeff.is_pos_integer();
                        if (canonicalizable && (! unit_normal))
                                icont = icont.mul(*_num_1_p);
>>> HERE ============================

                        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);
                        }
                }
------------

Why not leave away this bit of code, improve performance by a tiny
little bit, and get somewhat more predictable behaviour of GiNaC?

Jan


More information about the GiNaC-devel mailing list