]> www.ginac.de Git - ginac.git/blobdiff - ginac/power.cpp
info_flags::expanded added [A.Sheplyakov]
[ginac.git] / ginac / power.cpp
index 9e720b70b04280a150de8d6ab99e6932f4d39699..faaef1842d6e085faa12288448a0231cbb1733b2 100644 (file)
@@ -231,6 +231,8 @@ bool power::info(unsigned inf) const
                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);
 }
@@ -467,8 +469,9 @@ 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_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));
+                               }
                        }
                }
        
@@ -476,7 +479,31 @@ ex power::eval(int level) const
                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)) {
+                       const 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 (icont != *_num1_p) {
+                               return (new mul(power(ebasis/icont, *num_exponent), power(icont, *num_exponent))
+                                      )->setflag(status_flags::dynallocated);
+                       }
+
+                       if (canonicalizable && (! unit_normal)) {
+                               if (num_exponent->is_even()) {
+                                       return power(-ebasis, *num_exponent);
+                               } else {
+                                       return (new mul(power(-ebasis, *num_exponent), *_num_1_p)
+                                              )->setflag(status_flags::dynallocated);
+                               }
+                       }
+               }
+
                // ^(*(...,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)) {
@@ -943,7 +970,7 @@ ex power::expand_add_2(const add & a, unsigned options) const
        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
 {