* functions. */
/*
- * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2000 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <ginac/ginac.h>
+#include "ginac.h"
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
using namespace GiNaC;
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC
-/* Simple tests on the sine trigonometric function. */
+/* Some tests on the sine trigonometric function. */
static unsigned inifcns_consist_sin(void)
{
unsigned result = 0;
// sin(n*Pi) == 0?
errorflag = false;
for (int n=-10; n<=10; ++n) {
- if ( sin(n*Pi).eval() != numeric(0) ||
+ if (sin(n*Pi).eval() != numeric(0) ||
!sin(n*Pi).eval().info(info_flags::integer))
errorflag = true;
}
if (errorflag) {
+ // we don't count each of those errors
clog << "sin(n*Pi) with integer n does not always return exact 0"
<< endl;
++result;
// sin((n+1/2)*Pi) == {+|-}1?
errorflag = false;
for (int n=-10; n<=10; ++n) {
- if (! sin((n+numeric(1,2))*Pi).eval().info(info_flags::integer) ||
+ if (!sin((n+numeric(1,2))*Pi).eval().info(info_flags::integer) ||
!(sin((n+numeric(1,2))*Pi).eval() == numeric(1) ||
sin((n+numeric(1,2))*Pi).eval() == numeric(-1)))
errorflag = true;
++result;
}
+ // compare sin((q*Pi).evalf()) with sin(q*Pi).eval().evalf() at various
+ // points. E.g. if sin(Pi/10) returns something symbolic this should be
+ // equal to sqrt(5)/4-1/4. This routine will spot programming mistakes
+ // of this kind:
+ errorflag = false;
+ ex argument;
+ numeric epsilon(double(1e-8));
+ for (int n=-240; n<=240; ++n) {
+ argument = n*Pi/60;
+ if (abs(sin(evalf(argument))-evalf(sin(argument)))>epsilon) {
+ clog << "sin(" << argument << ") returns "
+ << sin(argument) << endl;
+ errorflag = true;
+ }
+ }
+ if (errorflag) {
+ ++result;
+ }
+
return result;
}
// cos((n+1/2)*Pi) == 0?
errorflag = false;
for (int n=-10; n<=10; ++n) {
- if ( cos((n+numeric(1,2))*Pi).eval() != numeric(0) ||
+ if (cos((n+numeric(1,2))*Pi).eval() != numeric(0) ||
!cos((n+numeric(1,2))*Pi).eval().info(info_flags::integer))
errorflag = true;
}
// cos(n*Pi) == 0?
errorflag = false;
for (int n=-10; n<=10; ++n) {
- if (! cos(n*Pi).eval().info(info_flags::integer) ||
+ if (!cos(n*Pi).eval().info(info_flags::integer) ||
!(cos(n*Pi).eval() == numeric(1) ||
cos(n*Pi).eval() == numeric(-1)))
errorflag = true;
++result;
}
+ // compare cos((q*Pi).evalf()) with cos(q*Pi).eval().evalf() at various
+ // points. E.g. if cos(Pi/12) returns something symbolic this should be
+ // equal to 1/4*(1+1/3*sqrt(3))*sqrt(6). This routine will spot
+ // programming mistakes of this kind:
+ errorflag = false;
+ ex argument;
+ numeric epsilon(double(1e-8));
+ for (int n=-240; n<=240; ++n) {
+ argument = n*Pi/60;
+ if (abs(cos(evalf(argument))-evalf(cos(argument)))>epsilon) {
+ clog << "cos(" << argument << ") returns "
+ << cos(argument) << endl;
+ errorflag = true;
+ }
+ }
+ if (errorflag) {
+ ++result;
+ }
+
+ return result;
+}
+
+/* Simple tests on the tangent trigonometric function. */
+static unsigned inifcns_consist_tan(void)
+{
+ unsigned result = 0;
+ bool errorflag;
+
+ // compare tan((q*Pi).evalf()) with tan(q*Pi).eval().evalf() at various
+ // points. E.g. if tan(Pi/12) returns something symbolic this should be
+ // equal to 2-sqrt(3). This routine will spot programming mistakes of
+ // this kind:
+ errorflag = false;
+ ex argument;
+ numeric epsilon(double(1e-8));
+ for (int n=-240; n<=240; ++n) {
+ if (!(n%30) && (n%60)) // skip poles
+ ++n;
+ argument = n*Pi/60;
+ if (abs(tan(evalf(argument))-evalf(tan(argument)))>epsilon) {
+ clog << "tan(" << argument << ") returns "
+ << tan(argument) << endl;
+ errorflag = true;
+ }
+ }
+ if (errorflag) {
+ ++result;
+ }
+
return result;
}
return result;
}
-/* Simple tests on the Gamma combinatorial function. We stuff in arguments
- * where the result exists in closed form and check if it's ok. */
+/* Simple tests on the Gamma function. We stuff in arguments where the results
+ * exists in closed form and check if it's ok. */
static unsigned inifcns_consist_gamma(void)
{
unsigned result = 0;
return result;
}
+/* 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(void)
+{
+ unsigned result = 0;
+ symbol x;
+ ex e, f;
+
+ // We check psi(1) and psi(1/2) implicitly by calculating the curious
+ // little identity gamma(1)'/gamma(1) - gamma(1/2)'/gamma(1/2) == 2*log(2).
+ e += (gamma(x).diff(x)/gamma(x)).subs(x==numeric(1));
+ e -= (gamma(x).diff(x)/gamma(x)).subs(x==numeric(1,2));
+ if (e!=2*log(2)) {
+ clog << "gamma(1)'/gamma(1) - gamma(1/2)'/gamma(1/2) erroneously returned "
+ << e << " instead of 2*log(2)" << endl;
+ ++result;
+ }
+
+ return result;
+}
+
/* Simple tests on the Riemann Zeta function. We stuff in arguments where the
* result exists in closed form and check if it's ok. Of course, this checks
* the Bernoulli numbers as a side effect. */
result += inifcns_consist_sin();
result += inifcns_consist_cos();
+ result += inifcns_consist_tan();
result += inifcns_consist_trans();
result += inifcns_consist_gamma();
+ result += inifcns_consist_psi();
result += inifcns_consist_zeta();
- if ( !result ) {
+ if (!result) {
cout << " passed ";
clog << "(no output)" << endl;
} else {