]> www.ginac.de Git - ginac.git/blobdiff - ginac/mul.cpp
Changed naming convention for the library. Now, it is only libginac.so
[ginac.git] / ginac / mul.cpp
index ad31139873cee8f2adc91a6b11681d55c75a653d..27add930cf56863ae7d635d3031e4dc2b1d7ea9f 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's products of expressions. */
 
 /*
- *  GiNaC Copyright (C) 1999-2008 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2011 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
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <iostream>
-#include <vector>
-#include <stdexcept>
-#include <limits>
-
 #include "mul.h"
 #include "add.h"
 #include "power.h"
 #include "symbol.h"
 #include "compiler.h"
 
+#include <iostream>
+#include <limits>
+#include <stdexcept>
+#include <vector>
+
 namespace GiNaC {
 
 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mul, expairseq,
@@ -113,8 +113,6 @@ mul::mul(const ex & lh, const ex & mh, const ex & rh)
 // archiving
 //////////
 
-DEFAULT_ARCHIVING(mul)
-
 //////////
 // functions overriding virtual functions from base classes
 //////////
@@ -280,6 +278,16 @@ bool mul::info(unsigned inf) const
                case info_flags::integer_polynomial:
                case info_flags::cinteger_polynomial:
                case info_flags::rational_polynomial:
+               case info_flags::real:
+               case info_flags::rational:
+               case info_flags::integer:
+               case info_flags::crational:
+               case info_flags::cinteger:
+               case info_flags::positive:
+               case info_flags::nonnegative:
+               case info_flags::posint:
+               case info_flags::nonnegint:
+               case info_flags::even:
                case info_flags::crational_polynomial:
                case info_flags::rational_function: {
                        epvector::const_iterator i = seq.begin(), end = seq.end();
@@ -288,6 +296,8 @@ bool mul::info(unsigned inf) const
                                        return false;
                                ++i;
                        }
+                       if (overall_coeff.is_equal(*_num1_p) && inf == info_flags::even)
+                               return true;
                        return overall_coeff.info(inf);
                }
                case info_flags::algebraic: {
@@ -299,10 +309,55 @@ bool mul::info(unsigned inf) const
                        }
                        return false;
                }
+               case info_flags::negative: {
+                       bool neg = false;
+                       epvector::const_iterator i = seq.begin(), end = seq.end();
+                       while (i != end) {
+                               const ex& factor = recombine_pair_to_ex(*i++);
+                               if (factor.info(info_flags::positive))
+                                       continue;
+                               else if (factor.info(info_flags::negative))
+                                       neg = !neg;
+                               else
+                                       return false;
+                       }
+                       if (overall_coeff.info(info_flags::negative))
+                               neg = !neg;
+                       return neg;
+               }
+               case info_flags::negint: {
+                       bool neg = false;
+                       epvector::const_iterator i = seq.begin(), end = seq.end();
+                       while (i != end) {
+                               const ex& factor = recombine_pair_to_ex(*i++);
+                               if (factor.info(info_flags::posint))
+                                       continue;
+                               else if (factor.info(info_flags::negint))
+                                       neg = !neg;
+                               else
+                                       return false;
+                       }
+                       if (overall_coeff.info(info_flags::negint))
+                               neg = !neg;
+                       else if (!overall_coeff.info(info_flags::posint))
+                               return false;
+                       return neg;
+               }
        }
        return inherited::info(inf);
 }
 
+bool mul::is_polynomial(const ex & var) const
+{
+       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+               if (!i->rest.is_polynomial(var) ||
+                   (i->rest.has(var) && !i->coeff.info(info_flags::integer))) {
+                       return false;
+               }
+       }
+       return true;
+}
+
 int mul::degree(const ex & s) const
 {
        // Sum up degrees of factors
@@ -685,7 +740,10 @@ bool algebraic_match_mul_with_mul(const mul &e, const ex &pat, exmap& repls,
                int factor, int &nummatches, const std::vector<bool> &subsed,
                std::vector<bool> &matched)
 {
-       if (factor == pat.nops())
+       GINAC_ASSERT(subsed.size() == e.nops());
+       GINAC_ASSERT(matched.size() == e.nops());
+
+       if (factor == (int)pat.nops())
                return true;
 
        for (size_t i=0; i<e.nops(); ++i) {
@@ -716,8 +774,8 @@ bool mul::has(const ex & pattern, unsigned options) const
        if(is_a<mul>(pattern)) {
                exmap repls;
                int nummatches = std::numeric_limits<int>::max();
-               std::vector<bool> subsed(seq.size(), false);
-               std::vector<bool> matched(seq.size(), false);
+               std::vector<bool> subsed(nops(), false);
+               std::vector<bool> matched(nops(), false);
                if(algebraic_match_mul_with_mul(*this, pattern, repls, 0, nummatches,
                                subsed, matched))
                        return true;
@@ -727,8 +785,7 @@ bool mul::has(const ex & pattern, unsigned options) const
 
 ex mul::algebraic_subs_mul(const exmap & m, unsigned options) const
 {      
-       std::vector<bool> subsed(seq.size(), false);
-       exvector subsresult(seq.size());
+       std::vector<bool> subsed(nops(), false);
        ex divide_by = 1;
        ex multiply_by = 1;
 
@@ -737,7 +794,7 @@ ex mul::algebraic_subs_mul(const exmap & m, unsigned options) const
                if (is_exactly_a<mul>(it->first)) {
 retry1:
                        int nummatches = std::numeric_limits<int>::max();
-                       std::vector<bool> currsubsed(seq.size(), false);
+                       std::vector<bool> currsubsed(nops(), false);
                        exmap repls;
                        
                        if(!algebraic_match_mul_with_mul(*this, it->first, repls, 0, nummatches, subsed, currsubsed))
@@ -785,6 +842,38 @@ retry1:
        return ((*this)/divide_by)*multiply_by;
 }
 
+ex mul::conjugate() const
+{
+       // The base class' method is wrong here because we have to be careful at
+       // branch cuts. power::conjugate takes care of that already, so use it.
+       epvector *newepv = 0;
+       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+               if (newepv) {
+                       newepv->push_back(split_ex_to_pair(recombine_pair_to_ex(*i).conjugate()));
+                       continue;
+               }
+               ex x = recombine_pair_to_ex(*i);
+               ex c = x.conjugate();
+               if (c.is_equal(x)) {
+                       continue;
+               }
+               newepv = new epvector;
+               newepv->reserve(seq.size());
+               for (epvector::const_iterator j=seq.begin(); j!=i; ++j) {
+                       newepv->push_back(*j);
+               }
+               newepv->push_back(split_ex_to_pair(c));
+       }
+       ex x = overall_coeff.conjugate();
+       if (!newepv && are_ex_trivially_equal(x, overall_coeff)) {
+               return *this;
+       }
+       ex result = thisexpairseq(newepv ? *newepv : seq, x);
+       delete newepv;
+       return result;
+}
+
+
 // protected
 
 /** Implementation of ex::diff() for a product.  It applies the product rule.
@@ -1210,4 +1299,6 @@ std::auto_ptr<epvector> mul::expandchildren(unsigned options) const
        return std::auto_ptr<epvector>(0); // nothing has changed
 }
 
+GINAC_BIND_UNARCHIVER(mul);
+
 } // namespace GiNaC