- added ex::to_rational() to convert general expression to rational expression
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 6 Apr 2000 19:58:15 +0000 (19:58 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 6 Apr 2000 19:58:15 +0000 (19:58 +0000)
  by replacing all non-rational parts with temporary symbols, e.g.:
    ex a = pow(sin(x), 2) - pow(cos(x), 2);
    ex b = sin(x) + cos(x);
    ex d;
    lst l;
    divide(a.to_rational(l), b.to_rational(l), d);
    cout << d.subs(l) << endl;
  will print "sin(x)-cos(x)"

ginac/basic.h
ginac/ex.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/normal.cpp
ginac/normal.h
ginac/numeric.h
ginac/power.h
ginac/symbol.h

index 574fa37c006872c99c487186c1305fc3eb852c38..ed049eaf1b239159b2770a227ec7bd2766555d23 100644 (file)
@@ -141,6 +141,7 @@ public: // only const functions please (may break reference counting)
     virtual ex series(const relational & r, int order) const;
     virtual ex subs(const lst & ls, const lst & lr) const;
     virtual ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    virtual ex to_rational(lst &repl_lst) const;
     virtual numeric integer_content(void) const;
     virtual ex smod(const numeric &xi) const;
     virtual numeric max_coefficient(void) const;
index 9b1d0fa1e399142bf2f1db285bd9213c71849538..bf8d0d6f45edb04246c8f4594b7d4d35620253b0 100644 (file)
@@ -260,6 +260,7 @@ public:
     ex primpart(const symbol &x, const basic &cont) const { return primpart(x,ex(cont)); }
 #endif // def CINT_CONVERSION_WORKAROUND
     ex normal(int level = 0) const;
+    ex to_rational(lst &repl_lst) const;
     ex smod(const numeric &xi) const;
     numeric max_coefficient(void) const;
     ex collect(const symbol & s) const;
@@ -418,6 +419,9 @@ inline ex denom(const ex & thisex)
 inline ex normal(const ex & thisex, int level=0)
 { return thisex.normal(level); }
 
+inline ex to_rational(const ex & thisex, lst & repl_lst)
+{ return thisex.to_rational(repl_lst); }
+
 inline ex collect(const ex & thisex, const symbol & s)
 { return thisex.collect(s); }
 
index 5c72362bce96023a01733fec851c61e484bfabf0..d4e13188c21c5cff02bd8b1ae2d66e370d49e165 100644 (file)
@@ -361,6 +361,17 @@ ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const
     return n.bp->basic::normal(sym_lst,repl_lst,level);
 }
 
+ex expairseq::to_rational(lst &repl_lst) const
+{
+    epvector s;
+    s.reserve(seq.size());
+    for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
+        s.push_back(combine_ex_with_coeff_to_pair((*it).rest.to_rational(repl_lst),
+                                                  (*it).coeff));
+    }
+    return thisexpairseq(s, overall_coeff);
+}
+
 ex expairseq::subs(const lst & ls, const lst & lr) const
 {
     epvector * vp=subschildren(ls,lr);
index bcd2f66fa8896c7f322eece6c3172a8379cf98d9..6284ce28bee1459834e8cb29e9c53abe120687ab 100644 (file)
@@ -102,6 +102,7 @@ public:
     ex eval(int level=0) const;
     ex evalf(int level=0) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    ex to_rational(lst &repl_lst) const;
     ex subs(const lst & ls, const lst & lr) const;
 protected:
     ex derivative(const symbol & s) const;
index 7d6ddca7cf3f4da9f0d212aa3dc3ebcda1621d3f..a4681122a662a0b03cb0e333f024aa360bc9d7b2 100644 (file)
@@ -3,8 +3,7 @@
  *  This file implements several functions that work on univariate and
  *  multivariate polynomials and rational functions.
  *  These functions include polynomial quotient and remainder, GCD and LCM
- *  computation, square-free factorization and rational function normalization.
- */
+ *  computation, square-free factorization and rational function normalization. */
 
 /*
  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
@@ -1460,8 +1459,8 @@ ex sqrfree(const ex &a, const symbol &x)
  */
 
 /** Create a symbol for replacing the expression "e" (or return a previously
- *  assigned symbol). The symbol is appended to sym_list and returned, the
- *  expression is appended to repl_list.
+ *  assigned symbol). The symbol is appended to sym_lst and returned, the
+ *  expression is appended to repl_lst.
  *  @see ex::normal */
 static ex replace_with_symbol(const ex &e, lst &sym_lst, lst &repl_lst)
 {
@@ -1481,6 +1480,26 @@ static ex replace_with_symbol(const ex &e, lst &sym_lst, lst &repl_lst)
     return es;
 }
 
+/** Create a symbol for replacing the expression "e" (or return a previously
+ *  assigned symbol). An expression of the form "symbol == expression" is added
+ *  to repl_lst and the symbol is returned.
+ *  @see ex::to_rational */
+static ex replace_with_symbol(const ex &e, lst &repl_lst)
+{
+    // Expression already in repl_lst? Then return the assigned symbol
+    for (unsigned i=0; i<repl_lst.nops(); i++)
+        if (repl_lst.op(i).op(1).is_equal(e))
+            return repl_lst.op(i).op(0);
+
+    // Otherwise create new symbol and add to list, taking care that the
+       // replacement expression doesn't contain symbols from the sym_lst
+       // because subs() is not recursive
+       symbol s;
+       ex es(s);
+       ex e_replaced = e.subs(repl_lst);
+    repl_lst.append(es == e_replaced);
+    return es;
+}
 
 /** Default implementation of ex::normal(). It replaces the object with a
  *  temporary symbol.
@@ -1747,8 +1766,8 @@ ex pseries::normal(lst &sym_lst, lst &repl_lst, int level) const
  *  This function converts an expression to its normal form
  *  "numerator/denominator", where numerator and denominator are (relatively
  *  prime) polynomials. Any subexpressions which are not rational functions
- *  (like non-rational numbers, non-integer powers or functions like Sin(),
- *  Cos() etc.) are replaced by temporary symbols which are re-substituted by
+ *  (like non-rational numbers, non-integer powers or functions like sin(),
+ *  cos() etc.) are replaced by temporary symbols which are re-substituted by
  *  the (normalized) subexpressions before normal() returns (this way, any
  *  expression can be treated as a rational function). normal() is applied
  *  recursively to arguments of functions etc.
@@ -1810,6 +1829,78 @@ ex ex::denom(void) const
                return e.op(1);
 }
 
+
+/** Default implementation of ex::to_rational(). It replaces the object with a
+ *  temporary symbol.
+ *  @see ex::to_rational */
+ex basic::to_rational(lst &repl_lst) const
+{
+       return replace_with_symbol(*this, repl_lst);
+}
+
+
+/** Implementation of ex::to_rational() for symbols. This returns the unmodified symbol.
+ *  @see ex::to_rational */
+ex symbol::to_rational(lst &repl_lst) const
+{
+    return *this;
+}
+
+
+/** Implementation of ex::to_rational() for a numeric. It splits complex numbers
+ *  into re+I*im and replaces I and non-rational real numbers with a temporary
+ *  symbol.
+ *  @see ex::to_rational */
+ex numeric::to_rational(lst &repl_lst) const
+{
+       numeric num = numer();
+       ex numex = num;
+
+    if (num.is_real()) {
+        if (!num.is_integer())
+            numex = replace_with_symbol(numex, repl_lst);
+    } else { // complex
+        numeric re = num.real(), im = num.imag();
+        ex re_ex = re.is_rational() ? re : replace_with_symbol(re, repl_lst);
+        ex im_ex = im.is_rational() ? im : replace_with_symbol(im, repl_lst);
+        numex = re_ex + im_ex * replace_with_symbol(I, repl_lst);
+    }
+       return numex;
+}
+
+
+/** Implementation of ex::to_rational() for powers. It replaces non-integer
+ *  powers by temporary symbols.
+ *  @see ex::to_rational */
+ex power::to_rational(lst &repl_lst) const
+{
+       if (exponent.info(info_flags::integer))
+               return power(basis.to_rational(repl_lst), exponent);
+       else
+               return replace_with_symbol(*this, repl_lst);
+}
+
+
+/** Rationalization of non-rational functions.
+ *  This function converts a general expression to a rational polynomial
+ *  by replacing all non-rational subexpressions (like non-rational numbers,
+ *  non-integer powers or functions like sin(), cos() etc.) to temporary
+ *  symbols. This makes it possible to use functions like gcd() and divide()
+ *  on non-rational functions by applying to_rational() on the arguments,
+ *  calling the desired function and re-substituting the temporary symbols
+ *  in the result. To make the last step possible, all temporary symbols and
+ *  their associated expressions are collected in the list specified by the
+ *  repl_lst parameter in the form {symbol == expression}, ready to be passed
+ *  as an argument to ex::subs().
+ *
+ *  @param repl_lst collects a list of all temporary symbols and their replacements
+ *  @return rationalized expression */
+ex ex::to_rational(lst &repl_lst) const
+{
+       return bp->to_rational(repl_lst);
+}
+
+
 #ifndef NO_NAMESPACE_GINAC
 } // namespace GiNaC
 #endif // ndef NO_NAMESPACE_GINAC
index f3e8920dbea4a1e1454d5fb7a592af42f150826f..25a1743bb6f15f4edb921d9769ca532488fdde47 100644 (file)
@@ -1,7 +1,9 @@
 /** @file normal.h
  *
- *  Functions for polynomial quotient and remainder, GCD and LCM computation
- *  and square-free factorization. */
+ *  This file defines several functions that work on univariate and
+ *  multivariate polynomials and rational functions.
+ *  These functions include polynomial quotient and remainder, GCD and LCM
+ *  computation, square-free factorization and rational function normalization. */
 
 /*
  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
index 0c729c683156c32ba48e2c53382e4f556268ac1d..51ee5e8f9b6a8c5d67f473962292b74dbafb2b86 100644 (file)
@@ -132,6 +132,7 @@ public:
     ex eval(int level=0) const;
     ex evalf(int level=0) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    ex to_rational(lst &repl_lst) const;
     numeric integer_content(void) const;
     ex smod(const numeric &xi) const;
     numeric max_coefficient(void) const;
index afb5b0940835aa265d08e06f961a7c9a5dfcfa0b..b4faa178a6daadfe8a708c218ab375e4023cb5a2 100644 (file)
@@ -76,6 +76,7 @@ public:
     ex series(const relational & s, int order) const;
     ex subs(const lst & ls, const lst & lr) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    ex to_rational(lst &repl_lst) const;
     ex simplify_ncmul(const exvector & v) const;
 protected:
     ex derivative(const symbol & s) const;
index 3a81f55d68f2e2bd52925c0117a26dea1928d97b..d2bc6792b2ba91ab0739bd75da8d7d5ac0762b7f 100644 (file)
@@ -83,6 +83,7 @@ public:
     ex eval(int level = 0) const;
     ex series(const relational & s, int order) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    ex to_rational(lst &repl_lst) const;
     ex subs(const lst & ls, const lst & lr) const;
 protected:
     ex derivative(const symbol & s) const;