/* Simple tests on the Psi-function (aka polygamma-function). We stuff in arguments where the result exists in closed form and check if it's ok. */ static unsigned inifcns_consist_psi() { using GiNaC::log; using GiNaC::tgamma; unsigned result = 0; symbol x; ex e, f; // We check psi(1) and psi(1/2) implicitly by calculating the curious // little identity tgamma(1)'/tgamma(1) - tgamma(1/2)'/tgamma(1/2) == 2*log(2). e += (tgamma(x).diff(x)/tgamma(x)).subs(x==numeric(1)); e -= (tgamma(x).diff(x)/tgamma(x)).subs(x==numeric(1,2)); if (e!=2*log(2)) { clog << "tgamma(1)'/tgamma(1) - tgamma(1/2)'/tgamma(1/2) erroneously returned " << e << " instead of 2*log(2)" << endl; ++result; } return result; }
/* Assorted tests on other transcendental functions. */ static unsigned inifcns_consist_trans() { using GiNaC::asin; using GiNaC::acos; using GiNaC::asinh; using GiNaC::acosh; using GiNaC::atanh; unsigned result = 0; symbol x("x"); ex chk; chk = asin(1)-acos(0); if (!chk.is_zero()) { clog << "asin(1)-acos(0) erroneously returned " << chk << " instead of 0" << endl; ++result; } // arbitrary check of type sin(f(x)): chk = pow(sin(acos(x)),2) + pow(sin(asin(x)),2) - (1+pow(x,2))*pow(sin(atan(x)),2); if (chk != 1-pow(x,2)) { clog << "sin(acos(x))^2 + sin(asin(x))^2 - (1+x^2)*sin(atan(x))^2 " << "erroneously returned " << chk << " instead of 1-x^2" << endl; ++result; } // arbitrary check of type cos(f(x)): chk = pow(cos(acos(x)),2) + pow(cos(asin(x)),2) - (1+pow(x,2))*pow(cos(atan(x)),2); if (!chk.is_zero()) { clog << "cos(acos(x))^2 + cos(asin(x))^2 - (1+x^2)*cos(atan(x))^2 " << "erroneously returned " << chk << " instead of 0" << endl; ++result; } // arbitrary check of type tan(f(x)): chk = tan(acos(x))*tan(asin(x)) - tan(atan(x)); if (chk != 1-x) { clog << "tan(acos(x))*tan(asin(x)) - tan(atan(x)) " << "erroneously returned " << chk << " instead of -x+1" << endl; ++result; } // arbitrary check of type sinh(f(x)): chk = -pow(sinh(acosh(x)),2).expand()*pow(sinh(atanh(x)),2) - pow(sinh(asinh(x)),2); if (!chk.is_zero()) { clog << "expand(-(sinh(acosh(x)))^2)*(sinh(atanh(x))^2) - sinh(asinh(x))^2 " << "erroneously returned " << chk << " instead of 0" << endl; ++result; } // arbitrary check of type cosh(f(x)): chk = (pow(cosh(asinh(x)),2) - 2*pow(cosh(acosh(x)),2)) * pow(cosh(atanh(x)),2); if (chk != 1) { clog << "(cosh(asinh(x))^2 - 2*cosh(acosh(x))^2) * cosh(atanh(x))^2 " << "erroneously returned " << chk << " instead of 1" << endl; ++result; } // arbitrary check of type tanh(f(x)): chk = (pow(tanh(asinh(x)),-2) - pow(tanh(acosh(x)),2)).expand() * pow(tanh(atanh(x)),2); if (chk != 2) { clog << "expand(tanh(acosh(x))^2 - tanh(asinh(x))^(-2)) * tanh(atanh(x))^2 " << "erroneously returned " << chk << " instead of 2" << endl; ++result; } // check consistency of log and eta phases: for (int r1=-1; r1<=1; ++r1) { for (int i1=-1; i1<=1; ++i1) { ex x1 = r1+I*i1; if (x1.is_zero()) continue; for (int r2=-1; r2<=1; ++r2) { for (int i2=-1; i2<=1; ++i2) { ex x2 = r2+I*i2; if (x2.is_zero()) continue; if (abs(evalf(eta(x1,x2)-log(x1*x2)+log(x1)+log(x2)))>.1e-12) { clog << "either eta(x,y), log(x), log(y) or log(x*y) is wrong" << " at x==" << x1 << ", y==" << x2 << endl; ++result; } } } } } return result; }
static unsigned inifcns_consist_log() { unsigned result = 0; symbol z("a"), w("b"); realsymbol a("a"), b("b"); possymbol p("p"), q("q"); // do not expand if (!log(z*w).expand(expand_options::expand_transcendental).is_equal(log(z*w))) ++result; // do not expand if (!log(a*b).expand(expand_options::expand_transcendental).is_equal(log(a*b))) ++result; // shall expand if (!log(p*q).expand(expand_options::expand_transcendental).is_equal(log(p) + log(q))) ++result; // a bit more complicated ex e1 = log(-7*p*pow(q,3)*a*pow(b,2)*z*w).expand(expand_options::expand_transcendental); ex e2 = log(7)+log(p)+log(pow(q,3))+log(-z*a*w*pow(b,2)); if (!e1.is_equal(e2)) ++result; // shall not do for non-real powers if (ex(log(pow(p,z))).is_equal(z*log(p))) ++result; // shall not do for non-positive basis if (ex(log(pow(a,b))).is_equal(b*log(a))) ++result; return result; }