/* Program to check that the FP stuff underlying these common FP
   functions isn't too badly broken.  Carefully kludged to print the
   same answers on different platforms (even when run natively). */

#include <stdio.h>
#include <math.h>

int main ( void )
{
   double d;
   float f;
   int i;

   const double tinyD = 0.0000000001;
   const double tinyF = 0.0001;

   /* -------------------- any arg -------------------- */

   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf("floorD(%+20.13e) = %+20.13e\n", d, floor(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf("floorF(%+20.4e) = %+20.4e\n", (double)f, (double)floorf(f));
      f += 0.1-tinyF;
   }


   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf(" ceilD(%+20.13e) = %+20.13e\n", d, ceil(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf(" ceilF(%+20.4e) = %+20.4e\n", (double)f, (double)ceilf(f));
      f += 0.1-tinyF;
   }


   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  sinD(%+20.13e) = %+20.13e\n", d, sin(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  sinF(%+20.4e) = %+20.4e\n", (double)f, (double)sinf(f));
      f += 0.1-tinyF;
   }


   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  cosD(%+20.13e) = %+20.13e\n", d, cos(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  cosF(%+20.4e) = %+20.4e\n", (double)f, (double)cosf(f));
      f += 0.1-tinyF;
   }


   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  tanD(%+20.13e) = %+20.13e\n", d, tan(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  tanF(%+20.4e) = %+20.4e\n", (double)f, (double)tanf(f));
      f += 0.1-tinyF;
   }


   d = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  expD(%+20.13e) = %+20.13e\n", d, exp(d));
      d += 0.1-tinyD;
   }
   f = -2.0;
   for (i = 0; i < 41; i++) {
      printf("  expF(%+20.4e) = %+20.4e\n", (double)f, (double)expf(f));
      f += 0.1-tinyF;
   }

   /* -------------------- >= 0 arg -------------------- */

   d = 0.0;
   for (i = 0; i < 21; i++) {
      printf(" sqrtD(%+20.13e) = %+20.13e\n", d, sqrt(d));
      d += 0.1-tinyD;
   }
   f = 0.0;
   for (i = 0; i < 21; i++) {
      printf(" sqrtF(%+20.4e) = %+20.4e\n", (double)f, (double)sqrtf(f));
      f += 0.1-tinyF;
   }


   d = 0.0;
   for (i = 0; i < 21; i++) {
      printf("  logD(%+20.13e) = %+20.13e\n", d, log(d));
      d += 0.1-tinyD;
   }
   f = 0.0;
   for (i = 0; i < 21; i++) {
      printf("  logF(%+20.4e) = %+20.4e\n", (double)f, (double)logf(f));
      f += 0.1-tinyF;
   }


   d = 0.0;
   for (i = 0; i < 21; i++) {
      printf("log10D(%+20.13e) = %+20.13e\n", d, log10(d));
      d += 0.1-tinyD;
   }
   f = 0.0;
   for (i = 0; i < 21; i++) {
      printf("log10F(%+20.4e) = %+20.4e\n", (double)f, (double)log10f(f));
      f += 0.1-tinyF;
   }

   /* -------------------- -1 .. +1 arg -------------------- */

   d = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" asinD(%+20.13e) = %+20.13e\n", d, asin(d));
      d += 0.1-tinyD;
   }
   f = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" asinF(%+20.4e) = %+20.4e\n", (double)f, (double)asinf(f));
      f += 0.1-tinyF;
   }

   /* acos(double) seems very prone to accuracy loss near the end of
      the range (arg --> +1.0).  Hence is different from the rest to
      stop it getting so close to 1.0. */
   d = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" acosD(%+20.13e) = %+20.10e\n", d, acos(d));
      d += 0.1 - 1000.0*tinyD;
   }
   f = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" acosF(%+20.4e) = %+20.4e\n", (double)f, (double)acosf(f));
      f += 0.1-tinyF;
   }


   d = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" atanD(%+20.13e) = %+20.13e\n", d, atan(d));
      d += 0.1-tinyD;
   }
   f = -1.0;
   for (i = 0; i < 21; i++) {
      printf(" atanF(%+20.4e) = %+20.4e\n", (double)f, (double)atanf(f));
      f += 0.1-tinyF;
   }


   d = -1.0;
   for (i = 0; i < 21; i++) {
      printf("atan2D(%+20.13e) = %+20.13e\n", d, atan2(d, 1.0));
      d += 0.1-tinyD;
   }
   f = -1.0;
   for (i = 0; i < 21; i++) {
      printf("atan2F(%+20.4e) = %+20.4e\n", (double)f, (double)atan2f(f,1.0));
      f += 0.1-tinyF;
   }

   return 0;
}