/* 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; }
int main(int argc, char *argv[]) { int N; if (argc == 2) { N = std::atoi(argv[1]); } else { N = 100; } ex e, f, s, a0, a1; a0 = symbol("a0"); a1 = symbol("a1"); e = a0 + a1; f = 0; for (long long i = 2; i < N; i++) { std::ostringstream o; o << "a" << i; s = symbol(o.str()); e = e + sin(s); f = f + sin(s); } f = -f; auto t1 = std::chrono::high_resolution_clock::now(); e = expand(pow(e, 2)); e = e.subs(a0 == f); e = expand(e); auto t2 = std::chrono::high_resolution_clock::now(); std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1) .count() << "ms" << std::endl; std::cout << e << std::endl; return 0; }
/* Simple tests on the tgamma function. We stuff in arguments where the results * exists in closed form and check if it's ok. */ static unsigned inifcns_consist_gamma() { using GiNaC::tgamma; unsigned result = 0; ex e; e = tgamma(1); for (int i=2; i<8; ++i) e += tgamma(ex(i)); if (e != numeric(874)) { clog << "tgamma(1)+...+tgamma(7) erroneously returned " << e << " instead of 874" << endl; ++result; } e = tgamma(1); for (int i=2; i<8; ++i) e *= tgamma(ex(i)); if (e != numeric(24883200)) { clog << "tgamma(1)*...*tgamma(7) erroneously returned " << e << " instead of 24883200" << endl; ++result; } e = tgamma(ex(numeric(5, 2)))*tgamma(ex(numeric(9, 2)))*64; if (e != 315*Pi) { clog << "64*tgamma(5/2)*tgamma(9/2) erroneously returned " << e << " instead of 315*Pi" << endl; ++result; } e = tgamma(ex(numeric(-13, 2))); for (int i=-13; i<7; i=i+2) e += tgamma(ex(numeric(i, 2))); e = (e*tgamma(ex(numeric(15, 2)))*numeric(512)); if (e != numeric(633935)*Pi) { clog << "512*(tgamma(-13/2)+...+tgamma(5/2))*tgamma(15/2) erroneously returned " << e << " instead of 633935*Pi" << endl; ++result; } return result; }
/* F_ab(a, i, b, j, "x") is a common pattern in all vertex evaluators. */ static ex F_ab(int a, int i, int b, int j, const symbol &x) { using GiNaC::tgamma; if ((i==0 && a<=0) || (j==0 && b<=0)) return 0; else return (tgamma(2-a-(i+1)*x)* tgamma(2-b-(1+j)*x)* tgamma(a+b-2+(1+i+j)*x)/ tgamma(a+i*x)/ tgamma(b+j*x)/tgamma(4-a-b-(2+i+j)*x)); }
/* 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; }