• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1///////////////////////////////////////////////////////////////////////////////////////////////////
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
728