libstdc++
simd_bit.h
1// Implementation of <simd> -*- C++ -*-
2
3// Copyright The GNU Toolchain Authors.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25#ifndef _GLIBCXX_SIMD_BIT_H
26#define _GLIBCXX_SIMD_BIT_H 1
27
28#ifdef _GLIBCXX_SYSHDR
29#pragma GCC system_header
30#endif
31
32#if __cplusplus >= 202400L
33
34#include "simd_vec.h"
35
36// psabi warnings are bogus because the ABI of the internal types never leaks into user code
37#pragma GCC diagnostic push
38#pragma GCC diagnostic ignored "-Wpsabi"
39
40// [simd.bit] -----------------------------------------------------------------
41namespace std _GLIBCXX_VISIBILITY(default)
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44namespace simd
45{
46 template<__simd_integral _Vp>
47 [[__gnu__::__always_inline__]]
48 constexpr _Vp
49 byteswap(const _Vp& __v) noexcept
50 {
51 if constexpr (sizeof(typename _Vp::value_type) == 1)
52 return __v;
53 else
54 return _Vp([&](int __i) { return std::byteswap(__v[__i]); });
55 }
56
57 template<__simd_unsigned_integer _Vp>
58 [[__gnu__::__always_inline__]]
59 constexpr _Vp
60 bit_ceil(const _Vp& __v)
61 {
62 using _Tp = typename _Vp::value_type;
63 constexpr _Tp __max = _Tp(1) << (sizeof(_Tp) * __CHAR_BIT__ - 1);
64 __glibcxx_simd_precondition(all_of(__v <= __max), "bit_ceil result is not representable");
65 return _Vp([&](int __i) { return std::bit_ceil(__v[__i]); });
66 }
67
68 template<__simd_unsigned_integer _Vp>
69 [[__gnu__::__always_inline__]]
70 constexpr _Vp
71 bit_floor(const _Vp& __v) noexcept
72 { return _Vp([&](int __i) { return std::bit_floor(__v[__i]); }); }
73
74 template<__simd_unsigned_integer _Vp>
75 [[__gnu__::__always_inline__]]
76 constexpr typename _Vp::mask_type
77 has_single_bit(const _Vp& __v) noexcept
78 { return typename _Vp::mask_type([&](int __i) { return std::has_single_bit(__v[__i]); }); }
79
80 template<__simd_unsigned_integer _V0, __simd_integral _V1>
81 requires (_V0::size() == _V1::size())
82 && (sizeof(typename _V0::value_type) == sizeof(typename _V1::value_type))
83 [[__gnu__::__always_inline__]]
84 constexpr _V0
85 rotl(const _V0& __v, const _V1& __s) noexcept
86 { return _V0([&](int __i) { return std::rotl(__v[__i], __s[__i]); }); }
87
88 template<__simd_unsigned_integer _Vp>
89 [[__gnu__::__always_inline__]]
90 constexpr _Vp
91 rotl(const _Vp& __v, int __s) noexcept
92 { return _Vp([&](int __i) { return std::rotl(__v[__i], __s); }); }
93
94 template<__simd_unsigned_integer _V0, __simd_integral _V1>
95 requires (_V0::size() == _V1::size())
96 && (sizeof(typename _V0::value_type) == sizeof(typename _V1::value_type))
97 [[__gnu__::__always_inline__]]
98 constexpr _V0
99 rotr(const _V0& __v, const _V1& __s) noexcept
100 { return _V0([&](int __i) { return std::rotr(__v[__i], __s[__i]); }); }
101
102 template<__simd_unsigned_integer _Vp>
103 [[__gnu__::__always_inline__]]
104 constexpr _Vp
105 rotr(const _Vp& __v, int __s) noexcept
106 { return _Vp([&](int __i) { return std::rotr(__v[__i], __s); }); }
107
108 template<__simd_unsigned_integer _Vp>
109 [[__gnu__::__always_inline__]]
110 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
111 bit_width(const _Vp& __v) noexcept
112 {
114 return rebind_t<_Ip, _Vp>([&](int __i) {
115 return static_cast<_Ip>(std::bit_width(__v[__i]));
116 });
117 }
118
119 template<__simd_unsigned_integer _Vp>
120 [[__gnu__::__always_inline__]]
121 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
122 countl_zero(const _Vp& __v) noexcept
123 {
125 return rebind_t<_Ip, _Vp>([&](int __i) {
126 return static_cast<_Ip>(std::countl_zero(__v[__i]));
127 });
128 }
129
130 template<__simd_unsigned_integer _Vp>
131 [[__gnu__::__always_inline__]]
132 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
133 countl_one(const _Vp& __v) noexcept
134 {
136 return rebind_t<_Ip, _Vp>([&](int __i) {
137 return static_cast<_Ip>(std::countl_one(__v[__i]));
138 });
139 }
140
141 template<__simd_unsigned_integer _Vp>
142 [[__gnu__::__always_inline__]]
143 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
144 countr_zero(const _Vp& __v) noexcept
145 {
147 return rebind_t<_Ip, _Vp>([&](int __i) {
148 return static_cast<_Ip>(std::countr_zero(__v[__i]));
149 });
150 }
151
152 template<__simd_unsigned_integer _Vp>
153 [[__gnu__::__always_inline__]]
154 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
155 countr_one(const _Vp& __v) noexcept
156 {
158 return rebind_t<_Ip, _Vp>([&](int __i) {
159 return static_cast<_Ip>(std::countr_one(__v[__i]));
160 });
161 }
162
163 template<__simd_unsigned_integer _Vp>
164 [[__gnu__::__always_inline__]]
165 constexpr rebind_t<make_signed_t<typename _Vp::value_type>, _Vp>
166 popcount(const _Vp& __v) noexcept
167 {
169 return rebind_t<_Ip, _Vp>([&](int __i) {
170 return static_cast<_Ip>(std::popcount(__v[__i]));
171 });
172 }
173} // namespace simd
174
175 using simd::byteswap;
176 using simd::bit_ceil;
177 using simd::bit_floor;
178 using simd::has_single_bit;
179 using simd::rotl;
180 using simd::rotr;
181 using simd::bit_width;
182 using simd::countl_zero;
183 using simd::countl_one;
184 using simd::countr_zero;
185 using simd::countr_one;
186 using simd::popcount;
187_GLIBCXX_END_NAMESPACE_VERSION
188} // namespace std
189
190#pragma GCC diagnostic pop
191#endif // C++26
192#endif // _GLIBCXX_SIMD_BIT_H
typename make_signed< _Tp >::type make_signed_t
Alias template for make_signed.
Definition type_traits:2269
ISO C++ entities toplevel namespace is std.