Plasma Engine  2.0
Loading...
Searching...
No Matches
SSEFloat_inl.h
1#pragma once
2
3PL_ALWAYS_INLINE plSimdFloat::plSimdFloat()
4{
5 PL_CHECK_SIMD_ALIGNMENT(this);
6
7#if PL_ENABLED(PL_MATH_CHECK_FOR_NAN)
8 // Initialize all data to NaN in debug mode to find problems with uninitialized data easier.
9 m_v = _mm_set1_ps(plMath::NaN<float>());
10#endif
11}
12
13PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(float f)
14{
15 PL_CHECK_SIMD_ALIGNMENT(this);
16
17 m_v = _mm_set1_ps(f);
18}
19
20PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plInt32 i)
21{
22 PL_CHECK_SIMD_ALIGNMENT(this);
23
24 __m128 v = _mm_cvtsi32_ss(_mm_setzero_ps(), i);
25 m_v = _mm_shuffle_ps(v, v, PL_TO_SHUFFLE(plSwizzle::XXXX));
26}
27
28PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plUInt32 i)
29{
30 PL_CHECK_SIMD_ALIGNMENT(this);
31
32#if PL_ENABLED(PL_PLATFORM_64BIT)
33 __m128 v = _mm_cvtsi64_ss(_mm_setzero_ps(), i);
34#else
35 __m128 v = _mm_cvtsi32_ss(_mm_setzero_ps(), i);
36#endif
37 m_v = _mm_shuffle_ps(v, v, PL_TO_SHUFFLE(plSwizzle::XXXX));
38}
39
40PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plAngle a)
41{
42 PL_CHECK_SIMD_ALIGNMENT(this);
43
44 m_v = _mm_set1_ps(a.GetRadian());
45}
46
48{
49 m_v = v;
50}
51
52PL_ALWAYS_INLINE plSimdFloat::operator float() const
53{
54 float f;
55 _mm_store_ss(&f, m_v);
56 return f;
57}
58
59// static
60PL_ALWAYS_INLINE plSimdFloat plSimdFloat::MakeZero()
61{
62 return _mm_setzero_ps();
63}
64
65// static
66PL_ALWAYS_INLINE plSimdFloat plSimdFloat::MakeNaN()
67{
68 return _mm_set1_ps(plMath::NaN<float>());
69}
70
71PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator+(const plSimdFloat& f) const
72{
73 return _mm_add_ps(m_v, f.m_v);
74}
75
76PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator-(const plSimdFloat& f) const
77{
78 return _mm_sub_ps(m_v, f.m_v);
79}
80
81PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator*(const plSimdFloat& f) const
82{
83 return _mm_mul_ps(m_v, f.m_v);
84}
85
86PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator/(const plSimdFloat& f) const
87{
88 return _mm_div_ps(m_v, f.m_v);
89}
90
91PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator+=(const plSimdFloat& f)
92{
93 m_v = _mm_add_ps(m_v, f.m_v);
94 return *this;
95}
96
97PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator-=(const plSimdFloat& f)
98{
99 m_v = _mm_sub_ps(m_v, f.m_v);
100 return *this;
101}
102
103PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator*=(const plSimdFloat& f)
104{
105 m_v = _mm_mul_ps(m_v, f.m_v);
106 return *this;
107}
108
109PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator/=(const plSimdFloat& f)
110{
111 m_v = _mm_div_ps(m_v, f.m_v);
112 return *this;
113}
114
115PL_ALWAYS_INLINE bool plSimdFloat::IsEqual(const plSimdFloat& rhs, const plSimdFloat& fEpsilon) const
116{
117 plSimdFloat minusEps = rhs - fEpsilon;
118 plSimdFloat plusEps = rhs + fEpsilon;
119 return ((*this >= minusEps) && (*this <= plusEps));
120}
121
122PL_ALWAYS_INLINE bool plSimdFloat::operator==(const plSimdFloat& f) const
123{
124 return _mm_comieq_ss(m_v, f.m_v) == 1;
125}
126
127PL_ALWAYS_INLINE bool plSimdFloat::operator!=(const plSimdFloat& f) const
128{
129 return _mm_comineq_ss(m_v, f.m_v) == 1;
130}
131
132PL_ALWAYS_INLINE bool plSimdFloat::operator>=(const plSimdFloat& f) const
133{
134 return _mm_comige_ss(m_v, f.m_v) == 1;
135}
136
137PL_ALWAYS_INLINE bool plSimdFloat::operator>(const plSimdFloat& f) const
138{
139 return _mm_comigt_ss(m_v, f.m_v) == 1;
140}
141
142PL_ALWAYS_INLINE bool plSimdFloat::operator<=(const plSimdFloat& f) const
143{
144 return _mm_comile_ss(m_v, f.m_v) == 1;
145}
146
147PL_ALWAYS_INLINE bool plSimdFloat::operator<(const plSimdFloat& f) const
148{
149 return _mm_comilt_ss(m_v, f.m_v) == 1;
150}
151
152PL_ALWAYS_INLINE bool plSimdFloat::operator==(float f) const
153{
154 return (*this) == plSimdFloat(f);
155}
156
157PL_ALWAYS_INLINE bool plSimdFloat::operator!=(float f) const
158{
159 return (*this) != plSimdFloat(f);
160}
161
162PL_ALWAYS_INLINE bool plSimdFloat::operator>(float f) const
163{
164 return (*this) > plSimdFloat(f);
165}
166
167PL_ALWAYS_INLINE bool plSimdFloat::operator>=(float f) const
168{
169 return (*this) >= plSimdFloat(f);
170}
171
172PL_ALWAYS_INLINE bool plSimdFloat::operator<(float f) const
173{
174 return (*this) < plSimdFloat(f);
175}
176
177PL_ALWAYS_INLINE bool plSimdFloat::operator<=(float f) const
178{
179 return (*this) <= plSimdFloat(f);
180}
181
182template <>
183PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::FULL>() const
184{
185 return _mm_div_ps(_mm_set1_ps(1.0f), m_v);
186}
187
188template <>
189PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::BITS_23>() const
190{
191 __m128 x0 = _mm_rcp_ps(m_v);
192
193 // One iteration of Newton-Raphson
194 __m128 x1 = _mm_mul_ps(x0, _mm_sub_ps(_mm_set1_ps(2.0f), _mm_mul_ps(m_v, x0)));
195
196 return x1;
197}
198
199template <>
200PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::BITS_12>() const
201{
202 return _mm_rcp_ps(m_v);
203}
204
205template <>
206PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::FULL>() const
207{
208 return _mm_div_ps(_mm_set1_ps(1.0f), _mm_sqrt_ps(m_v));
209}
210
211template <>
212PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::BITS_23>() const
213{
214 const __m128 x0 = _mm_rsqrt_ps(m_v);
215
216 // One iteration of Newton-Raphson
217 return _mm_mul_ps(_mm_mul_ps(_mm_set1_ps(0.5f), x0), _mm_sub_ps(_mm_set1_ps(3.0f), _mm_mul_ps(_mm_mul_ps(m_v, x0), x0)));
218}
219
220template <>
221PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::BITS_12>() const
222{
223 return _mm_rsqrt_ps(m_v);
224}
225
226template <>
227PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::FULL>() const
228{
229 return _mm_sqrt_ps(m_v);
230}
231
232template <>
233PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::BITS_23>() const
234{
235 return (*this) * GetInvSqrt<plMathAcc::BITS_23>();
236}
237
238template <>
239PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::BITS_12>() const
240{
241 return (*this) * GetInvSqrt<plMathAcc::BITS_12>();
242}
243
244PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Max(const plSimdFloat& f) const
245{
246 return _mm_max_ps(m_v, f.m_v);
247}
248
249PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Min(const plSimdFloat& f) const
250{
251 return _mm_min_ps(m_v, f.m_v);
252}
253
254PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Abs() const
255{
256 return _mm_andnot_ps(_mm_set1_ps(-0.0f), m_v);
257}
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
constexpr float GetRadian() const
Returns the radian value. (No need for any conversion)
Definition Angle_inl.h:48
Definition SimdFloat.h:7
plSimdFloat()
Default constructor, leaves the data uninitialized.
Definition FPUFloat_inl.h:3
static plSimdFloat MakeNaN()
Creates an plSimdFloat that is initialized to Not-A-Number (NaN).
Definition FPUFloat_inl.h:42
static plSimdFloat MakeZero()
Creates an plSimdFloat that is initialized to zero.
Definition FPUFloat_inl.h:36
constexpr TYPE NaN()
Returns the value for NaN as the template type. Returns zero, if the type does not support NaN.
Definition Constants_inl.h:58