From 3956eb4456d23f7ba937d9b2b726c1b6eac64530 Mon Sep 17 00:00:00 2001 From: "Vladimir V. Kisil" Date: Mon, 5 Apr 2021 21:01:30 +0200 Subject: [PATCH] [PATCH] Improve normalisation of negative exponents. If an expression contains exponents with opposite signs, then the respective symbolic substitutions need to be properly attributed to numerator/denominator slots. --- check/exam_normalization.cpp | 20 ++++++++++++++++++++ ginac/normal.cpp | 10 +++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/check/exam_normalization.cpp b/check/exam_normalization.cpp index 7ed7464d..17cf83db 100644 --- a/check/exam_normalization.cpp +++ b/check/exam_normalization.cpp @@ -252,6 +252,20 @@ static unsigned exam_exponent_law() result += check_normal(e, den); } + // Negative exponents + e = (exp(2*x)-exp(-2*x))/(exp(x)-exp(-x)); + ex en = e.normal(); + // Either exp(x) or exp(-x) can be viewed as a "symbol" during run-time + // thus two different forms of the result are possible + ex r1 = (exp(2*x)+1)/exp(x) ; + ex r2 = (exp(-2*x)+1)/exp(-x); + + if (!en.is_equal(r1) && !en.is_equal(r2)) { + clog << "normal form of " << e << " erroneously returned " + << en << " (should be " << r1 << " or " << r2 << ")" << endl; + result += 1; + } + return result; } @@ -305,6 +319,12 @@ static unsigned exam_power_law() e /= 2*pow(b, y/2)-3*pow(b, z/2); d = 2*pow(b, y/2)+3*pow(b, z/2); result += check_normal(e, d); + + // Negative powers + e = (b -pow(b,-1)); + e /= (pow(b, numeric(1,2)) - pow(b, numeric(-1,2))); + d = (b+1)*pow(b, numeric(-1,2)); + result += check_normal(e, d); } return result; diff --git a/ginac/normal.cpp b/ginac/normal.cpp index ce606f08..818aa808 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -2196,14 +2196,18 @@ ex basic::normal(exmap & repl, exmap & rev_lookup, lst & modifier) const normal_map_function map_normal; int nmod = modifier.nops(); // To watch new modifiers to the replacement list - lst result = dynallocate({replace_with_symbol(map(map_normal), repl, rev_lookup, modifier), _ex1}); + ex result = replace_with_symbol(map(map_normal), repl, rev_lookup, modifier); for (int imod = nmod; imod < modifier.nops(); ++imod) { exmap this_repl; this_repl.insert(std::make_pair(modifier.op(imod).op(0), modifier.op(imod).op(1))); - result = ex_to(result.subs(this_repl, subs_options::no_pattern)); + result = result.subs(this_repl, subs_options::no_pattern); } - return result; + // Sometimes we may obtain negative powers, they need to be placed to denominator + if (is_a(result) && result.op(1).info(info_flags::negative)) + return dynallocate({_ex1, power(result.op(0), -result.op(1))}); + else + return dynallocate({result, _ex1}); } -- 2.35.3