X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Finifcns.cpp;h=f7d2864ef9ae64035eae269d140b6c36b6d41169;hp=b3527e9c5a06475e1ec721080a35e9c0a805e9e6;hb=af0c47009ca7a15af966430bdf1a72fe05c1c6f9;hpb=5184d67c0ec1056ac039419e08558632793a4e2c;ds=sidebyside diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index b3527e9c..f7d2864e 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -62,9 +62,70 @@ static ex abs_eval(const ex & x) return abs(x).hold(); } -REGISTER_FUNCTION(abs, evalf_func(abs_eval). +REGISTER_FUNCTION(abs, eval_func(abs_eval). evalf_func(abs_evalf)); + +////////// +// Complex sign +////////// + +static ex csgn_evalf(const ex & x) +{ + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(csgn(x)) + + return csgn(ex_to_numeric(x)); +} + +static ex csgn_eval(const ex & x) +{ + if (is_ex_exactly_of_type(x, numeric)) + return csgn(ex_to_numeric(x)); + + if (is_ex_exactly_of_type(x, mul)) { + numeric oc = ex_to_numeric(x.op(x.nops()-1)); + if (oc.is_real()) { + if (oc > 0) + // csgn(42*x) -> csgn(x) + return csgn(x/oc).hold(); + else + // csgn(-42*x) -> -csgn(x) + return -csgn(x/oc).hold(); + } + if (oc.real().is_zero()) { + if (oc.imag() > 0) + // csgn(42*I*x) -> csgn(I*x) + return csgn(I*x/oc).hold(); + else + // csgn(-42*I*x) -> -csgn(I*x) + return -csgn(I*x/oc).hold(); + } + } + + return csgn(x).hold(); +} + +static ex csgn_series(const ex & x, const relational & rel, int order) +{ + const ex x_pt = x.subs(rel); + if (x_pt.info(info_flags::numeric)) { + if (ex_to_numeric(x_pt).real().is_zero()) + throw (std::domain_error("csgn_series(): on imaginary axis")); + epvector seq; + seq.push_back(expair(csgn(x_pt), _ex0())); + return pseries(rel,seq); + } + epvector seq; + seq.push_back(expair(csgn(x_pt), _ex0())); + return pseries(rel,seq); +} + +REGISTER_FUNCTION(csgn, eval_func(csgn_eval). + evalf_func(csgn_evalf). + series_func(csgn_series)); + ////////// // dilogarithm ////////// @@ -158,17 +219,38 @@ static ex Order_eval(const ex & x) return Order(x).hold(); } -static ex Order_series(const ex & x, const symbol & s, const ex & point, int order) +static ex Order_series(const ex & x, const relational & r, int order) { // Just wrap the function into a pseries object epvector new_seq; - new_seq.push_back(expair(Order(_ex1()), numeric(min(x.ldegree(s), order)))); - return pseries(s, point, new_seq); + GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); + const symbol *s = static_cast(r.lhs().bp); + new_seq.push_back(expair(Order(_ex1()), numeric(min(x.ldegree(*s), order)))); + return pseries(r, new_seq); } +// Differentiation is handled in function::derivative because of its special requirements + REGISTER_FUNCTION(Order, eval_func(Order_eval). series_func(Order_series)); +////////// +// 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 ////////// @@ -212,10 +294,10 @@ ex lsolve(const ex &eqns, const ex &symbols) matrix vars(symbols.nops(),1); for (unsigned r=0; r