间单实用的反三角函数库之C++实现

2023-09-17 14:24

        简单实用的反三角函数库

                                     周继光

                                     2006-2-27

    小弟对编程刚入门不久,自学路也是看着各位前辈们的贴子
走过来的,现偶有小得,不敢独享,遂与大家分享。
  小弟在写一个OpenGL引擎时,需要用到反余函数,但找了
好久都没找到,C语言的数学库提供的反三角函数又不好用,所
以便自己实现了一个,采用的是间单的查表法。
  恳请各位前辈指点不足,新手朋友们提问,欢迎大家灌水!

FMath.h 文件定义如下:

//2006-1-20
//1.0
//周继光
#ifndef FMATH_H_
#define FMATH_H_

const float PI    = 3.1415926535897932384626433832795f;
const float PI2    = 6.283185307179586476925286766559f;
const float A_PI  = 0.017453292519943295769236907684886f;
const float PI_A  = 57.324840764331210191082802547771f;

//
//常用算法定义
///
template
T Max( T a, T b )
{
 return ( a > b ? a : b );
}

template
T Min( T a, T b )
{
 return ( a > b ? b : a );
}

template
void ReleasePointer( T &point )
{
 if( NULL != point )
 {
  delete[] point;
 }

 point = NULL;
}

template
void CopyObject( T &Destination, T &Source )
{
 memcpy( &Destination, &Source, sizeof( Destination ) );
}


typedef union
{
 int i;
 float f;
}INTORFLOAT;

class CFloat
{
public:

 float Absolute( float f )
 {
  INTORFLOAT temp;
  temp.f = f;
  temp.i &= 0x7fffffff;
  return temp.f;
 }

 int ChangeToInt( float f )
 {
  INTORFLOAT basic, temp;

  basic.f = 12582912.0f;
  temp.f = f;
  temp.f += basic.f;
  temp.i -= basic.i;
  return temp.i;
 }

 bool AsZero( float f )
 {
  return Absolute( f ) < 0.000001; 
 }

 bool BiggerThanZero( float f )
 {
  INTORFLOAT temp;
  temp.f = f;
  temp.i &= 0x80000000;
  return !temp.i;
 }

 bool SmallThanZero( float f )
 {
  INTORFLOAT temp;
  temp.f = f;
  temp.i &= 0x80000000;
  return !( !temp.i );
 }

/*
 float UINT64ToFloat( UINT64 uint64 )
 {
  TSC tsc;
  tsc.tsc = uint64;
  
  float ret = ( float )tsc.low + ( float )tsc.heigh * 4294967296.0f;
  return ret;
 }
*/
};
//
//end
///


//Singleton template define
///
template class Singleton
{
    static T* ms_Singleton;

public:
    Singleton( void )
    {
        assert( !ms_Singleton );
        int offset = (int)(T*)1 - (int)(Singleton *)(T*)1;
        ms_Singleton = (T*)((int)this + offset);
    }
  
   ~Singleton( void )
    { assert( ms_Singleton );
  ms_Singleton = 0;
 }
   
 static T& GetSingleton( void )
    { 
  assert( ms_Singleton );
  return ( *ms_Singleton );
 }
   
 static T* GetSingletonPtr( void )
    {
  assert( ms_Singleton );
  return ( ms_Singleton );
 }
};

template T* Singleton ::ms_Singleton = 0;
/
//end
/


//精度控制 注意:精度定义不要大于7。
const DWORD MATH_PRECISION = 6;

const DWORD MATH_CONSTANT = 128 << MATH_PRECISION;
const DWORD MATH_MAX = MATH_CONSTANT - 1;
const DWORD MATH_LOCA = MATH_CONSTANT >> 2;
const float MATH_API = MATH_CONSTANT / PI2;
const float MATH_PIA = 1.0f / MATH_API;
const float MATH_RATE = 360.0f / MATH_CONSTANT;

class CMath : public Singleton
{
protected:
 float m_sintable[MATH_CONSTANT];

public:
 CMath::CMath()
 {
  for( DWORD dwLoop = 0; dwLoop < MATH_CONSTANT; ++dwLoop  )
  {
   m_sintable[dwLoop] = ( float )sin( ( double )dwLoop * MATH_PIA );
  }
 }

 ~CMath(){}

 float Sin( float theta );
 float Cos( float theta );
 float ArcSin( float sin );
 float ArcCos( float cos );
};
 
#define MATH_INSTANCE   static CMath math;
#define MATH   CMath::GetSingleton()


 inline float CMath::Sin( float theta )
 {
  theta = theta * MATH_API;
  CFloat Float;
  return m_sintable[( Float.ChangeToInt( theta ) )
       & MATH_MAX];
 }

 inline float CMath::Cos( float theta )
 {
  theta = theta * MATH_API;
  CFloat Float;
  return m_sintable[( Float.ChangeToInt( theta ) + MATH_LOCA )
       & MATH_MAX];
 }
 ///*
 //二分查找法
 inline float CMath::ArcSin( float sina )
 {
  CFloat Float;
  sina = Float.Absolute( sina );
  if( sina > 1.0f )
  {
   return 0.0f;
  }
  if( sina >= m_sintable[MATH_LOCA - 1] )
  {
   return 90.0f;
  }
  
  float sintemp = 1.0f / sina;
   
  DWORD dwBegin = 0;
  DWORD dwEnd = MATH_LOCA;
  DWORD dwMid = 0;
  DWORD dwNumber = 0;
  
  while( 1 != dwNumber )
  {
   dwNumber = ( dwEnd - dwBegin ) >> 1;
   dwMid = dwNumber + dwBegin;

   if( sina < m_sintable[dwMid] )
   {
    if( sina >= m_sintable[dwMid-1] )
    {
     return( float )( dwMid - 1 ) * m_sintable[dwMid-1] * sintemp * MATH_RATE;
    }
    else
    {
     dwEnd = dwMid;
    }
   }
   else
   {
    dwBegin = dwMid;
   }
  }
  return 90.0f;
 }
 //*/
 
 /*
 //顺序搜索法
 inline float CMath::ArcSin( float sina )
 {
  
  CFloat Float;
  sina = Float.Absolute( sina );
  if( sina > 1.0f )
  {
   return 0.0f;
  }
  if( sina >= m_sintable[MATH_LOCA - 1] )
  {
   return 90.0f;
  }
  if( sina < m_sintable[1] )
  {
   return 0.0f;
  }
  
  float sintemp = 1.0f / sina;

  for( DWORD dwLoop = 1; dwLoop < MATH_LOCA; ++dwLoop )
  {
   if( sina < m_sintable[dwLoop] )
   {
    return ( float )( dwLoop - 1 ) * m_sintable[dwLoop-1] * sintemp * MATH_RATE;
   }  
  }
  
  return 90.0f;
 }
 */
 
 inline float CMath::ArcCos( float cos )
 {
  return ( 90.0f - ArcSin( cos ) ); 
 }
#endif

如此使用:

TEST.CPP   :

#include
#include
#include
#include
#include
#include"FMath.h"

MATH_INSTANCE


int main()
{
 for( DWORD dwLoop = 0; dwLoop <= 90; ++dwLoop )
 {
  cout<<"Angle in:  "<  cout<<"Angle out: "<  cout<<"Sin: "<< MATH.Sin( dwLoop * A_PI )< }
 
 cout< for( dwLoop = 0; dwLoop <= 90; ++dwLoop )
 {
  cout<<"Angle in:  "<  cout<<"Angle out: "<  cout<<"Cos: "<< MATH.Cos( dwLoop * A_PI )< }
 return 0;
}