]> www.ginac.de Git - ginac.git/blobdiff - ginac/inifcns.cpp
- symmetrize eta(x,y).
[ginac.git] / ginac / inifcns.cpp
index 0daa97989abf8260202a0db99cfb572f576379ec..c18f4c6385c8a3500dac0ca4700b88de2c64d4fa 100644 (file)
 #include "lst.h"
 #include "matrix.h"
 #include "mul.h"
-#include "ncmul.h"
-#include "numeric.h"
 #include "power.h"
 #include "relational.h"
 #include "pseries.h"
 #include "symbol.h"
+#include "symmetry.h"
 #include "utils.h"
 
 namespace GiNaC {
@@ -49,13 +48,13 @@ static ex abs_evalf(const ex & arg)
                TYPECHECK(arg,numeric)
        END_TYPECHECK(abs(arg))
        
-       return abs(ex_to_numeric(arg));
+       return abs(ex_to<numeric>(arg));
 }
 
 static ex abs_eval(const ex & arg)
 {
        if (is_ex_exactly_of_type(arg, numeric))
-               return abs(ex_to_numeric(arg));
+               return abs(ex_to<numeric>(arg));
        else
                return abs(arg).hold();
 }
@@ -74,16 +73,17 @@ static ex csgn_evalf(const ex & arg)
                TYPECHECK(arg,numeric)
        END_TYPECHECK(csgn(arg))
        
-       return csgn(ex_to_numeric(arg));
+       return csgn(ex_to<numeric>(arg));
 }
 
 static ex csgn_eval(const ex & arg)
 {
        if (is_ex_exactly_of_type(arg, numeric))
-               return csgn(ex_to_numeric(arg));
+               return csgn(ex_to<numeric>(arg));
        
-       else if (is_ex_exactly_of_type(arg, mul)) {
-               numeric oc = ex_to_numeric(arg.op(arg.nops()-1));
+       else if (is_ex_of_type(arg, mul) &&
+                is_ex_of_type(arg.op(arg.nops()-1),numeric)) {
+               numeric oc = ex_to<numeric>(arg.op(arg.nops()-1));
                if (oc.is_real()) {
                        if (oc > 0)
                                // csgn(42*x) -> csgn(x)
@@ -101,7 +101,7 @@ static ex csgn_eval(const ex & arg)
                                return -csgn(I*arg/oc).hold();
                }
        }
-   
+       
        return csgn(arg).hold();
 }
 
@@ -112,7 +112,7 @@ static ex csgn_series(const ex & arg,
 {
        const ex arg_pt = arg.subs(rel);
        if (arg_pt.info(info_flags::numeric)
-           && ex_to_numeric(arg_pt).real().is_zero()
+           && ex_to<numeric>(arg_pt).real().is_zero()
            && !(options & series_options::suppress_branchcut))
                throw (std::domain_error("csgn_series(): on imaginary axis"));
        
@@ -127,58 +127,80 @@ REGISTER_FUNCTION(csgn, eval_func(csgn_eval).
 
 
 //////////
-// Eta function: log(x*y) == log(x) + log(y) + eta(x,y).
+// Eta function: eta(x,y) == log(x*y) - log(x) - log(y).
 //////////
 
-static ex eta_evalf(const ex & x, const ex & y)
+static ex eta_evalf(const ex &x, const ex &y)
 {
-       BEGIN_TYPECHECK
-               TYPECHECK(x,numeric)
-               TYPECHECK(y,numeric)
-       END_TYPECHECK(eta(x,y))
-               
-       numeric xim = imag(ex_to_numeric(x));
-       numeric yim = imag(ex_to_numeric(y));
-       numeric xyim = imag(ex_to_numeric(x*y));
-       return evalf(I/4*Pi)*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1));
+       // It seems like we basically have to replicate the eval function here,
+       // since the expression might not be fully evaluated yet.
+       if (x.info(info_flags::positive) || y.info(info_flags::positive))
+               return _ex0();
+
+       if (x.info(info_flags::numeric) &&      y.info(info_flags::numeric)) {
+               const numeric nx = ex_to<numeric>(x);
+               const numeric ny = ex_to<numeric>(y);
+               const numeric nxy = ex_to<numeric>(x*y);
+               int cut = 0;
+               if (nx.is_real() && nx.is_negative())
+                       cut -= 4;
+               if (ny.is_real() && ny.is_negative())
+                       cut -= 4;
+               if (nxy.is_real() && nxy.is_negative())
+                       cut += 4;
+               return evalf(I/4*Pi)*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
+                                     (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
+       }
+
+       return eta(x,y).hold();
 }
 
-static ex eta_eval(const ex & x, const ex & y)
+static ex eta_eval(const ex &x, const ex &y)
 {
-       if (is_ex_exactly_of_type(x, numeric) &&
-               is_ex_exactly_of_type(y, numeric)) {
+       // trivial:  eta(x,c) -> 0  if c is real and positive
+       if (x.info(info_flags::positive) || y.info(info_flags::positive))
+               return _ex0();
+
+       if (x.info(info_flags::numeric) &&      y.info(info_flags::numeric)) {
                // don't call eta_evalf here because it would call Pi.evalf()!
-               numeric xim = imag(ex_to_numeric(x));
-               numeric yim = imag(ex_to_numeric(y));
-               numeric xyim = imag(ex_to_numeric(x*y));
-               return (I/4)*Pi*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1));
+               const numeric nx = ex_to<numeric>(x);
+               const numeric ny = ex_to<numeric>(y);
+               const numeric nxy = ex_to<numeric>(x*y);
+               int cut = 0;
+               if (nx.is_real() && nx.is_negative())
+                       cut -= 4;
+               if (ny.is_real() && ny.is_negative())
+                       cut -= 4;
+               if (nxy.is_real() && nxy.is_negative())
+                       cut += 4;
+               return (I/4)*Pi*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
+                                (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
        }
        
        return eta(x,y).hold();
 }
 
-static ex eta_series(const ex & arg1,
-                     const ex & arg2,
+static ex eta_series(const ex & x, const ex & y,
                      const relational & rel,
                      int order,
                      unsigned options)
 {
-       const ex arg1_pt = arg1.subs(rel);
-       const ex arg2_pt = arg2.subs(rel);
-       if (ex_to_numeric(arg1_pt).imag().is_zero() ||
-               ex_to_numeric(arg2_pt).imag().is_zero() ||
-               ex_to_numeric(arg1_pt*arg2_pt).imag().is_zero()) {
-               throw (std::domain_error("eta_series(): on discontinuity"));
-       }
+       const ex x_pt = x.subs(rel);
+       const ex y_pt = y.subs(rel);
+       if ((x_pt.info(info_flags::numeric) && x_pt.info(info_flags::negative)) ||
+           (y_pt.info(info_flags::numeric) && y_pt.info(info_flags::negative)) ||
+           ((x_pt*y_pt).info(info_flags::numeric) && (x_pt*y_pt).info(info_flags::negative)))
+                       throw (std::domain_error("eta_series(): on discontinuity"));
        epvector seq;
-       seq.push_back(expair(eta(arg1_pt,arg2_pt), _ex0()));
+       seq.push_back(expair(eta(x_pt,y_pt), _ex0()));
        return pseries(rel,seq);
 }
 
 REGISTER_FUNCTION(eta, eval_func(eta_eval).
                        evalf_func(eta_evalf).
-                       series_func(eta_series).
-                       latex_name("\\eta"));
+                                      series_func(eta_series).
+                       latex_name("\\eta").
+                       set_symmetry(sy_symm(0, 1)));
 
 
 //////////
@@ -191,7 +213,7 @@ static ex Li2_evalf(const ex & x)
                TYPECHECK(x,numeric)
        END_TYPECHECK(Li2(x))
        
-       return Li2(ex_to_numeric(x));  // -> numeric Li2(numeric)
+       return Li2(ex_to<numeric>(x));  // -> numeric Li2(numeric)
 }
 
 static ex Li2_eval(const ex & x)
@@ -275,7 +297,7 @@ static ex Li2_series(const ex &x, const relational &rel, int order, unsigned opt
                        // method:
                        // construct series manually in a dummy symbol s
                        const symbol s;
-                       ex ser = zeta(2);
+                       ex ser = zeta(_ex2());
                        // manually construct the primitive expansion
                        for (int i=1; i<order; ++i)
                                ser += pow(1-s,i) * (numeric(1,i)*(I*Pi+log(s-1)) - numeric(1,i*i));
@@ -290,7 +312,7 @@ static ex Li2_series(const ex &x, const relational &rel, int order, unsigned opt
                }
                // third special case: x real, >=1 (branch cut)
                if (!(options & series_options::suppress_branchcut) &&
-                       ex_to_numeric(x_pt).is_real() && ex_to_numeric(x_pt)>1) {
+                       ex_to<numeric>(x_pt).is_real() && ex_to<numeric>(x_pt)>1) {
                        // method:
                        // This is the branch cut: assemble the primitive series manually
                        // and then add the corresponding complex step function.
@@ -345,7 +367,7 @@ static ex factorial_evalf(const ex & x)
 static ex factorial_eval(const ex & x)
 {
        if (is_ex_exactly_of_type(x, numeric))
-               return factorial(ex_to_numeric(x));
+               return factorial(ex_to<numeric>(x));
        else
                return factorial(x).hold();
 }
@@ -365,7 +387,7 @@ static ex binomial_evalf(const ex & x, const ex & y)
 static ex binomial_eval(const ex & x, const ex &y)
 {
        if (is_ex_exactly_of_type(x, numeric) && is_ex_exactly_of_type(y, numeric))
-               return binomial(ex_to_numeric(x), ex_to_numeric(y));
+               return binomial(ex_to<numeric>(x), ex_to<numeric>(y));
        else
                return binomial(x, y).hold();
 }
@@ -410,23 +432,6 @@ REGISTER_FUNCTION(Order, eval_func(Order_eval).
                          series_func(Order_series).
                          latex_name("\\mathcal{O}"));
 
-//////////
-// Inert partial differentiation operator
-//////////
-
-static ex Derivative_eval(const ex & f, const ex & l)
-{
-       if (!is_ex_exactly_of_type(f, function)) {
-               throw(std::invalid_argument("Derivative(): 1st argument must be a function"));
-       }
-       if (!is_ex_exactly_of_type(l, lst)) {
-               throw(std::invalid_argument("Derivative(): 2nd argument must be a list"));
-       }
-       return Derivative(f, l).hold();
-}
-
-REGISTER_FUNCTION(Derivative, eval_func(Derivative_eval));
-
 //////////
 // Solve linear system
 //////////
@@ -437,7 +442,7 @@ ex lsolve(const ex &eqns, const ex &symbols)
        if (eqns.info(info_flags::relation_equal)) {
                if (!symbols.info(info_flags::symbol))
                        throw(std::invalid_argument("lsolve(): 2nd argument must be a symbol"));
-               ex sol=lsolve(lst(eqns),lst(symbols));
+               const ex sol = lsolve(lst(eqns),lst(symbols));
                
                GINAC_ASSERT(sol.nops()==1);
                GINAC_ASSERT(is_ex_exactly_of_type(sol.op(0),relational));
@@ -469,20 +474,20 @@ ex lsolve(const ex &eqns, const ex &symbols)
        matrix vars(symbols.nops(),1);
        
        for (unsigned r=0; r<eqns.nops(); r++) {
-               ex eq = eqns.op(r).op(0)-eqns.op(r).op(1); // lhs-rhs==0
+               const ex eq = eqns.op(r).op(0)-eqns.op(r).op(1); // lhs-rhs==0
                ex linpart = eq;
                for (unsigned c=0; c<symbols.nops(); c++) {
-                       ex co = eq.coeff(ex_to_symbol(symbols.op(c)),1);
+                       const ex co = eq.coeff(ex_to<symbol>(symbols.op(c)),1);
                        linpart -= co*symbols.op(c);
-                       sys.set(r,c,co);
+                       sys(r,c) = co;
                }
                linpart = linpart.expand();
-               rhs.set(r,0,-linpart);
+               rhs(r,0) = -linpart;
        }
        
        // test if system is linear and fill vars matrix
        for (unsigned i=0; i<symbols.nops(); i++) {
-               vars.set(i,0,symbols.op(i));
+               vars(i,0) = symbols.op(i);
                if (sys.has(symbols.op(i)))
                        throw(std::logic_error("lsolve: system is not linear"));
                if (rhs.has(symbols.op(i)))
@@ -508,24 +513,8 @@ ex lsolve(const ex &eqns, const ex &symbols)
        return sollist;
 }
 
-/** non-commutative power. */
-ex ncpower(const ex &basis, unsigned exponent)
-{
-       if (exponent==0) {
-               return _ex1();
-       }
-
-       exvector v;
-       v.reserve(exponent);
-       for (unsigned i=0; i<exponent; ++i) {
-               v.push_back(basis);
-       }
-
-       return ncmul(v,1);
-}
-
-/** Force inclusion of functions from initcns_gamma and inifcns_zeta
- *  for static lib (so ginsh will see them). */
+/* Force inclusion of functions from inifcns_gamma and inifcns_zeta
+ * for static lib (so ginsh will see them). */
 unsigned force_include_tgamma = function_index_tgamma;
 unsigned force_include_zeta1 = function_index_zeta1;