]> www.ginac.de Git - ginac.git/blobdiff - ginac/inifcns.cpp
- symmetrize eta(x,y).
[ginac.git] / ginac / inifcns.cpp
index 7ac21530cc820c2fa98a8a400d46b714ce32aa33..c18f4c6385c8a3500dac0ca4700b88de2c64d4fa 100644 (file)
@@ -33,6 +33,7 @@
 #include "relational.h"
 #include "pseries.h"
 #include "symbol.h"
+#include "symmetry.h"
 #include "utils.h"
 
 namespace GiNaC {
@@ -126,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)));
 
 
 //////////
@@ -274,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));
@@ -409,44 +432,6 @@ REGISTER_FUNCTION(Order, eval_func(Order_eval).
                          series_func(Order_series).
                          latex_name("\\mathcal{O}"));
 
-//////////
-// Inert partial differentiation operator
-//////////
-
-ex Derivative_eval(const ex & f, const ex & l)
-{
-       if (!is_ex_of_type(f, function))
-               throw(std::invalid_argument("Derivative(): 1st argument must be a function"));
-       if (!is_ex_of_type(l, lst))
-               throw(std::invalid_argument("Derivative(): 2nd argument must be a list"));
-
-#if 0
-       // Perform differentiations if possible
-       const function &fcn = ex_to<function>(f);
-       if (fcn.registered_functions()[fcn.get_serial()].has_derivative() && l.nops() > 0) {
-
-               // The function actually seems to have a derivative, let's calculate it
-               ex d = fcn.pderivative(ex_to_numeric(l.op(0)).to_int());
-
-               // If this was the last differentiation, return the result
-               if (l.nops() == 1)
-                       return d;
-
-               // Otherwise recursively continue as long as the derivative is still
-               // a function
-               if (is_ex_of_type(d, function)) {
-                       lst l_copy = ex_to<lst>(l);
-                       l_copy.remove_first();
-                       return Derivative(d, l_copy);
-               }
-       }
-#endif
-       return Derivative(f, l).hold();
-}
-
-REGISTER_FUNCTION(Derivative, eval_func(Derivative_eval).
-                              latex_name("\\mathrm{D}"));
-
 //////////
 // Solve linear system
 //////////
@@ -457,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));
@@ -489,10 +474,10 @@ 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(r,c) = co;
                }