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

double cos_approx0 (double x, int steps)    // best approximation for |x| close to 0 
{
  double cos_x = 0;
  double x_2i = 1;
  double fak_2i = 1;
  for (int i = 0; i < steps; i++)
    {
      if (i % 2 == 0)
	cos_x += x_2i / fak_2i;
      else
	cos_x -= x_2i / fak_2i;
      fak_2i *= (2 * i + 1) * (2 * i + 2);
      x_2i *= x * x;
    }
  return cos_x;
}

double sin_approx0 (double x, int steps)    // best approximation for |x| close to 0
{
  double sin_x = 0;
  double x_2i_p1 = x;
  double fak_2i_p1 = 1;
  for (int i = 0; i < steps; i++)
    {
      if (i % 2 == 0)
	sin_x += x_2i_p1 / fak_2i_p1;
      else
	sin_x -= x_2i_p1 / fak_2i_p1;
      fak_2i_p1 *= (2 * i + 2) * (2 * i + 3);
      x_2i_p1 *= x * x;
    }
  return sin_x;
}

double sin_approx (double x)
{
  int steps = 5;

  if (x < M_PI / 4)
    return sin_approx0 (x, steps);
  if (x < 3 * M_PI / 4)
    return cos_approx0 (x - M_PI / 2, steps);

  return -sin_approx (x - M_PI);
}

int main()
{
  double max_error = 0.0;

  for (double x = 0; x < 2 * M_PI; x += 0.01)
    {
      double error = fabs (sin (x) - sin_approx (x));
      if (error > max_error)
	max_error = error;

      printf ("%g %g %g\n", x, sin_approx (x), error);
    }
  printf ("# max_error = %g\n", max_error);
}
