메뉴 건너뛰기


Computer Science > Algorithm

기타 삼각함수의 (속도)최적화 구현

2013.11.27 02:28

푸우 조회 수:12093


출처 : http://blog.naver.com/minzkn?Redirect=Log&logNo=60003908545


이 소스는 삼각함수(sin, cos, tan)를 계산에 의해서 구현하는 방법이 아니고 
이미 계산된 16bit 고정소숫점 table 을가지고 구현한것입니다. 

어쨌건 최적화 속도가 요구되는 실무에 적용하고자 만들어 본겁니다. 
FPU를 사용하지 않고 단순한 테이블 연산만 사용되므로 굉장히 빠른것은 당연하겠죠. 

그리고 일반 math library (libm.so) 에서는 삼각함수의 입력값을 radian 으로 받는데 반해서 이 예제 소스는 각도를 그대로 입력으로 받는다는 것이 꽤 유용한 분야가 있을겁니다. 

복잡하지도 않고 오히려 너무 단순무식한 방법이 이럴때는 유용한것 같네요. 


/*
 Copyright (C) Information Equipment co.,LTD.
 All rights reserved.
 Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
 CVSTAG="$Header$"
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int (mzapi_sin_16fp)(int s_angle);
int (mzapi_cos_16fp)(int s_angle);
int (mzapi_tan_16fp)(int s_angle);
double (mzapi_sin)(int s_angle);
double (mzapi_cos)(int s_angle);
double (mzapi_tan)(int s_angle);
void (mzapi_rotate)(int *s_x, int *s_y, int s_angle);
static int __g_mzapi_sin90_table__[] = { 
      0,  1143,  2287,  3429,  4571,  5711,  6850,  7986,  9120, 10252,
  11380, 12504, 13625, 14742, 15854, 16961, 18064, 19160, 20251, 21336,
  22414, 23486, 24550, 25606, 26655, 27696, 28729, 29752, 30767, 31772,
  32767, 33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243,
  42125, 42995, 43852, 44695, 45525, 46340, 47142, 47929, 48702, 49460,
  50203, 50931, 51643, 52339, 53019, 53683, 54331, 54963, 55577, 56175,
  56755, 57319, 57864, 58393, 58903, 59395, 59870, 60326, 60763, 61183,
  61583, 61965, 62328, 62672, 62997, 63302, 63589, 63856, 64103, 64331,
  64540, 64729, 64898, 65047, 65176, 65286, 65376, 65446, 65496, 65526,
  65536
};
 
#define __mzapi_sin90__(m_angle) __g_mzapi_sin90_table__[m_angle]
#define __mzapi_angle_degree_360__(m_angle) \
do \
{ \
 while((m_angle) < ((int)0))(m_angle) += (int)360; \
 while((m_angle) >= ((int)360))(m_angle) -= (int)360; \
}while(0)
#define __mzapi_fixed16_floating_point_to_double__(m_value) (((double)(m_value)) / ((double)65536.0))
int (mzapi_sin_16fp)(int s_angle)
{
 __mzapi_angle_degree_360__(s_angle);
 if(s_angle <= 90)return(__mzapi_sin90__(s_angle));
 if(s_angle <= 180)return(__mzapi_sin90__(((int)180) - s_angle));
 if(s_angle <= 270)return(-__mzapi_sin90__(s_angle - ((int)180)));
 return(-__mzapi_sin90__(((int)360) - s_angle));
}
int (mzapi_cos_16fp)(int s_angle)
{
 __mzapi_angle_degree_360__(s_angle);
 if(s_angle <= 90)return(__mzapi_sin90__(((int)90) - s_angle));
 if(s_angle <= 180)return(-__mzapi_sin90__(s_angle - ((int)90)));
 if(s_angle <= 270)return(-__mzapi_sin90__(((int)270) - s_angle));
 return(__mzapi_sin90__(s_angle - ((int)270)));
}
int (mzapi_tan_16fp)(int s_angle)
{
 __mzapi_angle_degree_360__(s_angle);
 if((s_angle == ((int)90)) || (s_angle == ((int)270)))s_angle = (int)89;
 return((mzapi_sin_16fp(s_angle) << 16) / mzapi_cos_16fp(s_angle));
}
double (mzapi_sin)(int s_angle)
{
 return(__mzapi_fixed16_floating_point_to_double__(mzapi_sin_16fp(s_angle)));
}
double (mzapi_cos)(int s_angle)
{
 return(__mzapi_fixed16_floating_point_to_double__(mzapi_cos_16fp(s_angle)));
}
double (mzapi_tan)(int s_angle)
{
 __mzapi_angle_degree_360__(s_angle);
 if((s_angle == ((int)90)) || (s_angle == ((int)270)))s_angle = (int)89;
 return((mzapi_sin(s_angle) * ((double)65536.0)) / mzapi_cos(s_angle));
}
void (mzapi_rotate)(int *s_x, int *s_y, int s_angle)
{
 int s_tx = *(s_x), s_ty = *(s_y);
 *(s_x) = ((s_tx * mzapi_sin_16fp(s_angle)) - (s_ty * mzapi_cos_16fp(s_angle))) / ((int)65536);
 *(s_y) = -(((s_ty * mzapi_sin_16fp(s_angle)) + (s_tx * mzapi_cos_16fp(s_angle))) / ((int)65536));
}
int (main)(void)
{
 do
 {
  int s_angle, s_col, s_count, s_columns = 60;
  double s_double;
  for(s_angle = 0;s_angle < 360;s_angle++)
  {
   s_double = mzapi_sin(s_angle);
   (void)fprintf(stdout, "%+.6f ", s_double);
   s_col = (s_columns >> 1) + (int)(((double)(s_columns >> 1)) * s_double);
   for(s_count = 0;s_count < s_col;s_count++)(void)fprintf(stdout, " ");
   (void)fprintf(stdout, "* %3d\n", s_angle);
   (void)fflush(stdout);
   usleep(10000);
  }
 }while(1);
 return(0);
}