simd_scalar.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. // Simd scalar ABI specific implementations -*- C++ -*-
  2. // Copyright (C) 2020-2021 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. #ifndef _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
  21. #define _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
  22. #if __cplusplus >= 201703L
  23. #include <cmath>
  24. _GLIBCXX_SIMD_BEGIN_NAMESPACE
  25. // __promote_preserving_unsigned{{{
  26. // work around crazy semantics of unsigned integers of lower rank than int:
  27. // Before applying an operator the operands are promoted to int. In which case
  28. // over- or underflow is UB, even though the operand types were unsigned.
  29. template <typename _Tp>
  30. _GLIBCXX_SIMD_INTRINSIC constexpr decltype(auto)
  31. __promote_preserving_unsigned(const _Tp& __x)
  32. {
  33. if constexpr (is_signed_v<decltype(+__x)> && is_unsigned_v<_Tp>)
  34. return static_cast<unsigned int>(__x);
  35. else
  36. return __x;
  37. }
  38. // }}}
  39. struct _CommonImplScalar;
  40. struct _CommonImplBuiltin;
  41. struct _SimdImplScalar;
  42. struct _MaskImplScalar;
  43. // simd_abi::_Scalar {{{
  44. struct simd_abi::_Scalar
  45. {
  46. template <typename _Tp>
  47. static constexpr size_t _S_size = 1;
  48. template <typename _Tp>
  49. static constexpr size_t _S_full_size = 1;
  50. template <typename _Tp>
  51. static constexpr bool _S_is_partial = false;
  52. struct _IsValidAbiTag : true_type {};
  53. template <typename _Tp>
  54. struct _IsValidSizeFor : true_type {};
  55. template <typename _Tp>
  56. struct _IsValid : __is_vectorizable<_Tp> {};
  57. template <typename _Tp>
  58. static constexpr bool _S_is_valid_v = _IsValid<_Tp>::value;
  59. _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_masked(bool __x)
  60. { return __x; }
  61. using _CommonImpl = _CommonImplScalar;
  62. using _SimdImpl = _SimdImplScalar;
  63. using _MaskImpl = _MaskImplScalar;
  64. template <typename _Tp, bool = _S_is_valid_v<_Tp>>
  65. struct __traits : _InvalidTraits {};
  66. template <typename _Tp>
  67. struct __traits<_Tp, true>
  68. {
  69. using _IsValid = true_type;
  70. using _SimdImpl = _SimdImplScalar;
  71. using _MaskImpl = _MaskImplScalar;
  72. using _SimdMember = _Tp;
  73. using _MaskMember = bool;
  74. static constexpr size_t _S_simd_align = alignof(_SimdMember);
  75. static constexpr size_t _S_mask_align = alignof(_MaskMember);
  76. // nothing the user can spell converts to/from simd/simd_mask
  77. struct _SimdCastType { _SimdCastType() = delete; };
  78. struct _MaskCastType { _MaskCastType() = delete; };
  79. struct _SimdBase {};
  80. struct _MaskBase {};
  81. };
  82. };
  83. // }}}
  84. // _CommonImplScalar {{{
  85. struct _CommonImplScalar
  86. {
  87. // _S_store {{{
  88. template <typename _Tp>
  89. _GLIBCXX_SIMD_INTRINSIC static void _S_store(_Tp __x, void* __addr)
  90. { __builtin_memcpy(__addr, &__x, sizeof(_Tp)); }
  91. // }}}
  92. // _S_store_bool_array(_BitMask) {{{
  93. template <size_t _Np, bool _Sanitized>
  94. _GLIBCXX_SIMD_INTRINSIC static constexpr void
  95. _S_store_bool_array(_BitMask<_Np, _Sanitized> __x, bool* __mem)
  96. {
  97. __make_dependent_t<decltype(__x), _CommonImplBuiltin>::_S_store_bool_array(
  98. __x, __mem);
  99. }
  100. // }}}
  101. };
  102. // }}}
  103. // _SimdImplScalar {{{
  104. struct _SimdImplScalar
  105. {
  106. // member types {{{2
  107. using abi_type = simd_abi::scalar;
  108. template <typename _Tp>
  109. using _TypeTag = _Tp*;
  110. // _S_broadcast {{{2
  111. template <typename _Tp>
  112. _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp _S_broadcast(_Tp __x) noexcept
  113. { return __x; }
  114. // _S_generator {{{2
  115. template <typename _Fp, typename _Tp>
  116. _GLIBCXX_SIMD_INTRINSIC static constexpr _Tp _S_generator(_Fp&& __gen,
  117. _TypeTag<_Tp>)
  118. { return __gen(_SizeConstant<0>()); }
  119. // _S_load {{{2
  120. template <typename _Tp, typename _Up>
  121. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_load(const _Up* __mem,
  122. _TypeTag<_Tp>) noexcept
  123. { return static_cast<_Tp>(__mem[0]); }
  124. // _S_masked_load {{{2
  125. template <typename _Tp, typename _Up>
  126. static inline _Tp _S_masked_load(_Tp __merge, bool __k,
  127. const _Up* __mem) noexcept
  128. {
  129. if (__k)
  130. __merge = static_cast<_Tp>(__mem[0]);
  131. return __merge;
  132. }
  133. // _S_store {{{2
  134. template <typename _Tp, typename _Up>
  135. static inline void _S_store(_Tp __v, _Up* __mem, _TypeTag<_Tp>) noexcept
  136. { __mem[0] = static_cast<_Up>(__v); }
  137. // _S_masked_store {{{2
  138. template <typename _Tp, typename _Up>
  139. static inline void _S_masked_store(const _Tp __v, _Up* __mem,
  140. const bool __k) noexcept
  141. { if (__k) __mem[0] = __v; }
  142. // _S_negate {{{2
  143. template <typename _Tp>
  144. static constexpr inline bool _S_negate(_Tp __x) noexcept
  145. { return !__x; }
  146. // _S_reduce {{{2
  147. template <typename _Tp, typename _BinaryOperation>
  148. static constexpr inline _Tp
  149. _S_reduce(const simd<_Tp, simd_abi::scalar>& __x, const _BinaryOperation&)
  150. { return __x._M_data; }
  151. // _S_min, _S_max {{{2
  152. template <typename _Tp>
  153. static constexpr inline _Tp _S_min(const _Tp __a, const _Tp __b)
  154. { return std::min(__a, __b); }
  155. template <typename _Tp>
  156. static constexpr inline _Tp _S_max(const _Tp __a, const _Tp __b)
  157. { return std::max(__a, __b); }
  158. // _S_complement {{{2
  159. template <typename _Tp>
  160. static constexpr inline _Tp _S_complement(_Tp __x) noexcept
  161. { return static_cast<_Tp>(~__x); }
  162. // _S_unary_minus {{{2
  163. template <typename _Tp>
  164. static constexpr inline _Tp _S_unary_minus(_Tp __x) noexcept
  165. { return static_cast<_Tp>(-__x); }
  166. // arithmetic operators {{{2
  167. template <typename _Tp>
  168. static constexpr inline _Tp _S_plus(_Tp __x, _Tp __y)
  169. {
  170. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  171. + __promote_preserving_unsigned(__y));
  172. }
  173. template <typename _Tp>
  174. static constexpr inline _Tp _S_minus(_Tp __x, _Tp __y)
  175. {
  176. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  177. - __promote_preserving_unsigned(__y));
  178. }
  179. template <typename _Tp>
  180. static constexpr inline _Tp _S_multiplies(_Tp __x, _Tp __y)
  181. {
  182. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  183. * __promote_preserving_unsigned(__y));
  184. }
  185. template <typename _Tp>
  186. static constexpr inline _Tp _S_divides(_Tp __x, _Tp __y)
  187. {
  188. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  189. / __promote_preserving_unsigned(__y));
  190. }
  191. template <typename _Tp>
  192. static constexpr inline _Tp _S_modulus(_Tp __x, _Tp __y)
  193. {
  194. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  195. % __promote_preserving_unsigned(__y));
  196. }
  197. template <typename _Tp>
  198. static constexpr inline _Tp _S_bit_and(_Tp __x, _Tp __y)
  199. {
  200. if constexpr (is_floating_point_v<_Tp>)
  201. {
  202. using _Ip = __int_for_sizeof_t<_Tp>;
  203. return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) & __bit_cast<_Ip>(__y));
  204. }
  205. else
  206. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  207. & __promote_preserving_unsigned(__y));
  208. }
  209. template <typename _Tp>
  210. static constexpr inline _Tp _S_bit_or(_Tp __x, _Tp __y)
  211. {
  212. if constexpr (is_floating_point_v<_Tp>)
  213. {
  214. using _Ip = __int_for_sizeof_t<_Tp>;
  215. return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) | __bit_cast<_Ip>(__y));
  216. }
  217. else
  218. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  219. | __promote_preserving_unsigned(__y));
  220. }
  221. template <typename _Tp>
  222. static constexpr inline _Tp _S_bit_xor(_Tp __x, _Tp __y)
  223. {
  224. if constexpr (is_floating_point_v<_Tp>)
  225. {
  226. using _Ip = __int_for_sizeof_t<_Tp>;
  227. return __bit_cast<_Tp>(__bit_cast<_Ip>(__x) ^ __bit_cast<_Ip>(__y));
  228. }
  229. else
  230. return static_cast<_Tp>(__promote_preserving_unsigned(__x)
  231. ^ __promote_preserving_unsigned(__y));
  232. }
  233. template <typename _Tp>
  234. static constexpr inline _Tp _S_bit_shift_left(_Tp __x, int __y)
  235. { return static_cast<_Tp>(__promote_preserving_unsigned(__x) << __y); }
  236. template <typename _Tp>
  237. static constexpr inline _Tp _S_bit_shift_right(_Tp __x, int __y)
  238. { return static_cast<_Tp>(__promote_preserving_unsigned(__x) >> __y); }
  239. // math {{{2
  240. // frexp, modf and copysign implemented in simd_math.h
  241. template <typename _Tp>
  242. using _ST = _SimdTuple<_Tp, simd_abi::scalar>;
  243. template <typename _Tp>
  244. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_acos(_Tp __x)
  245. { return std::acos(__x); }
  246. template <typename _Tp>
  247. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asin(_Tp __x)
  248. { return std::asin(__x); }
  249. template <typename _Tp>
  250. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan(_Tp __x)
  251. { return std::atan(__x); }
  252. template <typename _Tp>
  253. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cos(_Tp __x)
  254. { return std::cos(__x); }
  255. template <typename _Tp>
  256. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sin(_Tp __x)
  257. { return std::sin(__x); }
  258. template <typename _Tp>
  259. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tan(_Tp __x)
  260. { return std::tan(__x); }
  261. template <typename _Tp>
  262. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_acosh(_Tp __x)
  263. { return std::acosh(__x); }
  264. template <typename _Tp>
  265. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_asinh(_Tp __x)
  266. { return std::asinh(__x); }
  267. template <typename _Tp>
  268. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atanh(_Tp __x)
  269. { return std::atanh(__x); }
  270. template <typename _Tp>
  271. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cosh(_Tp __x)
  272. { return std::cosh(__x); }
  273. template <typename _Tp>
  274. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sinh(_Tp __x)
  275. { return std::sinh(__x); }
  276. template <typename _Tp>
  277. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tanh(_Tp __x)
  278. { return std::tanh(__x); }
  279. template <typename _Tp>
  280. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_atan2(_Tp __x, _Tp __y)
  281. { return std::atan2(__x, __y); }
  282. template <typename _Tp>
  283. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp(_Tp __x)
  284. { return std::exp(__x); }
  285. template <typename _Tp>
  286. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_exp2(_Tp __x)
  287. { return std::exp2(__x); }
  288. template <typename _Tp>
  289. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_expm1(_Tp __x)
  290. { return std::expm1(__x); }
  291. template <typename _Tp>
  292. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log(_Tp __x)
  293. { return std::log(__x); }
  294. template <typename _Tp>
  295. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log10(_Tp __x)
  296. { return std::log10(__x); }
  297. template <typename _Tp>
  298. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log1p(_Tp __x)
  299. { return std::log1p(__x); }
  300. template <typename _Tp>
  301. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_log2(_Tp __x)
  302. { return std::log2(__x); }
  303. template <typename _Tp>
  304. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_logb(_Tp __x)
  305. { return std::logb(__x); }
  306. template <typename _Tp>
  307. _GLIBCXX_SIMD_INTRINSIC static _ST<int> _S_ilogb(_Tp __x)
  308. { return {std::ilogb(__x)}; }
  309. template <typename _Tp>
  310. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_pow(_Tp __x, _Tp __y)
  311. { return std::pow(__x, __y); }
  312. template <typename _Tp>
  313. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_abs(_Tp __x)
  314. { return std::abs(__x); }
  315. template <typename _Tp>
  316. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fabs(_Tp __x)
  317. { return std::fabs(__x); }
  318. template <typename _Tp>
  319. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_sqrt(_Tp __x)
  320. { return std::sqrt(__x); }
  321. template <typename _Tp>
  322. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_cbrt(_Tp __x)
  323. { return std::cbrt(__x); }
  324. template <typename _Tp>
  325. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erf(_Tp __x)
  326. { return std::erf(__x); }
  327. template <typename _Tp>
  328. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_erfc(_Tp __x)
  329. { return std::erfc(__x); }
  330. template <typename _Tp>
  331. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_lgamma(_Tp __x)
  332. { return std::lgamma(__x); }
  333. template <typename _Tp>
  334. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_tgamma(_Tp __x)
  335. { return std::tgamma(__x); }
  336. template <typename _Tp>
  337. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_trunc(_Tp __x)
  338. { return std::trunc(__x); }
  339. template <typename _Tp>
  340. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_floor(_Tp __x)
  341. { return std::floor(__x); }
  342. template <typename _Tp>
  343. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ceil(_Tp __x)
  344. { return std::ceil(__x); }
  345. template <typename _Tp>
  346. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nearbyint(_Tp __x)
  347. { return std::nearbyint(__x); }
  348. template <typename _Tp>
  349. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_rint(_Tp __x)
  350. { return std::rint(__x); }
  351. template <typename _Tp>
  352. _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lrint(_Tp __x)
  353. { return {std::lrint(__x)}; }
  354. template <typename _Tp>
  355. _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llrint(_Tp __x)
  356. { return {std::llrint(__x)}; }
  357. template <typename _Tp>
  358. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_round(_Tp __x)
  359. { return std::round(__x); }
  360. template <typename _Tp>
  361. _GLIBCXX_SIMD_INTRINSIC static _ST<long> _S_lround(_Tp __x)
  362. { return {std::lround(__x)}; }
  363. template <typename _Tp>
  364. _GLIBCXX_SIMD_INTRINSIC static _ST<long long> _S_llround(_Tp __x)
  365. { return {std::llround(__x)}; }
  366. template <typename _Tp>
  367. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_ldexp(_Tp __x, _ST<int> __y)
  368. { return std::ldexp(__x, __y.first); }
  369. template <typename _Tp>
  370. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbn(_Tp __x, _ST<int> __y)
  371. { return std::scalbn(__x, __y.first); }
  372. template <typename _Tp>
  373. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_scalbln(_Tp __x, _ST<long> __y)
  374. { return std::scalbln(__x, __y.first); }
  375. template <typename _Tp>
  376. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmod(_Tp __x, _Tp __y)
  377. { return std::fmod(__x, __y); }
  378. template <typename _Tp>
  379. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_remainder(_Tp __x, _Tp __y)
  380. { return std::remainder(__x, __y); }
  381. template <typename _Tp>
  382. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_nextafter(_Tp __x, _Tp __y)
  383. { return std::nextafter(__x, __y); }
  384. template <typename _Tp>
  385. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fdim(_Tp __x, _Tp __y)
  386. { return std::fdim(__x, __y); }
  387. template <typename _Tp>
  388. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmax(_Tp __x, _Tp __y)
  389. { return std::fmax(__x, __y); }
  390. template <typename _Tp>
  391. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fmin(_Tp __x, _Tp __y)
  392. { return std::fmin(__x, __y); }
  393. template <typename _Tp>
  394. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_fma(_Tp __x, _Tp __y, _Tp __z)
  395. { return std::fma(__x, __y, __z); }
  396. template <typename _Tp>
  397. _GLIBCXX_SIMD_INTRINSIC static _Tp _S_remquo(_Tp __x, _Tp __y, _ST<int>* __z)
  398. { return std::remquo(__x, __y, &__z->first); }
  399. template <typename _Tp>
  400. _GLIBCXX_SIMD_INTRINSIC constexpr static _ST<int> _S_fpclassify(_Tp __x)
  401. { return {std::fpclassify(__x)}; }
  402. template <typename _Tp>
  403. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isfinite(_Tp __x)
  404. { return std::isfinite(__x); }
  405. template <typename _Tp>
  406. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isinf(_Tp __x)
  407. { return std::isinf(__x); }
  408. template <typename _Tp>
  409. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnan(_Tp __x)
  410. { return std::isnan(__x); }
  411. template <typename _Tp>
  412. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isnormal(_Tp __x)
  413. { return std::isnormal(__x); }
  414. template <typename _Tp>
  415. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_signbit(_Tp __x)
  416. { return std::signbit(__x); }
  417. template <typename _Tp>
  418. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreater(_Tp __x, _Tp __y)
  419. { return std::isgreater(__x, __y); }
  420. template <typename _Tp>
  421. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isgreaterequal(_Tp __x,
  422. _Tp __y)
  423. { return std::isgreaterequal(__x, __y); }
  424. template <typename _Tp>
  425. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isless(_Tp __x, _Tp __y)
  426. { return std::isless(__x, __y); }
  427. template <typename _Tp>
  428. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessequal(_Tp __x, _Tp __y)
  429. { return std::islessequal(__x, __y); }
  430. template <typename _Tp>
  431. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_islessgreater(_Tp __x,
  432. _Tp __y)
  433. { return std::islessgreater(__x, __y); }
  434. template <typename _Tp>
  435. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_isunordered(_Tp __x,
  436. _Tp __y)
  437. { return std::isunordered(__x, __y); }
  438. // _S_increment & _S_decrement{{{2
  439. template <typename _Tp>
  440. constexpr static inline void _S_increment(_Tp& __x)
  441. { ++__x; }
  442. template <typename _Tp>
  443. constexpr static inline void _S_decrement(_Tp& __x)
  444. { --__x; }
  445. // compares {{{2
  446. template <typename _Tp>
  447. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_equal_to(_Tp __x, _Tp __y)
  448. { return __x == __y; }
  449. template <typename _Tp>
  450. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_not_equal_to(_Tp __x,
  451. _Tp __y)
  452. { return __x != __y; }
  453. template <typename _Tp>
  454. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less(_Tp __x, _Tp __y)
  455. { return __x < __y; }
  456. template <typename _Tp>
  457. _GLIBCXX_SIMD_INTRINSIC constexpr static bool _S_less_equal(_Tp __x,
  458. _Tp __y)
  459. { return __x <= __y; }
  460. // smart_reference access {{{2
  461. template <typename _Tp, typename _Up>
  462. constexpr static void _S_set(_Tp& __v, [[maybe_unused]] int __i,
  463. _Up&& __x) noexcept
  464. {
  465. _GLIBCXX_DEBUG_ASSERT(__i == 0);
  466. __v = static_cast<_Up&&>(__x);
  467. }
  468. // _S_masked_assign {{{2
  469. template <typename _Tp>
  470. _GLIBCXX_SIMD_INTRINSIC constexpr static void
  471. _S_masked_assign(bool __k, _Tp& __lhs, _Tp __rhs)
  472. { if (__k) __lhs = __rhs; }
  473. // _S_masked_cassign {{{2
  474. template <typename _Op, typename _Tp>
  475. _GLIBCXX_SIMD_INTRINSIC constexpr static void
  476. _S_masked_cassign(const bool __k, _Tp& __lhs, const _Tp __rhs, _Op __op)
  477. { if (__k) __lhs = __op(_SimdImplScalar{}, __lhs, __rhs); }
  478. // _S_masked_unary {{{2
  479. template <template <typename> class _Op, typename _Tp>
  480. _GLIBCXX_SIMD_INTRINSIC constexpr static _Tp _S_masked_unary(const bool __k,
  481. const _Tp __v)
  482. { return static_cast<_Tp>(__k ? _Op<_Tp>{}(__v) : __v); }
  483. // }}}2
  484. };
  485. // }}}
  486. // _MaskImplScalar {{{
  487. struct _MaskImplScalar
  488. {
  489. // member types {{{
  490. template <typename _Tp>
  491. using _TypeTag = _Tp*;
  492. // }}}
  493. // _S_broadcast {{{
  494. template <typename>
  495. _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_broadcast(bool __x)
  496. { return __x; }
  497. // }}}
  498. // _S_load {{{
  499. template <typename>
  500. _GLIBCXX_SIMD_INTRINSIC static constexpr bool _S_load(const bool* __mem)
  501. { return __mem[0]; }
  502. // }}}
  503. // _S_to_bits {{{
  504. _GLIBCXX_SIMD_INTRINSIC static constexpr _SanitizedBitMask<1>
  505. _S_to_bits(bool __x)
  506. { return __x; }
  507. // }}}
  508. // _S_convert {{{
  509. template <typename, bool _Sanitized>
  510. _GLIBCXX_SIMD_INTRINSIC static constexpr bool
  511. _S_convert(_BitMask<1, _Sanitized> __x)
  512. { return __x[0]; }
  513. template <typename, typename _Up, typename _UAbi>
  514. _GLIBCXX_SIMD_INTRINSIC static constexpr bool
  515. _S_convert(simd_mask<_Up, _UAbi> __x)
  516. { return __x[0]; }
  517. // }}}
  518. // _S_from_bitmask {{{2
  519. template <typename _Tp>
  520. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  521. _S_from_bitmask(_SanitizedBitMask<1> __bits, _TypeTag<_Tp>) noexcept
  522. { return __bits[0]; }
  523. // _S_masked_load {{{2
  524. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  525. _S_masked_load(bool __merge, bool __mask, const bool* __mem) noexcept
  526. {
  527. if (__mask)
  528. __merge = __mem[0];
  529. return __merge;
  530. }
  531. // _S_store {{{2
  532. _GLIBCXX_SIMD_INTRINSIC static void _S_store(bool __v, bool* __mem) noexcept
  533. { __mem[0] = __v; }
  534. // _S_masked_store {{{2
  535. _GLIBCXX_SIMD_INTRINSIC static void
  536. _S_masked_store(const bool __v, bool* __mem, const bool __k) noexcept
  537. {
  538. if (__k)
  539. __mem[0] = __v;
  540. }
  541. // logical and bitwise operators {{{2
  542. static constexpr bool _S_logical_and(bool __x, bool __y)
  543. { return __x && __y; }
  544. static constexpr bool _S_logical_or(bool __x, bool __y)
  545. { return __x || __y; }
  546. static constexpr bool _S_bit_not(bool __x)
  547. { return !__x; }
  548. static constexpr bool _S_bit_and(bool __x, bool __y)
  549. { return __x && __y; }
  550. static constexpr bool _S_bit_or(bool __x, bool __y)
  551. { return __x || __y; }
  552. static constexpr bool _S_bit_xor(bool __x, bool __y)
  553. { return __x != __y; }
  554. // smart_reference access {{{2
  555. constexpr static void _S_set(bool& __k, [[maybe_unused]] int __i,
  556. bool __x) noexcept
  557. {
  558. _GLIBCXX_DEBUG_ASSERT(__i == 0);
  559. __k = __x;
  560. }
  561. // _S_masked_assign {{{2
  562. _GLIBCXX_SIMD_INTRINSIC static void _S_masked_assign(bool __k, bool& __lhs,
  563. bool __rhs)
  564. {
  565. if (__k)
  566. __lhs = __rhs;
  567. }
  568. // }}}2
  569. // _S_all_of {{{
  570. template <typename _Tp, typename _Abi>
  571. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  572. _S_all_of(simd_mask<_Tp, _Abi> __k)
  573. { return __k._M_data; }
  574. // }}}
  575. // _S_any_of {{{
  576. template <typename _Tp, typename _Abi>
  577. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  578. _S_any_of(simd_mask<_Tp, _Abi> __k)
  579. { return __k._M_data; }
  580. // }}}
  581. // _S_none_of {{{
  582. template <typename _Tp, typename _Abi>
  583. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  584. _S_none_of(simd_mask<_Tp, _Abi> __k)
  585. { return !__k._M_data; }
  586. // }}}
  587. // _S_some_of {{{
  588. template <typename _Tp, typename _Abi>
  589. _GLIBCXX_SIMD_INTRINSIC constexpr static bool
  590. _S_some_of(simd_mask<_Tp, _Abi>)
  591. { return false; }
  592. // }}}
  593. // _S_popcount {{{
  594. template <typename _Tp, typename _Abi>
  595. _GLIBCXX_SIMD_INTRINSIC constexpr static int
  596. _S_popcount(simd_mask<_Tp, _Abi> __k)
  597. { return __k._M_data; }
  598. // }}}
  599. // _S_find_first_set {{{
  600. template <typename _Tp, typename _Abi>
  601. _GLIBCXX_SIMD_INTRINSIC constexpr static int
  602. _S_find_first_set(simd_mask<_Tp, _Abi>)
  603. { return 0; }
  604. // }}}
  605. // _S_find_last_set {{{
  606. template <typename _Tp, typename _Abi>
  607. _GLIBCXX_SIMD_INTRINSIC constexpr static int
  608. _S_find_last_set(simd_mask<_Tp, _Abi>)
  609. { return 0; }
  610. // }}}
  611. };
  612. // }}}
  613. _GLIBCXX_SIMD_END_NAMESPACE
  614. #endif // __cplusplus >= 201703L
  615. #endif // _GLIBCXX_EXPERIMENTAL_SIMD_SCALAR_H_
  616. // vim: foldmethod=marker sw=2 noet ts=8 sts=2 tw=80