mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
449 lines
12 KiB
Plaintext
449 lines
12 KiB
Plaintext
// Filename: cmath.I
|
|
// Created by: drose (19May00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __INTEL_COMPILER
|
|
// see float.h
|
|
#define FPU_CONTROLWORD_WRITEMASK 0xFFFFF // if you look at defn of _CW_DEFAULT, all settings fall within 0xFFFFF
|
|
#define FPU_CONTROLWORD_NEW_SETTING _CW_DEFAULT
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csqrt
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
csqrt(float v) {
|
|
return sqrtf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csin
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
csin(float v) {
|
|
return sinf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ccos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
ccos(float v) {
|
|
return cosf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ctan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float ctan(float v) {
|
|
return tanf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csincos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void
|
|
csincos(float v, float *sin_result, float *cos_result) {
|
|
// MS VC defines _M_IX86 for x86. gcc should define _X86_
|
|
#if defined(_M_IX86) || defined(_X86_)
|
|
//#define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
|
|
__asm {
|
|
mov eax, sin_result
|
|
mov edx, cos_result
|
|
fld v
|
|
fsincos
|
|
fstp DWORD ptr [edx]
|
|
fstp DWORD ptr [eax]
|
|
}
|
|
#else //!_X86_
|
|
*sin_result = sinf(v);
|
|
*cos_result = cosf(v);
|
|
#endif //!_X86_
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csin_over_x
|
|
// Description: Computes sin(x) / x, well-behaved as x approaches 0.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
csin_over_x(float v) {
|
|
if (1.0f + v * v == 1.0f) {
|
|
return 1.0f;
|
|
} else {
|
|
return csin(v) / v;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cabs
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
cabs(float v) {
|
|
return fabs(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: catan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
catan(float v) {
|
|
return atanf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: catan2
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
catan2(float y, float x) {
|
|
return atan2f(y, x);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: casin
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
casin(float v) {
|
|
return asinf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cacos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
cacos(float v) {
|
|
return acosf(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cmod
|
|
// Description: This is similar to fmod(), but it behaves properly
|
|
// when x is negative: that is, it always returns a
|
|
// value in the range [0, y), assuming y is positive.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
cmod(float x, float y) {
|
|
return x - cfloor(x / y) * y;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cpow
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
cpow(float x, float y) {
|
|
return powf(x, y);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cfloor
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cfloor(double f) {
|
|
#ifdef __INTEL_COMPILER
|
|
// intel floor doesnt work right if fpu mode is not double, so make double-prec mode is on
|
|
unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
|
|
_controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
|
|
double retval=floor(f);
|
|
_controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
|
|
return retval;
|
|
#else
|
|
return floor(f);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cceil
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cceil(double f) {
|
|
#ifdef __INTEL_COMPILER
|
|
// intel ceil doesnt work right if fpu mode is not double, so make double-prec mode is on
|
|
unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
|
|
_controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
|
|
double retval=ceil(f);
|
|
_controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
|
|
return retval;
|
|
#else
|
|
return ceil(f);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cfrac
|
|
// Description: Returns the fractional component of f: f - cfloor(f).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cfrac(double f) {
|
|
return f - cfloor(f);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csqrt
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
csqrt(double v) {
|
|
return sqrt(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csin
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
csin(double v) {
|
|
return sin(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ccos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
ccos(double v) {
|
|
return cos(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: ctan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
ctan(double v) {
|
|
return tan(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csincos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void
|
|
csincos(double v, double *sin_result, double *cos_result) {
|
|
#if defined(_M_IX86) || defined(_X86_)
|
|
//#define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
|
|
__asm {
|
|
mov eax, sin_result
|
|
mov edx, cos_result
|
|
fld v
|
|
fsincos
|
|
fstp QWORD ptr [edx]
|
|
fstp QWORD ptr [eax]
|
|
}
|
|
#else //!_X86_
|
|
*sin_result = sin(v);
|
|
*cos_result = cos(v);
|
|
#endif //!_X86_
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: csin_over_x
|
|
// Description: Computes sin(x) / x, well-behaved as x approaches 0.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
csin_over_x(double v) {
|
|
if (1.0 + v * v == 1.0) {
|
|
return 1.0;
|
|
} else {
|
|
return csin(v) / v;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cabs
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cabs(double v) {
|
|
return fabs(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: catan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
catan(double v) {
|
|
return atan(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: catan2
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
catan2(double y, double x) {
|
|
return atan2(y, x);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: casin
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
casin(double v) {
|
|
return asin(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cacos
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cacos(double v) {
|
|
return acos(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cmod
|
|
// Description: This is similar to fmod(), but it behaves properly
|
|
// when x is negative: that is, it always returns a
|
|
// value in the range [0, y), assuming y is positive.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cmod(double x, double y) {
|
|
return x - cfloor(x / y) * y;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cpow
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
cpow(double x, double y) {
|
|
return pow(x, y);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cpow
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int
|
|
cpow(int x, int y) {
|
|
int result = 1;
|
|
|
|
if (y >= 0) {
|
|
for(; y > 0; --y) {
|
|
result *= x;
|
|
}
|
|
return result;
|
|
|
|
} else {
|
|
for(; y < 0; ++y) {
|
|
result *= x;
|
|
}
|
|
return 1 / result;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cnan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool
|
|
cnan(double v) {
|
|
#ifndef _WIN32
|
|
return std::isnan(v);
|
|
#else
|
|
return (_isnan(v) != 0);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cinf
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool
|
|
cinf(double v) {
|
|
#ifndef _WIN32
|
|
return std::isinf(v);
|
|
#else
|
|
return (_isnan(v) == 0 && _finite(v) == 0);
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: make_nan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
make_nan(float) {
|
|
#ifndef _WIN32
|
|
return nanf("");
|
|
#else
|
|
return std::numeric_limits<float>::quiet_NaN();
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: make_nan
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
make_nan(double) {
|
|
#ifndef _WIN32
|
|
return nan("");
|
|
#else
|
|
return std::numeric_limits<double>::quiet_NaN();
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: make_inf
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE float
|
|
make_inf(float) {
|
|
return std::numeric_limits<float>::infinity();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: make_inf
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double
|
|
make_inf(double) {
|
|
return std::numeric_limits<double>::infinity();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: cmod
|
|
// Description: This is similar to fmod(), but it behaves properly
|
|
// when x is negative: that is, it always returns a
|
|
// value in the range [0, y), assuming y is positive.
|
|
//
|
|
// This integer-valued function is provided since the
|
|
// built-in modulo operator % does not work properly for
|
|
// negative x.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int
|
|
cmod(int x, int y) {
|
|
if (x < 0) {
|
|
return y - 1 - ((-x - 1) % y);
|
|
} else {
|
|
return x % y;
|
|
}
|
|
}
|