>From 602cfe7640152c2d4252a7cfa4104fc1322e0a65 Mon Sep 17 00:00:00 2001
From: "Vladimir V. Kisil" <V.Kisil@leeds.ac.uk>
Date: Mon, 6 Apr 2020 13:34:04 +0100
Subject: [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 <kisilv@maths.leeds.ac.uk>
---
 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..88e68299 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.27.0

