Home | History | Annotate | Download | only in detail
      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