/* -*-C-*- tsin.c */ #include "elefunt.h" /*# PROGRAM to test sin/cos # # data required # # none # # subprograms required from this package # # machar - an environmental inquiry program providing # information on the floating-point arithmetic # system. note that the call to machar can # be deleted provided the following five # parameters are assigned the values indicated # # ibeta - the radix of the floating-point system # it - the number of base-ibeta digits in the # significand of a floating-point number # minexp - the largest in magnitude negative # integer such that float(ibeta)**minexp # is a positive floating-point number # eps - the smallest positive floating-point # number such that 1.0+eps != 1.0 # epsneg - the smallest positive floating-point # number such that 1.0-epsneg != 1.0 # # ran(k) - a function subprogram returning random real # numbers uniformly distributed over (0,1) # # # standard fortran subprograms required # # abs, alog, amax1, cos, float, sin, sqrt # # # latest revision - december 6, 1979 # # author - w. j. cody # argonne national laboratory # #*/ #if 0 #ifdef LDOUBLE static long double _sinl(long double x) { static long double PIO4L = 7.8539816339744830961566E-1L; static long double DP1 = 7.853981554508209228515625E-1L; static long double DP2 = 7.946627356147928367136046290398E-9L; static long double DP3 = 3.061616997868382943065164830688E-17L; static long double lossth = 5.49755813888e11L; /* 2^39 */ long double y, z; int sign = 1; long j; if( x < 0 ) { x = -x; sign = -1; } if( x > lossth ) { return _MATH_NANL; } y = floorl( x/PIO4L ); /* integer part of x/PIO4 */ z = y; j = z; /* convert to integer for tests on the phase angle */ /* map zeros to origin */ if( j & 1 ) { j += 1; y += 1.0; } j = j & 07; /* octant modulo 360 degrees */ /* reflect in x axis */ if( j > 3) { sign = -sign; j -= 4; } /* Extended precision modular arithmetic */ z = ((x - y * DP1) - y * DP2) - y * DP3; if( (j==1) || (j==2) ) { y = cosl(z); } else { y = sinl(z); } if(sign < 0) y = -y; return(y); } #undef sin #define sin _sinl #endif #endif void tsin() { int i, ibeta, iexp, irnd, it, i1, j, k1, k2, k3, machep, maxexp, minexp, n, negep, ngrd; float a, ait, albeta, b, beta, betap, c, del, eps, epsneg, expon, r6, r7, three, w, x, xl, xmax, xmin, xn, x1, y, z, zz; machar(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &eps, &epsneg, &xmin, &xmax); beta = (float) ibeta; albeta = ALOG(beta); ait = (float) it; three = 3.0e0L; a = ZERO; b = 1.570796327e0L; c = b; n = 2000; xn = (float) n; i1 = 0; /* random argument accuracy tests */ for (j = 1; j <= 3; ++j) { k1 = 0; k3 = 0; x1 = ZERO; r6 = ZERO; r7 = ZERO; del = (b - a) / xn; xl = a; for (i = 1; i <= n; ++i) { x = del * ran(i1) + xl; y = x / three; y += x; y -= x; x = three * y; if (j == 3) { z = cos(x); zz = cos(y); w = ONE; if (z != ZERO) w = (z + zz * (three - 4.0e0L * zz * zz)) / z; } else { z = sin(x); zz = sin(y); w = ONE; if (z != ZERO) w = (z - zz * (three - 4.0e0L * zz * zz)) / z; } if (w > ZERO) k1 = k1 + 1; if (w < ZERO) k3 = k3 + 1; w = ABS(w); if (w > r6) { r6 = w; x1 = x; } r7 = r7 + w * w; xl = xl + del; } k2 = n - k3 - k1; r7 = sqrt(r7 / xn); if (j == 3) { printf("\fTEST OF COS(X) VS 4*COS(X/3)**3-3*COS(X/3)\n\n"); printf("%7d RANDOM ARGUMENTS WERE TESTED FROM THE INTERVAL\n",n); printf(" (" F15P4E "," F15P4E ")\n\n\n", a, b); printf(" COS(X) WAS LARGER%6d TIMES,\n", k1); printf(" AGREED%6d TIMES, AND\n", k2); printf(" WAS SMALLER%6d TIMES.\n\n", k3); } else { printf("\fTEST OF SIN(X) VS 3*SIN(X/3)-4*SIN(X/3)**3\n\n"); printf("%7d RANDOM ARGUMENTS WERE TESTED FROM THE INTERVAL\n", n); printf(" (" F15P4E "," F15P4E ")\n\n\n", a, b); printf(" SIN(X) WAS LARGER%6d TIMES,\n", k1); printf(" AGREED%6d TIMES, AND\n", k2); printf(" WAS SMALLER%6d TIMES.\n\n", k3); } printf( " THERE ARE%4d BASE%4d SIGNIFICANT DIGITS IN A FLOATING-POINT NUMBER\n\n", it, ibeta); w = -999.0e0; if (r6 != ZERO) w = ALOG(ABS(r6)) / albeta; printf(" THE MAXIMUM RELATIVE ERROR OF" F15P4E " = %4d **" F7P2F "\n", r6, ibeta, w); printf(" OCCURRED FOR X =" F17P6E "\n", x1); w = AMAX1(ait + w, ZERO); printf( " THE ESTIMATED LOSS OF BASE%4d SIGNIFICANT DIGITS IS" F7P2F "\n\n\n", ibeta, w); w = -999.0e0; if (r7 != ZERO) w = ALOG(ABS(r7)) / albeta; printf(" THE ROOT MEAN SQUARE RELATIVE ERROR WAS" F15P4E " = %4d **" F7P2F "\n", r7, ibeta, w); w = AMAX1(ait + w, ZERO); printf( " THE ESTIMATED LOSS OF BASE%4d SIGNIFICANT DIGITS IS" F7P2F "\n\n\n", ibeta, w); a = 18.84955592e0L; if (j == 2) a = b + c; b = a + c; } /* special tests */ printf("\fSPECIAL TESTS\n\n"); c = ONE / ipow(beta, (it / 2)); z = (sin(a + c) - sin(a - c)) / (c + c); printf(" IF " F13P6E " IS NOT ALMOST 1.0E0, SIN HAS THE WRONG PERIOD.\n\n", z); printf(" THE IDENTITY SIN(-X) = -SIN(X) WILL BE TESTED.\n"); printf(" X F(X) + F(-X)\n"); for (i = 1; i <= 5; ++i) { x = ran(i1) * a; z = sin(x) + sin(-x); printf(F15P7E F15P7E "\n\n", x, z); } printf(" THE IDENTITY SIN(X) = X , X SMALL, WILL BE TESTED.\n"); printf(" X X - F(X)\n\n"); betap = ipow(beta, it); x = ran(i1) / betap; for (i = 1; i <= 5; ++i) { z = x - sin(x); printf(F15P7E F15P7E "\n\n", x, z); x = x / beta; } printf(" THE IDENTITY COS(-X) = COS(X) WILL BE TESTED.\n"); printf(" X F(X) - F(-X)\n"); for (i = 1; i <= 5; ++i) { x = ran(i1) * a; z = cos(x) - cos(-x); printf(F15P7E F15P7E "\n\n", x, z); } printf(" TEST OF UNDERFLOW FOR VERY SMALL ARGUMENT.\n\n"); expon = (float) minexp *0.75e0L; x = pow(beta, expon); y = sin(x); printf("\n SIN(" F13P6E ") = " F13P6E "\n", x, y); printf(" THE FOLLOWING THREE LINES ILLUSTRATE THE LOSS IN SIGNIFICANCE\n"); printf(" FOR LARGE ARGUMENTS. THE ARGUMENTS ARE CONSECUTIVE.\n"); z = sqrt(betap); x = z * (ONE - epsneg); y = sin(x); printf("\n SIN(" F13P6E ") =" F13P6E "\n", x, y); y = sin(z); printf("\n SIN(" F13P6E ") =" F13P6E "\n", z, y); x = z * (ONE + eps); y = sin(x); printf("\n SIN(" F13P6E ") =" F13P6E "\n", x, y); /* test of error returns */ printf("\fTEST OF ERROR RETURNS\n\n\n"); x = betap; printf(" SIN WILL BE CALLED WITH THE ARGUMENT" F15P4E "\n",x); printf(" THIS SHOULD TRIGGER AN ERROR MESSAGE\n\n\n"); fflush(stdout); errno = 0; y = sin(x); if (errno) perror("sin()"); printf(" SIN RETURNED THE VALUE" F15P4E "\n\n\n\n", y); printf(" THIS CONCLUDES THE TESTS\n"); }