• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PredatorCZ / PreCore / 461

pending completion
461

push

github-actions-ci

PredatorCZ
update readme

3204 of 6096 relevant lines covered (52.56%)

354.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/include/spike/type/vectors_simd.hpp
1
/*  SIMD Vector Classes with Intel intrinsics
2

3
    Copyright 2019-2023 Lukas Cone
4

5
    Licensed under the Apache License, Version 2.0 (the "License");
6
    you may not use this file except in compliance with the License.
7
    You may obtain a copy of the License at
8

9
      http://www.apache.org/licenses/LICENSE-2.0
10

11
    Unless required by applicable law or agreed to in writing, software
12
    distributed under the License is distributed on an "AS IS" BASIS,
13
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
    See the License for the specific language governing permissions and
15
    limitations under the License.
16
*/
17

18
#pragma once
19
#include "vectors.hpp"
20
#include <smmintrin.h>
21

22
#ifdef _MSC_VER
23
thread_local static float __V4SimdFltType_EPSILON = FLT_EPSILON;
24
#else
25
thread_local static __m128 __V4SimdFltType_EPSILON = _mm_set1_ps(FLT_EPSILON);
26
#endif
27

28
class alignas(16) V4SimdFltType {
29
  using vector = V4SimdFltType;
30
  using vec_ref = vector &;
31
  using vec_cref = const vector &;
32

33
public:
34
  using value_type = float;
35
  using store_type = __m128;
36

37
  union {
38
    __m128 _data;
39
    value_type _arr[4];
40
    struct {
41
      value_type X, Y, Z, W;
42
    };
43
    struct {
44
      value_type x, y, z, w;
45
    };
46
  };
47

48
private:
49
  static store_type GetEpsilon() {
50
    return
51
#ifdef _MSC_VER
52
        _mm_set1_ps(__V4SimdFltType_EPSILON);
53
#else
54
        __V4SimdFltType_EPSILON;
133✔
55
#endif
56
  }
57

58
  static int Compare(store_type input1, store_type input2) {
59
    const store_type result =
60
        _mm_and_ps(_mm_cmple_ps(input2, _mm_add_ps(input1, GetEpsilon())),
61
                   _mm_cmpge_ps(input2, _mm_sub_ps(input1, GetEpsilon())));
62

63
    return _mm_movemask_ps(result);
64
  }
65

66
public:
67
  V4SimdFltType(store_type input) { _data = input; }
1✔
68
  V4SimdFltType() { _data = _mm_setzero_ps(); }
71✔
69
  V4SimdFltType(value_type s) { _data = _mm_set1_ps(s); }
8✔
70
  V4SimdFltType(value_type x, value_type y, value_type z, value_type w) {
115✔
71
    _data = _mm_set_ps(w, z, y, x);
19✔
72
  }
73
  V4SimdFltType(const Vector &input, float w) {
1✔
74
    _data = _mm_set_ps(w, input.Z, input.Y, input.X);
1✔
75
  }
76
  V4SimdFltType(const Vector4 &input) {
1✔
77
    _data = _mm_set_ps(input.W, input.Z, input.Y, input.X);
3✔
78
  }
79

80
  // Set thread safe TU local expsilon for comparing
81
  // Default: FLT_EPSILON
82
  static void SetEpsilon(value_type newEpsilon) {
83
    __V4SimdFltType_EPSILON =
1✔
84
#ifdef _MSC_VER
85
        newEpsilon;
86
#else
87
        _mm_set1_ps(newEpsilon);
88
#endif
89
  }
90

91
  vector operator+(vec_cref input) const {
92
    return _mm_add_ps(_data, input._data);
×
93
  }
94
  vector operator-(vec_cref input) const {
95
    return _mm_sub_ps(_data, input._data);
96
  }
97
  vector operator*(vec_cref input) const {
98
    return _mm_mul_ps(_data, input._data);
5✔
99
  }
100
  vector operator/(vec_cref input) const {
101
    return _mm_div_ps(_data, input._data);
1✔
102
  }
103
  vector operator&(vec_cref input) const {
104
    return _mm_and_ps(_data, input._data);
105
  }
106
  vector operator|(vec_cref input) const {
107
    return _mm_or_ps(_data, input._data);
108
  }
109
  vector operator^(vec_cref input) const {
110
    return _mm_xor_ps(_data, input._data);
111
  }
112
  vector operator~() const {
113
    return *this ^ vector(_mm_castsi128_ps(_mm_set1_epi32(-1)));
114
  }
115

116
  vector operator*(value_type input) const { return *this * vector(input); }
117
  vector operator+(value_type input) const { return *this + vector(input); }
118
  vector operator-(value_type input) const { return *this - vector(input); }
119
  vector operator/(value_type input) const { return *this / vector(input); }
1✔
120
  vector operator&(value_type input) const { return *this & vector(input); }
121
  vector operator|(value_type input) const { return *this | vector(input); }
122
  vector operator^(value_type input) const { return *this ^ vector(input); }
123

124
  vec_ref operator+=(vec_cref input) { return *this = *this + input; }
1✔
125
  vec_ref operator-=(vec_cref input) { return *this = *this - input; }
1✔
126
  vec_ref operator*=(vec_cref input) { return *this = *this * input; }
1✔
127
  vec_ref operator/=(vec_cref input) { return *this = *this / input; }
1✔
128
  vec_ref operator&=(vec_cref input) { return *this = *this & input; }
129
  vec_ref operator|=(vec_cref input) { return *this = *this | input; }
130
  vec_ref operator^=(vec_cref input) { return *this = *this ^ input; }
131

132
  vec_ref operator+=(value_type input) { return *this = *this + input; }
1✔
133
  vec_ref operator-=(value_type input) { return *this = *this - input; }
1✔
134
  vec_ref operator*=(value_type input) { return *this = *this * input; }
1✔
135
  vec_ref operator/=(value_type input) { return *this = *this / input; }
2✔
136
  vec_ref operator&=(value_type input) { return *this = *this & input; }
137
  vec_ref operator|=(value_type input) { return *this = *this | input; }
138
  vec_ref operator^=(value_type input) { return *this = *this ^ input; }
139

140
  vector operator-() const { return *this * -1.f; }
141

142
  operator V4SimdIntType() const;
143

144
  template <typename T> V4ScalarType<T> Convert() const {
145
    return V4ScalarType<T>(static_cast<T>(X), static_cast<T>(Y),
×
146
                           static_cast<T>(Z), static_cast<T>(W));
147
  }
148

149
  bool operator==(vec_cref input) const { return Compare(input._data, _data) == 0xF; }
131✔
150
  bool operator!=(vec_cref input) const { return !(*this == input); }
129✔
151

152
  bool operator<(vec_cref input) const {
153
    return _mm_movemask_ps(_mm_cmplt_ps(_data, input._data)) == 0xF;
154
  }
155
  bool operator>(vec_cref input) const {
156
    return _mm_movemask_ps(_mm_cmpgt_ps(_data, input._data)) == 0xF;
157
  }
158
  bool operator<=(vec_cref input) const {
×
159
    return (_mm_movemask_ps(_mm_cmplt_ps(_data, input._data)) | Compare(_data, input._data)) == 0xF;
×
160
  }
161
  bool operator>=(vec_cref input) const {
×
162
    return (_mm_movemask_ps(_mm_cmpgt_ps(_data, input._data)) | Compare(_data, input._data)) == 0xF;
×
163
  }
164

165
  bool operator<(value_type input) const { return *this < vector(input); }
166
  bool operator>(value_type input) const { return *this > vector(input); }
167
  bool operator<=(value_type input) const { return *this <= vector(input); }
×
168
  bool operator>=(value_type input) const { return *this >= vector(input); }
×
169

170
  // Check if X == Y == Z == W
171
  bool IsSymetrical() const {
2✔
172
    const store_type temp =
173
        _mm_shuffle_ps(_data, _data, _MM_SHUFFLE(3, 1, 0, 2));
2✔
174
    return Compare(_mm_hsub_ps(_data, _data), _mm_hsub_ps(temp, temp)) == 0xF;
2✔
175
  }
176

177
  // Return -1 if [X | Y | Z | W] < 0
178
  int Sign() const { return _mm_movemask_ps(_data) ? -1 : 1; }
179

180
  value_type Length() const {
181
    const auto temp = _mm_sqrt_ss(DotV(*this)._data);
182
    return _mm_cvtss_f32(temp);
183
  }
184

185
  value_type Dot(vec_cref input) const {
186
    return _mm_cvtss_f32(_mm_dp_ps(_data, input._data, 0xf1));
1✔
187
  }
188

189
  vector DotV(vec_cref input) const {
190
    return _mm_dp_ps(_data, input._data, 0xff);
3✔
191
  }
192

193
  vector Cross(vec_cref input) const {
194
    const auto temp0 =
195
        vector(_mm_shuffle_ps(_data, _data, _MM_SHUFFLE(3, 0, 2, 1)));
×
196
    const auto temp1 = vector(
197
        _mm_shuffle_ps(input._data, input._data, _MM_SHUFFLE(3, 1, 0, 2)));
×
198
    const auto temp2 =
199
        vector(_mm_shuffle_ps(_data, _data, _MM_SHUFFLE(3, 1, 0, 2)));
200
    const auto temp3 = vector(
201
        _mm_shuffle_ps(input._data, input._data, _MM_SHUFFLE(3, 0, 2, 1)));
202
    return (temp0 * temp1) - (temp2 * temp3);
203
  }
204

205
  vector Normalized() const {
206
    value_type len = Length();
207

208
    if (len == value_type{}) {
1✔
209
      return *this;
210
    }
211

212
    return *this / len;
213
  }
214

215
  vec_ref Normalize() {
216
    return *this = Normalized();
1✔
217
  }
218

219
  vector QConjugate() const {
220
    return *this * vector(-1.0f, -1.0f, -1.0f, 1.0f);
221
  }
222

223
  template <size_t elementIndex = 3> vec_ref QComputeElement() {
224
    const auto res0 = vector(1.f) - DotV(*this);
225
    const auto res1 = _mm_sqrt_ss(res0._data);
226

227
    _data = _mm_insert_ps(_data, res1, _MM_MK_INSERTPS_NDX(0, elementIndex, 0));
228

229
    return *this;
230
  }
231

232
  vec_ref QComputeElementVar(int elementIndex = 3) {
233
    _arr[elementIndex] = sqrtf(1.0f - Dot(*this));
234

235
    return *this;
236
  }
237
};
238

239
template <class eType> class alignas(16) V4SimdIntType_t {
240
  using vector = V4SimdIntType_t;
241
  using vec_ref = vector &;
242
  using vec_cref = const vector &;
243

244
public:
245
  using value_type = eType;
246
  using store_type = __m128i;
247

248
  union {
249
    store_type _data;
250
    value_type _arr[4];
251
    struct {
252
      value_type X, Y, Z, W;
253
    };
254
    struct {
255
      value_type x, y, z, w;
256
    };
257
  };
258

259
  V4SimdIntType_t(store_type input) { _data = input; }
260
  V4SimdIntType_t() { _data = _mm_setzero_si128(); }
4✔
261
  template <class _other0>
262
  V4SimdIntType_t(const V4SimdIntType_t<_other0> &input) {
3✔
263
    _data = input._data;
3✔
264
  }
265
  V4SimdIntType_t(value_type s) { _data = _mm_set1_epi32(s); }
16✔
266
  V4SimdIntType_t(value_type x, value_type y, value_type z, value_type w) {
19✔
267
    _data = _mm_set_epi32(w, z, y, x);
20✔
268
  }
269
  V4SimdIntType_t(const t_Vector4<value_type> &input) {
270
    _data = _mm_set_epi32(input.W, input.Z, input.Y, input.X);
4✔
271
  }
272

273
  operator V4SimdFltType() const { return _mm_cvtepi32_ps(_data); }
×
274

275
  vector operator+(vec_cref input) const {
276
    return _mm_add_epi32(_data, input._data);
277
  }
278
  vector operator-(vec_cref input) const {
279
    return _mm_sub_epi32(_data, input._data);
13✔
280
  }
281
  vector operator*(vec_cref input) const {
282
    return _mm_mullo_epi32(_data, input._data);
283
  }
284
  vector operator&(vec_cref input) const {
285
    return _mm_and_si128(_data, input._data);
10✔
286
  }
287
  vector operator|(vec_cref input) const {
288
    return _mm_or_si128(_data, input._data);
13✔
289
  }
290
  vector operator^(vec_cref input) const {
291
    return _mm_xor_si128(_data, input._data);
292
  }
293

294
  vector operator~() const { return *this ^ vector(0xffffffff); }
295

296
  vector operator+(value_type input) const { return *this + vector(input); }
297
  vector operator-(value_type input) const { return *this - vector(input); }
298
  vector operator*(value_type input) const { return *this * vector(input); }
299
  vector operator&(value_type input) const { return *this & vector(input); }
300
  vector operator|(value_type input) const { return *this | vector(input); }
301
  vector operator<<(value_type input) const {
302
    return _mm_slli_epi32(_data, input);
13✔
303
  }
304

305
  vector operator>>(value_type input) const {
306
    if constexpr (std::is_unsigned_v<eType>) {
307
      return _mm_srli_epi32(_data, input);
308
    } else {
309
      return _mm_srai_epi32(_data, input);
310
    }
311
  }
312

313
  vec_ref operator+=(vec_cref input) { return *this = *this + input; }
314
  vec_ref operator-=(vec_cref input) { return *this = *this - input; }
315
  vec_ref operator*=(vec_cref input) { return *this = *this * input; }
316
  vec_ref operator&=(vec_cref input) { return *this = *this & input; }
317
  vec_ref operator|=(vec_cref input) { return *this = *this | input; }
318
  vec_ref operator^=(vec_cref input) { return *this = *this ^ input; }
319

320
  vec_ref operator+=(value_type input) { return *this = *this + input; }
321
  vec_ref operator-=(value_type input) { return *this = *this - input; }
322
  vec_ref operator*=(value_type input) { return *this = *this * input; }
323
  vec_ref operator&=(value_type input) { return *this = *this & input; }
324
  vec_ref operator|=(value_type input) { return *this = *this | input; }
325
  vec_ref operator^=(value_type input) { return *this = *this ^ input; }
326
  vec_ref operator<<=(value_type input) { return *this = *this << input; }
327
  vec_ref operator>>=(value_type input) { return *this = *this >> input; }
328

329
  template <typename T> V4ScalarType<T> Convert() const {
330
    return V4ScalarType<T>(static_cast<T>(X), static_cast<T>(Y),
331
                           static_cast<T>(Z), static_cast<T>(W));
332
  }
333

334
  bool operator==(vec_cref input) const {
335
    const store_type rsInt = _mm_cmpeq_epi32(input._data, _data);
35✔
336
    const __m128 result = reinterpret_cast<const __m128 &>(rsInt);
35✔
337
    return _mm_movemask_ps(result) == 0xF;
338
  }
339

340
  bool operator!=(vec_cref input) const { return !(*this == input); }
341
};
342

343
inline V4SimdFltType::operator V4SimdIntType() const {
344
  return _mm_cvtps_epi32(_data);
345
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc