blob: fc53e3fc1a97ef2638ad4a5162938776d3485672 [file] [log] [blame]
Tony-LunarGb0b195d2015-05-13 15:01:06 -06001///////////////////////////////////////////////////////////////////////////////////////////////////
2// OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
3///////////////////////////////////////////////////////////////////////////////////////////////////
4// Created : 2009-05-07
5// Updated : 2009-05-07
6// Licence : This source is under MIT License
7// File : glm/gtx/simd_vec4.inl
8///////////////////////////////////////////////////////////////////////////////////////////////////
9
10namespace glm{
11namespace detail{
12
13template <int Value>
14struct mask
15{
16 enum{value = Value};
17};
18
19//////////////////////////////////////
20// Implicit basic constructors
21
22GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD()
23#ifdef GLM_SIMD_ENABLE_DEFAULT_INIT
24 : Data(_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f))
25#endif
26{}
27
28GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(__m128 const & Data) :
29 Data(Data)
30{}
31
32GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(fvec4SIMD const & v) :
33 Data(v.Data)
34{}
35
36GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec4 const & v) :
37 Data(_mm_set_ps(v.w, v.z, v.y, v.x))
38{}
39
40//////////////////////////////////////
41// Explicit basic constructors
42
43GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s) :
44 Data(_mm_set1_ps(s))
45{}
46
47GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & x, float const & y, float const & z, float const & w) :
48// Data(_mm_setr_ps(x, y, z, w))
49 Data(_mm_set_ps(w, z, y, x))
50{}
51/*
52GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const v[4]) :
53 Data(_mm_load_ps(v))
54{}
55*/
56//////////////////////////////////////
57// Swizzle constructors
58
59//fvec4SIMD(ref4<float> const & r);
60
61//////////////////////////////////////
62// Conversion vector constructors
63
64GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec2 const & v, float const & s1, float const & s2) :
65 Data(_mm_set_ps(s2, s1, v.y, v.x))
66{}
67
68GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s1, vec2 const & v, float const & s2) :
69 Data(_mm_set_ps(s2, v.y, v.x, s1))
70{}
71
72GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s1, float const & s2, vec2 const & v) :
73 Data(_mm_set_ps(v.y, v.x, s2, s1))
74{}
75
76GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec3 const & v, float const & s) :
77 Data(_mm_set_ps(s, v.z, v.y, v.x))
78{}
79
80GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s, vec3 const & v) :
81 Data(_mm_set_ps(v.z, v.y, v.x, s))
82{}
83
84GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec2 const & v1, vec2 const & v2) :
85 Data(_mm_set_ps(v2.y, v2.x, v1.y, v1.x))
86{}
87
88//GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(ivec4SIMD const & v) :
89// Data(_mm_cvtepi32_ps(v.Data))
90//{}
91
92//////////////////////////////////////
93// Unary arithmetic operators
94
95GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator=(fvec4SIMD const & v)
96{
97 this->Data = v.Data;
98 return *this;
99}
100
101GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator+=(float const & s)
102{
103 this->Data = _mm_add_ps(Data, _mm_set_ps1(s));
104 return *this;
105}
106
107GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator+=(fvec4SIMD const & v)
108{
109 this->Data = _mm_add_ps(this->Data , v.Data);
110 return *this;
111}
112
113GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator-=(float const & s)
114{
115 this->Data = _mm_sub_ps(Data, _mm_set_ps1(s));
116 return *this;
117}
118
119GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator-=(fvec4SIMD const & v)
120{
121 this->Data = _mm_sub_ps(this->Data , v.Data);
122 return *this;
123}
124
125GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator*=(float const & s)
126{
127 this->Data = _mm_mul_ps(this->Data, _mm_set_ps1(s));
128 return *this;
129}
130
131GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator*=(fvec4SIMD const & v)
132{
133 this->Data = _mm_mul_ps(this->Data , v.Data);
134 return *this;
135}
136
137GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator/=(float const & s)
138{
139 this->Data = _mm_div_ps(Data, _mm_set1_ps(s));
140 return *this;
141}
142
143GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator/=(fvec4SIMD const & v)
144{
145 this->Data = _mm_div_ps(this->Data , v.Data);
146 return *this;
147}
148
149GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator++()
150{
151 this->Data = _mm_add_ps(this->Data , glm::detail::one);
152 return *this;
153}
154
155GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator--()
156{
157 this->Data = _mm_sub_ps(this->Data, glm::detail::one);
158 return *this;
159}
160
161//////////////////////////////////////
162// Swizzle operators
163
164template <comp X, comp Y, comp Z, comp W>
165GLM_FUNC_QUALIFIER fvec4SIMD fvec4SIMD::swizzle() const
166{
167 __m128 Data = _mm_shuffle_ps(
168 this->Data, this->Data,
169 mask<(W << 6) | (Z << 4) | (Y << 2) | (X << 0)>::value);
170 return fvec4SIMD(Data);
171}
172
173template <comp X, comp Y, comp Z, comp W>
174GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::swizzle()
175{
176 this->Data = _mm_shuffle_ps(
177 this->Data, this->Data,
178 mask<(W << 6) | (Z << 4) | (Y << 2) | (X << 0)>::value);
179 return *this;
180}
181
182// operator+
183GLM_FUNC_QUALIFIER fvec4SIMD operator+ (fvec4SIMD const & v, float s)
184{
185 return fvec4SIMD(_mm_add_ps(v.Data, _mm_set1_ps(s)));
186}
187
188GLM_FUNC_QUALIFIER fvec4SIMD operator+ (float s, fvec4SIMD const & v)
189{
190 return fvec4SIMD(_mm_add_ps(_mm_set1_ps(s), v.Data));
191}
192
193GLM_FUNC_QUALIFIER fvec4SIMD operator+ (fvec4SIMD const & v1, fvec4SIMD const & v2)
194{
195 return fvec4SIMD(_mm_add_ps(v1.Data, v2.Data));
196}
197
198//operator-
199GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v, float s)
200{
201 return fvec4SIMD(_mm_sub_ps(v.Data, _mm_set1_ps(s)));
202}
203
204GLM_FUNC_QUALIFIER fvec4SIMD operator- (float s, fvec4SIMD const & v)
205{
206 return fvec4SIMD(_mm_sub_ps(_mm_set1_ps(s), v.Data));
207}
208
209GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v1, fvec4SIMD const & v2)
210{
211 return fvec4SIMD(_mm_sub_ps(v1.Data, v2.Data));
212}
213
214//operator*
215GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v, float s)
216{
217 __m128 par0 = v.Data;
218 __m128 par1 = _mm_set1_ps(s);
219 return fvec4SIMD(_mm_mul_ps(par0, par1));
220}
221
222GLM_FUNC_QUALIFIER fvec4SIMD operator* (float s, fvec4SIMD const & v)
223{
224 __m128 par0 = _mm_set1_ps(s);
225 __m128 par1 = v.Data;
226 return fvec4SIMD(_mm_mul_ps(par0, par1));
227}
228
229GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v1, fvec4SIMD const & v2)
230{
231 return fvec4SIMD(_mm_mul_ps(v1.Data, v2.Data));
232}
233
234//operator/
235GLM_FUNC_QUALIFIER fvec4SIMD operator/ (fvec4SIMD const & v, float s)
236{
237 __m128 par0 = v.Data;
238 __m128 par1 = _mm_set1_ps(s);
239 return fvec4SIMD(_mm_div_ps(par0, par1));
240}
241
242GLM_FUNC_QUALIFIER fvec4SIMD operator/ (float s, fvec4SIMD const & v)
243{
244 __m128 par0 = _mm_set1_ps(s);
245 __m128 par1 = v.Data;
246 return fvec4SIMD(_mm_div_ps(par0, par1));
247}
248
249GLM_FUNC_QUALIFIER fvec4SIMD operator/ (fvec4SIMD const & v1, fvec4SIMD const & v2)
250{
251 return fvec4SIMD(_mm_div_ps(v1.Data, v2.Data));
252}
253
254// Unary constant operators
255GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v)
256{
257 return fvec4SIMD(_mm_sub_ps(_mm_setzero_ps(), v.Data));
258}
259
260GLM_FUNC_QUALIFIER fvec4SIMD operator++ (fvec4SIMD const & v, int)
261{
262 return fvec4SIMD(_mm_add_ps(v.Data, glm::detail::one));
263}
264
265GLM_FUNC_QUALIFIER fvec4SIMD operator-- (fvec4SIMD const & v, int)
266{
267 return fvec4SIMD(_mm_sub_ps(v.Data, glm::detail::one));
268}
269
270}//namespace detail
271
272GLM_FUNC_QUALIFIER vec4 vec4_cast
273(
274 detail::fvec4SIMD const & x
275)
276{
277 GLM_ALIGN(16) vec4 Result;
278 _mm_store_ps(&Result[0], x.Data);
279 return Result;
280}
281
282// Other possible implementation
283//float abs(float a)
284//{
285// return max(-a, a);
286//}
287GLM_FUNC_QUALIFIER detail::fvec4SIMD abs
288(
289 detail::fvec4SIMD const & x
290)
291{
292 return detail::sse_abs_ps(x.Data);
293}
294
295GLM_FUNC_QUALIFIER detail::fvec4SIMD sign
296(
297 detail::fvec4SIMD const & x
298)
299{
300 return detail::sse_sgn_ps(x.Data);
301}
302
303GLM_FUNC_QUALIFIER detail::fvec4SIMD floor
304(
305 detail::fvec4SIMD const & x
306)
307{
308 return detail::sse_flr_ps(x.Data);
309}
310
311GLM_FUNC_QUALIFIER detail::fvec4SIMD trunc
312(
313 detail::fvec4SIMD const & x
314)
315{
316 //return x < 0 ? -floor(-x) : floor(x);
317
318 __m128 Flr0 = detail::sse_flr_ps(_mm_sub_ps(_mm_setzero_ps(), x.Data));
319 __m128 Sub0 = _mm_sub_ps(Flr0, x.Data);
320 __m128 Flr1 = detail::sse_flr_ps(x.Data);
321
322 __m128 Cmp0 = _mm_cmplt_ps(x.Data, glm::detail::zero);
323 __m128 Cmp1 = _mm_cmpnlt_ps(x.Data, glm::detail::zero);
324
325 __m128 And0 = _mm_and_ps(Sub0, Cmp0);
326 __m128 And1 = _mm_and_ps(Flr1, Cmp1);
327
328 return _mm_or_ps(And0, And1);
329}
330
331GLM_FUNC_QUALIFIER detail::fvec4SIMD round
332(
333 detail::fvec4SIMD const & x
334)
335{
336 return detail::sse_rnd_ps(x.Data);
337}
338
339//GLM_FUNC_QUALIFIER detail::fvec4SIMD roundEven
340//(
341// detail::fvec4SIMD const & x
342//)
343//{
344
345//}
346
347GLM_FUNC_QUALIFIER detail::fvec4SIMD ceil
348(
349 detail::fvec4SIMD const & x
350)
351{
352 return detail::sse_ceil_ps(x.Data);
353}
354
355GLM_FUNC_QUALIFIER detail::fvec4SIMD fract
356(
357 detail::fvec4SIMD const & x
358)
359{
360 return detail::sse_frc_ps(x.Data);
361}
362
363GLM_FUNC_QUALIFIER detail::fvec4SIMD mod
364(
365 detail::fvec4SIMD const & x,
366 detail::fvec4SIMD const & y
367)
368{
369 return detail::sse_mod_ps(x.Data, y.Data);
370}
371
372GLM_FUNC_QUALIFIER detail::fvec4SIMD mod
373(
374 detail::fvec4SIMD const & x,
375 float const & y
376)
377{
378 return detail::sse_mod_ps(x.Data, _mm_set1_ps(y));
379}
380
381//GLM_FUNC_QUALIFIER detail::fvec4SIMD modf
382//(
383// detail::fvec4SIMD const & x,
384// detail::fvec4SIMD & i
385//)
386//{
387
388//}
389
390GLM_FUNC_QUALIFIER detail::fvec4SIMD min
391(
392 detail::fvec4SIMD const & x,
393 detail::fvec4SIMD const & y
394)
395{
396 return _mm_min_ps(x.Data, y.Data);
397}
398
399GLM_FUNC_QUALIFIER detail::fvec4SIMD min
400(
401 detail::fvec4SIMD const & x,
402 float const & y
403)
404{
405 return _mm_min_ps(x.Data, _mm_set1_ps(y));
406}
407
408GLM_FUNC_QUALIFIER detail::fvec4SIMD max
409(
410 detail::fvec4SIMD const & x,
411 detail::fvec4SIMD const & y
412)
413{
414 return _mm_max_ps(x.Data, y.Data);
415}
416
417GLM_FUNC_QUALIFIER detail::fvec4SIMD max
418(
419 detail::fvec4SIMD const & x,
420 float const & y
421)
422{
423 return _mm_max_ps(x.Data, _mm_set1_ps(y));
424}
425
426GLM_FUNC_QUALIFIER detail::fvec4SIMD clamp
427(
428 detail::fvec4SIMD const & x,
429 detail::fvec4SIMD const & minVal,
430 detail::fvec4SIMD const & maxVal
431)
432{
433 return detail::sse_clp_ps(x.Data, minVal.Data, maxVal.Data);
434}
435
436GLM_FUNC_QUALIFIER detail::fvec4SIMD clamp
437(
438 detail::fvec4SIMD const & x,
439 float const & minVal,
440 float const & maxVal
441)
442{
443 return detail::sse_clp_ps(x.Data, _mm_set1_ps(minVal), _mm_set1_ps(maxVal));
444}
445
446GLM_FUNC_QUALIFIER detail::fvec4SIMD mix
447(
448 detail::fvec4SIMD const & x,
449 detail::fvec4SIMD const & y,
450 detail::fvec4SIMD const & a
451)
452{
453 __m128 Sub0 = _mm_sub_ps(y.Data, x.Data);
454 __m128 Mul0 = _mm_mul_ps(a.Data, Sub0);
455 return _mm_add_ps(x.Data, Mul0);
456}
457
458GLM_FUNC_QUALIFIER detail::fvec4SIMD step
459(
460 detail::fvec4SIMD const & edge,
461 detail::fvec4SIMD const & x
462)
463{
464 __m128 cmp0 = _mm_cmpngt_ps(x.Data, edge.Data);
465 return _mm_max_ps(_mm_min_ps(cmp0, _mm_setzero_ps()), detail::one);
466}
467
468GLM_FUNC_QUALIFIER detail::fvec4SIMD step
469(
470 float const & edge,
471 detail::fvec4SIMD const & x
472)
473{
474 __m128 cmp0 = _mm_cmpngt_ps(x.Data, _mm_set1_ps(edge));
475 return _mm_max_ps(_mm_min_ps(cmp0, _mm_setzero_ps()), detail::one);
476}
477
478GLM_FUNC_QUALIFIER detail::fvec4SIMD smoothstep
479(
480 detail::fvec4SIMD const & edge0,
481 detail::fvec4SIMD const & edge1,
482 detail::fvec4SIMD const & x
483)
484{
485 return detail::sse_ssp_ps(edge0.Data, edge1.Data, x.Data);
486}
487
488GLM_FUNC_QUALIFIER detail::fvec4SIMD smoothstep
489(
490 float const & edge0,
491 float const & edge1,
492 detail::fvec4SIMD const & x
493)
494{
495 return detail::sse_ssp_ps(_mm_set1_ps(edge0), _mm_set1_ps(edge1), x.Data);
496}
497
498//GLM_FUNC_QUALIFIER bvec4 isnan(detail::fvec4SIMD const & x)
499//{
500
501//}
502
503//GLM_FUNC_QUALIFIER bvec4 isinf(detail::fvec4SIMD const & x)
504//{
505
506//}
507
508//GLM_FUNC_QUALIFIER detail::ivec4SIMD floatBitsToInt
509//(
510// detail::fvec4SIMD const & value
511//)
512//{
513
514//}
515
516//GLM_FUNC_QUALIFIER detail::fvec4SIMD intBitsToFloat
517//(
518// detail::ivec4SIMD const & value
519//)
520//{
521
522//}
523
524GLM_FUNC_QUALIFIER detail::fvec4SIMD fma
525(
526 detail::fvec4SIMD const & a,
527 detail::fvec4SIMD const & b,
528 detail::fvec4SIMD const & c
529)
530{
531 return _mm_add_ps(_mm_mul_ps(a.Data, b.Data), c.Data);
532}
533
534GLM_FUNC_QUALIFIER float length
535(
536 detail::fvec4SIMD const & x
537)
538{
539 detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data);
540 detail::fvec4SIMD sqt0 = sqrt(dot0);
541 float Result = 0;
542 _mm_store_ss(&Result, sqt0.Data);
543 return Result;
544}
545
546GLM_FUNC_QUALIFIER float fastLength
547(
548 detail::fvec4SIMD const & x
549)
550{
551 detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data);
552 detail::fvec4SIMD sqt0 = fastSqrt(dot0);
553 float Result = 0;
554 _mm_store_ss(&Result, sqt0.Data);
555 return Result;
556}
557
558GLM_FUNC_QUALIFIER float niceLength
559(
560 detail::fvec4SIMD const & x
561)
562{
563 detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data);
564 detail::fvec4SIMD sqt0 = niceSqrt(dot0);
565 float Result = 0;
566 _mm_store_ss(&Result, sqt0.Data);
567 return Result;
568}
569
570GLM_FUNC_QUALIFIER detail::fvec4SIMD length4
571(
572 detail::fvec4SIMD const & x
573)
574{
575 return sqrt(dot4(x, x));
576}
577
578GLM_FUNC_QUALIFIER detail::fvec4SIMD fastLength4
579(
580 detail::fvec4SIMD const & x
581)
582{
583 return fastSqrt(dot4(x, x));
584}
585
586GLM_FUNC_QUALIFIER detail::fvec4SIMD niceLength4
587(
588 detail::fvec4SIMD const & x
589)
590{
591 return niceSqrt(dot4(x, x));
592}
593
594GLM_FUNC_QUALIFIER float distance
595(
596 detail::fvec4SIMD const & p0,
597 detail::fvec4SIMD const & p1
598)
599{
600 float Result = 0;
601 _mm_store_ss(&Result, detail::sse_dst_ps(p0.Data, p1.Data));
602 return Result;
603}
604
605GLM_FUNC_QUALIFIER detail::fvec4SIMD distance4
606(
607 detail::fvec4SIMD const & p0,
608 detail::fvec4SIMD const & p1
609)
610{
611 return detail::sse_dst_ps(p0.Data, p1.Data);
612}
613
614GLM_FUNC_QUALIFIER float dot
615(
616 detail::fvec4SIMD const & x,
617 detail::fvec4SIMD const & y
618)
619{
620 float Result = 0;
621 _mm_store_ss(&Result, detail::sse_dot_ss(x.Data, y.Data));
622 return Result;
623}
624
625GLM_FUNC_QUALIFIER detail::fvec4SIMD dot4
626(
627 detail::fvec4SIMD const & x,
628 detail::fvec4SIMD const & y
629)
630{
631 return detail::sse_dot_ps(x.Data, y.Data);
632}
633
634GLM_FUNC_QUALIFIER detail::fvec4SIMD cross
635(
636 detail::fvec4SIMD const & x,
637 detail::fvec4SIMD const & y
638)
639{
640 return detail::sse_xpd_ps(x.Data, y.Data);
641}
642
643GLM_FUNC_QUALIFIER detail::fvec4SIMD normalize
644(
645 detail::fvec4SIMD const & x
646)
647{
648 __m128 dot0 = detail::sse_dot_ps(x.Data, x.Data);
649 __m128 isr0 = inversesqrt(detail::fvec4SIMD(dot0)).Data;
650 __m128 mul0 = _mm_mul_ps(x.Data, isr0);
651 return mul0;
652}
653
654GLM_FUNC_QUALIFIER detail::fvec4SIMD fastNormalize
655(
656 detail::fvec4SIMD const & x
657)
658{
659 __m128 dot0 = detail::sse_dot_ps(x.Data, x.Data);
660 __m128 isr0 = fastInversesqrt(dot0).Data;
661 __m128 mul0 = _mm_mul_ps(x.Data, isr0);
662 return mul0;
663}
664
665GLM_FUNC_QUALIFIER detail::fvec4SIMD faceforward
666(
667 detail::fvec4SIMD const & N,
668 detail::fvec4SIMD const & I,
669 detail::fvec4SIMD const & Nref
670)
671{
672 return detail::sse_ffd_ps(N.Data, I.Data, Nref.Data);
673}
674
675GLM_FUNC_QUALIFIER detail::fvec4SIMD reflect
676(
677 detail::fvec4SIMD const & I,
678 detail::fvec4SIMD const & N
679)
680{
681 return detail::sse_rfe_ps(I.Data, N.Data);
682}
683
684GLM_FUNC_QUALIFIER detail::fvec4SIMD refract
685(
686 detail::fvec4SIMD const & I,
687 detail::fvec4SIMD const & N,
688 float const & eta
689)
690{
691 return detail::sse_rfa_ps(I.Data, N.Data, _mm_set1_ps(eta));
692}
693
694GLM_FUNC_QUALIFIER detail::fvec4SIMD sqrt(detail::fvec4SIMD const & x)
695{
696 return _mm_mul_ps(inversesqrt(x).Data, x.Data);
697}
698
699GLM_FUNC_QUALIFIER detail::fvec4SIMD niceSqrt(detail::fvec4SIMD const & x)
700{
701 return _mm_sqrt_ps(x.Data);
702}
703
704GLM_FUNC_QUALIFIER detail::fvec4SIMD fastSqrt(detail::fvec4SIMD const & x)
705{
706 return _mm_mul_ps(fastInversesqrt(x.Data).Data, x.Data);
707}
708
709// SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration
710// By Elan Ruskin, http://assemblyrequired.crashworks.org/
711GLM_FUNC_QUALIFIER detail::fvec4SIMD inversesqrt(detail::fvec4SIMD const & x)
712{
713 GLM_ALIGN(4) static const __m128 three = {3, 3, 3, 3}; // aligned consts for fast load
714 GLM_ALIGN(4) static const __m128 half = {0.5,0.5,0.5,0.5};
715
716 __m128 recip = _mm_rsqrt_ps(x.Data); // "estimate" opcode
717 __m128 halfrecip = _mm_mul_ps(half, recip);
718 __m128 threeminus_xrr = _mm_sub_ps(three, _mm_mul_ps(x.Data, _mm_mul_ps(recip, recip)));
719 return _mm_mul_ps(halfrecip, threeminus_xrr);
720}
721
722GLM_FUNC_QUALIFIER detail::fvec4SIMD fastInversesqrt(detail::fvec4SIMD const & x)
723{
724 return _mm_rsqrt_ps(x.Data);
725}
726
727}//namespace glm