]> www.ginac.de Git - ginac.git/blobdiff - ginac/power.cpp
Fixed initialization order bug (references to flyweights removed!) [C.Dams].
[ginac.git] / ginac / power.cpp
index fe18097b15f78bcea22898a0f224a241059c5755..815c59306accc437a9234707919af9e855e77fe2 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's symbolic exponentiation (basis^exponent). */
 
 /*
- *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <vector>
@@ -222,12 +222,14 @@ bool power::info(unsigned inf) const
                case info_flags::cinteger_polynomial:
                case info_flags::rational_polynomial:
                case info_flags::crational_polynomial:
-                       return exponent.info(info_flags::nonnegint);
+                       return exponent.info(info_flags::nonnegint) &&
+                              basis.info(inf);
                case info_flags::rational_function:
-                       return exponent.info(info_flags::integer);
+                       return exponent.info(info_flags::integer) &&
+                              basis.info(inf);
                case info_flags::algebraic:
-                       return (!exponent.info(info_flags::integer) ||
-                                       basis.info(inf));
+                       return !exponent.info(info_flags::integer) ||
+                              basis.info(inf);
        }
        return inherited::info(inf);
 }
@@ -246,7 +248,14 @@ ex power::op(size_t i) const
 
 ex power::map(map_function & f) const
 {
-       return (new power(f(basis), f(exponent)))->setflag(status_flags::dynallocated);
+       const ex &mapped_basis = f(basis);
+       const ex &mapped_exponent = f(exponent);
+
+       if (!are_ex_trivially_equal(basis, mapped_basis)
+        || !are_ex_trivially_equal(exponent, mapped_exponent))
+               return (new power(mapped_basis, mapped_exponent))->setflag(status_flags::dynallocated);
+       else
+               return *this;
 }
 
 int power::degree(const ex & s) const
@@ -439,7 +448,7 @@ ex power::eval(int level) const
                        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).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));
                        }
                }
@@ -465,8 +474,8 @@ ex power::eval(int level) const
                                                return (new mul(power(*mulp,exponent),
                                                                power(num_coeff,*num_exponent)))->setflag(status_flags::dynallocated);
                                        } else {
-                                               GINAC_ASSERT(num_coeff.compare(_num0)<0);
-                                               if (!num_coeff.is_equal(_num_1)) {
+                                               GINAC_ASSERT(num_coeff.compare(*_num0_p)<0);
+                                               if (!num_coeff.is_equal(*_num_1_p)) {
                                                        mul *mulp = new mul(mulref);
                                                        mulp->overall_coeff = _ex_1;
                                                        mulp->clearflag(status_flags::evaluated);
@@ -558,6 +567,16 @@ ex power::eval_ncmul(const exvector & v) const
        return inherited::eval_ncmul(v);
 }
 
+ex power::conjugate() const
+{
+       ex newbasis = basis.conjugate();
+       ex newexponent = exponent.conjugate();
+       if (are_ex_trivially_equal(basis, newbasis) && are_ex_trivially_equal(exponent, newexponent)) {
+               return *this;
+       }
+       return (new power(newbasis, newexponent))->setflag(status_flags::dynallocated);
+}
+
 // protected
 
 /** Implementation of ex::diff() for a power.
@@ -595,7 +614,7 @@ unsigned power::return_type() const
 {
        return basis.return_type();
 }
-   
+
 unsigned power::return_type_tinfo() const
 {
        return basis.return_type_tinfo();
@@ -787,7 +806,7 @@ ex power::expand_add_2(const add & a, unsigned options) const
                
                if (c.is_equal(_ex1)) {
                        if (is_exactly_a<mul>(r)) {
-                               sum.push_back(expair(expand_mul(ex_to<mul>(r), _num2, options, true),
+                               sum.push_back(expair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
                                                     _ex1));
                        } else {
                                sum.push_back(expair((new power(r,_ex2))->setflag(status_flags::dynallocated),
@@ -795,11 +814,11 @@ ex power::expand_add_2(const add & a, unsigned options) const
                        }
                } else {
                        if (is_exactly_a<mul>(r)) {
-                               sum.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), _num2, options, true),
-                                                    ex_to<numeric>(c).power_dyn(_num2)));
+                               sum.push_back(a.combine_ex_with_coeff_to_pair(expand_mul(ex_to<mul>(r), *_num2_p, options, true),
+                                                    ex_to<numeric>(c).power_dyn(*_num2_p)));
                        } else {
                                sum.push_back(a.combine_ex_with_coeff_to_pair((new power(r,_ex2))->setflag(status_flags::dynallocated),
-                                                    ex_to<numeric>(c).power_dyn(_num2)));
+                                                    ex_to<numeric>(c).power_dyn(*_num2_p)));
                        }
                }
 
@@ -807,7 +826,7 @@ ex power::expand_add_2(const add & a, unsigned options) const
                        const ex & r1 = cit1->rest;
                        const ex & c1 = cit1->coeff;
                        sum.push_back(a.combine_ex_with_coeff_to_pair((new mul(r,r1))->setflag(status_flags::dynallocated),
-                                                                     _num2.mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
+                                                                     _num2_p->mul(ex_to<numeric>(c)).mul_dyn(ex_to<numeric>(c1))));
                }
        }
        
@@ -817,10 +836,10 @@ ex power::expand_add_2(const add & a, unsigned options) const
        if (!a.overall_coeff.is_zero()) {
                epvector::const_iterator i = a.seq.begin(), end = a.seq.end();
                while (i != end) {
-                       sum.push_back(a.combine_pair_with_coeff_to_pair(*i, ex_to<numeric>(a.overall_coeff).mul_dyn(_num2)));
+                       sum.push_back(a.combine_pair_with_coeff_to_pair(*i, ex_to<numeric>(a.overall_coeff).mul_dyn(*_num2_p)));
                        ++i;
                }
-               sum.push_back(expair(ex_to<numeric>(a.overall_coeff).power_dyn(_num2),_ex1));
+               sum.push_back(expair(ex_to<numeric>(a.overall_coeff).power_dyn(*_num2_p),_ex1));
        }
        
        GINAC_ASSERT(sum.size()==(a_nops*(a_nops+1))/2);
@@ -834,8 +853,17 @@ ex power::expand_mul(const mul & m, const numeric & n, unsigned options, bool fr
 {
        GINAC_ASSERT(n.is_integer());
 
-       if (n.is_zero())
+       if (n.is_zero()) {
                return _ex1;
+       }
+
+       // Leave it to multiplication since dummy indices have to be renamed
+       if (get_all_dummy_indices(m).size() > 0) {
+               ex result = m;
+               for (int i=1; i < n.to_int(); i++)
+                       result *= rename_dummy_indices_uniquely(m,m);
+               return result;
+       }
 
        epvector distrseq;
        distrseq.reserve(m.seq.size());