From 88cb1bc239cf2e52038a5111ba39117ce23093bb Mon Sep 17 00:00:00 2001 From: "Vladimir V. Kisil" Date: Sun, 11 Oct 2020 18:33:32 +0200 Subject: [PATCH] [PATCH 1/3] Automatic evaluation of (e^t)^s = e^(ts). If it safe to evaluate (e^t)^s = e^(ts) at least in two cases: a) t and s are reals, the respective formula can be found in any analysis textbook. b) if s is an integer, then the ambiguity of t up to the term 2*Pi*k does not cause a different value. Signed-off-by: Vladimir V. Kisil --- check/exam_misc.cpp | 24 ++++++++++++++++++++++++ ginac/inifcns_trans.cpp | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/check/exam_misc.cpp b/check/exam_misc.cpp index 93b6f8e7..8c28fb53 100644 --- a/check/exam_misc.cpp +++ b/check/exam_misc.cpp @@ -255,6 +255,29 @@ static unsigned exam_subs_algebraic() return result; } +/* Test suitable cases of the exponent power law: (e^t)^s=e^(ts). */ +static unsigned exam_exponent_power_law() +{ + unsigned result = 0; + symbol x("x"); + realsymbol s("s"); + possymbol t("t"); + + exmap pwr_exp = + { {pow(exp(x), 2), exp(2*x)}, + {pow(exp(s), t), exp(s*t)}, + {exp(x)*pow(exp(x),-1), 1} }; + + for (auto e : pwr_exp) { + if (! (e.first.is_equal(e.second)) ) { + clog << "power of exponent " << e.first << " produces error.\n"; + ++result; + } + } + + return result; +} + unsigned exam_misc() { unsigned result = 0; @@ -268,6 +291,7 @@ unsigned exam_misc() result += exam_subs(); cout << '.' << flush; result += exam_joris(); cout << '.' << flush; result += exam_subs_algebraic(); cout << '.' << flush; + result += exam_exponent_power_law(); cout << '.' << flush; return result; } diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index 49e30047..f6550f6d 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -128,6 +128,24 @@ static ex exp_conjugate(const ex & x) return exp(x.conjugate()); } +static ex exp_power(const ex & x, const ex & a) +{ + /* + * The power law (e^x)^a=e^(x*a) is used in two cases: + * a) a is an integer and x may be complex; + * b) both x and a are reals. + * Negative a is excluded to keep automatic simplifications like exp(x)/exp(x)=1. + */ + if (a.info(info_flags::nonnegative) + && (a.info(info_flags::integer) || (x.info(info_flags::real) && a.info(info_flags::real)))) + return exp(x*a); + else if (a.info(info_flags::negative) + && (a.info(info_flags::integer) || (x.info(info_flags::real) && a.info(info_flags::real)))) + return power(exp(-x*a), _ex_1).hold(); + + return power(exp(x), a).hold(); +} + REGISTER_FUNCTION(exp, eval_func(exp_eval). evalf_func(exp_evalf). expand_func(exp_expand). @@ -135,6 +153,7 @@ REGISTER_FUNCTION(exp, eval_func(exp_eval). real_part_func(exp_real_part). imag_part_func(exp_imag_part). conjugate_func(exp_conjugate). + power_func(exp_power). latex_name("\\exp")); ////////// -- 2.31.1