Plasma Engine  2.0
Loading...
Searching...
No Matches
NEONFloat_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 = vmovq_n_f32(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 = vmovq_n_f32(f);
18}
19
20PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plInt32 i)
21{
22 PL_CHECK_SIMD_ALIGNMENT(this);
23
24 m_v = vcvtq_f32_s32(vmovq_n_s32(i));
25}
26
27PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plUInt32 i)
28{
29 PL_CHECK_SIMD_ALIGNMENT(this);
30
31 m_v = vcvtq_f32_u32(vmovq_n_u32(i));
32}
33
34PL_ALWAYS_INLINE plSimdFloat::plSimdFloat(plAngle a)
35{
36 PL_CHECK_SIMD_ALIGNMENT(this);
37
38 m_v = vmovq_n_f32(a.GetRadian());
39}
40
42{
43 m_v = v;
44}
45
46PL_ALWAYS_INLINE plSimdFloat::operator float() const
47{
48 return vgetq_lane_f32(m_v, 0);
49}
50
51// static
52PL_ALWAYS_INLINE plSimdFloat plSimdFloat::MakeZero()
53{
54 return vmovq_n_f32(0.0f);
55}
56
57// static
58PL_ALWAYS_INLINE plSimdFloat plSimdFloat::MakeNaN()
59{
60 return vmovq_n_f32(plMath::NaN<float>());
61}
62
63PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator+(const plSimdFloat& f) const
64{
65 return vaddq_f32(m_v, f.m_v);
66}
67
68PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator-(const plSimdFloat& f) const
69{
70 return vsubq_f32(m_v, f.m_v);
71}
72
73PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator*(const plSimdFloat& f) const
74{
75 return vmulq_f32(m_v, f.m_v);
76}
77
78PL_ALWAYS_INLINE plSimdFloat plSimdFloat::operator/(const plSimdFloat& f) const
79{
80 return vdivq_f32(m_v, f.m_v);
81}
82
83PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator+=(const plSimdFloat& f)
84{
85 m_v = vaddq_f32(m_v, f.m_v);
86 return *this;
87}
88
89PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator-=(const plSimdFloat& f)
90{
91 m_v = vsubq_f32(m_v, f.m_v);
92 return *this;
93}
94
95PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator*=(const plSimdFloat& f)
96{
97 m_v = vmulq_f32(m_v, f.m_v);
98 return *this;
99}
100
101PL_ALWAYS_INLINE plSimdFloat& plSimdFloat::operator/=(const plSimdFloat& f)
102{
103 m_v = vdivq_f32(m_v, f.m_v);
104 return *this;
105}
106
107PL_ALWAYS_INLINE bool plSimdFloat::IsEqual(const plSimdFloat& rhs, const plSimdFloat& fEpsilon) const
108{
109 plSimdFloat minusEps = rhs - fEpsilon;
110 plSimdFloat plusEps = rhs + fEpsilon;
111 return ((*this >= minusEps) && (*this <= plusEps));
112}
113
114PL_ALWAYS_INLINE bool plSimdFloat::operator==(const plSimdFloat& f) const
115{
116 return vgetq_lane_u32(vceqq_f32(m_v, f.m_v), 0) & 1;
117}
118
119PL_ALWAYS_INLINE bool plSimdFloat::operator!=(const plSimdFloat& f) const
120{
121 return !operator==(f);
122}
123
124PL_ALWAYS_INLINE bool plSimdFloat::operator>=(const plSimdFloat& f) const
125{
126 return vgetq_lane_u32(vcgeq_f32(m_v, f.m_v), 0) & 1;
127}
128
129PL_ALWAYS_INLINE bool plSimdFloat::operator>(const plSimdFloat& f) const
130{
131 return vgetq_lane_u32(vcgtq_f32(m_v, f.m_v), 0) & 1;
132}
133
134PL_ALWAYS_INLINE bool plSimdFloat::operator<=(const plSimdFloat& f) const
135{
136 return vgetq_lane_u32(vcleq_f32(m_v, f.m_v), 0) & 1;
137}
138
139PL_ALWAYS_INLINE bool plSimdFloat::operator<(const plSimdFloat& f) const
140{
141 return vgetq_lane_u32(vcltq_f32(m_v, f.m_v), 0) & 1;
142}
143
144PL_ALWAYS_INLINE bool plSimdFloat::operator==(float f) const
145{
146 return (*this) == plSimdFloat(f);
147}
148
149PL_ALWAYS_INLINE bool plSimdFloat::operator!=(float f) const
150{
151 return (*this) != plSimdFloat(f);
152}
153
154PL_ALWAYS_INLINE bool plSimdFloat::operator>(float f) const
155{
156 return (*this) > plSimdFloat(f);
157}
158
159PL_ALWAYS_INLINE bool plSimdFloat::operator>=(float f) const
160{
161 return (*this) >= plSimdFloat(f);
162}
163
164PL_ALWAYS_INLINE bool plSimdFloat::operator<(float f) const
165{
166 return (*this) < plSimdFloat(f);
167}
168
169PL_ALWAYS_INLINE bool plSimdFloat::operator<=(float f) const
170{
171 return (*this) <= plSimdFloat(f);
172}
173
174template <>
175PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::FULL>() const
176{
177 return vdivq_f32(vmovq_n_f32(1.0f), m_v);
178}
179
180template <>
181PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::BITS_23>() const
182{
183 float32x4_t x0 = vrecpeq_f32(m_v);
184
185 // Two iterations of Newton-Raphson
186 float32x4_t x1 = vmulq_f32(vrecpsq_f32(m_v, x0), x0);
187 float32x4_t x2 = vmulq_f32(vrecpsq_f32(m_v, x1), x1);
188
189 return x2;
190}
191
192template <>
193PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetReciprocal<plMathAcc::BITS_12>() const
194{
195 float32x4_t x0 = vrecpeq_f32(m_v);
196
197 // One iteration of Newton-Raphson
198 float32x4_t x1 = vmulq_f32(vrecpsq_f32(m_v, x0), x0);
199
200 return x1;
201}
202
203template <>
204PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::FULL>() const
205{
206 return vdivq_f32(vmovq_n_f32(1.0f), vsqrtq_f32(m_v));
207}
208
209template <>
210PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::BITS_23>() const
211{
212 const float32x4_t x0 = vrsqrteq_f32(m_v);
213
214 // Two iterations of Newton-Raphson
215 const float32x4_t x1 = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x0, m_v), x0), x0);
216 return vmulq_f32(vrsqrtsq_f32(vmulq_f32(x1, m_v), x1), x1);
217}
218
219template <>
220PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetInvSqrt<plMathAcc::BITS_12>() const
221{
222 const float32x4_t x0 = vrsqrteq_f32(m_v);
223
224 // One iteration of Newton-Raphson
225 return vmulq_f32(vrsqrtsq_f32(vmulq_f32(x0, m_v), x0), x0);
226}
227
228template <>
229PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::FULL>() const
230{
231 return vsqrtq_f32(m_v);
232}
233
234template <>
235PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::BITS_23>() const
236{
237 return (*this) * GetInvSqrt<plMathAcc::BITS_23>();
238}
239
240template <>
241PL_ALWAYS_INLINE plSimdFloat plSimdFloat::GetSqrt<plMathAcc::BITS_12>() const
242{
243 return (*this) * GetInvSqrt<plMathAcc::BITS_12>();
244}
245
246PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Max(const plSimdFloat& f) const
247{
248 return vmaxq_f32(m_v, f.m_v);
249}
250
251PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Min(const plSimdFloat& f) const
252{
253 return vminq_f32(m_v, f.m_v);
254}
255
256PL_ALWAYS_INLINE plSimdFloat plSimdFloat::Abs() const
257{
258 return vabsq_f32(m_v);
259}
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