X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Finifcns_trans.cpp;h=81f92a93aca908aa6f698e79dd1a4380d5998d61;hp=12fabc0e98499ea5e4c11ff196f753b6d32b3872;hb=82c60cc9f90e6045e75e4aa4c48b29bcd7c5331f;hpb=f293ecba8b6026a7754795256b2f23910bf70507 diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index 12fabc0e..81f92a93 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -109,16 +109,16 @@ static ex log_evalf(const ex & x) static ex log_eval(const ex & x) { if (x.info(info_flags::numeric)) { + if (x.is_equal(_ex0())) // log(0) -> infinity + throw(std::domain_error("log_eval(): log(0)")); + if (x.info(info_flags::real) && x.info(info_flags::negative)) + return (log(-x)+I*Pi); if (x.is_equal(_ex1())) // log(1) -> 0 return _ex0(); - if (x.is_equal(_ex_1())) // log(-1) -> I*Pi - return (I*Pi); if (x.is_equal(I)) // log(I) -> Pi*I/2 return (Pi*I*_num1_2()); if (x.is_equal(-I)) // log(-I) -> -Pi*I/2 return (Pi*I*_num_1_2()); - if (x.is_equal(_ex0())) // log(0) -> infinity - throw(std::domain_error("log_eval(): log(0)")); // log(float) if (!x.info(info_flags::crational)) return log_evalf(x); @@ -139,19 +139,31 @@ static ex log_eval(const ex & x) static ex log_deriv(const ex & x, unsigned deriv_param) { GINAC_ASSERT(deriv_param==0); - + // d/dx log(x) -> 1/x return power(x, _ex_1()); } -static ex log_series(const ex &x, const relational &r, int order) +static ex log_series(const ex &x, const relational &rel, int order) { - if (x.subs(r).is_zero()) { - epvector seq; - seq.push_back(expair(log(x), _ex0())); - return pseries(r, seq); - } else - throw do_taylor(); + const ex x_pt = x.subs(rel); + if (!x_pt.info(info_flags::negative) && !x_pt.is_zero()) + throw do_taylor(); // caught by function::series() + // now we either have to care for the branch cut or the branch point: + if (x_pt.is_zero()) { // branch point: return a plain log(x). + epvector seq; + seq.push_back(expair(log(x), _ex0())); + return pseries(rel, seq); + } // on the branch cut: + const ex point = rel.rhs(); + const symbol *s = static_cast(rel.lhs().bp); + const symbol foo; + // compute the formal series: + ex replx = series(log(x),*s==foo,order).subs(foo==point); + epvector seq; + seq.push_back(expair(-I*csgn(x*I)*Pi,_ex0())); + seq.push_back(expair(Order(_ex1()),order)); + return series(replx - I*Pi + pseries(rel, seq),rel,order); } REGISTER_FUNCTION(log, eval_func(log_eval). @@ -363,7 +375,7 @@ static ex tan_eval(const ex & x) if (z.is_equal(_num25())) // tan(5/12*Pi) -> 2+sqrt(3) return sign*(power(_ex3(),_ex1_2())+_ex2()); if (z.is_equal(_num30())) // tan(Pi/2) -> infinity - throw (std::domain_error("tan_eval(): infinity")); + throw (std::domain_error("tan_eval(): simple pole")); } if (is_ex_exactly_of_type(x, function)) { @@ -395,16 +407,16 @@ static ex tan_deriv(const ex & x, unsigned deriv_param) return (_ex1()+power(tan(x),_ex2())); } -static ex tan_series(const ex &x, const relational &r, int order) +static ex tan_series(const ex &x, const relational &rel, int order) { // method: // Taylor series where there is no pole falls back to tan_deriv. // On a pole simply expand sin(x)/cos(x). - const ex x_pt = x.subs(r); + const ex x_pt = x.subs(rel); if (!(2*x_pt/Pi).info(info_flags::odd)) throw do_taylor(); // caught by function::series() // if we got here we have to care for a simple pole - return (sin(x)/cos(x)).series(r, order+2); + return (sin(x)/cos(x)).series(rel, order+2); } REGISTER_FUNCTION(tan, eval_func(tan_eval). @@ -752,16 +764,16 @@ static ex tanh_deriv(const ex & x, unsigned deriv_param) return _ex1()-power(tanh(x),_ex2()); } -static ex tanh_series(const ex &x, const relational &r, int order) +static ex tanh_series(const ex &x, const relational &rel, int order) { // method: // Taylor series where there is no pole falls back to tanh_deriv. // On a pole simply expand sinh(x)/cosh(x). - const ex x_pt = x.subs(r); + const ex x_pt = x.subs(rel); if (!(2*I*x_pt/Pi).info(info_flags::odd)) throw do_taylor(); // caught by function::series() // if we got here we have to care for a simple pole - return (sinh(x)/cosh(x)).series(r, order+2); + return (sinh(x)/cosh(x)).series(rel, order+2); } REGISTER_FUNCTION(tanh, eval_func(tanh_eval). @@ -873,8 +885,8 @@ static ex atanh_eval(const ex & x) if (x.is_zero()) return _ex0(); // atanh({+|-}1) -> throw - if (x.is_equal(_ex1()) || x.is_equal(_ex1())) - throw (std::domain_error("atanh_eval(): infinity")); + if (x.is_equal(_ex1()) || x.is_equal(_ex_1())) + throw (std::domain_error("atanh_eval(): logarithmic pole")); // atanh(float) -> float if (!x.info(info_flags::crational)) return atanh_evalf(x);