/***************************************************************************
 *                          Zanoza Modeler v2.x                            *
 *      This is unpublished propietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                   Copyright (c) 2002 Zanoza Software.                   *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler's fast math routines
 *--------------------------------------------------------------------------
 * @histroy: 16.04.2003. Created
 */
#ifndef zmfastmath_h_included
#define zmfastmath_h_included
#include <math.h>

namespace zmath
{

  //
  // add some stuff from Orge::Math(). sin/cos/tan lookup tables, etc.
  //

#define MINFLOAT 0.000001f

#ifdef G_PI
# undef G_PI
#endif
#define G_PI        ((float)3.141592654f)

#define G_INVPI     ((float)0.318309886f)   // 1.0f/G_PI
#define G_2PI       ((float)6.283185307f)   // 2*G_PI
#define G_PI2       ((float)1.570796326f)   // G_PI/2
#define DEG_IN_RAD  ((float)57.295779513f)  // 180/G_PI
#define RAD_IN_DEG  ((float)0.017453292f)   // G_PI/180
#define DEG2RAD(d)  ((d)*RAD_IN_DEG)        // degrees to radians convertion.
#define RAD2DEG(r)  ((r)*DEG_IN_RAD)        // radians to degrees convertion.

  //
  // sign
  //
  inline float sgn(float v) { return v > 0.0f ? 1.0f : v == 0.0f ? 0.0f : -1.0f; }
  inline long  sgn(long v)  { return v > 0 ? 1 : v == 0 ? 0 : -1; }


  //-------------------------------------------------------
  // @name : float2int
  // cast float to int
  // @param float f                        : 
  //-------------------------------------------------------
  inline int float2int(float f) 
  {
    return (int)f;
    /*
    int int_value;
    __asm  fld  f
    __asm  mov  edx, dword ptr [int_value]
    __asm  FRNDINT
    __asm  fistp dword ptr [edx];
    return int_value;
    */
  }

  //-------------------------------------------------------
  // @name : invSqrt
  // Computes 1/sqrt(x). Origin: Quake3 source
  // @param float x                        : 
  //-------------------------------------------------------
  inline float invSqrt (float x)
  {
    float xhalf = 0.5f*x;
    int i = *(int*)&x;
    i = 0x5f3759df - (i >> 1);
    x = *(float*)&i;
    //first iteration
    x = x*(1.5f - xhalf*x*x);
    //second iteration (better precision)
    x = x*(1.5f - xhalf*x*x);
    return x;
  }
  

  //-------------------------------------------------------
  // @name :  fSqrt
  // Computes sqrt(x);
  // @param float x                        : 
  //-------------------------------------------------------
  extern DLL_LINKAGE float  fSqrt(float x);

  // clamping function
  template <class T> inline T& clamp(T& f, const T _min, const T _max)
  { 
    if (f < _min)
      f = _min;
    else
      if (f > _max)
        f = _max;
    return f;
  }

};//zmath

#ifdef ZM_NO_ZMATH
# define SGN(x)             ((x) > 0 ? 1 : (x)==0 ? 0 : -1)
# define SQRTF(x)           sqrtf(x)
# define INV_SQRTF(x)       (1.0f/SQRTF(x))
# define INT(x)             ((int)(x))
#else
# define SGN(x)             zmath::sgn(x)
# define SQRTF(x)           zmath::fSqrt(x)
# define INV_SQRTF(x)       zmath::invSqrt(x)
# define INT(x)             zmath::float2int(x)
#endif//ZM_NO_ZMATH

#endif //zmfastmath_h_included


