1 /////////////////////////////////////////////////////////////////////////////////// 2 /// OpenGL Mathematics (glm.g-truc.net) 3 /// 4 /// Copyright (c) 2005 - 2014 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 29 namespace glm{ 30 namespace detail{ 31 32 #if(GLM_COMPILER & GLM_COMPILER_VC) 33 #pragma warning(push) 34 #pragma warning(disable : 4510 4512 4610) 35 #endif 36 37 union ieee754_QNAN 38 { 39 const float f; 40 struct i 41 { 42 const unsigned int mantissa:23, exp:8, sign:1; 43 }; 44 45 ieee754_QNAN() : f(0.0)/*, mantissa(0x7FFFFF), exp(0xFF), sign(0x0)*/ {} 46 }; 47 48 #if(GLM_COMPILER & GLM_COMPILER_VC) 49 #pragma warning(pop) 50 #endif 51 52 static const __m128 GLM_VAR_USED zero = _mm_setzero_ps(); 53 static const __m128 GLM_VAR_USED one = _mm_set_ps1(1.0f); 54 static const __m128 GLM_VAR_USED minus_one = _mm_set_ps1(-1.0f); 55 static const __m128 GLM_VAR_USED two = _mm_set_ps1(2.0f); 56 static const __m128 GLM_VAR_USED three = _mm_set_ps1(3.0f); 57 static const __m128 GLM_VAR_USED pi = _mm_set_ps1(3.1415926535897932384626433832795f); 58 static const __m128 GLM_VAR_USED hundred_eighty = _mm_set_ps1(180.f); 59 static const __m128 GLM_VAR_USED pi_over_hundred_eighty = _mm_set_ps1(0.017453292519943295769236907684886f); 60 static const __m128 GLM_VAR_USED hundred_eighty_over_pi = _mm_set_ps1(57.295779513082320876798154814105f); 61 62 static const ieee754_QNAN absMask; 63 static const __m128 GLM_VAR_USED abs4Mask = _mm_set_ps1(absMask.f); 64 65 static const __m128 GLM_VAR_USED _epi32_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000))); 66 //static const __m128 GLM_VAR_USED _epi32_inv_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)); 67 //static const __m128 GLM_VAR_USED _epi32_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000)); 68 //static const __m128 GLM_VAR_USED _epi32_inv_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x807FFFFF)); 69 //static const __m128 GLM_VAR_USED _epi32_min_norm_pos = _mm_castsi128_ps(_mm_set1_epi32(0x00800000)); 70 static const __m128 GLM_VAR_USED _epi32_0 = _mm_set_ps1(0); 71 static const __m128 GLM_VAR_USED _epi32_1 = _mm_set_ps1(1); 72 static const __m128 GLM_VAR_USED _epi32_2 = _mm_set_ps1(2); 73 static const __m128 GLM_VAR_USED _epi32_3 = _mm_set_ps1(3); 74 static const __m128 GLM_VAR_USED _epi32_4 = _mm_set_ps1(4); 75 static const __m128 GLM_VAR_USED _epi32_5 = _mm_set_ps1(5); 76 static const __m128 GLM_VAR_USED _epi32_6 = _mm_set_ps1(6); 77 static const __m128 GLM_VAR_USED _epi32_7 = _mm_set_ps1(7); 78 static const __m128 GLM_VAR_USED _epi32_8 = _mm_set_ps1(8); 79 static const __m128 GLM_VAR_USED _epi32_9 = _mm_set_ps1(9); 80 static const __m128 GLM_VAR_USED _epi32_127 = _mm_set_ps1(127); 81 //static const __m128 GLM_VAR_USED _epi32_ninf = _mm_castsi128_ps(_mm_set1_epi32(0xFF800000)); 82 //static const __m128 GLM_VAR_USED _epi32_pinf = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000)); 83 84 static const __m128 GLM_VAR_USED _ps_1_3 = _mm_set_ps1(0.33333333333333333333333333333333f); 85 static const __m128 GLM_VAR_USED _ps_0p5 = _mm_set_ps1(0.5f); 86 static const __m128 GLM_VAR_USED _ps_1 = _mm_set_ps1(1.0f); 87 static const __m128 GLM_VAR_USED _ps_m1 = _mm_set_ps1(-1.0f); 88 static const __m128 GLM_VAR_USED _ps_2 = _mm_set_ps1(2.0f); 89 static const __m128 GLM_VAR_USED _ps_3 = _mm_set_ps1(3.0f); 90 static const __m128 GLM_VAR_USED _ps_127 = _mm_set_ps1(127.0f); 91 static const __m128 GLM_VAR_USED _ps_255 = _mm_set_ps1(255.0f); 92 static const __m128 GLM_VAR_USED _ps_2pow23 = _mm_set_ps1(8388608.0f); 93 94 static const __m128 GLM_VAR_USED _ps_1_0_0_0 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); 95 static const __m128 GLM_VAR_USED _ps_0_1_0_0 = _mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f); 96 static const __m128 GLM_VAR_USED _ps_0_0_1_0 = _mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f); 97 static const __m128 GLM_VAR_USED _ps_0_0_0_1 = _mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f); 98 99 static const __m128 GLM_VAR_USED _ps_pi = _mm_set_ps1(3.1415926535897932384626433832795f); 100 static const __m128 GLM_VAR_USED _ps_pi2 = _mm_set_ps1(6.283185307179586476925286766560f); 101 static const __m128 GLM_VAR_USED _ps_2_pi = _mm_set_ps1(0.63661977236758134307553505349006f); 102 static const __m128 GLM_VAR_USED _ps_pi_2 = _mm_set_ps1(1.5707963267948966192313216916398f); 103 static const __m128 GLM_VAR_USED _ps_4_pi = _mm_set_ps1(1.2732395447351626861510701069801f); 104 static const __m128 GLM_VAR_USED _ps_pi_4 = _mm_set_ps1(0.78539816339744830961566084581988f); 105 106 static const __m128 GLM_VAR_USED _ps_sincos_p0 = _mm_set_ps1(0.15707963267948963959e1f); 107 static const __m128 GLM_VAR_USED _ps_sincos_p1 = _mm_set_ps1(-0.64596409750621907082e0f); 108 static const __m128 GLM_VAR_USED _ps_sincos_p2 = _mm_set_ps1(0.7969262624561800806e-1f); 109 static const __m128 GLM_VAR_USED _ps_sincos_p3 = _mm_set_ps1(-0.468175413106023168e-2f); 110 static const __m128 GLM_VAR_USED _ps_tan_p0 = _mm_set_ps1(-1.79565251976484877988e7f); 111 static const __m128 GLM_VAR_USED _ps_tan_p1 = _mm_set_ps1(1.15351664838587416140e6f); 112 static const __m128 GLM_VAR_USED _ps_tan_p2 = _mm_set_ps1(-1.30936939181383777646e4f); 113 static const __m128 GLM_VAR_USED _ps_tan_q0 = _mm_set_ps1(-5.38695755929454629881e7f); 114 static const __m128 GLM_VAR_USED _ps_tan_q1 = _mm_set_ps1(2.50083801823357915839e7f); 115 static const __m128 GLM_VAR_USED _ps_tan_q2 = _mm_set_ps1(-1.32089234440210967447e6f); 116 static const __m128 GLM_VAR_USED _ps_tan_q3 = _mm_set_ps1(1.36812963470692954678e4f); 117 static const __m128 GLM_VAR_USED _ps_tan_poleval = _mm_set_ps1(3.68935e19f); 118 static const __m128 GLM_VAR_USED _ps_atan_t0 = _mm_set_ps1(-0.91646118527267623468e-1f); 119 static const __m128 GLM_VAR_USED _ps_atan_t1 = _mm_set_ps1(-0.13956945682312098640e1f); 120 static const __m128 GLM_VAR_USED _ps_atan_t2 = _mm_set_ps1(-0.94393926122725531747e2f); 121 static const __m128 GLM_VAR_USED _ps_atan_t3 = _mm_set_ps1(0.12888383034157279340e2f); 122 static const __m128 GLM_VAR_USED _ps_atan_s0 = _mm_set_ps1(0.12797564625607904396e1f); 123 static const __m128 GLM_VAR_USED _ps_atan_s1 = _mm_set_ps1(0.21972168858277355914e1f); 124 static const __m128 GLM_VAR_USED _ps_atan_s2 = _mm_set_ps1(0.68193064729268275701e1f); 125 static const __m128 GLM_VAR_USED _ps_atan_s3 = _mm_set_ps1(0.28205206687035841409e2f); 126 127 static const __m128 GLM_VAR_USED _ps_exp_hi = _mm_set_ps1(88.3762626647949f); 128 static const __m128 GLM_VAR_USED _ps_exp_lo = _mm_set_ps1(-88.3762626647949f); 129 static const __m128 GLM_VAR_USED _ps_exp_rln2 = _mm_set_ps1(1.4426950408889634073599f); 130 static const __m128 GLM_VAR_USED _ps_exp_p0 = _mm_set_ps1(1.26177193074810590878e-4f); 131 static const __m128 GLM_VAR_USED _ps_exp_p1 = _mm_set_ps1(3.02994407707441961300e-2f); 132 static const __m128 GLM_VAR_USED _ps_exp_q0 = _mm_set_ps1(3.00198505138664455042e-6f); 133 static const __m128 GLM_VAR_USED _ps_exp_q1 = _mm_set_ps1(2.52448340349684104192e-3f); 134 static const __m128 GLM_VAR_USED _ps_exp_q2 = _mm_set_ps1(2.27265548208155028766e-1f); 135 static const __m128 GLM_VAR_USED _ps_exp_q3 = _mm_set_ps1(2.00000000000000000009e0f); 136 static const __m128 GLM_VAR_USED _ps_exp_c1 = _mm_set_ps1(6.93145751953125e-1f); 137 static const __m128 GLM_VAR_USED _ps_exp_c2 = _mm_set_ps1(1.42860682030941723212e-6f); 138 static const __m128 GLM_VAR_USED _ps_exp2_hi = _mm_set_ps1(127.4999961853f); 139 static const __m128 GLM_VAR_USED _ps_exp2_lo = _mm_set_ps1(-127.4999961853f); 140 static const __m128 GLM_VAR_USED _ps_exp2_p0 = _mm_set_ps1(2.30933477057345225087e-2f); 141 static const __m128 GLM_VAR_USED _ps_exp2_p1 = _mm_set_ps1(2.02020656693165307700e1f); 142 static const __m128 GLM_VAR_USED _ps_exp2_p2 = _mm_set_ps1(1.51390680115615096133e3f); 143 static const __m128 GLM_VAR_USED _ps_exp2_q0 = _mm_set_ps1(2.33184211722314911771e2f); 144 static const __m128 GLM_VAR_USED _ps_exp2_q1 = _mm_set_ps1(4.36821166879210612817e3f); 145 static const __m128 GLM_VAR_USED _ps_log_p0 = _mm_set_ps1(-7.89580278884799154124e-1f); 146 static const __m128 GLM_VAR_USED _ps_log_p1 = _mm_set_ps1(1.63866645699558079767e1f); 147 static const __m128 GLM_VAR_USED _ps_log_p2 = _mm_set_ps1(-6.41409952958715622951e1f); 148 static const __m128 GLM_VAR_USED _ps_log_q0 = _mm_set_ps1(-3.56722798256324312549e1f); 149 static const __m128 GLM_VAR_USED _ps_log_q1 = _mm_set_ps1(3.12093766372244180303e2f); 150 static const __m128 GLM_VAR_USED _ps_log_q2 = _mm_set_ps1(-7.69691943550460008604e2f); 151 static const __m128 GLM_VAR_USED _ps_log_c0 = _mm_set_ps1(0.693147180559945f); 152 static const __m128 GLM_VAR_USED _ps_log2_c0 = _mm_set_ps1(1.44269504088896340735992f); 153 154 GLM_FUNC_QUALIFIER __m128 sse_abs_ps(__m128 x) 155 { 156 return _mm_and_ps(glm::detail::abs4Mask, x); 157 } 158 159 GLM_FUNC_QUALIFIER __m128 sse_sgn_ps(__m128 x) 160 { 161 __m128 Neg = _mm_set1_ps(-1.0f); 162 __m128 Pos = _mm_set1_ps(1.0f); 163 164 __m128 Cmp0 = _mm_cmplt_ps(x, zero); 165 __m128 Cmp1 = _mm_cmpgt_ps(x, zero); 166 167 __m128 And0 = _mm_and_ps(Cmp0, Neg); 168 __m128 And1 = _mm_and_ps(Cmp1, Pos); 169 170 return _mm_or_ps(And0, And1); 171 } 172 173 //floor 174 GLM_FUNC_QUALIFIER __m128 sse_flr_ps(__m128 x) 175 { 176 __m128 rnd0 = sse_rnd_ps(x); 177 __m128 cmp0 = _mm_cmplt_ps(x, rnd0); 178 __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1); 179 __m128 sub0 = _mm_sub_ps(rnd0, and0); 180 return sub0; 181 } 182 183 //trunc 184 /* 185 GLM_FUNC_QUALIFIER __m128 _mm_trc_ps(__m128 v) 186 { 187 return __m128(); 188 } 189 */ 190 //round 191 GLM_FUNC_QUALIFIER __m128 sse_rnd_ps(__m128 x) 192 { 193 __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x); 194 __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23); 195 __m128 add0 = _mm_add_ps(x, or0); 196 __m128 sub0 = _mm_sub_ps(add0, or0); 197 return sub0; 198 } 199 200 //roundEven 201 GLM_FUNC_QUALIFIER __m128 sse_rde_ps(__m128 x) 202 { 203 __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x); 204 __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23); 205 __m128 add0 = _mm_add_ps(x, or0); 206 __m128 sub0 = _mm_sub_ps(add0, or0); 207 return sub0; 208 } 209 210 GLM_FUNC_QUALIFIER __m128 sse_ceil_ps(__m128 x) 211 { 212 __m128 rnd0 = sse_rnd_ps(x); 213 __m128 cmp0 = _mm_cmpgt_ps(x, rnd0); 214 __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1); 215 __m128 add0 = _mm_add_ps(rnd0, and0); 216 return add0; 217 } 218 219 GLM_FUNC_QUALIFIER __m128 sse_frc_ps(__m128 x) 220 { 221 __m128 flr0 = sse_flr_ps(x); 222 __m128 sub0 = _mm_sub_ps(x, flr0); 223 return sub0; 224 } 225 226 GLM_FUNC_QUALIFIER __m128 sse_mod_ps(__m128 x, __m128 y) 227 { 228 __m128 div0 = _mm_div_ps(x, y); 229 __m128 flr0 = sse_flr_ps(div0); 230 __m128 mul0 = _mm_mul_ps(y, flr0); 231 __m128 sub0 = _mm_sub_ps(x, mul0); 232 return sub0; 233 } 234 235 /// TODO 236 /* 237 GLM_FUNC_QUALIFIER __m128 sse_modf_ps(__m128 x, __m128i & i) 238 { 239 __m128 empty; 240 return empty; 241 } 242 */ 243 244 //GLM_FUNC_QUALIFIER __m128 _mm_min_ps(__m128 x, __m128 y) 245 246 //GLM_FUNC_QUALIFIER __m128 _mm_max_ps(__m128 x, __m128 y) 247 248 GLM_FUNC_QUALIFIER __m128 sse_clp_ps(__m128 v, __m128 minVal, __m128 maxVal) 249 { 250 __m128 min0 = _mm_min_ps(v, maxVal); 251 __m128 max0 = _mm_max_ps(min0, minVal); 252 return max0; 253 } 254 255 GLM_FUNC_QUALIFIER __m128 sse_mix_ps(__m128 v1, __m128 v2, __m128 a) 256 { 257 __m128 sub0 = _mm_sub_ps(glm::detail::one, a); 258 __m128 mul0 = _mm_mul_ps(v1, sub0); 259 __m128 mul1 = _mm_mul_ps(v2, a); 260 __m128 add0 = _mm_add_ps(mul0, mul1); 261 return add0; 262 } 263 264 GLM_FUNC_QUALIFIER __m128 sse_stp_ps(__m128 edge, __m128 x) 265 { 266 __m128 cmp = _mm_cmple_ps(x, edge); 267 if(_mm_movemask_ps(cmp) == 0) 268 return glm::detail::one; 269 else 270 return glm::detail::zero; 271 } 272 273 GLM_FUNC_QUALIFIER __m128 sse_ssp_ps(__m128 edge0, __m128 edge1, __m128 x) 274 { 275 __m128 sub0 = _mm_sub_ps(x, edge0); 276 __m128 sub1 = _mm_sub_ps(edge1, edge0); 277 __m128 div0 = _mm_sub_ps(sub0, sub1); 278 __m128 clp0 = sse_clp_ps(div0, glm::detail::zero, glm::detail::one); 279 __m128 mul0 = _mm_mul_ps(glm::detail::two, clp0); 280 __m128 sub2 = _mm_sub_ps(glm::detail::three, mul0); 281 __m128 mul1 = _mm_mul_ps(clp0, clp0); 282 __m128 mul2 = _mm_mul_ps(mul1, sub2); 283 return mul2; 284 } 285 286 /// \todo 287 //GLM_FUNC_QUALIFIER __m128 sse_nan_ps(__m128 x) 288 //{ 289 // __m128 empty; 290 // return empty; 291 //} 292 293 /// \todo 294 //GLM_FUNC_QUALIFIER __m128 sse_inf_ps(__m128 x) 295 //{ 296 // __m128 empty; 297 // return empty; 298 //} 299 300 // SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration 301 // By Elan Ruskin, http://assemblyrequired.crashworks.org/ 302 GLM_FUNC_QUALIFIER __m128 sse_sqrt_wip_ss(__m128 const & x) 303 { 304 __m128 recip = _mm_rsqrt_ss(x); // "estimate" opcode 305 const static __m128 three = {3, 3, 3, 3}; // aligned consts for fast load 306 const static __m128 half = {0.5,0.5,0.5,0.5}; 307 __m128 halfrecip = _mm_mul_ss(half, recip); 308 __m128 threeminus_xrr = _mm_sub_ss(three, _mm_mul_ss(x, _mm_mul_ss (recip, recip))); 309 return _mm_mul_ss( halfrecip, threeminus_xrr); 310 } 311 312 }//namespace detail 313 }//namespace glms 314