C++ sin using templates (last update: 2013-05-01, created: 2013-05-01) back to the list ↑
Calculating the value of sin during compilation (using C++ templates) for no apparent reason. See the comment at the beginning for details.


// Template Spagetti #1 by gynvael.coldwind//vx
#include <cstdio>
#include <math.h>

// Actually it kinda sucks that template cannot have a floating constant.
// (only enumeratable types and integers according to the standard)
// However, the -Os in GCC (and maybe other options as well, didn't test it)
// pre-calculates the returned values by the functions anyway.
// The only remaining problem is the radian angle values, that are normally
// not integral, hence the angles are given as Deg.
// A work around here might be using fixed-point (implemented as templates ofc).
//
// Anyway, a sample test run:
//
// 4:35:31 gynvael >g++ test1.cpp -Wall -Wextra -Os
//
// 4:37:58 gynvael >a
// sin(20 deg) == 0.342020 0.342020
// sin(30 deg) == 0.500000 0.500000
// sin(40 deg) == 0.642788 0.642788
// sin(50 deg) == 0.766044 0.766044
// sin(60 deg) == 0.866025 0.866025
//
// Yep, this code was written ~4am ;p

template<int Deg, int N>
struct my_sinpow {
  static double result() { return my_sinpow<Deg,N-1>::result() * (((double)Deg*M_PI)/180.0); }
};

template<int Deg>
struct my_sinpow<Deg,1> {
  static double result() { return (((double)Deg*M_PI)/180.0); }
};

template<int N>
struct my_factorial {
  static double result() { return (double)N * my_factorial<N-1>::result(); }
};

template<>
struct my_factorial<1> {
  static double result() { return 1.0; }
};

template<int X, int N>
struct my_pow {
  static const int result = X * my_pow<X,N-1>::result;
};

template<int X>
struct my_pow<X, 1> {
  static const int result = X;
};

template<int Deg, int N>
struct my_sin_worker {
  static double result() { return my_sin_worker<Deg, N-1>::result() + (double)my_pow<-1,N>::result * my_sinpow<Deg,2*N+1>::result() / (my_factorial<2*N+1>::result()); }
};

template<int Deg>
struct my_sin_worker<Deg,0> {
  static double result() { return (((double)Deg*M_PI)/180.0); }
};

template<int Deg> 
struct my_sin {
  static double result() { return my_sin_worker<Deg, 6>::result(); }
};

template<int Deg>
struct deg_to_rad {
  static double result() { return (((double)Deg*M_PI)/180.0); }
};

int
main(void)
{
  printf("sin(20 deg) == %f\t%f\n", sin(deg_to_rad<20>::result()), my_sin<20>::result());
  printf("sin(30 deg) == %f\t%f\n", sin(deg_to_rad<30>::result()), my_sin<30>::result());
  printf("sin(40 deg) == %f\t%f\n", sin(deg_to_rad<40>::result()), my_sin<40>::result());
  printf("sin(50 deg) == %f\t%f\n", sin(deg_to_rad<50>::result()), my_sin<50>::result());
  printf("sin(60 deg) == %f\t%f\n", sin(deg_to_rad<60>::result()), my_sin<60>::result());


  return 0;
}

【 design & art by Xa / Gynvael Coldwind 】 【 logo font (birdman regular) by utopiafonts / Dale Harris 】