cmath.I 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file cmath.I
  10. * @author drose
  11. * @date 2000-05-19
  12. */
  13. #ifdef __INTEL_COMPILER
  14. // see float.h
  15. #define FPU_CONTROLWORD_WRITEMASK 0xFFFFF // if you look at defn of _CW_DEFAULT, all settings fall within 0xFFFFF
  16. #define FPU_CONTROLWORD_NEW_SETTING _CW_DEFAULT
  17. #endif
  18. /**
  19. *
  20. */
  21. INLINE float
  22. csqrt(float v) {
  23. return sqrtf(v);
  24. }
  25. /**
  26. *
  27. */
  28. INLINE float
  29. csin(float v) {
  30. return sinf(v);
  31. }
  32. /**
  33. *
  34. */
  35. INLINE float
  36. ccos(float v) {
  37. return cosf(v);
  38. }
  39. /**
  40. *
  41. */
  42. INLINE float ctan(float v) {
  43. return tanf(v);
  44. }
  45. /**
  46. *
  47. */
  48. INLINE void
  49. csincos(float v, float *sin_result, float *cos_result) {
  50. // MS VC defines _M_IX86 for x86. gcc should define _X86_
  51. #if defined(_M_IX86) || defined(_X86_)
  52. // #define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
  53. __asm {
  54. mov eax, sin_result
  55. mov edx, cos_result
  56. fld v
  57. fsincos
  58. fstp DWORD ptr [edx]
  59. fstp DWORD ptr [eax]
  60. }
  61. #else //!_X86_
  62. *sin_result = sinf(v);
  63. *cos_result = cosf(v);
  64. #endif //!_X86_
  65. }
  66. /**
  67. * Computes sin(x) / x, well-behaved as x approaches 0.
  68. */
  69. INLINE float
  70. csin_over_x(float v) {
  71. if (1.0f + v * v == 1.0f) {
  72. return 1.0f;
  73. } else {
  74. return csin(v) / v;
  75. }
  76. }
  77. /**
  78. *
  79. */
  80. INLINE float
  81. cabs(float v) {
  82. return fabs(v);
  83. }
  84. /**
  85. *
  86. */
  87. INLINE float
  88. catan(float v) {
  89. return atanf(v);
  90. }
  91. /**
  92. *
  93. */
  94. INLINE float
  95. catan2(float y, float x) {
  96. return atan2f(y, x);
  97. }
  98. /**
  99. *
  100. */
  101. INLINE float
  102. casin(float v) {
  103. return asinf(v);
  104. }
  105. /**
  106. *
  107. */
  108. INLINE float
  109. cacos(float v) {
  110. return acosf(v);
  111. }
  112. /**
  113. * This is similar to fmod(), but it behaves properly when x is negative: that
  114. * is, it always returns a value in the range [0, y), assuming y is positive.
  115. */
  116. INLINE float
  117. cmod(float x, float y) {
  118. return x - floor(x / y) * y;
  119. }
  120. /**
  121. *
  122. */
  123. INLINE float
  124. cpow(float x, float y) {
  125. return powf(x, y);
  126. }
  127. /**
  128. *
  129. */
  130. INLINE double
  131. cfloor(double f) {
  132. #ifdef __INTEL_COMPILER
  133. // intel floor doesnt work right if fpu mode is not double, so make
  134. // double-prec mode is on
  135. unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
  136. _controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
  137. double retval=floor(f);
  138. _controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
  139. return retval;
  140. #else
  141. return floor(f);
  142. #endif
  143. }
  144. /**
  145. *
  146. */
  147. INLINE double
  148. cceil(double f) {
  149. #ifdef __INTEL_COMPILER
  150. // intel ceil doesnt work right if fpu mode is not double, so make double-
  151. // prec mode is on
  152. unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
  153. _controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
  154. double retval=ceil(f);
  155. _controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
  156. return retval;
  157. #else
  158. return ceil(f);
  159. #endif
  160. }
  161. /**
  162. * Returns the fractional component of f: f - cfloor(f).
  163. */
  164. INLINE double
  165. cfrac(double f) {
  166. return f - cfloor(f);
  167. }
  168. /**
  169. *
  170. */
  171. INLINE double
  172. csqrt(double v) {
  173. return sqrt(v);
  174. }
  175. /**
  176. *
  177. */
  178. INLINE double
  179. csin(double v) {
  180. return sin(v);
  181. }
  182. /**
  183. *
  184. */
  185. INLINE double
  186. ccos(double v) {
  187. return cos(v);
  188. }
  189. /**
  190. *
  191. */
  192. INLINE double
  193. ctan(double v) {
  194. return tan(v);
  195. }
  196. /**
  197. *
  198. */
  199. INLINE void
  200. csincos(double v, double *sin_result, double *cos_result) {
  201. #if defined(_M_IX86) || defined(_X86_)
  202. // #define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
  203. __asm {
  204. mov eax, sin_result
  205. mov edx, cos_result
  206. fld v
  207. fsincos
  208. fstp QWORD ptr [edx]
  209. fstp QWORD ptr [eax]
  210. }
  211. #else //!_X86_
  212. *sin_result = sin(v);
  213. *cos_result = cos(v);
  214. #endif //!_X86_
  215. }
  216. /**
  217. * Computes sin(x) / x, well-behaved as x approaches 0.
  218. */
  219. INLINE double
  220. csin_over_x(double v) {
  221. if (1.0 + v * v == 1.0) {
  222. return 1.0;
  223. } else {
  224. return csin(v) / v;
  225. }
  226. }
  227. /**
  228. *
  229. */
  230. INLINE double
  231. cabs(double v) {
  232. return fabs(v);
  233. }
  234. /**
  235. *
  236. */
  237. INLINE double
  238. catan(double v) {
  239. return atan(v);
  240. }
  241. /**
  242. *
  243. */
  244. INLINE double
  245. catan2(double y, double x) {
  246. return atan2(y, x);
  247. }
  248. /**
  249. *
  250. */
  251. INLINE double
  252. casin(double v) {
  253. return asin(v);
  254. }
  255. /**
  256. *
  257. */
  258. INLINE double
  259. cacos(double v) {
  260. return acos(v);
  261. }
  262. /**
  263. * This is similar to fmod(), but it behaves properly when x is negative: that
  264. * is, it always returns a value in the range [0, y), assuming y is positive.
  265. */
  266. INLINE double
  267. cmod(double x, double y) {
  268. return x - cfloor(x / y) * y;
  269. }
  270. /**
  271. *
  272. */
  273. INLINE double
  274. cpow(double x, double y) {
  275. return pow(x, y);
  276. }
  277. /**
  278. *
  279. */
  280. INLINE int
  281. cpow(int x, int y) {
  282. int result = 1;
  283. if (y >= 0) {
  284. for(; y > 0; --y) {
  285. result *= x;
  286. }
  287. return result;
  288. } else {
  289. for(; y < 0; ++y) {
  290. result *= x;
  291. }
  292. return 1 / result;
  293. }
  294. }
  295. /**
  296. *
  297. */
  298. INLINE bool
  299. cnan(float v) {
  300. #if __FINITE_MATH_ONLY__
  301. // GCC's isnan breaks when using -ffast-math.
  302. union { float f; uint32_t x; } u = { v };
  303. return ((u.x << 1) > 0xff000000u);
  304. #elif !defined(_WIN32)
  305. return std::isnan(v);
  306. #else
  307. return (_isnan(v) != 0);
  308. #endif
  309. }
  310. /**
  311. *
  312. */
  313. INLINE bool
  314. cnan(double v) {
  315. #if __FINITE_MATH_ONLY__
  316. // GCC's isnan breaks when using -ffast-math.
  317. union { double d; uint64_t x; } u = { v };
  318. return ((u.x << 1) > 0xffe0000000000000ull);
  319. #elif !defined(_WIN32)
  320. return std::isnan(v);
  321. #else
  322. return (_isnan(v) != 0);
  323. #endif
  324. }
  325. /**
  326. *
  327. */
  328. INLINE bool
  329. cinf(float v) {
  330. #if __FINITE_MATH_ONLY__
  331. // GCC's isinf breaks when using -ffast-math.
  332. union { float f; uint32_t x; } u = { v };
  333. return ((u.x << 1) == 0xff000000u);
  334. #elif !defined(_WIN32)
  335. return std::isinf(v);
  336. #else
  337. return (_isnan(v) == 0 && _finite(v) == 0);
  338. #endif
  339. }
  340. /**
  341. *
  342. */
  343. INLINE bool
  344. cinf(double v) {
  345. #if __FINITE_MATH_ONLY__
  346. // GCC's isinf breaks when using -ffast-math.
  347. union { double d; uint64_t x; } u = { v };
  348. return ((u.x << 1) == 0xffe0000000000000ull);
  349. #elif !defined(_WIN32)
  350. return std::isinf(v);
  351. #else
  352. return (_isnan(v) == 0 && _finite(v) == 0);
  353. #endif
  354. }
  355. /**
  356. *
  357. */
  358. INLINE float
  359. make_nan(float) {
  360. return std::numeric_limits<float>::quiet_NaN();
  361. }
  362. /**
  363. *
  364. */
  365. INLINE double
  366. make_nan(double) {
  367. return std::numeric_limits<double>::quiet_NaN();
  368. }
  369. /**
  370. *
  371. */
  372. INLINE float
  373. make_inf(float) {
  374. return std::numeric_limits<float>::infinity();
  375. }
  376. /**
  377. *
  378. */
  379. INLINE double
  380. make_inf(double) {
  381. return std::numeric_limits<double>::infinity();
  382. }
  383. /**
  384. * This is similar to fmod(), but it behaves properly when x is negative: that
  385. * is, it always returns a value in the range [0, y), assuming y is positive.
  386. *
  387. * This integer-valued function is provided since the built-in modulo operator
  388. * % does not work properly for negative x.
  389. */
  390. INLINE int
  391. cmod(int x, int y) {
  392. if (x < 0) {
  393. return y - 1 - ((-x - 1) % y);
  394. } else {
  395. return x % y;
  396. }
  397. }