X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=check%2Fexam_normalization.cpp;h=17cf83db1ea1e83cc37c3db5424ee75edc4a1175;hp=a184ad28ecd2d030e686d34bc36120efe5045b69;hb=3956eb4456d23f7ba937d9b2b726c1b6eac64530;hpb=2afa71937b3c12cdc70f01213baa8a92be4b604a diff --git a/check/exam_normalization.cpp b/check/exam_normalization.cpp index a184ad28..17cf83db 100644 --- a/check/exam_normalization.cpp +++ b/check/exam_normalization.cpp @@ -3,7 +3,7 @@ * Rational function normalization test suite. */ /* - * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2021 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -163,7 +163,12 @@ static unsigned exam_normal4() e = (pow(x-y*2,4)/pow(pow(x,2)-pow(y,2)*4,2)+1)*(x+y*2)*(y+z)/(pow(x,2)+pow(y,2)*4); d = (y*2 + z*2) / (x + y*2); result += check_normal(e, d); - + + // Replacement of nested functions with temporary symbols + e = x/(sqrt(sin(z)-1)) + y/(sqrt(sin(z)-1)); + d = (x + y)/(sqrt(sin(z)-1)); + result += check_normal(e, d); + return result; } @@ -218,6 +223,113 @@ static unsigned exam_content() return result; } +static unsigned exam_exponent_law() +{ + unsigned result = 0; + ex e, d; + + // simple case + e = exp(2*x)-1; + e /= exp(x)-1; + d = exp(x)+1; + result += check_normal(e, d); + + // More involved with powers of two exponents + e = exp(15*x)+exp(12*x)+2*exp(10*x)+2*exp(7*x); + e /= exp(5*x)+exp(2*x); + d = pow(exp(5*x), 2) +2*exp(5*x); + result += check_normal(e, d); + + lst bases = { + 5*exp(3*x)+7, // Powers of a single exponent + 5*exp(3*x)+7*exp(2*x), // Two different factors of a single variable + 5*exp(3*x)+7*exp(2*y) // Exponent with different variable + }; + + for (auto den : bases) { + e = pow(den, 3).expand(); + e /= pow(den, 2).expand(); + 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; +} + +static unsigned exam_power_law() +{ + unsigned result = 0; + ex e, d; + + lst bases = {x, pow(x, numeric(1,3)), exp(x), sin(x)}; // We run all check for power base of different kinds + + for ( auto b : bases ) { + + // simple case + e = 4*b-9; + e /= 2*sqrt(b)-3; + d = 2*sqrt(b)+3; + result += check_normal(e, d); + + // Fractional powers + e = 4*pow(b, numeric(2,3))-9; + e /= 2*pow(b, numeric(1,3))-3; + d = 2*pow(b, numeric(1,3))+3; + result += check_normal(e, d); + + // Different powers with the same base + e = 4*b-9*sqrt(b); + e /= 2*sqrt(b)-3*pow(b, numeric(1,4)); + d = 2*sqrt(b)+3*pow(b, numeric(1,4)); + result += check_normal(e, d); + + // Non-numeric powers + e = 4*pow(b, 2*y)-9; + e /= 2*pow(b, y)-3; + d = 2*pow(b, y)+3; + result += check_normal(e, d); + + // Non-numeric fractional powers + e = 4*pow(b, y)-9; + e /= 2*pow(b, y/2)-3; + d = 2*pow(b, y/2)+3; + result += check_normal(e, d); + + // Different non-numeric powers + e = 4*pow(b, 2*y)-9*pow(b, 2*z); + e /= 2*pow(b, y)-3*pow(b, z); + d = 2*pow(b, y)+3*pow(b, z); + result += check_normal(e, d); + + // Different non-numeric fractional powers + e = 4*pow(b, y)-9*pow(b, z); + 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; +} + unsigned exam_normalization() { unsigned result = 0; @@ -229,6 +341,8 @@ unsigned exam_normalization() result += exam_normal3(); cout << '.' << flush; result += exam_normal4(); cout << '.' << flush; result += exam_content(); cout << '.' << flush; + result += exam_exponent_law(); cout << '.' << flush; + result += exam_power_law(); cout << '.' << flush; return result; }