ReXGlue SDK
Loading...
Searching...
No Matches
vec128.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#include <charconv>
16#include <cstddef>
17#include <format>
18#include <iosfwd>
19#include <string>
20#include <string_view>
21
22#include <rex/assert.h>
23#include <rex/platform.h>
24#include <rex/string/numeric.h>
25#include <rex/types.h>
26
27#include <simde/x86/sse2.h>
28
29namespace rex::ppc {
30
36struct alignas(16) Vec128S {
37 union {
38 struct {
39 rex::f32 x;
40 rex::f32 y;
41 rex::f32 z;
42 rex::f32 w;
43 };
44 struct {
45 rex::i32 ix;
46 rex::i32 iy;
47 rex::i32 iz;
48 rex::i32 iw;
49 };
50 struct {
51 rex::u32 ux;
52 rex::u32 uy;
53 rex::u32 uz;
54 rex::u32 uw;
55 };
56 rex::f32 f32[4];
57 rex::f64 f64[2];
58 rex::i8 i8[16];
59 rex::u8 u8[16];
60 rex::i16 i16[8];
61 rex::u16 u16[8];
62 rex::i32 i32[4];
63 rex::u32 u32[4];
64 rex::i64 i64[2];
65 rex::u64 u64[2];
66 struct {
67 rex::u64 low;
68 rex::u64 high;
69 };
70 };
71
72 bool operator==(const Vec128S& b) const { return low == b.low && high == b.high; }
73
74 bool operator!=(const Vec128S& b) const { return low != b.low || high != b.high; }
75
76 Vec128S operator^(const Vec128S& b) const {
77 Vec128S a = *this;
78 a.high ^= b.high;
79 a.low ^= b.low;
80 return a;
81 };
82
89 *this = *this ^ b;
90 return *this;
91 };
92
93 Vec128S operator&(const Vec128S& b) const {
94 Vec128S a = *this;
95 a.high &= b.high;
96 a.low &= b.low;
97 return a;
98 };
99
106 *this = *this & b;
107 return *this;
108 };
109
110 Vec128S operator|(const Vec128S& b) const {
111 Vec128S a = *this;
112 a.high |= b.high;
113 a.low |= b.low;
114 return a;
115 };
116
123 *this = *this | b;
124 return *this;
125 };
126};
127
128using Vec128 = Vec128S;
129
131static inline Vec128 vec128i(u32 src) {
132 Vec128 v;
133 for (auto i = 0; i < 4; ++i) {
134 v.u32[i] = src;
135 }
136 return v;
137}
138
147static inline Vec128 vec128i(u32 x, u32 y, u32 z, u32 w) {
148 Vec128 v;
149 v.u32[0] = x;
150 v.u32[1] = y;
151 v.u32[2] = z;
152 v.u32[3] = w;
153 return v;
154}
155
157static inline Vec128 vec128q(u64 src) {
158 Vec128 v;
159 for (auto i = 0; i < 2; ++i) {
160 v.u64[i] = src;
161 }
162 return v;
163}
164
171static inline Vec128 vec128q(u64 x, u64 y) {
172 Vec128 v;
173 v.u64[0] = x;
174 v.u64[1] = y;
175 return v;
176}
177
179static inline Vec128 vec128d(f64 src) {
180 Vec128 v;
181 for (auto i = 0; i < 2; ++i) {
182 v.f64[i] = src;
183 }
184 return v;
185}
186
193static inline Vec128 vec128d(f64 x, f64 y) {
194 Vec128 v;
195 v.f64[0] = x;
196 v.f64[1] = y;
197 return v;
198}
199
201static inline Vec128 vec128f(f32 src) {
202 Vec128 v;
203 for (auto i = 0; i < 4; ++i) {
204 v.f32[i] = src;
205 }
206 return v;
207}
208
217static inline Vec128 vec128f(f32 x, f32 y, f32 z, f32 w) {
218 Vec128 v;
219 v.f32[0] = x;
220 v.f32[1] = y;
221 v.f32[2] = z;
222 v.f32[3] = w;
223 return v;
224}
225
227static inline Vec128 vec128s(u16 src) {
228 Vec128 v;
229 for (auto i = 0; i < 8; ++i) {
230 v.u16[i] = src;
231 }
232 return v;
233}
234
248static inline Vec128 vec128s(u16 x0, u16 x1, u16 y0, u16 y1, u16 z0, u16 z1, u16 w0, u16 w1) {
249 Vec128 v;
250 v.u16[0] = x1;
251 v.u16[1] = x0;
252 v.u16[2] = y1;
253 v.u16[3] = y0;
254 v.u16[4] = z1;
255 v.u16[5] = z0;
256 v.u16[6] = w1;
257 v.u16[7] = w0;
258 return v;
259}
260
262static inline Vec128 vec128b(u8 src) {
263 Vec128 v;
264 for (auto i = 0; i < 16; ++i) {
265 v.u8[i] = src;
266 }
267 return v;
268}
269
291static inline Vec128 vec128b(u8 x0, u8 x1, u8 x2, u8 x3, u8 y0, u8 y1, u8 y2, u8 y3, u8 z0, u8 z1,
292 u8 z2, u8 z3, u8 w0, u8 w1, u8 w2, u8 w3) {
293 Vec128 v;
294 v.u8[0] = x3;
295 v.u8[1] = x2;
296 v.u8[2] = x1;
297 v.u8[3] = x0;
298 v.u8[4] = y3;
299 v.u8[5] = y2;
300 v.u8[6] = y1;
301 v.u8[7] = y0;
302 v.u8[8] = z3;
303 v.u8[9] = z2;
304 v.u8[10] = z1;
305 v.u8[11] = z0;
306 v.u8[12] = w3;
307 v.u8[13] = w2;
308 v.u8[14] = w1;
309 v.u8[15] = w0;
310 return v;
311}
312
314std::string to_string(const Vec128& value);
315
317std::ostream& operator<<(std::ostream& os, const Vec128& value);
318
324inline std::string to_hex_string(const Vec128& value) {
325 return std::format("[{:08X} {:08X} {:08X} {:08X}]", value.u32[0], value.u32[1], value.u32[2],
326 value.u32[3]);
327}
328
329} // namespace rex::ppc
330
331namespace rex::string {
332
339template <>
340inline ppc::Vec128 from_string<ppc::Vec128>(const std::string_view value, bool force_hex) {
341 if (value.empty()) {
342 return ppc::Vec128();
343 }
344 ppc::Vec128 v;
345 auto p = value.data();
346 auto end = value.data() + value.size();
347 bool is_hex = force_hex;
348 if (p != end && *p == '[') {
349 is_hex = true;
350 ++p;
351 } else if (p != end && *p == '(') {
352 is_hex = false;
353 ++p;
354 } else {
355 is_hex = true;
356 }
357 if (p == end) {
359 return ppc::Vec128();
360 }
361 if (is_hex) {
362 for (size_t i = 0; i < 4; i++) {
363 while (p != end && (*p == ' ' || *p == ',')) {
364 ++p;
365 }
366 if (p == end) {
368 return ppc::Vec128();
369 }
370 auto result = std::from_chars(p, end, v.u32[i], 16);
371 if (result.ec != std::errc()) {
373 return ppc::Vec128();
374 }
375 p = result.ptr;
376 }
377 } else {
378 for (size_t i = 0; i < 4; i++) {
379 while (p != end && (*p == ' ' || *p == ',')) {
380 ++p;
381 }
382 if (p == end) {
384 return ppc::Vec128();
385 }
386#if REX_PLATFORM_MAC
387 auto result = detail::portable_float_from_chars(p, end, v.f32[i]);
388#else
389 auto result = std::from_chars(p, end, v.f32[i], std::chars_format::general);
390#endif
391 if (result.ec != std::errc()) {
393 return ppc::Vec128();
394 }
395 p = result.ptr;
396 }
397 }
398 return v;
399}
400
401} // namespace rex::string
402
403namespace rex::ppc {
404
410template <int N>
411f32 m128_f32(const simde__m128& v) {
412 f32 ret;
413 simde_mm_store_ss(&ret, simde_mm_shuffle_ps(v, v, SIMDE_MM_SHUFFLE(N, N, N, N)));
414 return ret;
415}
416
422template <int N>
423i32 m128_i32(const simde__m128& v) {
424 f32 f;
425 simde_mm_store_ss(&f, simde_mm_shuffle_ps(v, v, SIMDE_MM_SHUFFLE(N, N, N, N)));
426 return std::bit_cast<i32>(f);
427}
428
434template <int N>
435f64 m128_f64(const simde__m128d& v) {
436 f64 ret;
437 simde_mm_store_sd(&ret, simde_mm_shuffle_pd(v, v, SIMDE_MM_SHUFFLE2(N, N)));
438 return ret;
439}
440
447template <int N>
448f64 m128_f64(const simde__m128& v) {
449 return m128_f64<N>(simde_mm_castps_pd(v));
450}
451
457template <int N>
458i64 m128_i64(const simde__m128d& v) {
459 f64 f;
460 simde_mm_store_sd(&f, simde_mm_shuffle_pd(v, v, SIMDE_MM_SHUFFLE2(N, N)));
461 return std::bit_cast<i64>(f);
462}
463
470template <int N>
471i64 m128_i64(const simde__m128& v) {
472 return m128_i64<N>(simde_mm_castps_pd(v));
473}
474
475} // namespace rex::ppc
#define REX_ASSERT_ALWAYS(...)
Definition assert.h:102
Definition title_runtime.h:33
f32 m128_f32(const simde__m128 &v)
Definition vec128.h:411
f64 m128_f64(const simde__m128d &v)
Definition vec128.h:435
i64 m128_i64(const simde__m128d &v)
Definition vec128.h:458
i32 m128_i32(const simde__m128 &v)
Definition vec128.h:423
std::string to_string(const Vec128 &value)
std::ostream & operator<<(std::ostream &os, const Vec128 &value)
std::string to_hex_string(const Vec128 &value)
Definition vec128.h:324
T from_string(const std::string_view value, bool force_hex=false)
Definition numeric.h:83
Platform flags, packing macros and export markers.
Definition vec128.h:36
Vec128S & operator&=(const Vec128S &b)
Definition vec128.h:105
Vec128S & operator|=(const Vec128S &b)
Definition vec128.h:122
Vec128S & operator^=(const Vec128S &b)
Definition vec128.h:88
Integer types, byte order wrappers and size literals.