#include <stdio.h>
double frexp (double, int *);
double ldexp (double, int);
#define NPTS 100
double exp (double);
double log (double);
double sin (double);
double cos (double);
double tan (double);
double atan (double);
double asin (double);
double acos (double);
double sinh (double);
double cosh (double);
double tanh (double);
double asinh (double);
double acosh (double);
double atanh (double);
double gamma (double);
double fabs (double);
double floor (double);
#if 0
double polylog (int, double);
#endif
struct oneargument
{
char *name;
double (*func) (double);
double arg1;
double answer1;
double answer2;
double derivative;
int thresh;
};
#define OKERROR 0
static double MACHEP = 1.1102230246251565404236316680908203125e-16;
#if 0
double w_polylog_3 (double x) {return polylog (3, x);}
#endif
static struct oneargument test1[] =
{
{"exp", exp, 1.0, 2.7182769775390625,
4.85091998273536028747e-6, 2.71828182845904523536, 2},
{"exp", exp, -1.0, 3.678741455078125e-1,
5.29566362982159552377e-6, 3.678794411714423215955e-1, 2},
{"exp", exp, 0.5, 1.648712158203125,
9.1124970031468486507878e-6, 1.64872127070012814684865, 2},
{"exp", exp, -0.5, 6.065216064453125e-1,
9.0532673209236037995e-6, 6.0653065971263342360e-1, 2},
{"exp", exp, 2.0, 7.3890533447265625,
2.75420408772723042746e-6, 7.38905609893065022723, 2},
{"exp", exp, -2.0, 1.353302001953125e-1,
5.08304130019189399949e-6, 1.3533528323661269189e-1, 2},
{"log", log, 1.41421356237309492343, 3.465728759765625e-1,
7.1430341006605745676897e-7, 7.0710678118654758708668e-1, 2},
{"log", log, 7.07106781186547461715e-1, -3.46588134765625e-1,
1.45444856522566402246e-5, 1.41421356237309517417, 2},
{"sin", sin, 7.85398163397448278999e-1, 7.0709228515625e-1,
1.4496030297502751942956e-5, 7.071067811865475460497e-1, 2},
{"sin", sin, -7.85398163397448501044e-1, -7.071075439453125e-1,
7.62758764840238811175e-7, 7.07106781186547389040e-1, 2},
{"sin", sin, 1.570796326794896558, 9.999847412109375e-1,
1.52587890625e-5, 6.12323399573676588613e-17, 2},
{"sin", sin, -1.57079632679489678004, -1.0,
1.29302922820150306903e-32, -1.60812264967663649223e-16, 2},
{"sin", sin, 4.712388980384689674, -1.0,
1.68722975549458979398e-32, -1.83697019872102976584e-16, 2},
{"sin", sin, -4.71238898038468989604, 9.999847412109375e-1,
1.52587890625e-5, 3.83475850529283315008e-17, 2},
{"cos", cos, 3.92699081698724139500E-1, 9.23873901367187500000E-1,
5.63114409926198633370E-6, -3.82683432365089757586E-1, 2},
{"cos", cos, 7.85398163397448278999E-1, 7.07092285156250000000E-1,
1.44960302975460497458E-5, -7.07106781186547502752E-1, 2},
{"cos", cos, 1.17809724509617241850E0, 3.82675170898437500000E-1,
8.26146665231415693919E-6, -9.23879532511286738554E-1, 2},
{"cos", cos, 1.96349540849362069750E0, -3.82690429687500000000E-1,
6.99732241029898567203E-6, -9.23879532511286785419E-1, 2},
{"cos", cos, 2.35619449019234483700E0, -7.07107543945312500000E-1,
7.62758765040545859856E-7, -7.07106781186547589348E-1, 2},
{"cos", cos, 2.74889357189106897650E0, -9.23889160156250000000E-1,
9.62764496328487887036E-6, -3.82683432365089870728E-1, 2},
{"cos", cos, 3.14159265358979311600E0, -1.00000000000000000000E0,
7.49879891330928797323E-33, -1.22464679914735317723E-16, 2},
{"tan", tan, 7.85398163397448278999E-1, 9.999847412109375e-1,
1.52587890624387676600E-5, 1.99999999999999987754E0, 2},
{"tan", tan, 1.17809724509617241850E0, 2.41419982910156250000E0,
1.37332715322352112604E-5, 6.82842712474618858345E0, 2},
{"tan", tan, 1.96349540849362069750E0, -2.41421508789062500000E0,
1.52551752942854759743E-6, 6.82842712474619262118E0, 2},
{"tan", tan, 2.35619449019234483700E0, -1.00001525878906250000E0,
1.52587890623163029801E-5, 2.00000000000000036739E0, 2},
{"tan", tan, 2.74889357189106897650E0, -4.14215087890625000000E-1,
1.52551752982565655126E-6, 1.17157287525381000640E0, 2},
{"atan", atan, 4.14213562373094923430E-1, 3.92684936523437500000E-1,
1.41451752865477964149E-5, 8.53553390593273837869E-1, 2},
{"atan", atan, 1.0, 7.85385131835937500000E-1,
1.30315615108096156608E-5, 0.5, 2},
{"atan", atan, 2.41421356237309492343E0, 1.17808532714843750000E0,
1.19179477349460632350E-5, 1.46446609406726250782E-1, 2},
{"atan", atan, -2.41421356237309514547E0, -1.17810058593750000000E0,
3.34084132752141908545E-6, 1.46446609406726227789E-1, 2},
{"atan", atan, -1.0, -7.85400390625000000000E-1,
2.22722755169038433915E-6, 0.5, 2},
{"atan", atan, -4.14213562373095145475E-1, -3.92700195312500000000E-1,
1.11361377576267665972E-6, 8.53553390593273703853E-1, 2},
{"asin", asin, 3.82683432365089615246E-1, 3.92684936523437500000E-1,
1.41451752864854321970E-5, 1.08239220029239389286E0, 2},
{"asin", asin, 0.5, 5.23590087890625000000E-1,
8.68770767387307710723E-6, 1.15470053837925152902E0, 2},
{"asin", asin, 7.07106781186547461715E-1, 7.85385131835937500000E-1,
1.30315615107209645016E-5, 1.41421356237309492343E0, 2},
{"asin", asin, 9.23879532511286738483E-1, 1.17808532714843750000E0,
1.19179477349183147612E-5, 2.61312592975275276483E0, 2},
{"asin", asin, -0.5, -5.23605346679687500000E-1,
6.57108138862692289277E-6, 1.15470053837925152902E0, 2},
{"acos", acos, 1.95090322016128192573E-1, 1.37443542480468750000E0,
1.13611408471185777914E-5, -1.01959115820831832232E0, 2},
{"acos", acos, 3.82683432365089615246E-1, 1.17808532714843750000E0,
1.19179477351337991247E-5, -1.08239220029239389286E0, 2},
{"acos", acos, 0.5, 1.04719543457031250000E0,
2.11662628524615421446E-6, -1.15470053837925152902E0, 2},
{"acos", acos, 7.07106781186547461715E-1, 7.85385131835937500000E-1,
1.30315615108982668201E-5, -1.41421356237309492343E0, 2},
{"acos", acos, 9.23879532511286738483E-1, 3.92684936523437500000E-1,
1.41451752867009165605E-5, -2.61312592975275276483E0, 2},
{"acos", acos, 9.80785280403230430579E-1, 1.96334838867187500000E-1,
1.47019821746724723933E-5, -5.12583089548300990774E0, 2},
{"acos", acos, -0.5, 2.09439086914062500000E0,
4.23325257049230842892E-6, -1.15470053837925152902E0, 2},
{"sinh", sinh, 1.0, 1.17518615722656250000E0,
1.50364172389568823819E-5, 1.54308063481524377848E0, 2},
{"sinh", sinh, 7.09089565712818057364E2, 4.49423283712885057274E307,
4.25947714184369757620E208, 4.49423283712885057274E307, 2},
{"sinh", sinh, 2.22044604925031308085E-16, 0.00000000000000000000E0,
2.22044604925031308085E-16, 1.00000000000000000000E0, 2},
{"cosh", cosh, 7.09089565712818057364E2, 4.49423283712885057274E307,
4.25947714184369757620E208, 4.49423283712885057274E307, 2},
{"cosh", cosh, 1.0, 1.54307556152343750000E0,
5.07329180627847790562E-6, 1.17520119364380145688E0, 2},
{"cosh", cosh, 0.5, 1.12762451171875000000E0,
1.45348763078522622516E-6, 5.21095305493747361622E-1, 2},
{"tanh", tanh, 0.5, 4.62112426757812500000E-1,
4.73050219725850231848E-6, 7.86447732965927410150E-1, 3},
{"tanh", tanh, 5.49306144334054780032E-1, 4.99984741210937500000E-1,
1.52587890624507506378E-5, 7.50000000000000049249E-1, 2},
{"tanh", tanh, 0.625, 5.54595947265625000000E-1,
3.77508375729399903910E-6, 6.92419147969988069631E-1, 3},
{"asinh", asinh, 0.5, 4.81201171875000000000E-1,
1.06531846034474977589E-5, 8.94427190999915878564E-1, 2},
{"asinh", asinh, 1.0, 8.81362915039062500000E-1,
1.06719804805252326093E-5, 7.07106781186547524401E-1, 2},
{"asinh", asinh, 2.0, 1.44363403320312500000E0,
1.44197568534249327674E-6, 4.47213595499957939282E-1, 2},
{"acosh", acosh, 2.0, 1.31695556640625000000E0,
2.33051856670862504635E-6, 5.77350269189625764509E-1, 2},
{"acosh", acosh, 1.5, 9.62417602539062500000E-1,
6.04758014439499551783E-6, 8.94427190999915878564E-1, 2},
{"acosh", acosh, 1.03125, 2.49343872070312500000E-1,
9.62177257298785143908E-6, 3.96911150685467059809E0, 2},
{"atanh", atanh, 0.5, 5.49301147460937500000E-1,
4.99687311734569762262E-6, 1.33333333333333333333E0, 2},
#if 0
{"polylog_3", w_polylog_3, 0.875, 1.01392710208892822265625,
1.21106784918910854520955967e-8, 1.4149982649102631253520580, 2},
{"polylog_3", w_polylog_3, 8.0000000000000004440892e-1,
9.10605847835540771484375e-1, 7.570301035551561731571421485488e-9,
1.343493250010310486342647, 2},
#endif
#if 0
{"gamma", gamma, 1.0, 1.0,
0.0, -5.772156649015328606e-1, 2},
{"gamma", gamma, 2.0, 1.0,
0.0, 4.2278433509846713939e-1, 2},
{"gamma", gamma, 3.0, 2.0,
0.0, 1.845568670196934279, 2},
{"gamma", gamma, 4.0, 6.0,
0.0, 7.536706010590802836, 2},
#endif
{"null", NULL, 0.0, 0.0, 0.0, 2},
};
static volatile double volat1;
static volatile double volat2;
static double
nextval (x, updown)
double x;
int updown;
{
double m;
int i;
volat1 = x;
m = 0.25 * MACHEP * volat1 * updown;
volat2 = volat1 + m;
if (volat2 != volat1)
printf ("successor failed\n");
for (i = 2; i < 10; i++)
{
volat2 = volat1 + i * m;
if (volat1 != volat2)
return volat2;
}
printf ("nextval failed\n");
return volat1;
}
int
monot ()
{
double (*fun1) (double);
int i, j, errs, tests;
double x, x0, y, dy, err;
errs = 0;
tests = 0;
i = 0;
for (;;)
{
fun1 = test1[i].func;
if (fun1 == NULL)
break;
volat1 = test1[i].arg1;
x0 = volat1;
x = volat1;
for (j = 0; j <= NPTS; j++)
{
volat1 = x - x0;
dy = volat1 * test1[i].derivative;
dy = test1[i].answer2 + dy;
volat1 = test1[i].answer1 + dy;
volat2 = (*(fun1)) (x);
if (volat2 != volat1)
{
err = volat2 - test1[i].answer1;
err = err - dy;
err = err / volat1;
if (fabs (err) > ((OKERROR + test1[i].thresh) * MACHEP))
{
printf ("%d %s(%.16e) = %.16e, rel err = %.3e\n",
j, test1[i].name, x, volat2, err);
errs += 1;
}
}
x = nextval (x, 1);
tests += 1;
}
x = x0;
x = nextval (x, -1);
for (j = 1; j < NPTS; j++)
{
volat1 = x - x0;
dy = volat1 * test1[i].derivative;
dy = test1[i].answer2 + dy;
volat1 = test1[i].answer1 + dy;
volat2 = (*(fun1)) (x);
if (volat2 != volat1)
{
err = volat2 - test1[i].answer1;
err = err - dy;
err = err / volat1;
if (fabs (err) > ((OKERROR + test1[i].thresh) * MACHEP))
{
printf ("%d %s(%.16e) = %.16e, rel err = %.3e\n",
j, test1[i].name, x, volat2, err);
errs += 1;
}
}
x = nextval (x, -1);
tests += 1;
}
i += 1;
}
printf ("%d errors in %d tests\n", errs, tests);
return (errs);
}