You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
13 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. /// OpenGL Mathematics (glm.g-truc.net)
  3. ///
  4. /// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
  5. /// Permission is hereby granted, free of charge, to any person obtaining a copy
  6. /// of this software and associated documentation files (the "Software"), to deal
  7. /// in the Software without restriction, including without limitation the rights
  8. /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. /// copies of the Software, and to permit persons to whom the Software is
  10. /// furnished to do so, subject to the following conditions:
  11. ///
  12. /// The above copyright notice and this permission notice shall be included in
  13. /// all copies or substantial portions of the Software.
  14. ///
  15. /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. /// THE SOFTWARE.
  22. ///
  23. /// @ref core
  24. /// @file glm/core/intrinsic_common.inl
  25. /// @date 2009-05-08 / 2011-06-15
  26. /// @author Christophe Riccio
  27. ///////////////////////////////////////////////////////////////////////////////////
  28. namespace glm{
  29. namespace detail{
  30. #if(GLM_COMPILER & GLM_COMPILER_VC)
  31. #pragma warning(push)
  32. #pragma warning(disable : 4510 4512 4610)
  33. #endif
  34. union ieee754_QNAN
  35. {
  36. const float f;
  37. struct i
  38. {
  39. const unsigned int mantissa:23, exp:8, sign:1;
  40. };
  41. ieee754_QNAN() : f(0.0)/*, mantissa(0x7FFFFF), exp(0xFF), sign(0x0)*/ {}
  42. };
  43. #if(GLM_COMPILER & GLM_COMPILER_VC)
  44. #pragma warning(pop)
  45. #endif
  46. static const __m128 GLM_VAR_USED zero = _mm_setzero_ps();
  47. static const __m128 GLM_VAR_USED one = _mm_set_ps1(1.0f);
  48. static const __m128 GLM_VAR_USED minus_one = _mm_set_ps1(-1.0f);
  49. static const __m128 GLM_VAR_USED two = _mm_set_ps1(2.0f);
  50. static const __m128 GLM_VAR_USED three = _mm_set_ps1(3.0f);
  51. static const __m128 GLM_VAR_USED pi = _mm_set_ps1(3.1415926535897932384626433832795f);
  52. static const __m128 GLM_VAR_USED hundred_eighty = _mm_set_ps1(180.f);
  53. static const __m128 GLM_VAR_USED pi_over_hundred_eighty = _mm_set_ps1(0.017453292519943295769236907684886f);
  54. static const __m128 GLM_VAR_USED hundred_eighty_over_pi = _mm_set_ps1(57.295779513082320876798154814105f);
  55. static const ieee754_QNAN absMask;
  56. static const __m128 GLM_VAR_USED abs4Mask = _mm_set_ps1(absMask.f);
  57. static const __m128 GLM_VAR_USED _epi32_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000)));
  58. //static const __m128 GLM_VAR_USED _epi32_inv_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF));
  59. //static const __m128 GLM_VAR_USED _epi32_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000));
  60. //static const __m128 GLM_VAR_USED _epi32_inv_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x807FFFFF));
  61. //static const __m128 GLM_VAR_USED _epi32_min_norm_pos = _mm_castsi128_ps(_mm_set1_epi32(0x00800000));
  62. static const __m128 GLM_VAR_USED _epi32_0 = _mm_set_ps1(0);
  63. static const __m128 GLM_VAR_USED _epi32_1 = _mm_set_ps1(1);
  64. static const __m128 GLM_VAR_USED _epi32_2 = _mm_set_ps1(2);
  65. static const __m128 GLM_VAR_USED _epi32_3 = _mm_set_ps1(3);
  66. static const __m128 GLM_VAR_USED _epi32_4 = _mm_set_ps1(4);
  67. static const __m128 GLM_VAR_USED _epi32_5 = _mm_set_ps1(5);
  68. static const __m128 GLM_VAR_USED _epi32_6 = _mm_set_ps1(6);
  69. static const __m128 GLM_VAR_USED _epi32_7 = _mm_set_ps1(7);
  70. static const __m128 GLM_VAR_USED _epi32_8 = _mm_set_ps1(8);
  71. static const __m128 GLM_VAR_USED _epi32_9 = _mm_set_ps1(9);
  72. static const __m128 GLM_VAR_USED _epi32_127 = _mm_set_ps1(127);
  73. //static const __m128 GLM_VAR_USED _epi32_ninf = _mm_castsi128_ps(_mm_set1_epi32(0xFF800000));
  74. //static const __m128 GLM_VAR_USED _epi32_pinf = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000));
  75. static const __m128 GLM_VAR_USED _ps_1_3 = _mm_set_ps1(0.33333333333333333333333333333333f);
  76. static const __m128 GLM_VAR_USED _ps_0p5 = _mm_set_ps1(0.5f);
  77. static const __m128 GLM_VAR_USED _ps_1 = _mm_set_ps1(1.0f);
  78. static const __m128 GLM_VAR_USED _ps_m1 = _mm_set_ps1(-1.0f);
  79. static const __m128 GLM_VAR_USED _ps_2 = _mm_set_ps1(2.0f);
  80. static const __m128 GLM_VAR_USED _ps_3 = _mm_set_ps1(3.0f);
  81. static const __m128 GLM_VAR_USED _ps_127 = _mm_set_ps1(127.0f);
  82. static const __m128 GLM_VAR_USED _ps_255 = _mm_set_ps1(255.0f);
  83. static const __m128 GLM_VAR_USED _ps_2pow23 = _mm_set_ps1(8388608.0f);
  84. static const __m128 GLM_VAR_USED _ps_1_0_0_0 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
  85. static const __m128 GLM_VAR_USED _ps_0_1_0_0 = _mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f);
  86. static const __m128 GLM_VAR_USED _ps_0_0_1_0 = _mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f);
  87. static const __m128 GLM_VAR_USED _ps_0_0_0_1 = _mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f);
  88. static const __m128 GLM_VAR_USED _ps_pi = _mm_set_ps1(3.1415926535897932384626433832795f);
  89. static const __m128 GLM_VAR_USED _ps_pi2 = _mm_set_ps1(6.283185307179586476925286766560f);
  90. static const __m128 GLM_VAR_USED _ps_2_pi = _mm_set_ps1(0.63661977236758134307553505349006f);
  91. static const __m128 GLM_VAR_USED _ps_pi_2 = _mm_set_ps1(1.5707963267948966192313216916398f);
  92. static const __m128 GLM_VAR_USED _ps_4_pi = _mm_set_ps1(1.2732395447351626861510701069801f);
  93. static const __m128 GLM_VAR_USED _ps_pi_4 = _mm_set_ps1(0.78539816339744830961566084581988f);
  94. static const __m128 GLM_VAR_USED _ps_sincos_p0 = _mm_set_ps1(0.15707963267948963959e1f);
  95. static const __m128 GLM_VAR_USED _ps_sincos_p1 = _mm_set_ps1(-0.64596409750621907082e0f);
  96. static const __m128 GLM_VAR_USED _ps_sincos_p2 = _mm_set_ps1(0.7969262624561800806e-1f);
  97. static const __m128 GLM_VAR_USED _ps_sincos_p3 = _mm_set_ps1(-0.468175413106023168e-2f);
  98. static const __m128 GLM_VAR_USED _ps_tan_p0 = _mm_set_ps1(-1.79565251976484877988e7f);
  99. static const __m128 GLM_VAR_USED _ps_tan_p1 = _mm_set_ps1(1.15351664838587416140e6f);
  100. static const __m128 GLM_VAR_USED _ps_tan_p2 = _mm_set_ps1(-1.30936939181383777646e4f);
  101. static const __m128 GLM_VAR_USED _ps_tan_q0 = _mm_set_ps1(-5.38695755929454629881e7f);
  102. static const __m128 GLM_VAR_USED _ps_tan_q1 = _mm_set_ps1(2.50083801823357915839e7f);
  103. static const __m128 GLM_VAR_USED _ps_tan_q2 = _mm_set_ps1(-1.32089234440210967447e6f);
  104. static const __m128 GLM_VAR_USED _ps_tan_q3 = _mm_set_ps1(1.36812963470692954678e4f);
  105. static const __m128 GLM_VAR_USED _ps_tan_poleval = _mm_set_ps1(3.68935e19f);
  106. static const __m128 GLM_VAR_USED _ps_atan_t0 = _mm_set_ps1(-0.91646118527267623468e-1f);
  107. static const __m128 GLM_VAR_USED _ps_atan_t1 = _mm_set_ps1(-0.13956945682312098640e1f);
  108. static const __m128 GLM_VAR_USED _ps_atan_t2 = _mm_set_ps1(-0.94393926122725531747e2f);
  109. static const __m128 GLM_VAR_USED _ps_atan_t3 = _mm_set_ps1(0.12888383034157279340e2f);
  110. static const __m128 GLM_VAR_USED _ps_atan_s0 = _mm_set_ps1(0.12797564625607904396e1f);
  111. static const __m128 GLM_VAR_USED _ps_atan_s1 = _mm_set_ps1(0.21972168858277355914e1f);
  112. static const __m128 GLM_VAR_USED _ps_atan_s2 = _mm_set_ps1(0.68193064729268275701e1f);
  113. static const __m128 GLM_VAR_USED _ps_atan_s3 = _mm_set_ps1(0.28205206687035841409e2f);
  114. static const __m128 GLM_VAR_USED _ps_exp_hi = _mm_set_ps1(88.3762626647949f);
  115. static const __m128 GLM_VAR_USED _ps_exp_lo = _mm_set_ps1(-88.3762626647949f);
  116. static const __m128 GLM_VAR_USED _ps_exp_rln2 = _mm_set_ps1(1.4426950408889634073599f);
  117. static const __m128 GLM_VAR_USED _ps_exp_p0 = _mm_set_ps1(1.26177193074810590878e-4f);
  118. static const __m128 GLM_VAR_USED _ps_exp_p1 = _mm_set_ps1(3.02994407707441961300e-2f);
  119. static const __m128 GLM_VAR_USED _ps_exp_q0 = _mm_set_ps1(3.00198505138664455042e-6f);
  120. static const __m128 GLM_VAR_USED _ps_exp_q1 = _mm_set_ps1(2.52448340349684104192e-3f);
  121. static const __m128 GLM_VAR_USED _ps_exp_q2 = _mm_set_ps1(2.27265548208155028766e-1f);
  122. static const __m128 GLM_VAR_USED _ps_exp_q3 = _mm_set_ps1(2.00000000000000000009e0f);
  123. static const __m128 GLM_VAR_USED _ps_exp_c1 = _mm_set_ps1(6.93145751953125e-1f);
  124. static const __m128 GLM_VAR_USED _ps_exp_c2 = _mm_set_ps1(1.42860682030941723212e-6f);
  125. static const __m128 GLM_VAR_USED _ps_exp2_hi = _mm_set_ps1(127.4999961853f);
  126. static const __m128 GLM_VAR_USED _ps_exp2_lo = _mm_set_ps1(-127.4999961853f);
  127. static const __m128 GLM_VAR_USED _ps_exp2_p0 = _mm_set_ps1(2.30933477057345225087e-2f);
  128. static const __m128 GLM_VAR_USED _ps_exp2_p1 = _mm_set_ps1(2.02020656693165307700e1f);
  129. static const __m128 GLM_VAR_USED _ps_exp2_p2 = _mm_set_ps1(1.51390680115615096133e3f);
  130. static const __m128 GLM_VAR_USED _ps_exp2_q0 = _mm_set_ps1(2.33184211722314911771e2f);
  131. static const __m128 GLM_VAR_USED _ps_exp2_q1 = _mm_set_ps1(4.36821166879210612817e3f);
  132. static const __m128 GLM_VAR_USED _ps_log_p0 = _mm_set_ps1(-7.89580278884799154124e-1f);
  133. static const __m128 GLM_VAR_USED _ps_log_p1 = _mm_set_ps1(1.63866645699558079767e1f);
  134. static const __m128 GLM_VAR_USED _ps_log_p2 = _mm_set_ps1(-6.41409952958715622951e1f);
  135. static const __m128 GLM_VAR_USED _ps_log_q0 = _mm_set_ps1(-3.56722798256324312549e1f);
  136. static const __m128 GLM_VAR_USED _ps_log_q1 = _mm_set_ps1(3.12093766372244180303e2f);
  137. static const __m128 GLM_VAR_USED _ps_log_q2 = _mm_set_ps1(-7.69691943550460008604e2f);
  138. static const __m128 GLM_VAR_USED _ps_log_c0 = _mm_set_ps1(0.693147180559945f);
  139. static const __m128 GLM_VAR_USED _ps_log2_c0 = _mm_set_ps1(1.44269504088896340735992f);
  140. GLM_FUNC_QUALIFIER __m128 sse_abs_ps(__m128 x)
  141. {
  142. return _mm_and_ps(glm::detail::abs4Mask, x);
  143. }
  144. GLM_FUNC_QUALIFIER __m128 sse_sgn_ps(__m128 x)
  145. {
  146. __m128 Neg = _mm_set1_ps(-1.0f);
  147. __m128 Pos = _mm_set1_ps(1.0f);
  148. __m128 Cmp0 = _mm_cmplt_ps(x, zero);
  149. __m128 Cmp1 = _mm_cmpgt_ps(x, zero);
  150. __m128 And0 = _mm_and_ps(Cmp0, Neg);
  151. __m128 And1 = _mm_and_ps(Cmp1, Pos);
  152. return _mm_or_ps(And0, And1);
  153. }
  154. //floor
  155. GLM_FUNC_QUALIFIER __m128 sse_flr_ps(__m128 x)
  156. {
  157. __m128 rnd0 = sse_rnd_ps(x);
  158. __m128 cmp0 = _mm_cmplt_ps(x, rnd0);
  159. __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1);
  160. __m128 sub0 = _mm_sub_ps(rnd0, and0);
  161. return sub0;
  162. }
  163. //trunc
  164. /*
  165. GLM_FUNC_QUALIFIER __m128 _mm_trc_ps(__m128 v)
  166. {
  167. return __m128();
  168. }
  169. */
  170. //round
  171. GLM_FUNC_QUALIFIER __m128 sse_rnd_ps(__m128 x)
  172. {
  173. __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x);
  174. __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23);
  175. __m128 add0 = _mm_add_ps(x, or0);
  176. __m128 sub0 = _mm_sub_ps(add0, or0);
  177. return sub0;
  178. }
  179. //roundEven
  180. GLM_FUNC_QUALIFIER __m128 sse_rde_ps(__m128 x)
  181. {
  182. __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x);
  183. __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23);
  184. __m128 add0 = _mm_add_ps(x, or0);
  185. __m128 sub0 = _mm_sub_ps(add0, or0);
  186. return sub0;
  187. }
  188. GLM_FUNC_QUALIFIER __m128 sse_ceil_ps(__m128 x)
  189. {
  190. __m128 rnd0 = sse_rnd_ps(x);
  191. __m128 cmp0 = _mm_cmpgt_ps(x, rnd0);
  192. __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1);
  193. __m128 add0 = _mm_add_ps(rnd0, and0);
  194. return add0;
  195. }
  196. GLM_FUNC_QUALIFIER __m128 sse_frc_ps(__m128 x)
  197. {
  198. __m128 flr0 = sse_flr_ps(x);
  199. __m128 sub0 = _mm_sub_ps(x, flr0);
  200. return sub0;
  201. }
  202. GLM_FUNC_QUALIFIER __m128 sse_mod_ps(__m128 x, __m128 y)
  203. {
  204. __m128 div0 = _mm_div_ps(x, y);
  205. __m128 flr0 = sse_flr_ps(div0);
  206. __m128 mul0 = _mm_mul_ps(y, flr0);
  207. __m128 sub0 = _mm_sub_ps(x, mul0);
  208. return sub0;
  209. }
  210. /// TODO
  211. /*
  212. GLM_FUNC_QUALIFIER __m128 sse_modf_ps(__m128 x, __m128i & i)
  213. {
  214. __m128 empty;
  215. return empty;
  216. }
  217. */
  218. //GLM_FUNC_QUALIFIER __m128 _mm_min_ps(__m128 x, __m128 y)
  219. //GLM_FUNC_QUALIFIER __m128 _mm_max_ps(__m128 x, __m128 y)
  220. GLM_FUNC_QUALIFIER __m128 sse_clp_ps(__m128 v, __m128 minVal, __m128 maxVal)
  221. {
  222. __m128 min0 = _mm_min_ps(v, maxVal);
  223. __m128 max0 = _mm_max_ps(min0, minVal);
  224. return max0;
  225. }
  226. GLM_FUNC_QUALIFIER __m128 sse_mix_ps(__m128 v1, __m128 v2, __m128 a)
  227. {
  228. __m128 sub0 = _mm_sub_ps(glm::detail::one, a);
  229. __m128 mul0 = _mm_mul_ps(v1, sub0);
  230. __m128 mul1 = _mm_mul_ps(v2, a);
  231. __m128 add0 = _mm_add_ps(mul0, mul1);
  232. return add0;
  233. }
  234. GLM_FUNC_QUALIFIER __m128 sse_stp_ps(__m128 edge, __m128 x)
  235. {
  236. __m128 cmp = _mm_cmple_ps(x, edge);
  237. if(_mm_movemask_ps(cmp) == 0)
  238. return glm::detail::one;
  239. else
  240. return glm::detail::zero;
  241. }
  242. GLM_FUNC_QUALIFIER __m128 sse_ssp_ps(__m128 edge0, __m128 edge1, __m128 x)
  243. {
  244. __m128 sub0 = _mm_sub_ps(x, edge0);
  245. __m128 sub1 = _mm_sub_ps(edge1, edge0);
  246. __m128 div0 = _mm_sub_ps(sub0, sub1);
  247. __m128 clp0 = sse_clp_ps(div0, glm::detail::zero, glm::detail::one);
  248. __m128 mul0 = _mm_mul_ps(glm::detail::two, clp0);
  249. __m128 sub2 = _mm_sub_ps(glm::detail::three, mul0);
  250. __m128 mul1 = _mm_mul_ps(clp0, clp0);
  251. __m128 mul2 = _mm_mul_ps(mul1, sub2);
  252. return mul2;
  253. }
  254. /// \todo
  255. //GLM_FUNC_QUALIFIER __m128 sse_nan_ps(__m128 x)
  256. //{
  257. // __m128 empty;
  258. // return empty;
  259. //}
  260. /// \todo
  261. //GLM_FUNC_QUALIFIER __m128 sse_inf_ps(__m128 x)
  262. //{
  263. // __m128 empty;
  264. // return empty;
  265. //}
  266. // SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration
  267. // By Elan Ruskin, http://assemblyrequired.crashworks.org/
  268. GLM_FUNC_QUALIFIER __m128 sse_sqrt_wip_ss(__m128 const & x)
  269. {
  270. __m128 recip = _mm_rsqrt_ss(x); // "estimate" opcode
  271. const static __m128 three = {3, 3, 3, 3}; // aligned consts for fast load
  272. const static __m128 half = {0.5,0.5,0.5,0.5};
  273. __m128 halfrecip = _mm_mul_ss(half, recip);
  274. __m128 threeminus_xrr = _mm_sub_ss(three, _mm_mul_ss(x, _mm_mul_ss (recip, recip)));
  275. return _mm_mul_ss( halfrecip, threeminus_xrr);
  276. }
  277. }//namespace detail
  278. }//namespace glms