X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Finifcns.cpp;h=677d92f61925a47a10599375a72ae16e0f7be817;hp=e0d1e91edcaa0520ce5f94c017dff93e3e67a8a2;hb=db5765dc91202851739e196ba11bfccb0b3fe7bc;hpb=fe9dbfb9947b24149b3ce7dd9285f27ab286cbd7 diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index e0d1e91e..677d92f6 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -45,21 +45,21 @@ namespace GiNaC { // absolute value ////////// -static ex abs_evalf(const ex & x) +static ex abs_evalf(const ex & arg) { BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(abs(x)) + TYPECHECK(arg,numeric) + END_TYPECHECK(abs(arg)) - return abs(ex_to_numeric(x)); + return abs(ex_to_numeric(arg)); } -static ex abs_eval(const ex & x) +static ex abs_eval(const ex & arg) { - if (is_ex_exactly_of_type(x, numeric)) - return abs(ex_to_numeric(x)); + if (is_ex_exactly_of_type(arg, numeric)) + return abs(ex_to_numeric(arg)); else - return abs(x).hold(); + return abs(arg).hold(); } REGISTER_FUNCTION(abs, eval_func(abs_eval). @@ -70,41 +70,41 @@ REGISTER_FUNCTION(abs, eval_func(abs_eval). // Complex sign ////////// -static ex csgn_evalf(const ex & x) +static ex csgn_evalf(const ex & arg) { BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(csgn(x)) + TYPECHECK(arg,numeric) + END_TYPECHECK(csgn(arg)) - return csgn(ex_to_numeric(x)); + return csgn(ex_to_numeric(arg)); } -static ex csgn_eval(const ex & x) +static ex csgn_eval(const ex & arg) { - if (is_ex_exactly_of_type(x, numeric)) - return csgn(ex_to_numeric(x)); + if (is_ex_exactly_of_type(arg, numeric)) + return csgn(ex_to_numeric(arg)); - else if (is_ex_exactly_of_type(x, mul)) { - numeric oc = ex_to_numeric(x.op(x.nops()-1)); + else if (is_ex_exactly_of_type(arg, mul)) { + numeric oc = ex_to_numeric(arg.op(arg.nops()-1)); if (oc.is_real()) { if (oc > 0) // csgn(42*x) -> csgn(x) - return csgn(x/oc).hold(); + return csgn(arg/oc).hold(); else // csgn(-42*x) -> -csgn(x) - return -csgn(x/oc).hold(); + return -csgn(arg/oc).hold(); } if (oc.real().is_zero()) { if (oc.imag() > 0) // csgn(42*I*x) -> csgn(I*x) - return csgn(I*x/oc).hold(); + return csgn(I*arg/oc).hold(); else // csgn(-42*I*x) -> -csgn(I*x) - return -csgn(I*x/oc).hold(); + return -csgn(I*arg/oc).hold(); } } - return csgn(x).hold(); + return csgn(arg).hold(); } static ex csgn_series(const ex & arg, @@ -113,13 +113,10 @@ static ex csgn_series(const ex & arg, unsigned options) { const ex arg_pt = arg.subs(rel); - if (arg_pt.info(info_flags::numeric)) { - if (ex_to_numeric(arg_pt).real().is_zero()) - throw (std::domain_error("csgn_series(): on imaginary axis")); - epvector seq; - seq.push_back(expair(csgn(arg_pt), _ex0())); - return pseries(rel,seq); - } + if (arg_pt.info(info_flags::numeric) && + ex_to_numeric(arg_pt).real().is_zero()) + throw (std::domain_error("csgn_series(): on imaginary axis")); + epvector seq; seq.push_back(expair(csgn(arg_pt), _ex0())); return pseries(rel,seq); @@ -129,6 +126,61 @@ REGISTER_FUNCTION(csgn, eval_func(csgn_eval). evalf_func(csgn_evalf). series_func(csgn_series)); + +////////// +// Eta function: log(x*y) == log(x) + log(y) + eta(x,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)); +} + +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)) { + // 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)); + } + + return eta(x,y).hold(); +} + +static ex eta_series(const ex & arg1, + const ex & arg2, + 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")); + } + epvector seq; + seq.push_back(expair(eta(arg1_pt,arg2_pt), _ex0())); + return pseries(rel,seq); +} + +REGISTER_FUNCTION(eta, eval_func(eta_eval). + evalf_func(eta_evalf). + series_func(eta_series)); + + ////////// // dilogarithm ////////// @@ -325,21 +377,19 @@ REGISTER_FUNCTION(binomial, eval_func(binomial_eval). static ex Order_eval(const ex & x) { - if (is_ex_exactly_of_type(x, numeric)) { - - // O(c)=O(1) - return Order(_ex1()).hold(); - - } else if (is_ex_exactly_of_type(x, mul)) { - - mul *m = static_cast(x.bp); - if (is_ex_exactly_of_type(m->op(m->nops() - 1), numeric)) { - - // O(c*expr)=O(expr) - return Order(x / m->op(m->nops() - 1)).hold(); - } - } - return Order(x).hold(); + if (is_ex_exactly_of_type(x, numeric)) { + // O(c) -> O(1) or 0 + if (!x.is_zero()) + return Order(_ex1()).hold(); + else + return _ex0(); + } else if (is_ex_exactly_of_type(x, mul)) { + mul *m = static_cast(x.bp); + // O(c*expr) -> O(expr) + if (is_ex_exactly_of_type(m->op(m->nops() - 1), numeric)) + return Order(x / m->op(m->nops() - 1)).hold(); + } + return Order(x).hold(); } static ex Order_series(const ex & x, const relational & r, int order, unsigned options) @@ -383,7 +433,7 @@ ex lsolve(const ex &eqns, const ex &symbols) // solve a system of linear equations if (eqns.info(info_flags::relation_equal)) { if (!symbols.info(info_flags::symbol)) - throw(std::invalid_argument("lsolve: 2nd argument must be a symbol")); + throw(std::invalid_argument("lsolve(): 2nd argument must be a symbol")); ex sol=lsolve(lst(eqns),lst(symbols)); GINAC_ASSERT(sol.nops()==1); @@ -394,19 +444,19 @@ ex lsolve(const ex &eqns, const ex &symbols) // syntax checks if (!eqns.info(info_flags::list)) { - throw(std::invalid_argument("lsolve: 1st argument must be a list")); + throw(std::invalid_argument("lsolve(): 1st argument must be a list")); } for (unsigned i=0; i