-
Notifications
You must be signed in to change notification settings - Fork 1
/
simd_scalar.h
782 lines (630 loc) · 21.8 KB
/
simd_scalar.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
/* SPDX-License-Identifier: GPL-3.0-or-later WITH GCC-exception-3.1 */
/* Copyright © 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
* Matthias Kretz <[email protected]>
*/
#ifndef PROTOTYPE_SIMD_SCALAR_H_
#define PROTOTYPE_SIMD_SCALAR_H_
#include "detail.h"
#include "detail_bitmask.h"
#include <cmath>
namespace std::__detail
{
// __promote_preserving_unsigned
// work around crazy semantics of unsigned integers of lower rank than int:
// Before applying an operator the operands are promoted to int. In which case
// over- or underflow is UB, even though the operand types were unsigned.
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC constexpr decltype(auto)
__promote_preserving_unsigned(const _Tp& __x)
{
if constexpr (std::is_integral_v<_Tp>)
{
if constexpr (is_signed_v<decltype(+__x)> && is_unsigned_v<_Tp>)
return static_cast<unsigned int>(__x);
else
return __x;
}
else
return __x;
}
struct _SimdImplScalar;
struct _MaskImplScalar;
}
namespace std
{
struct _ScalarAbi
{
static constexpr __detail::_SimdSizeType _S_size = 1;
static constexpr __detail::_SimdSizeType _S_full_size = 1;
static constexpr bool _S_is_partial = false;
struct _IsValidAbiTag
: true_type
{};
template <typename>
struct _IsValidSizeFor
: true_type
{};
template <typename _Tp>
using _IsValid = __detail::__is_vectorizable<_Tp>;
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_masked(bool __x)
{ return __x; }
using _SimdImpl = __detail::_SimdImplScalar;
using _MaskImpl = __detail::_MaskImplScalar;
template <typename _Tp>
using _SimdMember = _Tp;
template <typename>
using _MaskMember = bool;
template <typename _Tp>
struct __traits
: __detail::_InvalidTraits
{};
template <typename _Tp>
requires _IsValid<_Tp>::value
struct __traits<_Tp>
{
// conversions to _ScalarAbi should always be implicit
template <typename _FromAbi>
static constexpr bool _S_explicit_mask_conversion = false;
using _SimdImpl = __detail::_SimdImplScalar;
using _MaskImpl = __detail::_MaskImplScalar;
using _SimdMember = _Tp;
using _MaskMember = bool;
static constexpr __detail::_SimdSizeType _S_size = 1;
static constexpr __detail::_SimdSizeType _S_full_size = 1;
static constexpr bool _S_is_partial = false;
static constexpr size_t _S_simd_align = alignof(_SimdMember);
static constexpr size_t _S_mask_align = alignof(_MaskMember);
struct _SimdCastType { _SimdCastType() = delete; };
struct _MaskCastType { _MaskCastType() = delete; };
};
};
}
namespace std::__detail
{
struct _SimdImplScalar
{
using abi_type = _ScalarAbi;
template <typename _Tp>
using _TypeTag = _Tp*;
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_broadcast(_Tp __x) noexcept
{ return __x; }
template <typename _Tp, typename _Fp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_generator(_Fp&& __gen)
{ return __gen(__ic<0>); }
template <typename _Tp, typename _Up>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_load(const _Up* __mem, _TypeTag<_Tp>) noexcept
{ return static_cast<_Tp>(__mem[0]); }
template <typename _Tp, typename _Up>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_masked_load(_Tp __merge, bool __k, const _Up* __mem) noexcept
{
if (__k)
__merge = static_cast<_Tp>(__mem[0]);
return __merge;
}
template <typename _Tp, typename _Up>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_store(_Tp __v, _Up* __mem, _TypeTag<_Tp>) noexcept
{ __mem[0] = static_cast<_Up>(__v); }
template <typename _Tp, typename _Up>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_masked_store(const _Tp __v, _Up* __mem, const bool __k) noexcept
{ if (__k) __mem[0] = __v; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_negate(_Tp __x) noexcept
{ return !__x; }
template <typename _Tp, typename _BinaryOperation>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_reduce(const basic_simd<_Tp, _ScalarAbi>& __x, const _BinaryOperation&)
{ return __x._M_data; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_min(const _Tp __a, const _Tp __b)
{ return std::min(__a, __b); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_max(const _Tp __a, const _Tp __b)
{ return std::max(__a, __b); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_complement(_Tp __x) noexcept
{ return static_cast<_Tp>(~__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_unary_minus(_Tp __x) noexcept
{ return static_cast<_Tp>(-__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_plus(_Tp __x, _Tp __y)
{
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
+ __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_minus(_Tp __x, _Tp __y)
{
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
- __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_multiplies(_Tp __x, _Tp __y)
{
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
* __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_divides(_Tp __x, _Tp __y)
{
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
/ __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_modulus(_Tp __x, _Tp __y)
{
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
% __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_bit_and(_Tp __x, _Tp __y)
{
if constexpr (is_floating_point_v<_Tp>)
{
using _Ip = __make_unsigned_int_t<_Tp>;
return bit_cast<_Tp>(bit_cast<_Ip>(__x) & bit_cast<_Ip>(__y));
}
else
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
& __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_bit_or(_Tp __x, _Tp __y)
{
if constexpr (is_floating_point_v<_Tp>)
{
using _Ip = __make_unsigned_int_t<_Tp>;
return _bit_cast<_Tp>(bit_cast<_Ip>(__x) | _bit_cast<_Ip>(__y));
}
else
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
| __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_bit_xor(_Tp __x, _Tp __y)
{
if constexpr (is_floating_point_v<_Tp>)
{
using _Ip = __make_unsigned_int_t<_Tp>;
return _bit_cast<_Tp>(_bit_cast<_Ip>(__x) ^ _bit_cast<_Ip>(__y));
}
else
return static_cast<_Tp>(__promote_preserving_unsigned(__x)
^ __promote_preserving_unsigned(__y));
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_bit_shift_left(_Tp __x, int __y)
{ return static_cast<_Tp>(__promote_preserving_unsigned(__x) << __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_bit_shift_right(_Tp __x, int __y)
{ return static_cast<_Tp>(__promote_preserving_unsigned(__x) >> __y); }
// frexp, modf and copysign implemented in simd_math.h
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_acos(_Tp __x)
{ return std::acos(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_asin(_Tp __x)
{ return std::asin(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_atan(_Tp __x)
{ return std::atan(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_cos(_Tp __x)
{ return std::cos(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_sin(_Tp __x)
{ return std::sin(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_tan(_Tp __x)
{ return std::tan(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_acosh(_Tp __x)
{ return std::acosh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_asinh(_Tp __x)
{ return std::asinh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_atanh(_Tp __x)
{ return std::atanh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_cosh(_Tp __x)
{ return std::cosh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_sinh(_Tp __x)
{ return std::sinh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_tanh(_Tp __x)
{ return std::tanh(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_atan2(_Tp __x, _Tp __y)
{ return std::atan2(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_exp(_Tp __x)
{ return std::exp(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_exp2(_Tp __x)
{ return std::exp2(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_expm1(_Tp __x)
{ return std::expm1(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_log(_Tp __x)
{ return std::log(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_log10(_Tp __x)
{ return std::log10(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_log1p(_Tp __x)
{ return std::log1p(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_log2(_Tp __x)
{ return std::log2(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_logb(_Tp __x)
{ return std::logb(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static int
_S_ilogb(_Tp __x)
{ return std::ilogb(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_pow(_Tp __x, _Tp __y)
{ return std::pow(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_abs(_Tp __x)
{ return std::abs(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fabs(_Tp __x)
{ return std::fabs(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_sqrt(_Tp __x)
{ return std::sqrt(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_cbrt(_Tp __x)
{ return std::cbrt(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_erf(_Tp __x)
{ return std::erf(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_erfc(_Tp __x)
{ return std::erfc(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_lgamma(_Tp __x)
{ return std::lgamma(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_tgamma(_Tp __x)
{ return std::tgamma(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_trunc(_Tp __x)
{ return std::trunc(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_floor(_Tp __x)
{ return std::floor(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_ceil(_Tp __x)
{ return std::ceil(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_nearbyint(_Tp __x)
{ return std::nearbyint(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_rint(_Tp __x)
{ return std::rint(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static long
_S_lrint(_Tp __x)
{ return std::lrint(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static long long
_S_llrint(_Tp __x)
{ return std::llrint(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_round(_Tp __x)
{ return std::round(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static long
_S_lround(_Tp __x)
{ return std::lround(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static long long
_S_llround(_Tp __x)
{ return std::llround(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_ldexp(_Tp __x, int __y)
{ return std::ldexp(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_scalbn(_Tp __x, int __y)
{ return std::scalbn(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_scalbln(_Tp __x, long __y)
{ return std::scalbln(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fmod(_Tp __x, _Tp __y)
{ return std::fmod(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_remainder(_Tp __x, _Tp __y)
{ return std::remainder(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_nextafter(_Tp __x, _Tp __y)
{ return std::nextafter(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fdim(_Tp __x, _Tp __y)
{ return std::fdim(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fmax(_Tp __x, _Tp __y)
{ return std::fmax(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fmin(_Tp __x, _Tp __y)
{ return std::fmin(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_fma(_Tp __x, _Tp __y, _Tp __z)
{ return std::fma(__x, __y, __z); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static _Tp
_S_remquo(_Tp __x, _Tp __y, int* __z)
{ return std::remquo(__x, __y, __z); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr int
_S_fpclassify(_Tp __x)
{ return std::fpclassify(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isfinite(_Tp __x)
{ return std::isfinite(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isinf(_Tp __x)
{ return std::isinf(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isnan(_Tp __x)
{ return std::isnan(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isnormal(_Tp __x)
{ return std::isnormal(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_signbit(_Tp __x)
{ return std::signbit(__x); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isgreater(_Tp __x, _Tp __y)
{ return std::isgreater(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isgreaterequal(_Tp __x, _Tp __y)
{ return std::isgreaterequal(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isless(_Tp __x, _Tp __y)
{ return std::isless(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_islessequal(_Tp __x, _Tp __y)
{ return std::islessequal(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_islessgreater(_Tp __x, _Tp __y)
{ return std::islessgreater(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_isunordered(_Tp __x, _Tp __y)
{ return std::isunordered(__x, __y); }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_increment(_Tp& __x)
{ ++__x; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_decrement(_Tp& __x)
{ --__x; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_equal_to(_Tp __x, _Tp __y)
{ return __x == __y; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_not_equal_to(_Tp __x, _Tp __y)
{ return __x != __y; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_less(_Tp __x, _Tp __y)
{ return __x < __y; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_less_equal(_Tp __x, _Tp __y)
{ return __x <= __y; }
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr _Tp
_S_get(_Tp __v, _SimdSizeType __i)
{
if (__i != 0)
__invoke_ub("Subscript %d is out of range: must be 0", __i);
return __v;
}
template <typename _Tp, typename _Up>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_set(_Tp& __v, _SimdSizeType __i, _Up&& __x)
{
if (__i != 0)
__invoke_ub("Subscript %d is out of range: must be 0", __i);
__v = static_cast<_Up&&>(__x);
}
template <typename _Tp>
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_masked_assign(bool __k, _Tp& __lhs, __type_identity_t<_Tp> __rhs)
{ if (__k) __lhs = __rhs; }
};
struct _MaskImplScalar
{
using abi_type = _ScalarAbi;
template <typename _Tp>
using _TypeTag = _Tp*;
template <typename>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_broadcast(bool __x)
{ return __x; }
template <typename>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_load(const bool* __mem)
{ return __mem[0]; }
_GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
_S_to_bits(bool __x)
{ return _SanitizedBitMask<1>::__create_unchecked(__x); }
template <same_as<bool>, bool _Sanitized>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_convert_mask(_BitMask<1, _Sanitized> __x)
{ return __x[__ic<0>]; }
template <typename, size_t _Bs, typename _UAbi>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_convert(basic_simd_mask<_Bs, _UAbi> __x)
{ return __x[0]; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
{
if (__mask)
__merge = __mem[0];
return __merge;
}
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_store(bool __v, bool* __mem) noexcept
{ __mem[0] = __v; }
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
{
if (__k)
__mem[0] = __v;
}
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_logical_and(bool __x, bool __y)
{ return __x && __y; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_logical_or(bool __x, bool __y)
{ return __x || __y; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_bit_not(bool __x)
{ return !__x; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_bit_and(bool __x, bool __y)
{ return __x && __y; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_bit_or(bool __x, bool __y)
{ return __x || __y; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_bit_xor(bool __x, bool __y)
{ return __x != __y; }
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_get(bool __k, _SimdSizeType __i)
{
if (__i != 0)
__invoke_ub("Subscript %d is out of range: must be 0", __i);
return __k;
}
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_set(bool& __k, _SimdSizeType __i, bool __x)
{
if (__i != 0)
__invoke_ub("Subscript %d is out of range: must be 0", __i);
__k = __x;
}
_GLIBCXX_SIMD_INTRINSIC static constexpr void
_S_masked_assign(bool __k, bool& __lhs, bool __rhs)
{
if (__k)
__lhs = __rhs;
}
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_all_of(basic_simd_mask<_Bs, abi_type> __k)
{ return __data(__k); }
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_any_of(basic_simd_mask<_Bs, abi_type> __k)
{ return __data(__k); }
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_none_of(basic_simd_mask<_Bs, abi_type> __k)
{ return !__data(__k); }
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr bool
_S_popcount(basic_simd_mask<_Bs, abi_type> __k)
{ return __data(__k); }
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr int
_S_find_first_set(basic_simd_mask<_Bs, abi_type>)
{ return 0; }
template <size_t _Bs>
_GLIBCXX_SIMD_INTRINSIC static constexpr int
_S_find_last_set(basic_simd_mask<_Bs, abi_type>)
{ return 0; }
};
}
#endif // PROTOTYPE_SIMD_SCALAR_H_