#include <iostream>
#include <cmath>
#include <vector>
#include <iterator>
#include <numeric>
#include <algorithm>
#include <iomanip>

long double factorial(int i)
{
  long double fac = 1.0;
  
  for (; i > 0; i--)
    fac *= i;
  
  return fac;
}

struct Gen {
  Gen(int i, double rad) : n(i), r(rad) {}
  double operator()() {
    double x = std::pow(r, 2 * n + 1);
    long double y = factorial(2 * n + 1);
    
    return static_cast<double>(x / y * ((n++ % 2 == 0) ? 1.0 : -1.0));
  }
private:
  int n;
  double r;
};

int main(void)
{
  std::vector<double> vd;
  double rad, sinrad;
  int n;
  
//  std::cout << "input rad = ";
//  std::cin >> rad;
//  std::cout << "input N = ";
//  std::cin >> n;
  
  rad = M_PI / 3;
  n = 500;
  
  // radの正規化
  if (rad > 2 * M_PI)
    rad -= 2.0 * M_PI * static_cast<int>(rad / (2.0 * M_PI));
  else if (rad < 0.0)
    rad += 2.0 * M_PI * static_cast<int>(std::fabs(rad) / (2.0 * M_PI) + 1.0);

  std::generate_n(std::back_inserter(vd), n, Gen(0, rad));
  sinrad = std::accumulate(vd.begin(), vd.end(), 0.0);
  
  std::cout << std::setprecision(15);
  
  std::cout << "sin(rad)        = " << std::sin(rad);
  std::cout << "\ntaylor sin(rad) = " << sinrad << std::endl;;

  // 逆順に足して積み残し誤差を確認してみる
  sinrad = std::accumulate(vd.rbegin(), vd.rend(), 0.0);
  
  std::cout << "reverse sum";
  std::cout << "\nsin(rad)        = " << std::sin(rad);
  std::cout << "\ntaylor sin(rad) = " << sinrad << std::endl;;

}
